packages feed

tidal-link (empty) → 1.0

raw patch · 717 files changed

+176207/−0 lines, 717 filesdep +basedep +tidal-link

Dependencies added: base, tidal-link

Files

+ LICENSE view
@@ -0,0 +1,674 @@+                    GNU GENERAL PUBLIC LICENSE+                       Version 3, 29 June 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 General Public License is a free, copyleft license for+software and other kinds of works.++  The licenses for most software and other practical works are designed+to take away your freedom to share and change the works.  By contrast,+the GNU General Public License is 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.  We, the Free Software Foundation, use the+GNU General Public License for most of our software; it applies also to+any other work released this way by its authors.  You can apply it to+your programs, too.++  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.++  To protect your rights, we need to prevent others from denying you+these rights or asking you to surrender the rights.  Therefore, you have+certain responsibilities if you distribute copies of the software, or if+you modify it: responsibilities to respect the freedom of others.++  For example, if you distribute copies of such a program, whether+gratis or for a fee, you must pass on to the recipients the same+freedoms that you received.  You must make sure that they, too, receive+or can get the source code.  And you must show them these terms so they+know their rights.++  Developers that use the GNU GPL protect your rights with two steps:+(1) assert copyright on the software, and (2) offer you this License+giving you legal permission to copy, distribute and/or modify it.++  For the developers' and authors' protection, the GPL clearly explains+that there is no warranty for this free software.  For both users' and+authors' sake, the GPL requires that modified versions be marked as+changed, so that their problems will not be attributed erroneously to+authors of previous versions.++  Some devices are designed to deny users access to install or run+modified versions of the software inside them, although the manufacturer+can do so.  This is fundamentally incompatible with the aim of+protecting users' freedom to change the software.  The systematic+pattern of such abuse occurs in the area of products for individuals to+use, which is precisely where it is most unacceptable.  Therefore, we+have designed this version of the GPL to prohibit the practice for those+products.  If such problems arise substantially in other domains, we+stand ready to extend this provision to those domains in future versions+of the GPL, as needed to protect the freedom of users.++  Finally, every program is threatened constantly by software patents.+States should not allow patents to restrict development and use of+software on general-purpose computers, but in those that do, we wish to+avoid the special danger that patents applied to a free program could+make it effectively proprietary.  To prevent this, the GPL assures that+patents cannot be used to render the program non-free.++  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 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. Use with the GNU Affero General Public License.++  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 Affero 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 special requirements of the GNU Affero General Public License,+section 13, concerning interaction through a network will apply to the+combination as such.++  14. Revised Versions of this License.++  The Free Software Foundation may publish revised and/or new versions of+the GNU 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 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 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 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.++    <one line to give the program's name and a brief idea of what it does.>+    Copyright (C) <year>  <name of author>++    This program is free software: you can redistribute it and/or modify+    it under the terms of the GNU 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 General Public License for more details.++    You should have received a copy of the GNU 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 the program does terminal interaction, make it output a short+notice like this when it starts in an interactive mode:++    <program>  Copyright (C) <year>  <name of author>+    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.+    This is free software, and you are welcome to redistribute it+    under certain conditions; type `show c' for details.++The hypothetical commands `show w' and `show c' should show the appropriate+parts of the General Public License.  Of course, your program's commands+might be different; for a GUI interface, you would use an "about box".++  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 GPL, see+<https://www.gnu.org/licenses/>.++  The GNU General Public License does not permit incorporating your program+into proprietary programs.  If your program is a subroutine library, you+may consider it more useful to permit linking proprietary applications with+the library.  If this is what you want to do, use the GNU Lesser General+Public License instead of this License.  But first, please read+<https://www.gnu.org/licenses/why-not-lgpl.html>.
+ README.md view
@@ -0,0 +1,6 @@+# tidal-link++Ableton Link integration for Tidal++Requires fixes to GHC on Windows (see https://gitlab.haskell.org/ghc/ghc/-/issues/20918)+which are available from GHC 9.2.4.
+ link/examples/linkaudio/AudioEngine.hpp view
@@ -0,0 +1,81 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++// Make sure to define this before <cmath> is included for Windows+#define _USE_MATH_DEFINES+#include <ableton/Link.hpp>+#include <atomic>+#include <mutex>++namespace ableton+{+namespace linkaudio+{++class AudioEngine+{+public:+  AudioEngine(Link& link);+  void startPlaying();+  void stopPlaying();+  bool isPlaying() const;+  double beatTime() const;+  void setTempo(double tempo);+  double quantum() const;+  void setQuantum(double quantum);+  bool isStartStopSyncEnabled() const;+  void setStartStopSyncEnabled(bool enabled);++private:+  struct EngineData+  {+    double requestedTempo;+    bool requestStart;+    bool requestStop;+    double quantum;+    bool startStopSyncOn;+  };++  void setBufferSize(std::size_t size);+  void setSampleRate(double sampleRate);+  EngineData pullEngineData();+  void renderMetronomeIntoBuffer(Link::SessionState sessionState,+    double quantum,+    std::chrono::microseconds beginHostTime,+    std::size_t numSamples);+  void audioCallback(const std::chrono::microseconds hostTime, std::size_t numSamples);++  Link& mLink;+  double mSampleRate;+  std::atomic<std::chrono::microseconds> mOutputLatency;+  std::vector<double> mBuffer;+  EngineData mSharedEngineData;+  EngineData mLockfreeEngineData;+  std::chrono::microseconds mTimeAtLastClick;+  bool mIsPlaying;+  std::mutex mEngineDataGuard;++  friend class AudioPlatform;+};+++} // namespace linkaudio+} // namespace ableton
+ link/examples/linkaudio/AudioPlatform.hpp view
@@ -0,0 +1,44 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#if defined(LINKHUT_AUDIO_PLATFORM_ASIO)+#include "AudioPlatform_Asio.hpp"+#endif++#if defined(LINKHUT_AUDIO_PLATFORM_COREAUDIO)+#include "AudioPlatform_CoreAudio.hpp"+#endif++#if defined(LINKHUT_AUDIO_PLATFORM_DUMMY)+#include "AudioPlatform_Dummy.hpp"+#endif++#if defined(LINKHUT_AUDIO_PLATFORM_JACK)+#include "AudioPlatform_Jack.hpp"+#endif++#if defined(LINKHUT_AUDIO_PLATFORM_PORTAUDIO)+#include "AudioPlatform_Portaudio.hpp"+#endif++#if defined(LINKHUT_AUDIO_PLATFORM_WASAPI)+#include "AudioPlatform_Wasapi.hpp"+#endif
+ link/examples/linkaudio/AudioPlatform_Asio.hpp view
@@ -0,0 +1,103 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include "AudioEngine.hpp"++#include <ableton/Link.hpp>+#include <ableton/link/HostTimeFilter.hpp>++#include "asiosys.h" // Should be included before asio.h++#include "asio.h"+#include "asiodrivers.h"++// External functions in the ASIO SDK which aren't declared in the SDK headers+extern AsioDrivers* asioDrivers;+bool loadAsioDriver(char* name);++namespace ableton+{+namespace linkaudio+{++#ifndef LINK_ASIO_DRIVER_NAME+#define LINK_ASIO_DRIVER_NAME "ASIO4ALL v2"+#endif+#ifndef LINK_ASIO_INPUT_CHANNELS+#define LINK_ASIO_INPUT_CHANNELS 0+#endif+#ifndef LINK_ASIO_OUTPUT_CHANNELS+#define LINK_ASIO_OUTPUT_CHANNELS 2+#endif++struct DriverInfo+{+  ASIODriverInfo driverInfo;+  long inputChannels;+  long outputChannels;+  long preferredSize;+  ASIOSampleRate sampleRate;+  bool outputReady;+  long numBuffers;+  ASIOBufferInfo bufferInfos[LINK_ASIO_INPUT_CHANNELS + LINK_ASIO_OUTPUT_CHANNELS];+  ASIOChannelInfo channelInfos[LINK_ASIO_INPUT_CHANNELS + LINK_ASIO_OUTPUT_CHANNELS];+};++// Helper functions++// Convenience function to print out an ASIO error code along with the function called+void fatalError(const ASIOError result, const std::string& function);+double asioSamplesToDouble(const ASIOSamples& samples);++ASIOTime* bufferSwitchTimeInfo(ASIOTime* timeInfo, long index, ASIOBool);+void bufferSwitch(long index, ASIOBool processNow);++class AudioPlatform+{+public:+  AudioPlatform(Link& link);+  ~AudioPlatform();++  void audioCallback(ASIOTime* timeInfo, long index);++  AudioEngine mEngine;++  // Unfortunately, the ASIO SDK does not allow passing void* user data to callback+  // functions, so we need to keep a singleton instance of the audio engine+  static AudioPlatform* singleton();+  static void setSingleton(AudioPlatform* platform);++private:+  void createAsioBuffers();+  void initializeDriverInfo();+  void initialize();+  void start();+  void stop();++  DriverInfo mDriverInfo;+  ASIOCallbacks mAsioCallbacks;+  link::HostTimeFilter<platforms::windows::Clock> mHostTimeFilter;++  static AudioPlatform* _singleton;+};++} // namespace linkaudio+} // namespace ableton
+ link/examples/linkaudio/AudioPlatform_CoreAudio.hpp view
@@ -0,0 +1,54 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include "AudioEngine.hpp"+#include <AudioToolbox/AudioToolbox.h>++namespace ableton+{+namespace linkaudio+{++class AudioPlatform+{+public:+  AudioPlatform(Link& link);+  ~AudioPlatform();+  AudioEngine mEngine;++private:+  static OSStatus audioCallback(void* inRefCon,+    AudioUnitRenderActionFlags*,+    const AudioTimeStamp* inTimeStamp,+    UInt32,+    UInt32 inNumberFrames,+    AudioBufferList* ioData);++  void initialize();+  void uninitialize();+  void start();+  void stop();++  AudioUnit mIoUnit;+};++} // namespace linkaudio+} // namespace ableton
+ link/examples/linkaudio/AudioPlatform_Dummy.hpp view
@@ -0,0 +1,112 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/Link.hpp>++namespace ableton+{+namespace linkaudio+{++class AudioPlatform+{+  class AudioEngine+  {+  public:+    AudioEngine(Link& link)+      : mLink(link)+      , mQuantum(4.)+    {+    }++    void startPlaying()+    {+      auto sessionState = mLink.captureAppSessionState();+      sessionState.setIsPlayingAndRequestBeatAtTime(true, now(), 0., mQuantum);+      mLink.commitAppSessionState(sessionState);+    }++    void stopPlaying()+    {+      auto sessionState = mLink.captureAppSessionState();+      sessionState.setIsPlaying(false, now());+      mLink.commitAppSessionState(sessionState);+    }++    bool isPlaying() const+    {+      return mLink.captureAppSessionState().isPlaying();+    }++    double beatTime() const+    {+      auto sessionState = mLink.captureAppSessionState();+      return sessionState.beatAtTime(now(), mQuantum);+    }++    void setTempo(double tempo)+    {+      auto sessionState = mLink.captureAppSessionState();+      sessionState.setTempo(tempo, now());+      mLink.commitAppSessionState(sessionState);+    }++    double quantum() const+    {+      return mQuantum;+    }++    void setQuantum(double quantum)+    {+      mQuantum = quantum;+    }++    bool isStartStopSyncEnabled() const+    {+      return mLink.isStartStopSyncEnabled();+    }++    void setStartStopSyncEnabled(bool enabled)+    {+      mLink.enableStartStopSync(enabled);+    }++  private:+    std::chrono::microseconds now() const+    {+      return mLink.clock().micros();+    }++    Link& mLink;+    double mQuantum;+  };++public:+  AudioPlatform(Link& link)+    : mEngine(link)+  {+  }++  AudioEngine mEngine;+};++} // namespace linkaudio+} // namespace ableton
+ link/examples/linkaudio/AudioPlatform_Jack.hpp view
@@ -0,0 +1,58 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include "AudioEngine.hpp"+#include <ableton/link/HostTimeFilter.hpp>+#include <ableton/platforms/Config.hpp>+#include <jack/jack.h>++namespace ableton+{+namespace linkaudio+{++class AudioPlatform+{+public:+  AudioPlatform(Link& link);+  ~AudioPlatform();++  AudioEngine mEngine;++private:+  static int audioCallback(jack_nframes_t nframes, void* pvUserData);+  int audioCallback(jack_nframes_t nframes);+  static void latencyCallback(jack_latency_callback_mode_t mode, void* pvUserData);+  void updateLatency();++  void initialize();+  void uninitialize();+  void start();+  void stop();++  link::HostTimeFilter<link::platform::Clock> mHostTimeFilter;+  double mSampleTime;+  jack_client_t* mpJackClient;+  jack_port_t** mpJackPorts;+};++} // namespace linkaudio+} // namespace ableton
+ link/examples/linkaudio/AudioPlatform_Portaudio.hpp view
@@ -0,0 +1,59 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include "AudioEngine.hpp"+#include <ableton/link/HostTimeFilter.hpp>+#include <ableton/platforms/Config.hpp>+#include <portaudio.h>++namespace ableton+{+namespace linkaudio+{++class AudioPlatform+{+public:+  AudioPlatform(Link& link);+  ~AudioPlatform();++  AudioEngine mEngine;++private:+  static int audioCallback(const void* inputBuffer,+    void* outputBuffer,+    unsigned long inNumFrames,+    const PaStreamCallbackTimeInfo* timeInfo,+    PaStreamCallbackFlags statusFlags,+    void* userData);++  void initialize();+  void uninitialize();+  void start();+  void stop();++  link::HostTimeFilter<link::platform::Clock> mHostTimeFilter;+  double mSampleTime;+  PaStream* pStream;+};++} // namespace linkaudio+} // namespace ableton
+ link/examples/linkaudio/AudioPlatform_Wasapi.hpp view
@@ -0,0 +1,72 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include "AudioEngine.hpp"+#include <Audioclient.h>+#include <Mmdeviceapi.h>+#include <ableton/link/HostTimeFilter.hpp>+#include <atomic>++// WARNING: This file provides an audio driver for Windows using WASAPI. This driver is+// considered experimental and has problems with low-latency playback. Please consider+// using the ASIO driver instead.++namespace ableton+{+namespace linkaudio+{++// Convenience function to look up the human-readable WinAPI error code, print it out,+// and then terminate the application.+void fatalError(HRESULT result, LPCTSTR context);++DWORD renderAudioRunloop(LPVOID);++class AudioPlatform+{+public:+  AudioPlatform(Link& link);+  ~AudioPlatform();++  DWORD audioRunloop();++  AudioEngine mEngine;++private:+  UINT32 bufferSize();++  void initialize();+  void start();++  link::HostTimeFilter<platforms::windows::Clock> mHostTimeFilter;+  double mSampleTime;++  IMMDevice* mDevice;+  IAudioClient* mAudioClient;+  IAudioRenderClient* mRenderClient;+  WAVEFORMATEX* mStreamFormat;+  HANDLE mEventHandle;+  HANDLE mAudioThreadHandle;+  std::atomic<bool> mIsRunning;+};++} // namespace linkaudio+} // namespace ableton
+ link/extensions/abl_link/include/abl_link.h view
@@ -0,0 +1,352 @@+/* Copyright 2021, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#include <stdbool.h>+#include <stdint.h>++#ifdef __cplusplus+extern "C"+{+#endif // __cplusplus++  /*!+   *  @discussion Each abl_link instance has its own session state which+   *  represents a beat timeline and a transport start/stop state. The+   *  timeline starts running from beat 0 at the initial tempo when+   *  constructed. The timeline always advances at a speed defined by+   *  its current tempo, even if transport is stopped. Synchronizing to the+   *  transport start/stop state of Link is optional for every peer.+   *  The transport start/stop state is only shared with other peers when+   *  start/stop synchronization is enabled.+   *+   *  An abl_link instance is initially disabled after construction, which+   *  means that it will not communicate on the network. Once enabled,+   *  an abl_link instance initiates network communication in an effort to+   *  discover other peers. When peers are discovered, they immediately+   *  become part of a shared Link session.+   *+   *  Each function documents its thread-safety and+   *  realtime-safety properties. When a function is marked thread-safe,+   *  it means it is safe to call from multiple threads+   *  concurrently. When a function is marked realtime-safe, it means that+   *  it does not block and is appropriate for use in the thread that+   *  performs audio IO.+   *+   *  One session state capture/commit function pair for use+   *  in the audio thread and one for all other application contexts is provided.+   *  In general, modifying the session state should be done in the audio+   *  thread for the most accurate timing results. The ability to modify+   *  the session state from application threads should only be used in+   *  cases where an application's audio thread is not actively running+   *  or if it doesn't generate audio at all. Modifying the Link session+   *  state from both the audio thread and an application thread+   *  concurrently is not advised and will potentially lead to unexpected+   *  behavior.+   */++  /*! @brief The representation of an abl_link instance*/+  typedef struct abl_link+  {+    void *impl;+  } abl_link;++  /*! @brief Construct a new abl_link instance with an initial tempo.+   *  Thread-safe: yes+   *  Realtime-safe: no+   */+  abl_link abl_link_create(double bpm);++  /*! @brief Delete an abl_link instance.+   *  Thread-safe: yes+   *  Realtime-safe: no+   */+  void abl_link_destroy(abl_link link);++  /*! @brief Is Link currently enabled?+   *  Thread-safe: yes+   *  Realtime-safe: yes+   */+  bool abl_link_is_enabled(abl_link link);++  /*! @brief Enable/disable Link.+   *  Thread-safe: yes+   *  Realtime-safe: no+   */+  void abl_link_enable(abl_link link, bool enable);++  /*! @brief: Is start/stop synchronization enabled?+   *  Thread-safe: yes+   *  Realtime-safe: no+   */+  bool abl_link_is_start_stop_sync_enabled(abl_link link);++  /*! @brief: Enable start/stop synchronization.+   *  Thread-safe: yes+   *  Realtime-safe: no+   */+  void abl_link_enable_start_stop_sync(abl_link link, bool enabled);++  /*! @brief How many peers are currently connected in a Link session?+   *  Thread-safe: yes+   *  Realtime-safe: yes+   */+  uint64_t abl_link_num_peers(abl_link link);++  /*! @brief Register a callback to be notified when the number of+   *  peers in the Link session changes.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion The callback is invoked on a Link-managed thread.+   */+  typedef void (*abl_link_num_peers_callback)(uint64_t num_peers, void *context);+  void abl_link_set_num_peers_callback(+    abl_link link, abl_link_num_peers_callback callback, void *context);++  /*! @brief Register a callback to be notified when the session+   *  tempo changes.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion The callback is invoked on a Link-managed thread.+   */+  typedef void (*abl_link_tempo_callback)(double tempo, void *context);+  void abl_link_set_tempo_callback(+    abl_link link, abl_link_tempo_callback callback, void *context);++  /*! brief: Register a callback to be notified when the state of+   *  start/stop isPlaying changes.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion The callback is invoked on a Link-managed thread.+   */+  typedef void (*abl_link_start_stop_callback)(bool is_playing, void *context);+  void abl_link_set_start_stop_callback(+    abl_link link, abl_link_start_stop_callback callback, void *context);++  /*! brief: Get the current link clock time in microseconds.+   *  Thread-safe: yes+   *  Realtime-safe: yes+   */+  int64_t abl_link_clock_micros(abl_link link);++  /*! @brief The representation of the current local state of a client in a Link Session+   *+   *  @discussion A session state represents a timeline and the start/stop+   *  state. The timeline is a representation of a mapping between time and+   *  beats for varying quanta. The start/stop state represents the user+   *  intention to start or stop transport at a specific time. Start stop+   *  synchronization is an optional feature that allows to share the user+   *  request to start or stop transport between a subgroup of peers in a+   *  Link session. When observing a change of start/stop state, audio+   *  playback of a peer should be started or stopped the same way it would+   *  have happened if the user had requested that change at the according+   *  time locally. The start/stop state can only be changed by the user.+   *  This means that the current local start/stop state persists when+   *  joining or leaving a Link session. After joining a Link session+   *  start/stop change requests will be communicated to all connected peers.+   */+  typedef struct abl_link_session_state+  {+    void *impl;+  } abl_link_session_state;++  /*! @brief Create a new session_state instance.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion The session_state is to be used with the abl_link_capture... and+   *  abl_link_commit... functions to capture snapshots of the current link state and pass+   *  changes to the link session.+   */+  abl_link_session_state abl_link_create_session_state(void);++  /*! @brief Delete a session_state instance.+   *  Thread-safe: yes+   *  Realtime-safe: no+   */+  void abl_link_destroy_session_state(abl_link_session_state abl_link_session_state);++  /*! @brief Capture the current Link Session State from the audio thread.+   *  Thread-safe: no+   *  Realtime-safe: yes+   *+   *  @discussion This function should ONLY be called in the audio thread and must not be+   *  accessed from any other threads. After capturing the session_state holds a snapshot+   *  of the current Link Session State, so it should be used in a local scope. The+   *  session_state should not be created on the audio thread.+   */+  void abl_link_capture_audio_session_state(+    abl_link link, abl_link_session_state session_state);++  /*! @brief Commit the given Session State to the Link session from the+   *  audio thread.+   *  Thread-safe: no+   *  Realtime-safe: yes+   *+   *  @discussion This function should ONLY be called in the audio thread. The given+   *  session_state will replace the current Link state. Modifications will be+   *  communicated to other peers in the session.+   */+  void abl_link_commit_audio_session_state(+    abl_link link, abl_link_session_state session_state);++  /*! @brief Capture the current Link Session State from an application thread.+   *  Thread-safe: no+   *  Realtime-safe: yes+   *+   *  @discussion Provides a mechanism for capturing the Link Session State from an+   *  application thread (other than the audio thread). After capturing the session_state+   *  contains a snapshot of the current Link state, so it should be used in a local+   *  scope.+   */+  void abl_link_capture_app_session_state(+    abl_link link, abl_link_session_state session_state);++  /*! @brief Commit the given Session State to the Link session from an+   *  application thread.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion The given session_state will replace the current Link Session State.+   *  Modifications of the Session State will be communicated to other peers in the+   *  session.+   */+  void abl_link_commit_app_session_state(+    abl_link link, abl_link_session_state session_state);++  /*! @brief: The tempo of the timeline, in Beats Per Minute.+   *+   *  @discussion This is a stable value that is appropriate for display to the user. Beat+   *  time progress will not necessarily match this tempo exactly because of clock drift+   *  compensation.+   */+  double abl_link_tempo(abl_link_session_state session_state);++  /*! @brief: Set the timeline tempo to the given bpm value, taking effect at the given+   *  time.+   */+  void abl_link_set_tempo(+    abl_link_session_state session_state, double bpm, int64_t at_time);++  /*! @brief: Get the beat value corresponding to the given time for the given quantum.+   *+   *  @discussion: The magnitude of the resulting beat value is unique to this Link+   *  client, but its phase with respect to the provided quantum is shared among all+   *  session peers. For non-negative beat values, the following property holds:+   *  fmod(beatAtTime(t, q), q) == phaseAtTime(t, q)+   */+  double abl_link_beat_at_time(+    abl_link_session_state session_state, int64_t time, double quantum);++  /*! @brief: Get the session phase at the given time for the given quantum.+   *+   *  @discussion: The result is in the interval [0, quantum). The result is equivalent to+   *  fmod(beatAtTime(t, q), q) for non-negative beat values. This function is convenient+   *  if the client application is only interested in the phase and not the beat+   *  magnitude. Also, unlike fmod, it handles negative beat values correctly.+   */+  double abl_link_phase_at_time(+    abl_link_session_state session_state, int64_t time, double quantum);++  /*! @brief: Get the time at which the given beat occurs for the given quantum.+   *+   *  @discussion: The inverse of beatAtTime, assuming a constant tempo.+   *  beatAtTime(timeAtBeat(b, q), q) === b.+   */+  int64_t abl_link_time_at_beat(+    abl_link_session_state session_state, double beat, double quantum);++  /*! @brief: Attempt to map the given beat to the given time in the context of the given+   * quantum.+   *+   *  @discussion: This function behaves differently depending on the state of the+   *  session. If no other peers are connected, then this abl_link instance is in a+   *  session by itself and is free to re-map the beat/time relationship whenever it+   *  pleases. In this case, beatAtTime(time, quantum) == beat after this funtion has been+   *  called.+   *+   *  If there are other peers in the session, this abl_link instance should not abruptly+   *  re-map the beat/time relationship in the session because that would lead to beat+   *  discontinuities among the other peers. In this case, the given beat will be mapped+   *  to the next time value greater than the given time with the same phase as the given+   *  beat.+   *+   *  This function is specifically designed to enable the concept of "quantized launch"+   *  in client applications. If there are no other peers in the session, then an event+   *  (such as starting transport) happens immediately when it is requested. If there are+   *  other peers, however, we wait until the next time at which the session phase matches+   *  the phase of the event, thereby executing the event in-phase with the other peers in+   *  the session. The client application only needs to invoke this function to achieve+   *  this behavior and should not need to explicitly check the number of peers.+   */+  void abl_link_request_beat_at_time(+    abl_link_session_state session_state, double beat, int64_t time, double quantum);++  /*! @brief: Rudely re-map the beat/time relationship for all peers in a session.+   *+   *  @discussion: DANGER: This function should only be needed in certain special+   *  circumstances. Most applications should not use it. It is very similar to+   *  requestBeatAtTime except that it does not fall back to the quantizing behavior when+   *  it is in a session with other peers. Calling this function will unconditionally map+   *  the given beat to the given time and broadcast the result to the session. This is+   *  very anti-social behavior and should be avoided.+   *+   *  One of the few legitimate uses of this function is to synchronize a Link session+   *  with an external clock source. By periodically forcing the beat/time mapping+   *  according to an external clock source, a peer can effectively bridge that clock into+   *  a Link session. Much care must be taken at the application layer when implementing+   *  such a feature so that users do not accidentally disrupt Link sessions that they may+   *  join.+   */+  void abl_link_force_beat_at_time(+    abl_link_session_state session_state, double beat, uint64_t time, double quantum);++  /*! @brief: Set if transport should be playing or stopped, taking effect at the given+   *  time.+   */+  void abl_link_set_is_playing(+    abl_link_session_state session_state, bool is_playing, uint64_t time);++  /*! @brief: Is transport playing? */+  bool abl_link_is_playing(abl_link_session_state session_state);++  /*! @brief: Get the time at which a transport start/stop occurs */+  uint64_t abl_link_time_for_is_playing(abl_link_session_state session_state);++  /*! @brief: Convenience function to attempt to map the given beat to the time+   *  when transport is starting to play in context of the given quantum.+   *  This function evaluates to a no-op if abl_link_is_playing equals false.+   */+  void abl_link_request_beat_at_start_playing_time(+    abl_link_session_state session_state, double beat, double quantum);++  /*! @brief: Convenience function to start or stop transport at a given time and attempt+   *  to map the given beat to this time in context of the given quantum. */+  void abl_link_set_is_playing_and_request_beat_at_time(+    abl_link_session_state session_state,+    bool is_playing,+    uint64_t time,+    double beat,+    double quantum);++#ifdef __cplusplus+} // extern "C"+#endif // __cplusplus
+ link/extensions/abl_link/src/abl_link.cpp view
@@ -0,0 +1,214 @@+/* Copyright 2021, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#include <abl_link.h>+#include <ableton/Link.hpp>++extern "C"+{+  abl_link abl_link_create(double bpm)+  {+    return abl_link{reinterpret_cast<void *>(new ableton::Link(bpm))};+  }++  void abl_link_destroy(abl_link link)+  {+    delete reinterpret_cast<ableton::Link *>(link.impl);+  }++  bool abl_link_is_enabled(abl_link link)+  {+    return reinterpret_cast<ableton::Link *>(link.impl)->isEnabled();+  }++  void abl_link_enable(abl_link link, bool enabled)+  {+    reinterpret_cast<ableton::Link *>(link.impl)->enable(enabled);+  }++  bool abl_link_is_start_stop_sync_enabled(abl_link link)+  {+    return reinterpret_cast<ableton::Link *>(link.impl)->isStartStopSyncEnabled();+  }++  void abl_link_enable_start_stop_sync(abl_link link, bool enabled)+  {+    reinterpret_cast<ableton::Link *>(link.impl)->enableStartStopSync(enabled);+  }++  uint64_t abl_link_num_peers(abl_link link)+  {+    return reinterpret_cast<ableton::Link *>(link.impl)->numPeers();+  }++  void abl_link_set_num_peers_callback(+    abl_link link, abl_link_num_peers_callback callback, void *context)+  {+    reinterpret_cast<ableton::Link *>(link.impl)->setNumPeersCallback(+      [callback, context](+        std::size_t numPeers) { (*callback)(static_cast<uint64_t>(numPeers), context); });+  }++  void abl_link_set_tempo_callback(+    abl_link link, abl_link_tempo_callback callback, void *context)+  {+    reinterpret_cast<ableton::Link *>(link.impl)->setTempoCallback(+      [callback, context](double tempo) { (*callback)(tempo, context); });+  }++  void abl_link_set_start_stop_callback(+    abl_link link, abl_link_start_stop_callback callback, void *context)+  {+    reinterpret_cast<ableton::Link *>(link.impl)->setStartStopCallback(+      [callback, context](bool isPlaying) { (*callback)(isPlaying, context); });+  }++  int64_t abl_link_clock_micros(abl_link link)+  {+    return reinterpret_cast<ableton::Link *>(link.impl)->clock().micros().count();+  }++  abl_link_session_state abl_link_create_session_state(void)+  {+    return abl_link_session_state{reinterpret_cast<void *>(+      new ableton::Link::SessionState{ableton::link::ApiState{}, {}})};+  }++  void abl_link_destroy_session_state(abl_link_session_state session_state)+  {+    delete reinterpret_cast<ableton::Link::SessionState *>(session_state.impl);+  }++  void abl_link_capture_app_session_state(+    abl_link link, abl_link_session_state session_state)+  {+    *reinterpret_cast<ableton::Link::SessionState *>(session_state.impl) =+      reinterpret_cast<ableton::Link *>(link.impl)->captureAppSessionState();+  }++  void abl_link_commit_app_session_state(+    abl_link link, abl_link_session_state session_state)+  {+    reinterpret_cast<ableton::Link *>(link.impl)->commitAppSessionState(+      *reinterpret_cast<ableton::Link::SessionState *>(session_state.impl));+  }++  void abl_link_capture_audio_session_state(+    abl_link link, abl_link_session_state session_state)+  {+    *reinterpret_cast<ableton::Link::SessionState *>(session_state.impl) =+      reinterpret_cast<ableton::Link *>(link.impl)->captureAudioSessionState();+  }++  void abl_link_commit_audio_session_state(+    abl_link link, abl_link_session_state session_state)+  {+    reinterpret_cast<ableton::Link *>(link.impl)->commitAudioSessionState(+      *reinterpret_cast<ableton::Link::SessionState *>(session_state.impl));+  }++  double abl_link_tempo(abl_link_session_state session_state)+  {+    return reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)->tempo();+  }++  void abl_link_set_tempo(+    abl_link_session_state session_state, double bpm, int64_t at_time)+  {+    reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->setTempo(bpm, std::chrono::microseconds{at_time});+  }++  double abl_link_beat_at_time(+    abl_link_session_state session_state, int64_t time, double quantum)+  {+    auto micros = std::chrono::microseconds{time};+    return reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->beatAtTime(micros, quantum);+  }++  double abl_link_phase_at_time(+    abl_link_session_state session_state, int64_t time, double quantum)+  {+    return reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->phaseAtTime(std::chrono::microseconds{time}, quantum);+  }++  int64_t abl_link_time_at_beat(+    abl_link_session_state session_state, double beat, double quantum)+  {+    return reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->timeAtBeat(beat, quantum)+      .count();+  }++  void abl_link_request_beat_at_time(+    abl_link_session_state session_state, double beat, int64_t time, double quantum)+  {+    reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->requestBeatAtTime(beat, std::chrono::microseconds{time}, quantum);+  }++  void abl_link_force_beat_at_time(+    abl_link_session_state session_state, double beat, uint64_t time, double quantum)+  {+    reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->forceBeatAtTime(beat, std::chrono::microseconds{time}, quantum);+  }++  void abl_link_set_is_playing(+    abl_link_session_state session_state, bool is_playing, uint64_t time)+  {+    reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->setIsPlaying(is_playing, std::chrono::microseconds(time));+  }++  bool abl_link_is_playing(abl_link_session_state session_state)+  {+    return reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->isPlaying();+  }++  uint64_t abl_link_time_for_is_playing(abl_link_session_state session_state)+  {+    return static_cast<uint64_t>(+      reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+        ->timeForIsPlaying()+        .count());+  }++  void abl_link_request_beat_at_start_playing_time(+    abl_link_session_state session_state, double beat, double quantum)+  {+    reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->requestBeatAtStartPlayingTime(beat, quantum);+  }++  void abl_link_set_is_playing_and_request_beat_at_time(+    abl_link_session_state session_state,+    bool is_playing,+    uint64_t time,+    double beat,+    double quantum)+  {+    reinterpret_cast<ableton::Link::SessionState *>(session_state.impl)+      ->setIsPlayingAndRequestBeatAtTime(+        is_playing, std::chrono::microseconds{time}, beat, quantum);+  }+}
+ link/include/ableton/Link.hpp view
@@ -0,0 +1,403 @@+/*! @file Link.hpp+ *  @copyright 2016, Ableton AG, Berlin. All rights reserved.+ *  @brief Library for cross-device shared tempo and quantized beat grid+ *+ *  @license:+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/Config.hpp>+#include <chrono>+#include <mutex>++namespace ableton+{++/*! @class Link and BasicLink+ *  @brief Classes representing a participant in a Link session.+ *  The BasicLink type allows to customize the clock. The Link type+ *  uses the recommended platform-dependent representation of the+ *  system clock as defined in platforms/Config.hpp.+ *  It's preferred to use Link instead of BasicLink.+ *+ *  @discussion Each Link instance has its own session state which+ *  represents a beat timeline and a transport start/stop state. The+ *  timeline starts running from beat 0 at the initial tempo when+ *  constructed. The timeline always advances at a speed defined by+ *  its current tempo, even if transport is stopped. Synchronizing to the+ *  transport start/stop state of Link is optional for every peer.+ *  The transport start/stop state is only shared with other peers when+ *  start/stop synchronization is enabled.+ *+ *  A Link instance is initially disabled after construction, which+ *  means that it will not communicate on the network. Once enabled,+ *  a Link instance initiates network communication in an effort to+ *  discover other peers. When peers are discovered, they immediately+ *  become part of a shared Link session.+ *+ *  Each method of the Link type documents its thread-safety and+ *  realtime-safety properties. When a method is marked thread-safe,+ *  it means it is safe to call from multiple threads+ *  concurrently. When a method is marked realtime-safe, it means that+ *  it does not block and is appropriate for use in the thread that+ *  performs audio IO.+ *+ *  Link provides one session state capture/commit method pair for use+ *  in the audio thread and one for all other application contexts. In+ *  general, modifying the session state should be done in the audio+ *  thread for the most accurate timing results. The ability to modify+ *  the session state from application threads should only be used in+ *  cases where an application's audio thread is not actively running+ *  or if it doesn't generate audio at all. Modifying the Link session+ *  state from both the audio thread and an application thread+ *  concurrently is not advised and will potentially lead to unexpected+ *  behavior.+ *+ *  Only use the BasicLink class if the default platform clock does not+ *  fulfill other requirements of the client application. Please note this+ *  will require providing a custom Clock implementation. See the clock()+ *  documentation for details.+ */+template <typename Clock>+class BasicLink+{+public:+  class SessionState;++  /*! @brief Construct with an initial tempo. */+  BasicLink(double bpm);++  /*! @brief Link instances cannot be copied or moved */+  BasicLink(const BasicLink<Clock>&) = delete;+  BasicLink& operator=(const BasicLink<Clock>&) = delete;+  BasicLink(BasicLink<Clock>&&) = delete;+  BasicLink& operator=(BasicLink<Clock>&&) = delete;++  /*! @brief Is Link currently enabled?+   *  Thread-safe: yes+   *  Realtime-safe: yes+   */+  bool isEnabled() const;++  /*! @brief Enable/disable Link.+   *  Thread-safe: yes+   *  Realtime-safe: no+   */+  void enable(bool bEnable);++  /*! @brief: Is start/stop synchronization enabled?+   *  Thread-safe: yes+   *  Realtime-safe: no+   */+  bool isStartStopSyncEnabled() const;++  /*! @brief: Enable start/stop synchronization.+   *  Thread-safe: yes+   *  Realtime-safe: no+   */+  void enableStartStopSync(bool bEnable);++  /*! @brief How many peers are currently connected in a Link session?+   *  Thread-safe: yes+   *  Realtime-safe: yes+   */+  std::size_t numPeers() const;++  /*! @brief Register a callback to be notified when the number of+   *  peers in the Link session changes.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion The callback is invoked on a Link-managed thread.+   *+   *  @param callback The callback signature is:+   *  void (std::size_t numPeers)+   */+  template <typename Callback>+  void setNumPeersCallback(Callback callback);++  /*! @brief Register a callback to be notified when the session+   *  tempo changes.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion The callback is invoked on a Link-managed thread.+   *+   *  @param callback The callback signature is: void (double bpm)+   */+  template <typename Callback>+  void setTempoCallback(Callback callback);++  /*! brief: Register a callback to be notified when the state of+   *  start/stop isPlaying changes.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion The callback is invoked on a Link-managed thread.+   *+   *  @param callback The callback signature is:+   *  void (bool isPlaying)+   */+  template <typename Callback>+  void setStartStopCallback(Callback callback);++  /*! @brief The clock used by Link.+   *  Thread-safe: yes+   *  Realtime-safe: yes+   *+   *  @discussion The Clock type is a platform-dependent representation+   *  of the system clock. It exposes a micros() method, which is a+   *  normalized representation of the current system time in+   *  std::chrono::microseconds.+   */+  Clock clock() const;++  /*! @brief Capture the current Link Session State from the audio thread.+   *  Thread-safe: no+   *  Realtime-safe: yes+   *+   *  @discussion This method should ONLY be called in the audio thread+   *  and must not be accessed from any other threads. The returned+   *  object stores a snapshot of the current Link Session State, so it+   *  should be captured and used in a local scope. Storing the+   *  Session State for later use in a different context is not advised+   *  because it will provide an outdated view.+   */+  SessionState captureAudioSessionState() const;++  /*! @brief Commit the given Session State to the Link session from the+   *  audio thread.+   *  Thread-safe: no+   *  Realtime-safe: yes+   *+   *  @discussion This method should ONLY be called in the audio+   *  thread. The given Session State will replace the current Link+   *  state. Modifications will be communicated to other peers in the+   *  session.+   */+  void commitAudioSessionState(SessionState state);++  /*! @brief Capture the current Link Session State from an application+   *  thread.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion Provides a mechanism for capturing the Link Session+   *  State from an application thread (other than the audio thread).+   *  The returned Session State stores a snapshot of the current Link+   *  state, so it should be captured and used in a local scope.+   *  Storing the it for later use in a different context is not+   *  advised because it will provide an outdated view.+   */+  SessionState captureAppSessionState() const;++  /*! @brief Commit the given Session State to the Link session from an+   *  application thread.+   *  Thread-safe: yes+   *  Realtime-safe: no+   *+   *  @discussion The given Session State will replace the current Link+   *  Session State. Modifications of the Session State will be+   *  communicated to other peers in the session.+   */+  void commitAppSessionState(SessionState state);++  /*! @class SessionState+   *  @brief Representation of a timeline and the start/stop state+   *+   *  @discussion A SessionState object is intended for use in a local scope within+   *  a single thread - none of its methods are thread-safe. All of its methods are+   *  non-blocking, so it is safe to use from a realtime thread.+   *  It provides functions to observe and manipulate the timeline and start/stop+   *  state.+   *+   *  The timeline is a representation of a mapping between time and beats for varying+   *  quanta.+   *  The start/stop state represents the user intention to start or stop transport at+   *  a specific time. Start stop synchronization is an optional feature that allows to+   *  share the user request to start or stop transport between a subgroup of peers in+   *  a Link session. When observing a change of start/stop state, audio playback of a+   *  peer should be started or stopped the same way it would have happened if the user+   *  had requested that change at the according time locally. The start/stop state can+   *  only be changed by the user. This means that the current local start/stop state+   *  persists when joining or leaving a Link session. After joining a Link session+   *  start/stop change requests will be communicated to all connected peers.+   */+  class SessionState+  {+  public:+    SessionState(const link::ApiState state, const bool bRespectQuantum);++    /*! @brief: The tempo of the timeline, in Beats Per Minute.+     *+     *  @discussion This is a stable value that is appropriate for display+     *  to the user. Beat time progress will not necessarily match this tempo+     *  exactly because of clock drift compensation.+     */+    double tempo() const;++    /*! @brief: Set the timeline tempo to the given bpm value, taking+     *  effect at the given time.+     */+    void setTempo(double bpm, std::chrono::microseconds atTime);++    /*! @brief: Get the beat value corresponding to the given time+     *  for the given quantum.+     *+     *  @discussion: The magnitude of the resulting beat value is+     *  unique to this Link instance, but its phase with respect to+     *  the provided quantum is shared among all session+     *  peers. For non-negative beat values, the following+     *  property holds: fmod(beatAtTime(t, q), q) == phaseAtTime(t, q)+     */+    double beatAtTime(std::chrono::microseconds time, double quantum) const;++    /*! @brief: Get the session phase at the given time for the given+     *  quantum.+     *+     *  @discussion: The result is in the interval [0, quantum). The+     *  result is equivalent to fmod(beatAtTime(t, q), q) for+     *  non-negative beat values. This method is convenient if the+     *  client is only interested in the phase and not the beat+     *  magnitude. Also, unlike fmod, it handles negative beat values+     *  correctly.+     */+    double phaseAtTime(std::chrono::microseconds time, double quantum) const;++    /*! @brief: Get the time at which the given beat occurs for the+     *  given quantum.+     *+     *  @discussion: The inverse of beatAtTime, assuming a constant+     *  tempo. beatAtTime(timeAtBeat(b, q), q) === b.+     */+    std::chrono::microseconds timeAtBeat(double beat, double quantum) const;++    /*! @brief: Attempt to map the given beat to the given time in the+     *  context of the given quantum.+     *+     *  @discussion: This method behaves differently depending on the+     *  state of the session. If no other peers are connected,+     *  then this instance is in a session by itself and is free to+     *  re-map the beat/time relationship whenever it pleases. In this+     *  case, beatAtTime(time, quantum) == beat after this method has+     *  been called.+     *+     *  If there are other peers in the session, this instance+     *  should not abruptly re-map the beat/time relationship in the+     *  session because that would lead to beat discontinuities among+     *  the other peers. In this case, the given beat will be mapped+     *  to the next time value greater than the given time with the+     *  same phase as the given beat.+     *+     *  This method is specifically designed to enable the concept of+     *  "quantized launch" in client applications. If there are no other+     *  peers in the session, then an event (such as starting+     *  transport) happens immediately when it is requested. If there+     *  are other peers, however, we wait until the next time at which+     *  the session phase matches the phase of the event, thereby+     *  executing the event in-phase with the other peers in the+     *  session. The client only needs to invoke this method to+     *  achieve this behavior and should not need to explicitly check+     *  the number of peers.+     */+    void requestBeatAtTime(double beat, std::chrono::microseconds time, double quantum);++    /*! @brief: Rudely re-map the beat/time relationship for all peers+     *  in a session.+     *+     *  @discussion: DANGER: This method should only be needed in+     *  certain special circumstances. Most applications should not+     *  use it. It is very similar to requestBeatAtTime except that it+     *  does not fall back to the quantizing behavior when it is in a+     *  session with other peers. Calling this method will+     *  unconditionally map the given beat to the given time and+     *  broadcast the result to the session. This is very anti-social+     *  behavior and should be avoided.+     *+     *  One of the few legitimate uses of this method is to+     *  synchronize a Link session with an external clock source. By+     *  periodically forcing the beat/time mapping according to an+     *  external clock source, a peer can effectively bridge that+     *  clock into a Link session. Much care must be taken at the+     *  application layer when implementing such a feature so that+     *  users do not accidentally disrupt Link sessions that they may+     *  join.+     */+    void forceBeatAtTime(double beat, std::chrono::microseconds time, double quantum);++    /*! @brief: Set if transport should be playing or stopped, taking effect+     *  at the given time.+     */+    void setIsPlaying(bool isPlaying, std::chrono::microseconds time);++    /*! @brief: Is transport playing? */+    bool isPlaying() const;++    /*! @brief: Get the time at which a transport start/stop occurs */+    std::chrono::microseconds timeForIsPlaying() const;++    /*! @brief: Convenience function to attempt to map the given beat to the time+     *  when transport is starting to play in context of the given quantum.+     *  This function evaluates to a no-op if isPlaying() equals false.+     */+    void requestBeatAtStartPlayingTime(double beat, double quantum);++    /*! @brief: Convenience function to start or stop transport at a given time and+     *  attempt to map the given beat to this time in context of the given quantum.+     */+    void setIsPlayingAndRequestBeatAtTime(+      bool isPlaying, std::chrono::microseconds time, double beat, double quantum);++  private:+    friend BasicLink<Clock>;+    link::ApiState mOriginalState;+    link::ApiState mState;+    bool mbRespectQuantum;+  };++private:+  using Controller = ableton::link::Controller<link::PeerCountCallback,+    link::TempoCallback,+    link::StartStopStateCallback,+    Clock,+    link::platform::Random,+    link::platform::IoContext>;++  std::mutex mCallbackMutex;+  link::PeerCountCallback mPeerCountCallback = [](std::size_t) {};+  link::TempoCallback mTempoCallback = [](link::Tempo) {};+  link::StartStopStateCallback mStartStopCallback = [](bool) {};+  Clock mClock;+  Controller mController;+};++class Link : public BasicLink<link::platform::Clock>+{+public:+  using Clock = link::platform::Clock;++  Link(double bpm)+    : BasicLink(bpm)+  {+  }+};++} // namespace ableton++#include <ableton/Link.ipp>
+ link/include/ableton/Link.ipp view
@@ -0,0 +1,280 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/Phase.hpp>++namespace ableton+{+namespace detail+{++template <typename Clock>+inline typename BasicLink<Clock>::SessionState toSessionState(+  const link::ClientState& state, const bool isConnected)+{+  return {{state.timeline, {state.startStopState.isPlaying, state.startStopState.time}},+    isConnected};+}++inline link::IncomingClientState toIncomingClientState(const link::ApiState& state,+  const link::ApiState& originalState,+  const std::chrono::microseconds timestamp)+{+  const auto timeline = originalState.timeline != state.timeline+                          ? link::OptionalTimeline{state.timeline}+                          : link::OptionalTimeline{};+  const auto startStopState =+    originalState.startStopState != state.startStopState+      ? link::OptionalClientStartStopState{{state.startStopState.isPlaying,+          state.startStopState.time, timestamp}}+      : link::OptionalClientStartStopState{};+  return {timeline, startStopState, timestamp};+}++} // namespace detail++template <typename Clock>+inline BasicLink<Clock>::BasicLink(const double bpm)+  : mController(link::Tempo(bpm),+      [this](const std::size_t peers) {+        std::lock_guard<std::mutex> lock(mCallbackMutex);+        mPeerCountCallback(peers);+      },+      [this](const link::Tempo tempo) {+        std::lock_guard<std::mutex> lock(mCallbackMutex);+        mTempoCallback(tempo);+      },+      [this](const bool isPlaying) {+        std::lock_guard<std::mutex> lock(mCallbackMutex);+        mStartStopCallback(isPlaying);+      },+      mClock)+{+}++template <typename Clock>+inline bool BasicLink<Clock>::isEnabled() const+{+  return mController.isEnabled();+}++template <typename Clock>+inline void BasicLink<Clock>::enable(const bool bEnable)+{+  mController.enable(bEnable);+}++template <typename Clock>+inline bool BasicLink<Clock>::isStartStopSyncEnabled() const+{+  return mController.isStartStopSyncEnabled();+}++template <typename Clock>+inline void BasicLink<Clock>::enableStartStopSync(bool bEnable)+{+  mController.enableStartStopSync(bEnable);+}++template <typename Clock>+inline std::size_t BasicLink<Clock>::numPeers() const+{+  return mController.numPeers();+}++template <typename Clock>+template <typename Callback>+void BasicLink<Clock>::setNumPeersCallback(Callback callback)+{+  std::lock_guard<std::mutex> lock(mCallbackMutex);+  mPeerCountCallback = [callback](const std::size_t numPeers) { callback(numPeers); };+}++template <typename Clock>+template <typename Callback>+void BasicLink<Clock>::setTempoCallback(Callback callback)+{+  std::lock_guard<std::mutex> lock(mCallbackMutex);+  mTempoCallback = [callback](const link::Tempo tempo) { callback(tempo.bpm()); };+}++template <typename Clock>+template <typename Callback>+void BasicLink<Clock>::setStartStopCallback(Callback callback)+{+  std::lock_guard<std::mutex> lock(mCallbackMutex);+  mStartStopCallback = callback;+}++template <typename Clock>+inline Clock BasicLink<Clock>::clock() const+{+  return mClock;+}++template <typename Clock>+inline typename BasicLink<Clock>::SessionState BasicLink<+  Clock>::captureAudioSessionState() const+{+  return detail::toSessionState<Clock>(mController.clientStateRtSafe(), numPeers() > 0);+}++template <typename Clock>+inline void BasicLink<Clock>::commitAudioSessionState(+  const typename BasicLink<Clock>::SessionState state)+{+  mController.setClientStateRtSafe(+    detail::toIncomingClientState(state.mState, state.mOriginalState, mClock.micros()));+}++template <typename Clock>+inline typename BasicLink<Clock>::SessionState BasicLink<Clock>::captureAppSessionState()+  const+{+  return detail::toSessionState<Clock>(mController.clientState(), numPeers() > 0);+}++template <typename Clock>+inline void BasicLink<Clock>::commitAppSessionState(+  const typename BasicLink<Clock>::SessionState state)+{+  mController.setClientState(+    detail::toIncomingClientState(state.mState, state.mOriginalState, mClock.micros()));+}++// Link::SessionState++template <typename Clock>+inline BasicLink<Clock>::SessionState::SessionState(+  const link::ApiState state, const bool bRespectQuantum)+  : mOriginalState(state)+  , mState(state)+  , mbRespectQuantum(bRespectQuantum)+{+}++template <typename Clock>+inline double BasicLink<Clock>::SessionState::tempo() const+{+  return mState.timeline.tempo.bpm();+}++template <typename Clock>+inline void BasicLink<Clock>::SessionState::setTempo(+  const double bpm, const std::chrono::microseconds atTime)+{+  const auto desiredTl = link::clampTempo(+    link::Timeline{link::Tempo(bpm), mState.timeline.toBeats(atTime), atTime});+  mState.timeline.tempo = desiredTl.tempo;+  mState.timeline.timeOrigin = desiredTl.fromBeats(mState.timeline.beatOrigin);+}++template <typename Clock>+inline double BasicLink<Clock>::SessionState::beatAtTime(+  const std::chrono::microseconds time, const double quantum) const+{+  return link::toPhaseEncodedBeats(mState.timeline, time, link::Beats{quantum})+    .floating();+}++template <typename Clock>+inline double BasicLink<Clock>::SessionState::phaseAtTime(+  const std::chrono::microseconds time, const double quantum) const+{+  return link::phase(link::Beats{beatAtTime(time, quantum)}, link::Beats{quantum})+    .floating();+}++template <typename Clock>+inline std::chrono::microseconds BasicLink<Clock>::SessionState::timeAtBeat(+  const double beat, const double quantum) const+{+  return link::fromPhaseEncodedBeats(+    mState.timeline, link::Beats{beat}, link::Beats{quantum});+}++template <typename Clock>+inline void BasicLink<Clock>::SessionState::requestBeatAtTime(+  const double beat, std::chrono::microseconds time, const double quantum)+{+  if (mbRespectQuantum)+  {+    time = timeAtBeat(link::nextPhaseMatch(link::Beats{beatAtTime(time, quantum)},+                        link::Beats{beat}, link::Beats{quantum})+                        .floating(),+      quantum);+  }+  forceBeatAtTime(beat, time, quantum);+}++template <typename Clock>+inline void BasicLink<Clock>::SessionState::forceBeatAtTime(+  const double beat, const std::chrono::microseconds time, const double quantum)+{+  // There are two components to the beat adjustment: a phase shift+  // and a beat magnitude adjustment.+  const auto curBeatAtTime = link::Beats{beatAtTime(time, quantum)};+  const auto closestInPhase =+    link::closestPhaseMatch(curBeatAtTime, link::Beats{beat}, link::Beats{quantum});+  mState.timeline = shiftClientTimeline(mState.timeline, closestInPhase - curBeatAtTime);+  // Now adjust the magnitude+  mState.timeline.beatOrigin =+    mState.timeline.beatOrigin + (link::Beats{beat} - closestInPhase);+}++template <typename Clock>+inline void BasicLink<Clock>::SessionState::setIsPlaying(+  const bool isPlaying, const std::chrono::microseconds time)+{+  mState.startStopState = {isPlaying, time};+}++template <typename Clock>+inline bool BasicLink<Clock>::SessionState::isPlaying() const+{+  return mState.startStopState.isPlaying;+}++template <typename Clock>+inline std::chrono::microseconds BasicLink<Clock>::SessionState::timeForIsPlaying() const+{+  return mState.startStopState.time;+}++template <typename Clock>+inline void BasicLink<Clock>::SessionState::requestBeatAtStartPlayingTime(+  const double beat, const double quantum)+{+  if (isPlaying())+  {+    requestBeatAtTime(beat, mState.startStopState.time, quantum);+  }+}++template <typename Clock>+inline void BasicLink<Clock>::SessionState::setIsPlayingAndRequestBeatAtTime(+  bool isPlaying, std::chrono::microseconds time, double beat, double quantum)+{+  mState.startStopState = {isPlaying, time};+  requestBeatAtStartPlayingTime(beat, quantum);+}++} // namespace ableton
+ link/include/ableton/discovery/InterfaceScanner.hpp view
@@ -0,0 +1,102 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/util/Injected.hpp>+#include <chrono>+#include <vector>++namespace ableton+{+namespace discovery+{++// Callback takes a range of asio::ip:address which is+// guaranteed to be sorted and unique+template <typename Callback, typename IoContext>+class InterfaceScanner+{+public:+  using Timer = typename util::Injected<IoContext>::type::Timer;++  InterfaceScanner(const std::chrono::seconds period,+    util::Injected<Callback> callback,+    util::Injected<IoContext> io)+    : mPeriod(period)+    , mCallback(std::move(callback))+    , mIo(std::move(io))+    , mTimer(mIo->makeTimer())+  {+  }++  void enable(const bool bEnable)+  {+    if (bEnable)+    {+      scan();+    }+    else+    {+      mTimer.cancel();+    }+  }++  void scan()+  {+    using namespace std;+    debug(mIo->log()) << "Scanning network interfaces";+    // Rescan the hardware for available network interface addresses+    vector<asio::ip::address> addrs = mIo->scanNetworkInterfaces();+    // Sort and unique them to guarantee consistent comparison+    sort(begin(addrs), end(addrs));+    addrs.erase(unique(begin(addrs), end(addrs)), end(addrs));+    // Pass them to the callback+    (*mCallback)(std::move(addrs));+    // setup the next scanning+    mTimer.expires_from_now(mPeriod);+    using ErrorCode = typename Timer::ErrorCode;+    mTimer.async_wait([this](const ErrorCode e) {+      if (!e)+      {+        scan();+      }+    });+  }++private:+  const std::chrono::seconds mPeriod;+  util::Injected<Callback> mCallback;+  util::Injected<IoContext> mIo;+  Timer mTimer;+};++// Factory function+template <typename Callback, typename IoContext>+InterfaceScanner<Callback, IoContext> makeInterfaceScanner(+  const std::chrono::seconds period,+  util::Injected<Callback> callback,+  util::Injected<IoContext> io)+{+  return {period, std::move(callback), std::move(io)};+}++} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/IpV4Interface.hpp view
@@ -0,0 +1,123 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/util/Injected.hpp>++namespace ableton+{+namespace discovery+{++inline asio::ip::udp::endpoint multicastEndpoint()+{+  return {asio::ip::address_v4::from_string("224.76.78.75"), 20808};+}++// Type tags for dispatching between unicast and multicast packets+struct MulticastTag+{+};+struct UnicastTag+{+};++template <typename IoContext, std::size_t MaxPacketSize>+class IpV4Interface+{+public:+  using Socket = typename util::Injected<IoContext>::type::template Socket<MaxPacketSize>;++  IpV4Interface(util::Injected<IoContext> io, const asio::ip::address_v4& addr)+    : mIo(std::move(io))+    , mMulticastReceiveSocket(mIo->template openMulticastSocket<MaxPacketSize>(addr))+    , mSendSocket(mIo->template openUnicastSocket<MaxPacketSize>(addr))+  {+  }++  IpV4Interface(const IpV4Interface&) = delete;+  IpV4Interface& operator=(const IpV4Interface&) = delete;++  IpV4Interface(IpV4Interface&& rhs)+    : mIo(std::move(rhs.mIo))+    , mMulticastReceiveSocket(std::move(rhs.mMulticastReceiveSocket))+    , mSendSocket(std::move(rhs.mSendSocket))+  {+  }+++  std::size_t send(+    const uint8_t* const pData, const size_t numBytes, const asio::ip::udp::endpoint& to)+  {+    return mSendSocket.send(pData, numBytes, to);+  }++  template <typename Handler>+  void receive(Handler handler, UnicastTag)+  {+    mSendSocket.receive(SocketReceiver<UnicastTag, Handler>{std::move(handler)});+  }++  template <typename Handler>+  void receive(Handler handler, MulticastTag)+  {+    mMulticastReceiveSocket.receive(+      SocketReceiver<MulticastTag, Handler>(std::move(handler)));+  }++  asio::ip::udp::endpoint endpoint() const+  {+    return mSendSocket.endpoint();+  }++private:+  template <typename Tag, typename Handler>+  struct SocketReceiver+  {+    SocketReceiver(Handler handler)+      : mHandler(std::move(handler))+    {+    }++    template <typename It>+    void operator()(+      const asio::ip::udp::endpoint& from, const It messageBegin, const It messageEnd)+    {+      mHandler(Tag{}, from, messageBegin, messageEnd);+    }++    Handler mHandler;+  };++  util::Injected<IoContext> mIo;+  Socket mMulticastReceiveSocket;+  Socket mSendSocket;+};++template <std::size_t MaxPacketSize, typename IoContext>+IpV4Interface<IoContext, MaxPacketSize> makeIpV4Interface(+  util::Injected<IoContext> io, const asio::ip::address_v4& addr)+{+  return {std::move(io), addr};+}++} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/MessageTypes.hpp view
@@ -0,0 +1,50 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++namespace ableton+{+namespace discovery+{++// Message types used in the Ableton service discovery protocol. There+// are two logical messages: a state dump and a bye bye.+//+// A state dump provides all relevant information about the peer's+// current state as well as a Time To Live (TTL) value that indicates+// how many seconds this state should be considered valid.+//+// The bye bye indicates that the sender is leaving the session.++template <typename NodeState>+struct PeerState+{+  NodeState peerState;+  int ttl;+};++template <typename NodeId>+struct ByeBye+{+  NodeId peerId;+};++} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/NetworkByteStreamSerializable.hpp view
@@ -0,0 +1,462 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#if defined(LINK_PLATFORM_MACOSX)+#include <ableton/platforms/darwin/Darwin.hpp>+#elif defined(LINK_PLATFORM_LINUX)+#include <ableton/platforms/linux/Linux.hpp>+#elif defined(LINK_PLATFORM_WINDOWS)+#include <ableton/platforms/windows/Windows.hpp>+#elif defined(ESP_PLATFORM)+#include <ableton/platforms/esp32/Esp32.hpp>+#endif++#include <chrono>+#include <cstdint>+#include <type_traits>+#include <utility>+#include <vector>++#if defined(LINK_PLATFORM_WINDOWS)+#include <WS2tcpip.h>+#include <WinSock2.h>+#include <Windows.h>+#endif++namespace ableton+{+namespace discovery+{++// Concept: NetworkByteStreamSerializable+//+// A type that can be encoded to a stream of bytes and decoded from a+// stream of bytes in network byte order. The following type is for+// documentation purposes only.++struct NetworkByteStreamSerializable+{+  friend std::uint32_t sizeInByteStream(const NetworkByteStreamSerializable&);++  // The byte stream pointed to by 'out' must have sufficient space to+  // hold this object, as defined by sizeInByteStream.+  template <typename It>+  friend It toNetworkByteStream(const NetworkByteStreamSerializable&, It out);+};++// Deserialization aspect of the concept. Outside of the demonstration+// type above because clients must specify the type+// explicitly. Default implementation just defers to a class static+// method on T. For types that can't provide such a method, specialize+// this template.+template <typename T>+struct Deserialize+{+  // Throws std::runtime_exception if parsing the type from the given+  // byte range fails. Returns a pair of the correctly parsed value+  // and an iterator to the next byte to parse.+  template <typename It>+  static std::pair<T, It> fromNetworkByteStream(It begin, It end)+  {+    return T::fromNetworkByteStream(std::move(begin), std::move(end));+  }+};+++// Default size implementation. Works for primitive types.++template <typename T,+  typename std::enable_if<std::is_fundamental<T>::value>::type* = nullptr>+std::uint32_t sizeInByteStream(T)+{+  return sizeof(T);+}++namespace detail+{++// utilities for implementing concept for primitive types++template <typename T, typename It>+It copyToByteStream(T t, It out)+{+  using namespace std;+  return copy_n(+    reinterpret_cast<typename iterator_traits<It>::pointer>(&t), sizeof(t), out);+}++template <typename T, typename It>+std::pair<T, It> copyFromByteStream(It begin, const It end)+{+  using namespace std;+  using ItDiff = typename iterator_traits<It>::difference_type;++  if (distance(begin, end) < static_cast<ItDiff>(sizeof(T)))+  {+    throw range_error("Parsing type from byte stream failed");+  }+  else+  {+    T t;+    const auto n = sizeof(t);+    copy_n(begin, n, reinterpret_cast<uint8_t*>(&t));+    return make_pair(t, begin + n);+  }+}++} // namespace detail+++// Model the concept for unsigned integral types++// uint8_t+template <typename It>+It toNetworkByteStream(const uint8_t byte, It out)+{+  return detail::copyToByteStream(byte, std::move(out));+}++template <>+struct Deserialize<uint8_t>+{+  template <typename It>+  static std::pair<uint8_t, It> fromNetworkByteStream(It begin, It end)+  {+    return detail::copyFromByteStream<uint8_t>(std::move(begin), std::move(end));+  }+};++// uint16_t+template <typename It>+It toNetworkByteStream(uint16_t s, It out)+{+  return detail::copyToByteStream(htons(s), std::move(out));+}++template <>+struct Deserialize<uint16_t>+{+  template <typename It>+  static std::pair<uint16_t, It> fromNetworkByteStream(It begin, It end)+  {+    auto result = detail::copyFromByteStream<uint16_t>(std::move(begin), std::move(end));+    result.first = ntohs(result.first);+    return result;+  }+};++// uint32_t+template <typename It>+It toNetworkByteStream(uint32_t l, It out)+{+  return detail::copyToByteStream(htonl(l), std::move(out));+}++template <>+struct Deserialize<uint32_t>+{+  template <typename It>+  static std::pair<uint32_t, It> fromNetworkByteStream(It begin, It end)+  {+    auto result = detail::copyFromByteStream<uint32_t>(std::move(begin), std::move(end));+    result.first = ntohl(result.first);+    return result;+  }+};++// int32_t in terms of uint32_t+template <typename It>+It toNetworkByteStream(int32_t l, It out)+{+  return toNetworkByteStream(reinterpret_cast<const uint32_t&>(l), std::move(out));+}++template <>+struct Deserialize<int32_t>+{+  template <typename It>+  static std::pair<int32_t, It> fromNetworkByteStream(It begin, It end)+  {+    auto result =+      Deserialize<uint32_t>::fromNetworkByteStream(std::move(begin), std::move(end));+    return std::make_pair(reinterpret_cast<const int32_t&>(result.first), result.second);+  }+};++// uint64_t+template <typename It>+It toNetworkByteStream(uint64_t ll, It out)+{+  return detail::copyToByteStream(htonll(ll), std::move(out));+}++template <>+struct Deserialize<uint64_t>+{+  template <typename It>+  static std::pair<uint64_t, It> fromNetworkByteStream(It begin, It end)+  {+    auto result = detail::copyFromByteStream<uint64_t>(std::move(begin), std::move(end));+    result.first = ntohll(result.first);+    return result;+  }+};++// int64_t in terms of uint64_t+template <typename It>+It toNetworkByteStream(int64_t ll, It out)+{+  return toNetworkByteStream(reinterpret_cast<const uint64_t&>(ll), std::move(out));+}++template <>+struct Deserialize<int64_t>+{+  template <typename It>+  static std::pair<int64_t, It> fromNetworkByteStream(It begin, It end)+  {+    auto result =+      Deserialize<uint64_t>::fromNetworkByteStream(std::move(begin), std::move(end));+    return std::make_pair(reinterpret_cast<const int64_t&>(result.first), result.second);+  }+};++// bool+inline std::uint32_t sizeInByteStream(bool)+{+  return sizeof(uint8_t);+}++template <typename It>+It toNetworkByteStream(bool bl, It out)+{+  return toNetworkByteStream(static_cast<uint8_t>(bl), std::move(out));+}++template <>+struct Deserialize<bool>+{+  template <typename It>+  static std::pair<bool, It> fromNetworkByteStream(It begin, It end)+  {+    auto result =+      Deserialize<uint8_t>::fromNetworkByteStream(std::move(begin), std::move(end));+    return std::make_pair(result.first != 0, result.second);+  }+};++// std::chrono::microseconds+inline std::uint32_t sizeInByteStream(const std::chrono::microseconds micros)+{+  return sizeInByteStream(micros.count());+}++template <typename It>+It toNetworkByteStream(const std::chrono::microseconds micros, It out)+{+  static_assert(sizeof(int64_t) == sizeof(std::chrono::microseconds::rep),+    "The size of microseconds::rep must matche the size of int64_t.");+  return toNetworkByteStream(static_cast<int64_t>(micros.count()), std::move(out));+}++template <>+struct Deserialize<std::chrono::microseconds>+{+  template <typename It>+  static std::pair<std::chrono::microseconds, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto result =+      Deserialize<int64_t>::fromNetworkByteStream(std::move(begin), std::move(end));+    return make_pair(chrono::microseconds{result.first}, result.second);+  }+};++namespace detail+{++// Generic serialize/deserialize utilities for containers++template <typename Container>+std::uint32_t containerSizeInByteStream(const Container& container)+{+  std::uint32_t totalSize = 0;+  for (const auto& val : container)+  {+    totalSize += sizeInByteStream(val);+  }+  return totalSize;+}++template <typename Container, typename It>+It containerToNetworkByteStream(const Container& container, It out)+{+  for (const auto& val : container)+  {+    out = toNetworkByteStream(val, out);+  }+  return out;+}++template <typename T, typename BytesIt, typename InsertIt>+BytesIt deserializeContainer(BytesIt bytesBegin,+  const BytesIt bytesEnd,+  InsertIt contBegin,+  const std::uint32_t maxElements)+{+  using namespace std;+  std::uint32_t numElements = 0;+  while (bytesBegin < bytesEnd && numElements < maxElements)+  {+    T newVal;+    tie(newVal, bytesBegin) = Deserialize<T>::fromNetworkByteStream(bytesBegin, bytesEnd);+    *contBegin++ = newVal;+    ++numElements;+  }+  return bytesBegin;+}++} // namespace detail++// Need specific overloads for each container type, but use above+// utilities for common implementation++// array+template <typename T, std::size_t Size>+std::uint32_t sizeInByteStream(const std::array<T, Size>& arr)+{+  return detail::containerSizeInByteStream(arr);+}++template <typename T, std::size_t Size, typename It>+It toNetworkByteStream(const std::array<T, Size>& arr, It out)+{+  return detail::containerToNetworkByteStream(arr, std::move(out));+}++template <typename T, std::size_t Size>+struct Deserialize<std::array<T, Size>>+{+  template <typename It>+  static std::pair<std::array<T, Size>, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    array<T, Size> result{};+    auto resultIt = detail::deserializeContainer<T>(+      std::move(begin), std::move(end), std::move(result.begin()), Size);+    return make_pair(std::move(result), std::move(resultIt));+  }+};++// vector+template <typename T, typename Alloc>+std::uint32_t sizeInByteStream(const std::vector<T, Alloc>& vec)+{+  return sizeof(uint32_t) + detail::containerSizeInByteStream(vec);+}++template <typename T, typename Alloc, typename It>+It toNetworkByteStream(const std::vector<T, Alloc>& vec, It out)+{+  out = toNetworkByteStream(static_cast<uint32_t>(vec.size()), out);+  return detail::containerToNetworkByteStream(vec, std::move(out));+}++template <typename T, typename Alloc>+struct Deserialize<std::vector<T, Alloc>>+{+  template <typename It>+  static std::pair<std::vector<T, Alloc>, It> fromNetworkByteStream(+    It bytesBegin, It bytesEnd)+  {+    using namespace std;+    auto result_size =+      Deserialize<uint32_t>::fromNetworkByteStream(std::move(bytesBegin), bytesEnd);+    vector<T, Alloc> result;+    auto resultIt = detail::deserializeContainer<T>(std::move(result_size.second),+      std::move(bytesEnd), back_inserter(result), result_size.first);+    return make_pair(std::move(result), std::move(resultIt));+  }+};++// 2-tuple+template <typename X, typename Y>+std::uint32_t sizeInByteStream(const std::tuple<X, Y>& tup)+{+  return sizeInByteStream(std::get<0>(tup)) + sizeInByteStream(std::get<1>(tup));+}++template <typename X, typename Y, typename It>+It toNetworkByteStream(const std::tuple<X, Y>& tup, It out)+{+  return toNetworkByteStream(+    std::get<1>(tup), toNetworkByteStream(std::get<0>(tup), std::move(out)));+}++template <typename X, typename Y>+struct Deserialize<std::tuple<X, Y>>+{+  template <typename It>+  static std::pair<std::tuple<X, Y>, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto xres = Deserialize<X>::fromNetworkByteStream(begin, end);+    auto yres = Deserialize<Y>::fromNetworkByteStream(xres.second, end);+    return make_pair(+      make_tuple(std::move(xres.first), std::move(yres.first)), std::move(yres.second));+  }+};++// 3-tuple+template <typename X, typename Y, typename Z>+std::uint32_t sizeInByteStream(const std::tuple<X, Y, Z>& tup)+{+  return sizeInByteStream(std::get<0>(tup)) + sizeInByteStream(std::get<1>(tup))+         + sizeInByteStream(std::get<2>(tup));+}++template <typename X, typename Y, typename Z, typename It>+It toNetworkByteStream(const std::tuple<X, Y, Z>& tup, It out)+{+  return toNetworkByteStream(+    std::get<2>(tup), toNetworkByteStream(std::get<1>(tup),+                        toNetworkByteStream(std::get<0>(tup), std::move(out))));+}++template <typename X, typename Y, typename Z>+struct Deserialize<std::tuple<X, Y, Z>>+{+  template <typename It>+  static std::pair<std::tuple<X, Y, Z>, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto xres = Deserialize<X>::fromNetworkByteStream(begin, end);+    auto yres = Deserialize<Y>::fromNetworkByteStream(xres.second, end);+    auto zres = Deserialize<Z>::fromNetworkByteStream(yres.second, end);+    return make_pair(+      make_tuple(std::move(xres.first), std::move(yres.first), std::move(zres.first)),+      std::move(zres.second));+  }+};++} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/Payload.hpp view
@@ -0,0 +1,296 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/NetworkByteStreamSerializable.hpp>+#include <functional>+#include <sstream>+#include <unordered_map>++namespace ableton+{+namespace discovery+{++struct PayloadEntryHeader+{+  using Key = std::uint32_t;+  using Size = std::uint32_t;++  Key key;+  Size size;++  friend Size sizeInByteStream(const PayloadEntryHeader& header)+  {+    return sizeInByteStream(header.key) + sizeInByteStream(header.size);+  }++  template <typename It>+  friend It toNetworkByteStream(const PayloadEntryHeader& header, It out)+  {+    return toNetworkByteStream(+      header.size, toNetworkByteStream(header.key, std::move(out)));+  }++  template <typename It>+  static std::pair<PayloadEntryHeader, It> fromNetworkByteStream(It begin, const It end)+  {+    using namespace std;+    Key key;+    Size size;+    tie(key, begin) = Deserialize<Key>::fromNetworkByteStream(begin, end);+    tie(size, begin) = Deserialize<Size>::fromNetworkByteStream(begin, end);+    return make_pair(+      PayloadEntryHeader{std::move(key), std::move(size)}, std::move(begin));+  }+};++template <typename EntryType>+struct PayloadEntry+{+  PayloadEntry(EntryType entryVal)+    : value(std::move(entryVal))+  {+    header = {EntryType::key, sizeInByteStream(value)};+  }++  PayloadEntryHeader header;+  EntryType value;++  friend std::uint32_t sizeInByteStream(const PayloadEntry& entry)+  {+    return sizeInByteStream(entry.header) + sizeInByteStream(entry.value);+  }++  template <typename It>+  friend It toNetworkByteStream(const PayloadEntry& entry, It out)+  {+    return toNetworkByteStream(+      entry.value, toNetworkByteStream(entry.header, std::move(out)));+  }+};++namespace detail+{++template <typename It>+using HandlerMap =+  std::unordered_map<typename PayloadEntryHeader::Key, std::function<void(It, It)>>;++// Given an index of handlers and a byte range, parse the bytes as a+// sequence of payload entries and invoke the appropriate handler for+// each entry type. Entries that are encountered that do not have a+// corresponding handler in the map are ignored. Throws+// std::runtime_error if parsing fails for any entry. Note that if an+// exception is thrown, some of the handlers may have already been called.+template <typename It>+void parseByteStream(HandlerMap<It>& map, It bsBegin, const It bsEnd)+{+  using namespace std;++  while (bsBegin < bsEnd)+  {+    // Try to parse an entry header at this location in the byte stream+    PayloadEntryHeader header;+    It valueBegin;+    tie(header, valueBegin) =+      Deserialize<PayloadEntryHeader>::fromNetworkByteStream(bsBegin, bsEnd);++    // Ensure that the reported size of the entry does not exceed the+    // length of the byte stream+    It valueEnd = valueBegin + header.size;+    if (bsEnd < valueEnd)+    {+      throw range_error("Payload with incorrect size.");+    }++    // The next entry will start at the end of this one+    bsBegin = valueEnd;++    // Use the appropriate handler for this entry, if available+    auto handlerIt = map.find(header.key);+    if (handlerIt != end(map))+    {+      handlerIt->second(std::move(valueBegin), std::move(valueEnd));+    }+  }+}++} // namespace detail+++// Payload encoding+template <typename... Entries>+struct Payload;++template <typename First, typename Rest>+struct Payload<First, Rest>+{+  Payload(First first, Rest rest)+    : mFirst(std::move(first))+    , mRest(std::move(rest))+  {+  }++  Payload(PayloadEntry<First> first, Rest rest)+    : mFirst(std::move(first))+    , mRest(std::move(rest))+  {+  }++  template <typename RhsFirst, typename RhsRest>+  using PayloadSum =+    Payload<First, typename Rest::template PayloadSum<RhsFirst, RhsRest>>;++  // Concatenate payloads together into a single payload+  template <typename RhsFirst, typename RhsRest>+  friend PayloadSum<RhsFirst, RhsRest> operator+(+    Payload lhs, Payload<RhsFirst, RhsRest> rhs)+  {+    return {std::move(lhs.mFirst), std::move(lhs.mRest) + std::move(rhs)};+  }++  friend std::size_t sizeInByteStream(const Payload& payload)+  {+    return sizeInByteStream(payload.mFirst) + sizeInByteStream(payload.mRest);+  }++  template <typename It>+  friend It toNetworkByteStream(const Payload& payload, It streamIt)+  {+    return toNetworkByteStream(+      payload.mRest, toNetworkByteStream(payload.mFirst, std::move(streamIt)));+  }++  PayloadEntry<First> mFirst;+  Rest mRest;+};++template <>+struct Payload<>+{+  template <typename RhsFirst, typename RhsRest>+  using PayloadSum = Payload<RhsFirst, RhsRest>;++  template <typename RhsFirst, typename RhsRest>+  friend PayloadSum<RhsFirst, RhsRest> operator+(Payload, Payload<RhsFirst, RhsRest> rhs)+  {+    return rhs;+  }++  friend std::size_t sizeInByteStream(const Payload&)+  {+    return 0;+  }++  template <typename It>+  friend It toNetworkByteStream(const Payload&, It streamIt)+  {+    return streamIt;+  }+};++template <typename... Entries>+struct PayloadBuilder;++// Payload factory function+template <typename... Entries>+auto makePayload(Entries... entries)+  -> decltype(PayloadBuilder<Entries...>{}(std::move(entries)...))+{+  return PayloadBuilder<Entries...>{}(std::move(entries)...);+}++template <typename First, typename... Rest>+struct PayloadBuilder<First, Rest...>+{+  auto operator()(First first, Rest... rest)+    -> Payload<First, decltype(makePayload(std::move(rest)...))>+  {+    return {std::move(first), makePayload(std::move(rest)...)};+  }+};++template <>+struct PayloadBuilder<>+{+  Payload<> operator()()+  {+    return {};+  }+};++// Parse payloads to values+template <typename... Entries>+struct ParsePayload;++template <typename First, typename... Rest>+struct ParsePayload<First, Rest...>+{+  template <typename It, typename... Handlers>+  static void parse(It begin, It end, Handlers... handlers)+  {+    detail::HandlerMap<It> map;+    collectHandlers(map, std::move(handlers)...);+    detail::parseByteStream(map, std::move(begin), std::move(end));+  }++  template <typename It, typename FirstHandler, typename... RestHandlers>+  static void collectHandlers(+    detail::HandlerMap<It>& map, FirstHandler handler, RestHandlers... rest)+  {+    using namespace std;+    map[First::key] = [handler](const It begin, const It end) {+      const auto res = First::fromNetworkByteStream(begin, end);+      if (res.second != end)+      {+        std::ostringstream stringStream;+        stringStream << "Parsing payload entry " << First::key+                     << " did not consume the expected number of bytes. "+                     << " Expected: " << distance(begin, end)+                     << ", Actual: " << distance(begin, res.second);+        throw range_error(stringStream.str());+      }+      handler(res.first);+    };++    ParsePayload<Rest...>::collectHandlers(map, std::move(rest)...);+  }+};++template <>+struct ParsePayload<>+{+  template <typename It>+  static void collectHandlers(detail::HandlerMap<It>&)+  {+  }+};++template <typename... Entries, typename It, typename... Handlers>+void parsePayload(It begin, It end, Handlers... handlers)+{+  using namespace std;+  ParsePayload<Entries...>::parse(+    std::move(begin), std::move(end), std::move(handlers)...);+}++} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/PeerGateway.hpp view
@@ -0,0 +1,251 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/UdpMessenger.hpp>+#include <ableton/discovery/v1/Messages.hpp>+#include <ableton/util/SafeAsyncHandler.hpp>+#include <memory>++namespace ableton+{+namespace discovery+{++template <typename Messenger, typename PeerObserver, typename IoContext>+class PeerGateway+{+public:+  // The peer types are defined by the observer but must match with those+  // used by the Messenger+  using ObserverT = typename util::Injected<PeerObserver>::type;+  using NodeState = typename ObserverT::GatewayObserverNodeState;+  using NodeId = typename ObserverT::GatewayObserverNodeId;+  using Timer = typename util::Injected<IoContext>::type::Timer;+  using TimerError = typename Timer::ErrorCode;++  PeerGateway(util::Injected<Messenger> messenger,+    util::Injected<PeerObserver> observer,+    util::Injected<IoContext> io)+    : mpImpl(new Impl(std::move(messenger), std::move(observer), std::move(io)))+  {+    mpImpl->listen();+  }++  PeerGateway(const PeerGateway&) = delete;+  PeerGateway& operator=(const PeerGateway&) = delete;++  PeerGateway(PeerGateway&& rhs)+    : mpImpl(std::move(rhs.mpImpl))+  {+  }++  void updateState(NodeState state)+  {+    mpImpl->updateState(std::move(state));+  }++private:+  using PeerTimeout = std::pair<std::chrono::system_clock::time_point, NodeId>;+  using PeerTimeouts = std::vector<PeerTimeout>;++  struct Impl : std::enable_shared_from_this<Impl>+  {+    Impl(util::Injected<Messenger> messenger,+      util::Injected<PeerObserver> observer,+      util::Injected<IoContext> io)+      : mMessenger(std::move(messenger))+      , mObserver(std::move(observer))+      , mIo(std::move(io))+      , mPruneTimer(mIo->makeTimer())+    {+    }++    void updateState(NodeState state)+    {+      mMessenger->updateState(std::move(state));+      try+      {+        mMessenger->broadcastState();+      }+      catch (const std::runtime_error& err)+      {+        info(mIo->log()) << "State broadcast failed on gateway: " << err.what();+      }+    }++    void listen()+    {+      mMessenger->receive(util::makeAsyncSafe(this->shared_from_this()));+    }++    // Operators for handling incoming messages+    void operator()(const PeerState<NodeState>& msg)+    {+      onPeerState(msg.peerState, msg.ttl);+      listen();+    }++    void operator()(const ByeBye<NodeId>& msg)+    {+      onByeBye(msg.peerId);+      listen();+    }++    void onPeerState(const NodeState& nodeState, const int ttl)+    {+      using namespace std;+      const auto peerId = nodeState.ident();+      const auto existing = findPeer(peerId);+      if (existing != end(mPeerTimeouts))+      {+        // If the peer is already present in our timeout list, remove it+        // as it will be re-inserted below.+        mPeerTimeouts.erase(existing);+      }++      auto newTo = make_pair(mPruneTimer.now() + std::chrono::seconds(ttl), peerId);+      mPeerTimeouts.insert(+        upper_bound(begin(mPeerTimeouts), end(mPeerTimeouts), newTo, TimeoutCompare{}),+        std::move(newTo));++      sawPeer(*mObserver, nodeState);+      scheduleNextPruning();+    }++    void onByeBye(const NodeId& peerId)+    {+      const auto it = findPeer(peerId);+      if (it != mPeerTimeouts.end())+      {+        peerLeft(*mObserver, it->second);+        mPeerTimeouts.erase(it);+      }+    }++    void pruneExpiredPeers()+    {+      using namespace std;++      const auto test = make_pair(mPruneTimer.now(), NodeId{});+      debug(mIo->log()) << "pruning peers @ " << test.first.time_since_epoch().count();++      const auto endExpired =+        lower_bound(begin(mPeerTimeouts), end(mPeerTimeouts), test, TimeoutCompare{});++      for_each(begin(mPeerTimeouts), endExpired, [this](const PeerTimeout& pto) {+        info(mIo->log()) << "pruning peer " << pto.second;+        peerTimedOut(*mObserver, pto.second);+      });+      mPeerTimeouts.erase(begin(mPeerTimeouts), endExpired);+      scheduleNextPruning();+    }++    void scheduleNextPruning()+    {+      // Find the next peer to expire and set the timer based on it+      if (!mPeerTimeouts.empty())+      {+        // Add a second of padding to the timer to avoid over-eager timeouts+        const auto t = mPeerTimeouts.front().first + std::chrono::seconds(1);++        debug(mIo->log()) << "scheduling next pruning for "+                          << t.time_since_epoch().count() << " because of peer "+                          << mPeerTimeouts.front().second;++        mPruneTimer.expires_at(t);+        mPruneTimer.async_wait([this](const TimerError e) {+          if (!e)+          {+            pruneExpiredPeers();+          }+        });+      }+    }++    struct TimeoutCompare+    {+      bool operator()(const PeerTimeout& lhs, const PeerTimeout& rhs) const+      {+        return lhs.first < rhs.first;+      }+    };++    typename PeerTimeouts::iterator findPeer(const NodeId& peerId)+    {+      return std::find_if(begin(mPeerTimeouts), end(mPeerTimeouts),+        [&peerId](const PeerTimeout& pto) { return pto.second == peerId; });+    }++    util::Injected<Messenger> mMessenger;+    util::Injected<PeerObserver> mObserver;+    util::Injected<IoContext> mIo;+    Timer mPruneTimer;+    PeerTimeouts mPeerTimeouts; // Invariant: sorted by time_point+  };++  std::shared_ptr<Impl> mpImpl;+};++template <typename Messenger, typename PeerObserver, typename IoContext>+PeerGateway<Messenger, PeerObserver, IoContext> makePeerGateway(+  util::Injected<Messenger> messenger,+  util::Injected<PeerObserver> observer,+  util::Injected<IoContext> io)+{+  return {std::move(messenger), std::move(observer), std::move(io)};+}++// IpV4 gateway types+template <typename StateQuery, typename IoContext>+using IpV4Messenger = UdpMessenger<+  IpV4Interface<typename util::Injected<IoContext>::type&, v1::kMaxMessageSize>,+  StateQuery,+  IoContext>;++template <typename PeerObserver, typename StateQuery, typename IoContext>+using IpV4Gateway =+  PeerGateway<IpV4Messenger<StateQuery, typename util::Injected<IoContext>::type&>,+    PeerObserver,+    IoContext>;++// Factory function to bind a PeerGateway to an IpV4Interface with the given address.+template <typename PeerObserver, typename NodeState, typename IoContext>+IpV4Gateway<PeerObserver, NodeState, IoContext> makeIpV4Gateway(+  util::Injected<IoContext> io,+  const asio::ip::address_v4& addr,+  util::Injected<PeerObserver> observer,+  NodeState state)+{+  using namespace std;+  using namespace util;++  const uint8_t ttl = 5;+  const uint8_t ttlRatio = 20;++  auto iface = makeIpV4Interface<v1::kMaxMessageSize>(injectRef(*io), addr);++  auto messenger = makeUdpMessenger(+    injectVal(std::move(iface)), std::move(state), injectRef(*io), ttl, ttlRatio);+  return {injectVal(std::move(messenger)), std::move(observer), std::move(io)};+}++} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/PeerGateways.hpp view
@@ -0,0 +1,182 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/InterfaceScanner.hpp>+#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <map>++namespace ableton+{+namespace discovery+{++// GatewayFactory must have an operator()(NodeState, IoRef, asio::ip::address)+// that constructs a new PeerGateway on a given interface address.+template <typename NodeState, typename GatewayFactory, typename IoContext>+class PeerGateways+{+public:+  using IoType = typename util::Injected<IoContext>::type;+  using Gateway = typename std::result_of<GatewayFactory(+    NodeState, util::Injected<IoType&>, asio::ip::address)>::type;+  using GatewayMap = std::map<asio::ip::address, Gateway>;++  PeerGateways(const std::chrono::seconds rescanPeriod,+    NodeState state,+    GatewayFactory factory,+    util::Injected<IoContext> io)+    : mIo(std::move(io))+  {+    mpScannerCallback =+      std::make_shared<Callback>(std::move(state), std::move(factory), *mIo);+    mpScanner = std::make_shared<Scanner>(+      rescanPeriod, util::injectShared(mpScannerCallback), util::injectRef(*mIo));+  }++  ~PeerGateways()+  {+    mpScanner.reset();+    mpScannerCallback.reset();+  }++  PeerGateways(const PeerGateways&) = delete;+  PeerGateways& operator=(const PeerGateways&) = delete;++  PeerGateways(PeerGateways&&) = delete;+  PeerGateways& operator=(PeerGateways&&) = delete;++  void enable(const bool bEnable)+  {+    mpScannerCallback->mGateways.clear();+    mpScanner->enable(bEnable);+  }++  template <typename Handler>+  void withGateways(Handler handler)+  {+    handler(mpScannerCallback->mGateways.begin(), mpScannerCallback->mGateways.end());+  }++  void updateNodeState(const NodeState& state)+  {+    mpScannerCallback->mState = state;+    for (const auto& entry : mpScannerCallback->mGateways)+    {+      entry.second->updateNodeState(state);+    }+  }++  // If a gateway has become non-responsive or is throwing exceptions,+  // this method can be invoked to either fix it or discard it.+  void repairGateway(const asio::ip::address& gatewayAddr)+  {+    if (mpScannerCallback->mGateways.erase(gatewayAddr))+    {+      // If we erased a gateway, rescan again immediately so that+      // we will re-initialize it if it's still present+      mpScanner->scan();+    }+  }++private:+  struct Callback+  {+    Callback(NodeState state, GatewayFactory factory, IoType& io)+      : mState(std::move(state))+      , mFactory(std::move(factory))+      , mIo(io)+    {+    }++    template <typename AddrRange>+    void operator()(const AddrRange& range)+    {+      using namespace std;+      // Get the set of current addresses.+      vector<asio::ip::address> curAddrs;+      curAddrs.reserve(mGateways.size());+      transform(std::begin(mGateways), std::end(mGateways), back_inserter(curAddrs),+        [](const typename GatewayMap::value_type& vt) { return vt.first; });++      // Now use set_difference to determine the set of addresses that+      // are new and the set of cur addresses that are no longer there+      vector<asio::ip::address> newAddrs;+      set_difference(std::begin(range), std::end(range), std::begin(curAddrs),+        std::end(curAddrs), back_inserter(newAddrs));++      vector<asio::ip::address> staleAddrs;+      set_difference(std::begin(curAddrs), std::end(curAddrs), std::begin(range),+        std::end(range), back_inserter(staleAddrs));++      // Remove the stale addresses+      for (const auto& addr : staleAddrs)+      {+        mGateways.erase(addr);+      }++      // Add the new addresses+      for (const auto& addr : newAddrs)+      {+        try+        {+          // Only handle v4 for now+          if (addr.is_v4())+          {+            info(mIo.log()) << "initializing peer gateway on interface " << addr;+            mGateways.emplace(addr, mFactory(mState, util::injectRef(mIo), addr.to_v4()));+          }+        }+        catch (const runtime_error& e)+        {+          warning(mIo.log()) << "failed to init gateway on interface " << addr+                             << " reason: " << e.what();+        }+      }+    }++    NodeState mState;+    GatewayFactory mFactory;+    IoType& mIo;+    GatewayMap mGateways;+  };++  using Scanner = InterfaceScanner<std::shared_ptr<Callback>, IoType&>;+  std::shared_ptr<Callback> mpScannerCallback;+  std::shared_ptr<Scanner> mpScanner;+  util::Injected<IoContext> mIo;+};++// Factory function+template <typename NodeState, typename GatewayFactory, typename IoContext>+std::unique_ptr<PeerGateways<NodeState, GatewayFactory, IoContext>> makePeerGateways(+  const std::chrono::seconds rescanPeriod,+  NodeState state,+  GatewayFactory factory,+  util::Injected<IoContext> io)+{+  using namespace std;+  using Gateways = PeerGateways<NodeState, GatewayFactory, IoContext>;+  return unique_ptr<Gateways>{+    new Gateways{rescanPeriod, std::move(state), std::move(factory), std::move(io)}};+}++} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/Service.hpp view
@@ -0,0 +1,72 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/PeerGateways.hpp>++namespace ableton+{+namespace discovery+{++template <typename NodeState, typename GatewayFactory, typename IoContext>+class Service+{+public:+  using ServicePeerGateways = PeerGateways<NodeState, GatewayFactory, IoContext>;++  Service(NodeState state, GatewayFactory factory, util::Injected<IoContext> io)+    : mGateways(+        std::chrono::seconds(5), std::move(state), std::move(factory), std::move(io))+  {+  }++  void enable(const bool bEnable)+  {+    mGateways.enable(bEnable);+  }++  // Asynchronously operate on the current set of peer gateways. The+  // handler will be invoked in the service's io context.+  template <typename Handler>+  void withGateways(Handler handler)+  {+    mGateways.withGateways(std::move(handler));+  }++  void updateNodeState(const NodeState& state)+  {+    mGateways.updateNodeState(state);+  }++  // Repair the gateway with the given address if possible. Its+  // sockets may have been closed, for example, and the gateway needs+  // to be regenerated.+  void repairGateway(const asio::ip::address& gatewayAddr)+  {+    mGateways.repairGateway(gatewayAddr);+  }++private:+  ServicePeerGateways mGateways;+};++} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/UdpMessenger.hpp view
@@ -0,0 +1,330 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/IpV4Interface.hpp>+#include <ableton/discovery/MessageTypes.hpp>+#include <ableton/discovery/v1/Messages.hpp>+#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/util/Injected.hpp>+#include <ableton/util/SafeAsyncHandler.hpp>+#include <algorithm>+#include <memory>++namespace ableton+{+namespace discovery+{++// An exception thrown when sending a udp message fails. Stores the+// interface through which the sending failed.+struct UdpSendException : std::runtime_error+{+  UdpSendException(const std::runtime_error& e, asio::ip::address ifAddr)+    : std::runtime_error(e.what())+    , interfaceAddr(std::move(ifAddr))+  {+  }++  asio::ip::address interfaceAddr;+};++// Throws UdpSendException+template <typename Interface, typename NodeId, typename Payload>+void sendUdpMessage(Interface& iface,+  NodeId from,+  const uint8_t ttl,+  const v1::MessageType messageType,+  const Payload& payload,+  const asio::ip::udp::endpoint& to)+{+  using namespace std;+  v1::MessageBuffer buffer;+  const auto messageBegin = begin(buffer);+  const auto messageEnd =+    v1::detail::encodeMessage(std::move(from), ttl, messageType, payload, messageBegin);+  const auto numBytes = static_cast<size_t>(distance(messageBegin, messageEnd));+  try+  {+    iface.send(buffer.data(), numBytes, to);+  }+  catch (const std::runtime_error& err)+  {+    throw UdpSendException{err, iface.endpoint().address()};+  }+}++// UdpMessenger uses a "shared_ptr pImpl" pattern to make it movable+// and to support safe async handler callbacks when receiving messages+// on the given interface.+template <typename Interface, typename NodeStateT, typename IoContext>+class UdpMessenger+{+public:+  using NodeState = NodeStateT;+  using NodeId = typename NodeState::IdType;+  using Timer = typename util::Injected<IoContext>::type::Timer;+  using TimerError = typename Timer::ErrorCode;+  using TimePoint = typename Timer::TimePoint;++  UdpMessenger(util::Injected<Interface> iface,+    NodeState state,+    util::Injected<IoContext> io,+    const uint8_t ttl,+    const uint8_t ttlRatio)+    : mpImpl(std::make_shared<Impl>(+        std::move(iface), std::move(state), std::move(io), ttl, ttlRatio))+  {+    // We need to always listen for incoming traffic in order to+    // respond to peer state broadcasts+    mpImpl->listen(MulticastTag{});+    mpImpl->listen(UnicastTag{});+    mpImpl->broadcastState();+  }++  UdpMessenger(const UdpMessenger&) = delete;+  UdpMessenger& operator=(const UdpMessenger&) = delete;++  UdpMessenger(UdpMessenger&& rhs)+    : mpImpl(std::move(rhs.mpImpl))+  {+  }++  ~UdpMessenger()+  {+    if (mpImpl != nullptr)+    {+      try+      {+        mpImpl->sendByeBye();+      }+      catch (const UdpSendException& err)+      {+        debug(mpImpl->mIo->log()) << "Failed to send bye bye message: " << err.what();+      }+    }+  }++  void updateState(NodeState state)+  {+    mpImpl->updateState(std::move(state));+  }++  // Broadcast the current state of the system to all peers. May throw+  // std::runtime_error if assembling a broadcast message fails or if+  // there is an error at the transport layer. Throws on failure.+  void broadcastState()+  {+    mpImpl->broadcastState();+  }++  // Asynchronous receive function for incoming messages from peers. Will+  // return immediately and the handler will be invoked when a message+  // is received. Handler must have operator() overloads for PeerState and+  // ByeBye messages.+  template <typename Handler>+  void receive(Handler handler)+  {+    mpImpl->setReceiveHandler(std::move(handler));+  }++private:+  struct Impl : std::enable_shared_from_this<Impl>+  {+    Impl(util::Injected<Interface> iface,+      NodeState state,+      util::Injected<IoContext> io,+      const uint8_t ttl,+      const uint8_t ttlRatio)+      : mIo(std::move(io))+      , mInterface(std::move(iface))+      , mState(std::move(state))+      , mTimer(mIo->makeTimer())+      , mLastBroadcastTime{}+      , mTtl(ttl)+      , mTtlRatio(ttlRatio)+      , mPeerStateHandler([](PeerState<NodeState>) {})+      , mByeByeHandler([](ByeBye<NodeId>) {})+    {+    }++    template <typename Handler>+    void setReceiveHandler(Handler handler)+    {+      mPeerStateHandler = [handler](+                            PeerState<NodeState> state) { handler(std::move(state)); };++      mByeByeHandler = [handler](ByeBye<NodeId> byeBye) { handler(std::move(byeBye)); };+    }++    void sendByeBye()+    {+      sendUdpMessage(+        *mInterface, mState.ident(), 0, v1::kByeBye, makePayload(), multicastEndpoint());+    }++    void updateState(NodeState state)+    {+      mState = std::move(state);+    }++    void broadcastState()+    {+      using namespace std::chrono;++      const auto minBroadcastPeriod = milliseconds{50};+      const auto nominalBroadcastPeriod = milliseconds(mTtl * 1000 / mTtlRatio);+      const auto timeSinceLastBroadcast =+        duration_cast<milliseconds>(mTimer.now() - mLastBroadcastTime);++      // The rate is limited to maxBroadcastRate to prevent flooding the network.+      const auto delay = minBroadcastPeriod - timeSinceLastBroadcast;++      // Schedule the next broadcast before we actually send the+      // message so that if sending throws an exception we are still+      // scheduled to try again. We want to keep trying at our+      // interval as long as this instance is alive.+      mTimer.expires_from_now(delay > milliseconds{0} ? delay : nominalBroadcastPeriod);+      mTimer.async_wait([this](const TimerError e) {+        if (!e)+        {+          broadcastState();+        }+      });++      // If we're not delaying, broadcast now+      if (delay < milliseconds{1})+      {+        debug(mIo->log()) << "Broadcasting state";+        sendPeerState(v1::kAlive, multicastEndpoint());+      }+    }++    void sendPeerState(+      const v1::MessageType messageType, const asio::ip::udp::endpoint& to)+    {+      sendUdpMessage(+        *mInterface, mState.ident(), mTtl, messageType, toPayload(mState), to);+      mLastBroadcastTime = mTimer.now();+    }++    void sendResponse(const asio::ip::udp::endpoint& to)+    {+      sendPeerState(v1::kResponse, to);+    }++    template <typename Tag>+    void listen(Tag tag)+    {+      mInterface->receive(util::makeAsyncSafe(this->shared_from_this()), tag);+    }++    template <typename Tag, typename It>+    void operator()(Tag tag,+      const asio::ip::udp::endpoint& from,+      const It messageBegin,+      const It messageEnd)+    {+      auto result = v1::parseMessageHeader<NodeId>(messageBegin, messageEnd);++      const auto& header = result.first;+      // Ignore messages from self and other groups+      if (header.ident != mState.ident() && header.groupId == 0)+      {+        debug(mIo->log()) << "Received message type "+                          << static_cast<int>(header.messageType) << " from peer "+                          << header.ident;++        switch (header.messageType)+        {+        case v1::kAlive:+          sendResponse(from);+          receivePeerState(std::move(result.first), result.second, messageEnd);+          break;+        case v1::kResponse:+          receivePeerState(std::move(result.first), result.second, messageEnd);+          break;+        case v1::kByeBye:+          receiveByeBye(std::move(result.first.ident));+          break;+        default:+          info(mIo->log()) << "Unknown message received of type: " << header.messageType;+        }+      }+      listen(tag);+    }++    template <typename It>+    void receivePeerState(+      v1::MessageHeader<NodeId> header, It payloadBegin, It payloadEnd)+    {+      try+      {+        auto state = NodeState::fromPayload(+          std::move(header.ident), std::move(payloadBegin), std::move(payloadEnd));++        // Handlers must only be called once+        auto handler = std::move(mPeerStateHandler);+        mPeerStateHandler = [](PeerState<NodeState>) {};+        handler(PeerState<NodeState>{std::move(state), header.ttl});+      }+      catch (const std::runtime_error& err)+      {+        info(mIo->log()) << "Ignoring peer state message: " << err.what();+      }+    }++    void receiveByeBye(NodeId nodeId)+    {+      // Handlers must only be called once+      auto byeByeHandler = std::move(mByeByeHandler);+      mByeByeHandler = [](ByeBye<NodeId>) {};+      byeByeHandler(ByeBye<NodeId>{std::move(nodeId)});+    }++    util::Injected<IoContext> mIo;+    util::Injected<Interface> mInterface;+    NodeState mState;+    Timer mTimer;+    TimePoint mLastBroadcastTime;+    uint8_t mTtl;+    uint8_t mTtlRatio;+    std::function<void(PeerState<NodeState>)> mPeerStateHandler;+    std::function<void(ByeBye<NodeId>)> mByeByeHandler;+  };++  std::shared_ptr<Impl> mpImpl;+};++// Factory function+template <typename Interface, typename NodeState, typename IoContext>+UdpMessenger<Interface, NodeState, IoContext> makeUdpMessenger(+  util::Injected<Interface> iface,+  NodeState state,+  util::Injected<IoContext> io,+  const uint8_t ttl,+  const uint8_t ttlRatio)+{+  return UdpMessenger<Interface, NodeState, IoContext>{+    std::move(iface), std::move(state), std::move(io), ttl, ttlRatio};+}++} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/test/Interface.hpp view
@@ -0,0 +1,75 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/util/Log.hpp>++namespace ableton+{+namespace discovery+{+namespace test+{++class Interface+{+public:+  void send(const uint8_t* const bytes,+    const size_t numBytes,+    const asio::ip::udp::endpoint& endpoint)+  {+    sentMessages.push_back(+      std::make_pair(std::vector<uint8_t>{bytes, bytes + numBytes}, endpoint));+  }++  template <typename Callback, typename Tag>+  void receive(Callback callback, Tag tag)+  {+    mCallback = [callback, tag](const asio::ip::udp::endpoint& from,+                  const std::vector<uint8_t>& buffer) {+      callback(tag, from, begin(buffer), end(buffer));+    };+  }++  template <typename It>+  void incomingMessage(+    const asio::ip::udp::endpoint& from, It messageBegin, It messageEnd)+  {+    std::vector<uint8_t> buffer{messageBegin, messageEnd};+    mCallback(from, buffer);+  }++  asio::ip::udp::endpoint endpoint() const+  {+    return asio::ip::udp::endpoint({}, 0);+  }++  using SentMessage = std::pair<std::vector<uint8_t>, asio::ip::udp::endpoint>;+  std::vector<SentMessage> sentMessages;++private:+  using ReceiveCallback =+    std::function<void(const asio::ip::udp::endpoint&, const std::vector<uint8_t>&)>;+  ReceiveCallback mCallback;+};++} // namespace test+} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/test/PayloadEntries.hpp view
@@ -0,0 +1,133 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/NetworkByteStreamSerializable.hpp>+#include <cstdint>+#include <tuple>+#include <utility>++namespace ableton+{+namespace discovery+{+namespace test+{++// Test payload entries++// A fixed-size entry type+struct Foo+{+  static const std::int32_t key = '_foo';+  static_assert(key == 0x5f666f6f, "Unexpected byte order");++  std::int32_t fooVal;++  friend std::uint32_t sizeInByteStream(const Foo& foo)+  {+    // Namespace qualification is needed to avoid ambiguous function definitions+    return discovery::sizeInByteStream(foo.fooVal);+  }++  template <typename It>+  friend It toNetworkByteStream(const Foo& foo, It out)+  {+    return discovery::toNetworkByteStream(foo.fooVal, std::move(out));+  }++  template <typename It>+  static std::pair<Foo, It> fromNetworkByteStream(It begin, It end)+  {+    auto result = Deserialize<decltype(fooVal)>::fromNetworkByteStream(+      std::move(begin), std::move(end));+    return std::make_pair(Foo{std::move(result.first)}, std::move(result.second));+  }+};++// A variable-size entry type+struct Bar+{+  static const std::int32_t key = '_bar';+  static_assert(key == 0x5f626172, "Unexpected byte order");++  std::vector<std::uint64_t> barVals;++  friend std::uint32_t sizeInByteStream(const Bar& bar)+  {+    return discovery::sizeInByteStream(bar.barVals);+  }++  template <typename It>+  friend It toNetworkByteStream(const Bar& bar, It out)+  {+    return discovery::toNetworkByteStream(bar.barVals, out);+  }++  template <typename It>+  static std::pair<Bar, It> fromNetworkByteStream(It begin, It end)+  {+    auto result = Deserialize<decltype(barVals)>::fromNetworkByteStream(+      std::move(begin), std::move(end));+    return std::make_pair(Bar{std::move(result.first)}, std::move(result.second));+  }+};++// An entry type with two vectors+struct Foobar+{+  static const std::int32_t key = 'fbar';+  static_assert(key == 0x66626172, "Unexpected byte order");++  using FoobarVector = std::vector<std::uint64_t>;+  using FoobarTuple = std::tuple<FoobarVector, FoobarVector>;++  FoobarVector fooVals;+  FoobarVector barVals;++  friend std::uint32_t sizeInByteStream(const Foobar& foobar)+  {+    return discovery::sizeInByteStream(foobar.asTuple());+  }++  template <typename It>+  friend It toNetworkByteStream(const Foobar& foobar, It out)+  {+    return discovery::toNetworkByteStream(foobar.asTuple(), out);+  }++  template <typename It>+  static std::pair<Foobar, It> fromNetworkByteStream(It begin, It end)+  {+    const auto result =+      Deserialize<FoobarTuple>::fromNetworkByteStream(std::move(begin), std::move(end));+    const auto foobar = Foobar{std::get<0>(result.first), std::get<1>(result.first)};+    return std::make_pair(std::move(foobar), std::move(result.second));+  }++  FoobarTuple asTuple() const+  {+    return std::make_tuple(fooVals, barVals);+  }+};++} // namespace test+} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/test/Socket.hpp view
@@ -0,0 +1,85 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/util/Log.hpp>+#include <ableton/util/test/IoService.hpp>++namespace ableton+{+namespace discovery+{+namespace test+{++class Socket+{+public:+  Socket(util::test::IoService&)+  {+  }++  friend void configureUnicastSocket(Socket&, const asio::ip::address_v4&)+  {+  }++  std::size_t send(+    const uint8_t* const pData, const size_t numBytes, const asio::ip::udp::endpoint& to)+  {+    sentMessages.push_back(+      std::make_pair(std::vector<uint8_t>{pData, pData + numBytes}, to));+    return numBytes;+  }++  template <typename Handler>+  void receive(Handler handler)+  {+    mCallback = [handler](const asio::ip::udp::endpoint& from,+                  const std::vector<uint8_t>& buffer) {+      handler(from, begin(buffer), end(buffer));+    };+  }++  template <typename It>+  void incomingMessage(+    const asio::ip::udp::endpoint& from, It messageBegin, It messageEnd)+  {+    std::vector<uint8_t> buffer{messageBegin, messageEnd};+    mCallback(from, buffer);+  }++  asio::ip::udp::endpoint endpoint() const+  {+    return asio::ip::udp::endpoint({}, 0);+  }++  using SentMessage = std::pair<std::vector<uint8_t>, asio::ip::udp::endpoint>;+  std::vector<SentMessage> sentMessages;++private:+  using ReceiveCallback =+    std::function<void(const asio::ip::udp::endpoint&, const std::vector<uint8_t>&)>;+  ReceiveCallback mCallback;+};++} // namespace test+} // namespace discovery+} // namespace ableton
+ link/include/ableton/discovery/v1/Messages.hpp view
@@ -0,0 +1,168 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/Payload.hpp>+#include <array>++namespace ableton+{+namespace discovery+{+namespace v1+{++// The maximum size of a message, in bytes+const std::size_t kMaxMessageSize = 512;+// Utility typedef for an array of bytes of maximum message size+using MessageBuffer = std::array<uint8_t, v1::kMaxMessageSize>;++using MessageType = uint8_t;+using SessionGroupId = uint16_t;++const MessageType kInvalid = 0;+const MessageType kAlive = 1;+const MessageType kResponse = 2;+const MessageType kByeBye = 3;++template <typename NodeId>+struct MessageHeader+{+  MessageType messageType;+  uint8_t ttl;+  SessionGroupId groupId;+  NodeId ident;++  friend std::uint32_t sizeInByteStream(const MessageHeader& header)+  {+    return discovery::sizeInByteStream(header.messageType)+           + discovery::sizeInByteStream(header.ttl)+           + discovery::sizeInByteStream(header.groupId)+           + discovery::sizeInByteStream(header.ident);+  }++  template <typename It>+  friend It toNetworkByteStream(const MessageHeader& header, It out)+  {+    return discovery::toNetworkByteStream(header.ident,+      discovery::toNetworkByteStream(header.groupId,+        discovery::toNetworkByteStream(header.ttl,+          discovery::toNetworkByteStream(header.messageType, std::move(out)))));+  }++  template <typename It>+  static std::pair<MessageHeader, It> fromNetworkByteStream(It begin, const It end)+  {+    using namespace std;++    MessageHeader header;+    tie(header.messageType, begin) =+      Deserialize<decltype(header.messageType)>::fromNetworkByteStream(begin, end);+    tie(header.ttl, begin) =+      Deserialize<decltype(header.ttl)>::fromNetworkByteStream(begin, end);+    tie(header.groupId, begin) =+      Deserialize<decltype(header.groupId)>::fromNetworkByteStream(begin, end);+    tie(header.ident, begin) =+      Deserialize<decltype(header.ident)>::fromNetworkByteStream(begin, end);++    return make_pair(std::move(header), std::move(begin));+  }+};++namespace detail+{++// Types that are only used in the sending/parsing of messages, not+// publicly exposed.+using ProtocolHeader = std::array<char, 8>;+const ProtocolHeader kProtocolHeader = {{'_', 'a', 's', 'd', 'p', '_', 'v', 1}};++// Must have at least kMaxMessageSize bytes available in the output stream+template <typename NodeId, typename Payload, typename It>+It encodeMessage(NodeId from,+  const uint8_t ttl,+  const MessageType messageType,+  const Payload& payload,+  It out)+{+  using namespace std;+  const MessageHeader<NodeId> header = {messageType, ttl, 0, std::move(from)};+  const auto messageSize =+    kProtocolHeader.size() + sizeInByteStream(header) + sizeInByteStream(payload);++  if (messageSize < kMaxMessageSize)+  {+    return toNetworkByteStream(+      payload, toNetworkByteStream(header,+                 copy(begin(kProtocolHeader), end(kProtocolHeader), std::move(out))));+  }+  else+  {+    throw range_error("Exceeded maximum message size");+  }+}++} // namespace detail++template <typename NodeId, typename Payload, typename It>+It aliveMessage(NodeId from, const uint8_t ttl, const Payload& payload, It out)+{+  return detail::encodeMessage(std::move(from), ttl, kAlive, payload, std::move(out));+}++template <typename NodeId, typename Payload, typename It>+It responseMessage(NodeId from, const uint8_t ttl, const Payload& payload, It out)+{+  return detail::encodeMessage(std::move(from), ttl, kResponse, payload, std::move(out));+}++template <typename NodeId, typename It>+It byeByeMessage(NodeId from, It out)+{+  return detail::encodeMessage(+    std::move(from), 0, kByeBye, makePayload(), std::move(out));+}++template <typename NodeId, typename It>+std::pair<MessageHeader<NodeId>, It> parseMessageHeader(It bytesBegin, const It bytesEnd)+{+  using namespace std;+  using ItDiff = typename iterator_traits<It>::difference_type;++  MessageHeader<NodeId> header = {};+  const auto protocolHeaderSize = discovery::sizeInByteStream(detail::kProtocolHeader);+  const auto minMessageSize =+    static_cast<ItDiff>(protocolHeaderSize + sizeInByteStream(header));++  // If there are enough bytes in the stream to make a header and if+  // the first bytes in the stream are the protocol header, then+  // proceed to parse the stream.+  if (distance(bytesBegin, bytesEnd) >= minMessageSize+      && equal(begin(detail::kProtocolHeader), end(detail::kProtocolHeader), bytesBegin))+  {+    tie(header, bytesBegin) = MessageHeader<NodeId>::fromNetworkByteStream(+      bytesBegin + protocolHeaderSize, bytesEnd);+  }+  return make_pair(std::move(header), std::move(bytesBegin));+}++} // namespace v1+} // namespace discovery+} // namespace ableton
+ link/include/ableton/link/Beats.hpp view
@@ -0,0 +1,125 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/NetworkByteStreamSerializable.hpp>+#include <cmath>+#include <cstdint>++namespace ableton+{+namespace link+{++struct Beats+{+  Beats() = default;++  explicit Beats(const double beats)+    : mValue(std::llround(beats * 1e6))+  {+  }++  explicit Beats(const std::int64_t microBeats)+    : mValue(microBeats)+  {+  }++  double floating() const+  {+    return static_cast<double>(mValue) / 1e6;+  }++  std::int64_t microBeats() const+  {+    return mValue;+  }++  Beats operator-() const+  {+    return Beats{-mValue};+  }++  friend Beats abs(const Beats b)+  {+    return Beats{std::abs(b.mValue)};+  }++  friend Beats operator+(const Beats lhs, const Beats rhs)+  {+    return Beats{lhs.mValue + rhs.mValue};+  }++  friend Beats operator-(const Beats lhs, const Beats rhs)+  {+    return Beats{lhs.mValue - rhs.mValue};+  }++  friend Beats operator%(const Beats lhs, const Beats rhs)+  {+    return Beats{rhs.mValue == 0 ? 0 : (lhs.mValue % rhs.mValue)};+  }++  friend bool operator<(const Beats lhs, const Beats rhs)+  {+    return lhs.mValue < rhs.mValue;+  }++  friend bool operator>(const Beats lhs, const Beats rhs)+  {+    return lhs.mValue > rhs.mValue;+  }++  friend bool operator==(const Beats lhs, const Beats rhs)+  {+    return lhs.mValue == rhs.mValue;+  }++  friend bool operator!=(const Beats lhs, const Beats rhs)+  {+    return lhs.mValue != rhs.mValue;+  }++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const Beats beats)+  {+    return discovery::sizeInByteStream(beats.microBeats());+  }++  template <typename It>+  friend It toNetworkByteStream(const Beats beats, It out)+  {+    return discovery::toNetworkByteStream(beats.microBeats(), std::move(out));+  }++  template <typename It>+  static std::pair<Beats, It> fromNetworkByteStream(It begin, It end)+  {+    auto result = discovery::Deserialize<std::int64_t>::fromNetworkByteStream(+      std::move(begin), std::move(end));+    return std::make_pair(Beats{result.first}, std::move(result.second));+  }++private:+  std::int64_t mValue = 0;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/ClientSessionTimelines.hpp view
@@ -0,0 +1,115 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/GhostXForm.hpp>+#include <ableton/link/Timeline.hpp>++namespace ableton+{+namespace link+{++// Clamp the tempo of the given timeline to the valid Link range+inline Timeline clampTempo(const Timeline timeline)+{+  const double kMinBpm = 20.0;+  const double kMaxBpm = 999.0;+  return {Tempo{(std::min)((std::max)(timeline.tempo.bpm(), kMinBpm), kMaxBpm)},+    timeline.beatOrigin, timeline.timeOrigin};+}++// Given an existing client timeline, a session timeline, and the+// global host transform of the session, return a new version of the client+// timeline. The resulting new client timeline is continuous with the+// previous timeline so that curClient.toBeats(atTime) ==+// result.toBeats(atTime).+inline Timeline updateClientTimelineFromSession(const Timeline curClient,+  const Timeline session,+  const std::chrono::microseconds atTime,+  const GhostXForm xform)+{+  // An intermediate timeline representing the continuation of the+  // existing client timeline with the tempo from the session timeline.+  const auto tempTl = Timeline{session.tempo, curClient.toBeats(atTime), atTime};+  // The host time corresponding to beat 0 on the session+  // timeline. Beat 0 on the session timeline is important because it+  // serves as the origin of the quantization grid for all participants.+  const auto hostBeatZero = xform.ghostToHost(session.fromBeats(Beats{INT64_C(0)}));+  // The new client timeline becomes the result of sliding the+  // intermediate timeline back so that it's anchor corresponds to+  // beat zero on the session timeline. The result preserves the+  // magnitude of beats on the client timeline while encoding the+  // quantization reference point in the time and beatOrigins.+  return {tempTl.tempo, tempTl.toBeats(hostBeatZero), hostBeatZero};+}+++inline Timeline updateSessionTimelineFromClient(const Timeline curSession,+  const Timeline client,+  const std::chrono::microseconds atTime,+  const GhostXForm xform)+{+  // The client timeline was constructed so that it's timeOrigin+  // corresponds to beat 0 on the session timeline.+  const auto ghostBeat0 = xform.hostToGhost(client.timeOrigin);++  const auto zero = Beats{INT64_C(0)};+  // If beat 0 was not shifted and there is not a new tempo, an update+  // of the session timeline is not required. Don't create an+  // equivalent timeline with different anchor points if not needed as+  // this will trigger other unnecessary changes.+  if (curSession.toBeats(ghostBeat0) == zero && client.tempo == curSession.tempo)+  {+    return curSession;+  }+  else+  {+    // An intermediate timeline representing the new tempo, the+    // effective time, and a possibly adjusted origin.+    const auto tempTl = Timeline{client.tempo, zero, ghostBeat0};+    // The final session timeline must have the beat corresponding to+    // atTime on the old session timeline as its beatOrigin because this is+    // used for prioritization of timelines among peers - we can't let a+    // modification applied by the client artificially increase or+    // reduce the timeline's priority in the session. The new beat+    // origin should be as close as possible to lining up with atTime,+    // but we must also make sure that it's > curSession.beatOrigin+    // because otherwise it will get ignored.+    const auto newBeatOrigin = (std::max)(curSession.toBeats(xform.hostToGhost(atTime)),+      curSession.beatOrigin + Beats{INT64_C(1)});+    return {client.tempo, newBeatOrigin, tempTl.fromBeats(newBeatOrigin)};+  }+}++// Shift timeline so result.toBeats(t) == client.toBeats(t) ++// shift. This takes into account the fact that the timeOrigin+// corresponds to beat 0 on the session timeline. Using this function+// and then setting the session timeline with the result will change+// the phase of the session by the given shift amount.+inline Timeline shiftClientTimeline(Timeline client, const Beats shift)+{+  const auto timeDelta = client.fromBeats(shift) - client.fromBeats(Beats{INT64_C(0)});+  client.timeOrigin = client.timeOrigin - timeDelta;+  return client;+}++} // namespace link+} // namespace ableton
+ link/include/ableton/link/Controller.hpp view
@@ -0,0 +1,792 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/Service.hpp>+#include <ableton/link/ClientSessionTimelines.hpp>+#include <ableton/link/Gateway.hpp>+#include <ableton/link/GhostXForm.hpp>+#include <ableton/link/NodeState.hpp>+#include <ableton/link/Peers.hpp>+#include <ableton/link/SessionState.hpp>+#include <ableton/link/Sessions.hpp>+#include <ableton/link/StartStopState.hpp>+#include <ableton/link/TripleBuffer.hpp>+#include <condition_variable>+#include <mutex>++namespace ableton+{+namespace link+{+namespace detail+{++template <typename Clock>+GhostXForm initXForm(const Clock& clock)+{+  // Make the current time map to a ghost time of 0 with ghost time+  // increasing at the same rate as clock time+  return {1.0, -clock.micros()};+}++template <typename Clock>+inline SessionState initSessionState(const Tempo tempo, const Clock& clock)+{+  using namespace std::chrono;+  return {clampTempo(Timeline{tempo, Beats{0.}, microseconds{0}}),+    StartStopState{false, Beats{0.}, microseconds{0}}, initXForm(clock)};+}++inline ClientState initClientState(const SessionState& sessionState)+{+  const auto hostTime = sessionState.ghostXForm.ghostToHost(std::chrono::microseconds{0});+  return {+    Timeline{sessionState.timeline.tempo, sessionState.timeline.beatOrigin, hostTime},+    ClientStartStopState{sessionState.startStopState.isPlaying, hostTime, hostTime}};+}++inline RtClientState initRtClientState(const ClientState& clientState)+{+  using namespace std::chrono;+  return {+    clientState.timeline, clientState.startStopState, microseconds{0}, microseconds{0}};+}++// The timespan in which local modifications to the timeline will be+// preferred over any modifications coming from the network.+const auto kLocalModGracePeriod = std::chrono::milliseconds(1000);+const auto kRtHandlerFallbackPeriod = kLocalModGracePeriod / 2;++inline ClientStartStopState selectPreferredStartStopState(+  const ClientStartStopState currentStartStopState,+  const ClientStartStopState startStopState)+{+  return startStopState.timestamp > currentStartStopState.timestamp+           ? startStopState+           : currentStartStopState;+}++inline ClientStartStopState mapStartStopStateFromSessionToClient(+  const StartStopState& sessionStartStopState,+  const Timeline& sessionTimeline,+  const GhostXForm& xForm)+{+  const auto time =+    xForm.ghostToHost(sessionTimeline.fromBeats(sessionStartStopState.beats));+  const auto timestamp = xForm.ghostToHost(sessionStartStopState.timestamp);+  return ClientStartStopState{sessionStartStopState.isPlaying, time, timestamp};+}++inline StartStopState mapStartStopStateFromClientToSession(+  const ClientStartStopState& clientStartStopState,+  const Timeline& sessionTimeline,+  const GhostXForm& xForm)+{+  const auto sessionBeats =+    sessionTimeline.toBeats(xForm.hostToGhost(clientStartStopState.time));+  const auto timestamp = xForm.hostToGhost(clientStartStopState.timestamp);+  return StartStopState{clientStartStopState.isPlaying, sessionBeats, timestamp};+}++} // namespace detail++// function types corresponding to the Controller callback type params+using PeerCountCallback = std::function<void(std::size_t)>;+using TempoCallback = std::function<void(ableton::link::Tempo)>;+using StartStopStateCallback = std::function<void(bool)>;+++// The main Link controller+template <typename PeerCountCallback,+  typename TempoCallback,+  typename StartStopStateCallback,+  typename Clock,+  typename Random,+  typename IoContext>+class Controller+{+public:+  Controller(Tempo tempo,+    PeerCountCallback peerCallback,+    TempoCallback tempoCallback,+    StartStopStateCallback startStopStateCallback,+    Clock clock)+    : mTempoCallback(std::move(tempoCallback))+    , mStartStopStateCallback(std::move(startStopStateCallback))+    , mClock(std::move(clock))+    , mNodeId(NodeId::random<Random>())+    , mSessionId(mNodeId)+    , mSessionState(detail::initSessionState(tempo, mClock))+    , mClientState(detail::initClientState(mSessionState))+    , mLastIsPlayingForStartStopStateCallback(false)+    , mRtClientState(detail::initRtClientState(mClientState.get()))+    , mHasPendingRtClientStates(false)+    , mSessionPeerCounter(*this, std::move(peerCallback))+    , mEnabled(false)+    , mStartStopSyncEnabled(false)+    , mIo(IoContext{UdpSendExceptionHandler{this}})+    , mRtClientStateSetter(*this)+    , mPeers(util::injectRef(*mIo),+        std::ref(mSessionPeerCounter),+        SessionTimelineCallback{*this},+        SessionStartStopStateCallback{*this})+    , mSessions(+        {mSessionId, mSessionState.timeline, {mSessionState.ghostXForm, mClock.micros()}},+        util::injectRef(mPeers),+        MeasurePeer{*this},+        JoinSessionCallback{*this},+        util::injectRef(*mIo),+        mClock)+    , mDiscovery(std::make_pair(NodeState{mNodeId, mSessionId, mSessionState.timeline,+                                  mSessionState.startStopState},+                   mSessionState.ghostXForm),+        GatewayFactory{*this},+        util::injectRef(*mIo))+  {+  }++  Controller(const Controller&) = delete;+  Controller(Controller&&) = delete;++  Controller& operator=(const Controller&) = delete;+  Controller& operator=(Controller&&) = delete;++  ~Controller()+  {+    std::mutex mutex;+    std::condition_variable condition;+    auto stopped = false;++    mIo->async([this, &mutex, &condition, &stopped]() {+      enable(false);+      std::unique_lock<std::mutex> lock(mutex);+      stopped = true;+      condition.notify_one();+    });++    std::unique_lock<std::mutex> lock(mutex);+    condition.wait(lock, [&stopped] { return stopped; });++    mIo->stop();+  }++  void enable(const bool bEnable)+  {+    const bool bWasEnabled = mEnabled.exchange(bEnable);+    if (bWasEnabled != bEnable)+    {+      mIo->async([this, bEnable] {+        if (bEnable)+        {+          // Process the pending client states to make sure we don't push one after we+          // have joined a running session+          mRtClientStateSetter.processPendingClientStates();+          // Always reset when first enabling to avoid hijacking+          // tempo in existing sessions+          resetState();+        }+        mDiscovery.enable(bEnable);+      });+    }+  }++  bool isEnabled() const+  {+    return mEnabled;+  }++  void enableStartStopSync(const bool bEnable)+  {+    mStartStopSyncEnabled = bEnable;+  }++  bool isStartStopSyncEnabled() const+  {+    return mStartStopSyncEnabled;+  }++  std::size_t numPeers() const+  {+    return mSessionPeerCounter.mSessionPeerCount;+  }++  // Get the current Link client state. Thread-safe but may block, so+  // it cannot be used from audio thread.+  ClientState clientState() const+  {+    return mClientState.get();+  }++  // Set the client state to be used, starting at the given time.+  // Thread-safe but may block, so it cannot be used from audio thread.+  void setClientState(IncomingClientState newClientState)+  {+    mClientState.update([&](ClientState& clientState) {+      if (newClientState.timeline)+      {+        *newClientState.timeline = clampTempo(*newClientState.timeline);+        clientState.timeline = *newClientState.timeline;+      }+      if (newClientState.startStopState)+      {+        // Prevent updating client start stop state with an outdated start stop state+        *newClientState.startStopState = detail::selectPreferredStartStopState(+          clientState.startStopState, *newClientState.startStopState);+        clientState.startStopState = *newClientState.startStopState;+      }+    });+    mIo->async([this, newClientState] { handleClientState(newClientState); });+  }++  // Non-blocking client state access for a realtime context. NOT+  // thread-safe. Must not be called from multiple threads+  // concurrently and must not be called concurrently with setClientStateRtSafe.+  ClientState clientStateRtSafe() const+  {+    // Respect the session state guard and the client state guard but don't+    // block on them. If we can't access one or both because of concurrent modification+    // we fall back to our cached version of the timeline and/or start stop state.++    if (!mHasPendingRtClientStates)+    {+      const auto now = mClock.micros();+      const auto timelineGracePeriodOver =+        now - mRtClientState.timelineTimestamp > detail::kLocalModGracePeriod;+      const auto startStopStateGracePeriodOver =+        now - mRtClientState.startStopStateTimestamp > detail::kLocalModGracePeriod;++      if (timelineGracePeriodOver || startStopStateGracePeriodOver)+      {+        const auto clientState = mClientState.getRt();++        if (timelineGracePeriodOver && clientState.timeline != mRtClientState.timeline)+        {+          mRtClientState.timeline = clientState.timeline;+        }++        if (startStopStateGracePeriodOver+            && clientState.startStopState != mRtClientState.startStopState)+        {+          mRtClientState.startStopState = clientState.startStopState;+        }+      }+    }++    return {mRtClientState.timeline, mRtClientState.startStopState};+  }++  // should only be called from the audio thread+  void setClientStateRtSafe(IncomingClientState newClientState)+  {+    if (!newClientState.timeline && !newClientState.startStopState)+    {+      return;+    }++    if (newClientState.timeline)+    {+      *newClientState.timeline = clampTempo(*newClientState.timeline);+    }++    if (newClientState.startStopState)+    {+      // Prevent updating client start stop state with an outdated start stop state+      *newClientState.startStopState = detail::selectPreferredStartStopState(+        mRtClientState.startStopState, *newClientState.startStopState);+    }++    // This flag ensures that mRtClientState is only updated after all incoming+    // client states were processed+    mHasPendingRtClientStates = true;+    mRtClientStateSetter.push(newClientState);+    const auto now = mClock.micros();+    // Cache the new timeline and StartStopState for serving back to the client+    if (newClientState.timeline)+    {+      // Cache the new timeline and StartStopState for serving back to the client+      mRtClientState.timeline = *newClientState.timeline;+      mRtClientState.timelineTimestamp = makeRtTimestamp(now);+    }+    if (newClientState.startStopState)+    {+      mRtClientState.startStopState = *newClientState.startStopState;+      mRtClientState.startStopStateTimestamp = makeRtTimestamp(now);+    }+  }++private:+  std::chrono::microseconds makeRtTimestamp(const std::chrono::microseconds now) const+  {+    return isEnabled() ? now : std::chrono::microseconds(0);+  }++  void invokeStartStopStateCallbackIfChanged()+  {+    bool shouldInvokeCallback = false;++    mClientState.update([&](ClientState& clientState) {+      shouldInvokeCallback =+        mLastIsPlayingForStartStopStateCallback != clientState.startStopState.isPlaying;+      mLastIsPlayingForStartStopStateCallback = clientState.startStopState.isPlaying;+    });++    if (shouldInvokeCallback)+    {+      mStartStopStateCallback(mLastIsPlayingForStartStopStateCallback);+    }+  }++  void updateDiscovery()+  {+    // Push the change to the discovery service+    mDiscovery.updateNodeState(+      std::make_pair(NodeState{mNodeId, mSessionId, mSessionState.timeline,+                       mSessionState.startStopState},+        mSessionState.ghostXForm));+  }++  void updateSessionTiming(Timeline newTimeline, const GhostXForm newXForm)+  {+    // Clamp the session tempo because it may slightly overshoot (999 bpm is+    // transferred as 60606 us/beat and received as 999.000999... bpm).+    newTimeline = clampTempo(newTimeline);+    const auto oldTimeline = mSessionState.timeline;+    const auto oldXForm = mSessionState.ghostXForm;++    if (oldTimeline != newTimeline || oldXForm != newXForm)+    {+      {+        std::lock_guard<std::mutex> lock(mSessionStateGuard);+        mSessionState.timeline = newTimeline;+        mSessionState.ghostXForm = newXForm;+      }++      // Update the client timeline and start stop state based on the new session timing+      mClientState.update([&](ClientState& clientState) {+        clientState.timeline = updateClientTimelineFromSession(clientState.timeline,+          mSessionState.timeline, mClock.micros(), mSessionState.ghostXForm);+        // Don't pass the start stop state to the client when start stop sync is disabled+        // or when we have a default constructed start stop state+        if (mStartStopSyncEnabled && mSessionState.startStopState != StartStopState{})+        {+          std::lock_guard<std::mutex> startStopStateLock(mSessionStateGuard);+          clientState.startStopState =+            detail::mapStartStopStateFromSessionToClient(mSessionState.startStopState,+              mSessionState.timeline, mSessionState.ghostXForm);+        }+      });++      if (oldTimeline.tempo != newTimeline.tempo)+      {+        mTempoCallback(newTimeline.tempo);+      }+    }+  }++  void handleTimelineFromSession(SessionId id, Timeline timeline)+  {+    debug(mIo->log()) << "Received timeline with tempo: " << timeline.tempo.bpm()+                      << " for session: " << id;+    updateSessionTiming(mSessions.sawSessionTimeline(std::move(id), std::move(timeline)),+      mSessionState.ghostXForm);+    updateDiscovery();+  }++  void resetSessionStartStopState()+  {+    mSessionState.startStopState = StartStopState{};+  }++  void handleStartStopStateFromSession(SessionId sessionId, StartStopState startStopState)+  {+    debug(mIo->log()) << "Received start stop state. isPlaying: "+                      << startStopState.isPlaying+                      << ", beats: " << startStopState.beats.floating()+                      << ", time: " << startStopState.timestamp.count()+                      << " for session: " << sessionId;+    if (sessionId == mSessionId+        && startStopState.timestamp > mSessionState.startStopState.timestamp)+    {+      mSessionState.startStopState = startStopState;++      // Always propagate the session start stop state so even a client that doesn't have+      // the feature enabled can function as a relay.+      updateDiscovery();++      if (mStartStopSyncEnabled)+      {+        mClientState.update([&](ClientState& clientState) {+          clientState.startStopState = detail::mapStartStopStateFromSessionToClient(+            startStopState, mSessionState.timeline, mSessionState.ghostXForm);+        });+        invokeStartStopStateCallbackIfChanged();+      }+    }+  }++  void handleClientState(const IncomingClientState clientState)+  {+    auto mustUpdateDiscovery = false;++    if (clientState.timeline)+    {+      auto sessionTimeline = updateSessionTimelineFromClient(mSessionState.timeline,+        *clientState.timeline, clientState.timelineTimestamp, mSessionState.ghostXForm);++      mSessions.resetTimeline(sessionTimeline);+      mPeers.setSessionTimeline(mSessionId, sessionTimeline);+      updateSessionTiming(std::move(sessionTimeline), mSessionState.ghostXForm);++      mustUpdateDiscovery = true;+    }++    if (mStartStopSyncEnabled && clientState.startStopState)+    {+      // Prevent updating with an outdated start stop state+      const auto newGhostTime =+        mSessionState.ghostXForm.hostToGhost(clientState.startStopState->timestamp);+      if (newGhostTime > mSessionState.startStopState.timestamp)+      {+        mClientState.update([&](ClientState& currentClientState) {+          mSessionState.startStopState =+            detail::mapStartStopStateFromClientToSession(*clientState.startStopState,+              mSessionState.timeline, mSessionState.ghostXForm);+          currentClientState.startStopState = *clientState.startStopState;+        });++        mustUpdateDiscovery = true;+      }+    }++    if (mustUpdateDiscovery)+    {+      updateDiscovery();+    }++    invokeStartStopStateCallbackIfChanged();+  }++  void handleRtClientState(IncomingClientState clientState)+  {+    mClientState.update([&](ClientState& currentClientState) {+      if (clientState.timeline)+      {+        currentClientState.timeline = *clientState.timeline;+      }+      if (clientState.startStopState)+      {+        // Prevent updating client start stop state with an outdated start stop state+        *clientState.startStopState = detail::selectPreferredStartStopState(+          currentClientState.startStopState, *clientState.startStopState);+        currentClientState.startStopState = *clientState.startStopState;+      }+    });++    handleClientState(clientState);+    mHasPendingRtClientStates = false;+  }++  void joinSession(const Session& session)+  {+    const bool sessionIdChanged = mSessionId != session.sessionId;+    mSessionId = session.sessionId;++    // Prevent passing the state of the previous session to the new one.+    if (sessionIdChanged)+    {+      mRtClientStateSetter.processPendingClientStates();+      resetSessionStartStopState();+    }++    updateSessionTiming(session.timeline, session.measurement.xform);+    updateDiscovery();++    if (sessionIdChanged)+    {+      debug(mIo->log()) << "Joining session " << session.sessionId << " with tempo "+                        << session.timeline.tempo.bpm();+      mSessionPeerCounter();+    }+  }++  void resetState()+  {+    mNodeId = NodeId::random<Random>();+    mSessionId = mNodeId;++    const auto xform = detail::initXForm(mClock);+    const auto hostTime = -xform.intercept;+    // When creating the new timeline, make it continuous by finding+    // the beat on the old session timeline corresponding to the+    // current host time and mapping it to the new ghost time+    // representation of the current host time.+    const auto newTl = Timeline{mSessionState.timeline.tempo,+      mSessionState.timeline.toBeats(mSessionState.ghostXForm.hostToGhost(hostTime)),+      xform.hostToGhost(hostTime)};++    resetSessionStartStopState();++    updateSessionTiming(newTl, xform);+    updateDiscovery();++    mSessions.resetSession({mNodeId, newTl, {xform, hostTime}});+    mPeers.resetPeers();+  }++  struct SessionTimelineCallback+  {+    void operator()(SessionId id, Timeline timeline)+    {+      mController.handleTimelineFromSession(std::move(id), std::move(timeline));+    }++    Controller& mController;+  };++  struct RtClientStateSetter+  {+    using CallbackDispatcher =+      typename IoContext::template LockFreeCallbackDispatcher<std::function<void()>,+        std::chrono::milliseconds>;++    RtClientStateSetter(Controller& controller)+      : mController(controller)+      , mCallbackDispatcher(+          [this] { mController.mIo->async([this]() { processPendingClientStates(); }); },+          detail::kRtHandlerFallbackPeriod)+    {+    }++    void push(const IncomingClientState clientState)+    {+      if (clientState.timeline)+      {+        mTimelineBuffer.write(+          std::make_pair(clientState.timelineTimestamp, *clientState.timeline));+      }++      if (clientState.startStopState)+      {+        mStartStopStateBuffer.write(*clientState.startStopState);+      }++      if (clientState.timeline || clientState.startStopState)+      {+        mCallbackDispatcher.invoke();+      }+    }++    void processPendingClientStates()+    {+      const auto clientState = buildMergedPendingClientState();+      mController.handleRtClientState(clientState);+    }++  private:+    IncomingClientState buildMergedPendingClientState()+    {+      auto clientState = IncomingClientState{};+      if (auto tl = mTimelineBuffer.readNew())+      {+        clientState.timelineTimestamp = (*tl).first;+        clientState.timeline = OptionalTimeline{(*tl).second};+      }+      if (auto sss = mStartStopStateBuffer.readNew())+      {+        clientState.startStopState = sss;+      }+      return clientState;+    }++    Controller& mController;+    // Use separate TripleBuffers for the Timeline and the StartStopState so we read the+    // latest set value from either optional.+    TripleBuffer<std::pair<std::chrono::microseconds, Timeline>> mTimelineBuffer;+    TripleBuffer<ClientStartStopState> mStartStopStateBuffer;+    CallbackDispatcher mCallbackDispatcher;+  };++  struct SessionStartStopStateCallback+  {+    void operator()(SessionId sessionId, StartStopState startStopState)+    {+      mController.handleStartStopStateFromSession(sessionId, startStopState);+    }++    Controller& mController;+  };++  struct SessionPeerCounter+  {+    SessionPeerCounter(Controller& controller, PeerCountCallback callback)+      : mController(controller)+      , mCallback(std::move(callback))+      , mSessionPeerCount(0)+    {+    }++    void operator()()+    {+      const auto count =+        mController.mPeers.uniqueSessionPeerCount(mController.mSessionId);+      const auto oldCount = mSessionPeerCount.exchange(count);+      if (oldCount != count)+      {+        if (count == 0)+        {+          // When the count goes down to zero, completely reset the+          // state, effectively founding a new session+          mController.mIo->async([this] { mController.resetState(); });+        }+        mCallback(count);+      }+    }++    Controller& mController;+    PeerCountCallback mCallback;+    std::atomic<std::size_t> mSessionPeerCount;+  };++  struct MeasurePeer+  {+    template <typename Peer, typename Handler>+    void operator()(Peer peer, Handler handler)+    {+      using It = typename Discovery::ServicePeerGateways::GatewayMap::iterator;+      using ValueType = typename Discovery::ServicePeerGateways::GatewayMap::value_type;+      mController.mDiscovery.withGateways([peer, handler](It begin, const It end) {+        const auto addr = peer.second;+        const auto it = std::find_if(+          begin, end, [&addr](const ValueType& vt) { return vt.first == addr; });+        if (it != end)+        {+          it->second->measurePeer(std::move(peer.first), std::move(handler));+        }+        else+        {+          // invoke the handler with an empty result if we couldn't+          // find the peer's gateway+          handler(GhostXForm{});+        }+      });+    }++    Controller& mController;+  };++  struct JoinSessionCallback+  {+    void operator()(Session session)+    {+      mController.joinSession(std::move(session));+    }++    Controller& mController;+  };++  using IoType = typename util::Injected<IoContext>::type;++  using ControllerPeers = Peers<IoType&,+    std::reference_wrapper<SessionPeerCounter>,+    SessionTimelineCallback,+    SessionStartStopStateCallback>;++  using ControllerGateway =+    Gateway<typename ControllerPeers::GatewayObserver, Clock, IoType&>;+  using GatewayPtr = std::shared_ptr<ControllerGateway>;++  struct GatewayFactory+  {+    GatewayPtr operator()(std::pair<NodeState, GhostXForm> state,+      util::Injected<IoType&> io,+      const asio::ip::address& addr)+    {+      if (addr.is_v4())+      {+        return GatewayPtr{new ControllerGateway{std::move(io), addr.to_v4(),+          util::injectVal(makeGatewayObserver(mController.mPeers, addr)),+          std::move(state.first), std::move(state.second), mController.mClock}};+      }+      else+      {+        throw std::runtime_error("Could not create peer gateway on non-ipV4 address");+      }+    }++    Controller& mController;+  };++  struct UdpSendExceptionHandler+  {+    using Exception = discovery::UdpSendException;++    void operator()(const Exception exception)+    {+      mpController->mIo->async([this, exception] {+        mpController->mDiscovery.repairGateway(exception.interfaceAddr);+      });+    }++    Controller* mpController;+  };++  TempoCallback mTempoCallback;+  StartStopStateCallback mStartStopStateCallback;+  Clock mClock;+  NodeId mNodeId;+  SessionId mSessionId;++  mutable std::mutex mSessionStateGuard;+  SessionState mSessionState;++  ControllerClientState mClientState;+  bool mLastIsPlayingForStartStopStateCallback;++  mutable RtClientState mRtClientState;+  std::atomic<bool> mHasPendingRtClientStates;++  SessionPeerCounter mSessionPeerCounter;++  std::atomic<bool> mEnabled;++  std::atomic<bool> mStartStopSyncEnabled;++  util::Injected<IoContext> mIo;++  RtClientStateSetter mRtClientStateSetter;++  ControllerPeers mPeers;++  using ControllerSessions = Sessions<ControllerPeers&,+    MeasurePeer,+    JoinSessionCallback,+    typename util::Injected<IoContext>::type&,+    Clock>;+  ControllerSessions mSessions;++  using Discovery = discovery::Service<std::pair<NodeState, GhostXForm>,+    GatewayFactory,+    typename util::Injected<IoContext>::type&>;+  Discovery mDiscovery;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/Gateway.hpp view
@@ -0,0 +1,93 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/PeerGateway.hpp>+#include <ableton/link/MeasurementService.hpp>+#include <ableton/link/PeerState.hpp>++namespace ableton+{+namespace link+{++template <typename PeerObserver, typename Clock, typename IoContext>+class Gateway+{+public:+  Gateway(util::Injected<IoContext> io,+    asio::ip::address_v4 addr,+    util::Injected<PeerObserver> observer,+    NodeState nodeState,+    GhostXForm ghostXForm,+    Clock clock)+    : mIo(std::move(io))+    , mMeasurement(addr,+        nodeState.sessionId,+        std::move(ghostXForm),+        std::move(clock),+        util::injectRef(*mIo))+    , mPeerGateway(discovery::makeIpV4Gateway(util::injectRef(*mIo),+        std::move(addr),+        std::move(observer),+        PeerState{std::move(nodeState), mMeasurement.endpoint()}))+  {+  }++  Gateway(const Gateway& rhs) = delete;+  Gateway& operator=(const Gateway& rhs) = delete;++  Gateway(Gateway&& rhs)+    : mIo(std::move(rhs.mIo))+    , mMeasurement(std::move(rhs.mMeasurement))+    , mPeerGateway(std::move(rhs.mPeerGateway))+  {+  }++  Gateway& operator=(Gateway&& rhs)+  {+    mIo = std::move(rhs.mIo);+    mMeasurement = std::move(rhs.mMeasurement);+    mPeerGateway = std::move(rhs.mPeerGateway);+    return *this;+  }++  void updateNodeState(std::pair<NodeState, GhostXForm> state)+  {+    mMeasurement.updateNodeState(state.first.sessionId, state.second);+    mPeerGateway.updateState(PeerState{std::move(state.first), mMeasurement.endpoint()});+  }++  template <typename Handler>+  void measurePeer(const PeerState& peer, Handler handler)+  {+    mMeasurement.measurePeer(peer, std::move(handler));+  }++private:+  util::Injected<IoContext> mIo;+  MeasurementService<Clock, typename util::Injected<IoContext>::type&> mMeasurement;+  discovery::+    IpV4Gateway<PeerObserver, PeerState, typename util::Injected<IoContext>::type&>+      mPeerGateway;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/GhostXForm.hpp view
@@ -0,0 +1,61 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <chrono>+#include <cmath>++namespace ableton+{+namespace link+{++using std::chrono::microseconds;++struct GhostXForm+{+  microseconds hostToGhost(const microseconds hostTime) const+  {+    return microseconds{llround(slope * static_cast<double>(hostTime.count()))}+           + intercept;+  }++  microseconds ghostToHost(const microseconds ghostTime) const+  {+    return microseconds{+      llround(static_cast<double>((ghostTime - intercept).count()) / slope)};+  }++  friend bool operator==(const GhostXForm lhs, const GhostXForm rhs)+  {+    return lhs.slope == rhs.slope && lhs.intercept == rhs.intercept;+  }++  friend bool operator!=(const GhostXForm lhs, const GhostXForm rhs)+  {+    return !(lhs == rhs);+  }++  double slope;+  microseconds intercept;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/HostTimeFilter.hpp view
@@ -0,0 +1,86 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/LinearRegression.hpp>+#include <chrono>+#include <cmath>+#include <utility>+#include <vector>++namespace ableton+{+namespace link+{++template <typename Clock, typename NumberType, std::size_t kNumPoints = 512>+class BasicHostTimeFilter+{+  using Points = std::vector<std::pair<NumberType, NumberType>>;+  using PointIt = typename Points::iterator;++public:+  BasicHostTimeFilter()+    : mIndex(0)+  {+    mPoints.reserve(kNumPoints);+  }++  ~BasicHostTimeFilter() = default;++  void reset()+  {+    mIndex = 0;+    mPoints.clear();+  }++  std::chrono::microseconds sampleTimeToHostTime(const NumberType sampleTime)+  {+    const auto micros = static_cast<NumberType>(mHostTimeSampler.micros().count());+    const auto point = std::make_pair(sampleTime, micros);++    if (mPoints.size() < kNumPoints)+    {+      mPoints.push_back(point);+    }+    else+    {+      mPoints[mIndex] = point;+    }+    mIndex = (mIndex + 1) % kNumPoints;++    const auto result = linearRegression(mPoints.begin(), mPoints.end());++    const auto hostTime = (result.first * sampleTime) + result.second;++    return std::chrono::microseconds(llround(hostTime));+  }++private:+  std::size_t mIndex;+  Points mPoints;+  Clock mHostTimeSampler;+};++template <typename Clock>+using HostTimeFilter = BasicHostTimeFilter<Clock, double, 512>;++} // namespace link+} // namespace ableton
+ link/include/ableton/link/LinearRegression.hpp view
@@ -0,0 +1,61 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <cassert>+#include <iterator>+#include <utility>++namespace ableton+{+namespace link+{++template <typename It>+typename std::iterator_traits<It>::value_type linearRegression(It begin, It end)+{+  using NumberType =+    typename std::tuple_element<0, typename std::iterator_traits<It>::value_type>::type;++  NumberType sumX = 0.0;+  NumberType sumXX = 0.0;+  NumberType sumXY = 0.0;+  NumberType sumY = 0.0;+  for (auto i = begin; i != end; ++i)+  {+    sumX += i->first;+    sumXX += i->first * i->first;+    sumXY += i->first * i->second;+    sumY += i->second;+  }++  const NumberType numPoints = static_cast<NumberType>(distance(begin, end));+  assert(numPoints > 0);+  const NumberType denominator = numPoints * sumXX - sumX * sumX;+  const NumberType slope = denominator == NumberType{0}+                             ? NumberType{0}+                             : (numPoints * sumXY - sumX * sumY) / denominator;+  const NumberType intercept = (sumY - slope * sumX) / numPoints;++  return std::make_pair(slope, intercept);+}++} // namespace link+} // namespace ableton
+ link/include/ableton/link/Measurement.hpp view
@@ -0,0 +1,250 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/Payload.hpp>+#include <ableton/link/PayloadEntries.hpp>+#include <ableton/link/PeerState.hpp>+#include <ableton/link/SessionId.hpp>+#include <ableton/link/v1/Messages.hpp>+#include <ableton/util/Injected.hpp>+#include <ableton/util/SafeAsyncHandler.hpp>+#include <chrono>+#include <memory>++namespace ableton+{+namespace link+{++template <typename Clock, typename IoContext>+struct Measurement+{+  using Callback = std::function<void(std::vector<double>&)>;+  using Micros = std::chrono::microseconds;++  static const std::size_t kNumberDataPoints = 100;+  static const std::size_t kNumberMeasurements = 5;++  Measurement(const PeerState& state,+    Callback callback,+    asio::ip::address_v4 address,+    Clock clock,+    util::Injected<IoContext> io)+    : mIo(std::move(io))+    , mpImpl(std::make_shared<Impl>(+        std::move(state), std::move(callback), std::move(address), std::move(clock), mIo))+  {+    mpImpl->listen();+  }++  Measurement(const Measurement&) = delete;+  Measurement& operator=(Measurement&) = delete;+  Measurement(const Measurement&&) = delete;+  Measurement& operator=(Measurement&&) = delete;++  struct Impl : std::enable_shared_from_this<Impl>+  {+    using Socket =+      typename util::Injected<IoContext>::type::template Socket<v1::kMaxMessageSize>;+    using Timer = typename util::Injected<IoContext>::type::Timer;+    using Log = typename util::Injected<IoContext>::type::Log;++    Impl(const PeerState& state,+      Callback callback,+      asio::ip::address_v4 address,+      Clock clock,+      util::Injected<IoContext> io)+      : mSocket(io->template openUnicastSocket<v1::kMaxMessageSize>(address))+      , mSessionId(state.nodeState.sessionId)+      , mEndpoint(state.endpoint)+      , mCallback(std::move(callback))+      , mClock(std::move(clock))+      , mTimer(io->makeTimer())+      , mMeasurementsStarted(0)+      , mLog(channel(io->log(), "Measurement on gateway@" + address.to_string()))+      , mSuccess(false)+    {+      const auto ht = HostTime{mClock.micros()};+      sendPing(mEndpoint, discovery::makePayload(ht));+      resetTimer();+    }++    void resetTimer()+    {+      mTimer.cancel();+      mTimer.expires_from_now(std::chrono::milliseconds(50));+      mTimer.async_wait([this](const typename Timer::ErrorCode e) {+        if (!e)+        {+          if (mMeasurementsStarted < kNumberMeasurements)+          {+            const auto ht = HostTime{mClock.micros()};+            sendPing(mEndpoint, discovery::makePayload(ht));+            ++mMeasurementsStarted;+            resetTimer();+          }+          else+          {+            fail();+          }+        }+      });+    }++    void listen()+    {+      mSocket.receive(util::makeAsyncSafe(this->shared_from_this()));+    }++    // Operator to handle incoming messages on the interface+    template <typename It>+    void operator()(+      const asio::ip::udp::endpoint& from, const It messageBegin, const It messageEnd)+    {+      using namespace std;+      const auto result = v1::parseMessageHeader(messageBegin, messageEnd);+      const auto& header = result.first;+      const auto payloadBegin = result.second;++      if (header.messageType == v1::kPong)+      {+        debug(mLog) << "Received Pong message from " << from;++        // parse for all entries+        SessionId sessionId{};+        std::chrono::microseconds ghostTime{0};+        std::chrono::microseconds prevGHostTime{0};+        std::chrono::microseconds prevHostTime{0};++        try+        {+          discovery::parsePayload<SessionMembership, GHostTime, PrevGHostTime, HostTime>(+            payloadBegin, messageEnd,+            [&sessionId](const SessionMembership& sms) { sessionId = sms.sessionId; },+            [&ghostTime](GHostTime gt) { ghostTime = std::move(gt.time); },+            [&prevGHostTime](PrevGHostTime gt) { prevGHostTime = std::move(gt.time); },+            [&prevHostTime](HostTime ht) { prevHostTime = std::move(ht.time); });+        }+        catch (const std::runtime_error& err)+        {+          warning(mLog) << "Failed parsing payload, caught exception: " << err.what();+          listen();+          return;+        }++        if (mSessionId == sessionId)+        {+          const auto hostTime = mClock.micros();++          const auto payload =+            discovery::makePayload(HostTime{hostTime}, PrevGHostTime{ghostTime});++          sendPing(from, payload);+          listen();+++          if (ghostTime != Micros{0} && prevHostTime != Micros{0})+          {+            mData.push_back(+              static_cast<double>(ghostTime.count())+              - (static_cast<double>((hostTime + prevHostTime).count()) * 0.5));++            if (prevGHostTime != Micros{0})+            {+              mData.push_back(+                (static_cast<double>((ghostTime + prevGHostTime).count()) * 0.5)+                - static_cast<double>(prevHostTime.count()));+            }+          }++          if (mData.size() > kNumberDataPoints)+          {+            finish();+          }+          else+          {+            resetTimer();+          }+        }+        else+        {+          fail();+        }+      }+      else+      {+        debug(mLog) << "Received invalid message from " << from;+        listen();+      }+    }++    template <typename Payload>+    void sendPing(asio::ip::udp::endpoint to, const Payload& payload)+    {+      v1::MessageBuffer buffer;+      const auto msgBegin = std::begin(buffer);+      const auto msgEnd = v1::pingMessage(payload, msgBegin);+      const auto numBytes = static_cast<size_t>(std::distance(msgBegin, msgEnd));++      try+      {+        mSocket.send(buffer.data(), numBytes, to);+      }+      catch (const std::runtime_error& err)+      {+        info(mLog) << "Failed to send Ping to " << to.address().to_string() << ": "+                   << err.what();+      }+    }++    void finish()+    {+      mTimer.cancel();+      mSuccess = true;+      debug(mLog) << "Measuring " << mEndpoint << " done.";+      mCallback(mData);+    }++    void fail()+    {+      mData.clear();+      debug(mLog) << "Measuring " << mEndpoint << " failed.";+      mCallback(mData);+    }++    Socket mSocket;+    SessionId mSessionId;+    asio::ip::udp::endpoint mEndpoint;+    std::vector<double> mData;+    Callback mCallback;+    Clock mClock;+    Timer mTimer;+    std::size_t mMeasurementsStarted;+    Log mLog;+    bool mSuccess;+  };++  util::Injected<IoContext> mIo;+  std::shared_ptr<Impl> mpImpl;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/MeasurementEndpointV4.hpp view
@@ -0,0 +1,69 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/NetworkByteStreamSerializable.hpp>+#include <ableton/platforms/asio/AsioWrapper.hpp>++namespace ableton+{+namespace link+{++struct MeasurementEndpointV4+{+  static const std::int32_t key = 'mep4';+  static_assert(key == 0x6d657034, "Unexpected byte order");++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const MeasurementEndpointV4 mep)+  {+    return discovery::sizeInByteStream(+             static_cast<std::uint32_t>(mep.ep.address().to_v4().to_ulong()))+           + discovery::sizeInByteStream(mep.ep.port());+  }++  template <typename It>+  friend It toNetworkByteStream(const MeasurementEndpointV4 mep, It out)+  {+    return discovery::toNetworkByteStream(mep.ep.port(),+      discovery::toNetworkByteStream(+        static_cast<std::uint32_t>(mep.ep.address().to_v4().to_ulong()), std::move(out)));+  }++  template <typename It>+  static std::pair<MeasurementEndpointV4, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto addrRes =+      discovery::Deserialize<std::uint32_t>::fromNetworkByteStream(std::move(begin), end);+    auto portRes = discovery::Deserialize<std::uint16_t>::fromNetworkByteStream(+      std::move(addrRes.second), end);+    return make_pair(+      MeasurementEndpointV4{+        {asio::ip::address_v4{std::move(addrRes.first)}, std::move(portRes.first)}},+      std::move(portRes.second));+  }++  asio::ip::udp::endpoint ep;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/MeasurementService.hpp view
@@ -0,0 +1,144 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/GhostXForm.hpp>+#include <ableton/link/LinearRegression.hpp>+#include <ableton/link/Measurement.hpp>+#include <ableton/link/Median.hpp>+#include <ableton/link/PeerState.hpp>+#include <ableton/link/PingResponder.hpp>+#include <ableton/link/SessionId.hpp>+#include <ableton/link/v1/Messages.hpp>+#include <map>+#include <memory>++namespace ableton+{+namespace link+{++template <typename Clock, typename IoContext>+class MeasurementService+{+public:+  using IoType = util::Injected<IoContext>;+  using MeasurementInstance = Measurement<Clock, IoContext>;++  MeasurementService(asio::ip::address_v4 address,+    SessionId sessionId,+    GhostXForm ghostXForm,+    Clock clock,+    IoType io)+    : mClock(std::move(clock))+    , mIo(std::move(io))+    , mPingResponder(std::move(address),+        std::move(sessionId),+        std::move(ghostXForm),+        mClock,+        util::injectRef(*mIo))+  {+  }++  MeasurementService(const MeasurementService&) = delete;+  MeasurementService(MeasurementService&&) = delete;++  void updateNodeState(const SessionId& sessionId, const GhostXForm& xform)+  {+    mPingResponder.updateNodeState(sessionId, xform);+  }++  asio::ip::udp::endpoint endpoint() const+  {+    return mPingResponder.endpoint();+  }++  // Measure the peer and invoke the handler with a GhostXForm+  template <typename Handler>+  void measurePeer(const PeerState& state, const Handler handler)+  {+    using namespace std;++    const auto nodeId = state.nodeState.nodeId;+    auto addr = mPingResponder.endpoint().address().to_v4();+    auto callback = CompletionCallback<Handler>{*this, nodeId, handler};++    try+    {+      mMeasurementMap[nodeId] =+        std::unique_ptr<MeasurementInstance>(new MeasurementInstance{+          state, std::move(callback), std::move(addr), mClock, mIo});+    }+    catch (const runtime_error& err)+    {+      info(mIo->log()) << "gateway@" + addr.to_string()+                       << " Failed to measure. Reason: " << err.what();+      handler(GhostXForm{});+    }+  }++private:+  template <typename Handler>+  struct CompletionCallback+  {+    void operator()(std::vector<double>& data)+    {+      using namespace std;+      using std::chrono::microseconds;++      // Post this to the measurement service's IoContext so that we+      // don't delete the measurement object in its stack. Capture all+      // needed data separately from this, since this object may be+      // gone by the time the block gets executed.+      auto nodeId = mNodeId;+      auto handler = mHandler;+      auto& measurementMap = mMeasurementService.mMeasurementMap;+      const auto it = measurementMap.find(nodeId);+      if (it != measurementMap.end())+      {+        if (data.empty())+        {+          handler(GhostXForm{});+        }+        else+        {+          handler(GhostXForm{1, microseconds(llround(median(data.begin(), data.end())))});+        }+        measurementMap.erase(it);+      }+    }++    MeasurementService& mMeasurementService;+    NodeId mNodeId;+    Handler mHandler;+  };++  // Make sure the measurement map outlives the IoContext so that the rest of+  // the members are guaranteed to be valid when any final handlers+  // are begin run.+  using MeasurementMap = std::map<NodeId, std::unique_ptr<MeasurementInstance>>;+  MeasurementMap mMeasurementMap;+  Clock mClock;+  IoType mIo;+  PingResponder<Clock, IoContext> mPingResponder;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/Median.hpp view
@@ -0,0 +1,50 @@+/* Copyright 2021, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <algorithm>+#include <cassert>+#include <vector>++namespace ableton+{+namespace link+{++template <typename It>+double median(It begin, It end)+{+  const auto n = std::distance(begin, end);+  assert(n > 2);+  if (n % 2 == 0)+  {+    std::nth_element(begin, begin + n / 2, end);+    std::nth_element(begin, begin + (n - 1) / 2, end);+    return (*(begin + (n / 2)) + *(begin + (n - 1) / 2)) / 2.0;+  }+  else+  {+    std::nth_element(begin, begin + n / 2, end);+    return *(begin + (n / 2));+  }+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/NodeId.hpp view
@@ -0,0 +1,78 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/NetworkByteStreamSerializable.hpp>+#include <algorithm>+#include <array>+#include <cstdint>+#include <string>++namespace ableton+{+namespace link+{++using NodeIdArray = std::array<std::uint8_t, 8>;++struct NodeId : NodeIdArray+{+  NodeId() = default;++  NodeId(NodeIdArray rhs)+    : NodeIdArray(std::move(rhs))+  {+  }++  template <typename Random>+  static NodeId random()+  {+    using namespace std;+    NodeId nodeId;++    Random random;+    generate(nodeId.begin(), nodeId.end(), [&] { return random(); });++    return nodeId;+  }++  friend std::ostream& operator<<(std::ostream& stream, const NodeId& id)+  {+    return stream << std::string{id.cbegin(), id.cend()};+  }++  template <typename It>+  friend It toNetworkByteStream(const NodeId& nodeId, It out)+  {+    return discovery::toNetworkByteStream(nodeId, std::move(out));+  }++  template <typename It>+  static std::pair<NodeId, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto result = discovery::Deserialize<NodeIdArray>::fromNetworkByteStream(+      std::move(begin), std::move(end));+    return make_pair(NodeId(std::move(result.first)), std::move(result.second));+  }+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/NodeState.hpp view
@@ -0,0 +1,77 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/Payload.hpp>+#include <ableton/link/NodeId.hpp>+#include <ableton/link/SessionId.hpp>+#include <ableton/link/StartStopState.hpp>+#include <ableton/link/Timeline.hpp>++namespace ableton+{+namespace link+{++struct NodeState+{+  using Payload =+    decltype(discovery::makePayload(Timeline{}, SessionMembership{}, StartStopState{}));++  NodeId ident() const+  {+    return nodeId;+  }++  friend bool operator==(const NodeState& lhs, const NodeState& rhs)+  {+    return std::tie(lhs.nodeId, lhs.sessionId, lhs.timeline, lhs.startStopState)+           == std::tie(rhs.nodeId, rhs.sessionId, rhs.timeline, rhs.startStopState);+  }++  friend Payload toPayload(const NodeState& state)+  {+    return discovery::makePayload(+      state.timeline, SessionMembership{state.sessionId}, state.startStopState);+  }++  template <typename It>+  static NodeState fromPayload(NodeId nodeId, It begin, It end)+  {+    using namespace std;+    auto nodeState = NodeState{std::move(nodeId), {}, {}, {}};+    discovery::parsePayload<Timeline, SessionMembership, StartStopState>(std::move(begin),+      std::move(end), [&nodeState](Timeline tl) { nodeState.timeline = std::move(tl); },+      [&nodeState](SessionMembership membership) {+        nodeState.sessionId = std::move(membership.sessionId);+      },+      [&nodeState](+        StartStopState ststst) { nodeState.startStopState = std::move(ststst); });+    return nodeState;+  }++  NodeId nodeId;+  SessionId sessionId;+  Timeline timeline;+  StartStopState startStopState;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/Optional.hpp view
@@ -0,0 +1,97 @@+/* Copyright 2017, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <cassert>+#include <utility>++namespace ableton+{+namespace link+{++// Subset of the C++ 17 std::optional API. T has to be default constructible.+template <typename T>+struct Optional+{+  Optional()+    : mHasValue(false)+  {+  }++  explicit Optional(T value)+    : mValue(std::move(value))+    , mHasValue(true)+  {+  }++  Optional(const Optional&) = default;++  Optional(Optional&& other)+    : mValue(std::move(other.mValue))+    , mHasValue(other.mHasValue)+  {+  }++  Optional& operator=(const Optional&) = default;++  Optional& operator=(Optional&& other)+  {+    mValue = std::move(other.mValue);+    mHasValue = other.mHasValue;+    return *this;+  }++  explicit operator bool() const+  {+    return mHasValue;+  }++  const T& operator*() const+  {+    assert(mHasValue);+    return mValue;+  }++  T& operator*()+  {+    assert(mHasValue);+    return mValue;+  }++  const T* operator->() const+  {+    assert(mHasValue);+    return &mValue;+  }++  T* operator->()+  {+    assert(mHasValue);+    return &mValue;+  }++private:+  T mValue;+  bool mHasValue;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/PayloadEntries.hpp view
@@ -0,0 +1,140 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/NetworkByteStreamSerializable.hpp>+#include <cmath>+#include <cstdint>++namespace ableton+{+namespace link+{++struct HostTime+{+  static const std::int32_t key = '__ht';+  static_assert(key == 0x5f5f6874, "Unexpected byte order");++  HostTime() = default;++  HostTime(const std::chrono::microseconds tm)+    : time(tm)+  {+  }++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const HostTime& sht)+  {+    return discovery::sizeInByteStream(std::move(sht.time));+  }++  template <typename It>+  friend It toNetworkByteStream(const HostTime& sht, It out)+  {+    return discovery::toNetworkByteStream(std::move(sht.time), std::move(out));+  }++  template <typename It>+  static std::pair<HostTime, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto result = discovery::Deserialize<chrono::microseconds>::fromNetworkByteStream(+      std::move(begin), std::move(end));+    return make_pair(HostTime{std::move(result.first)}, std::move(result.second));+  }++  std::chrono::microseconds time;+};++struct GHostTime+{+  static const std::int32_t key = '__gt';+  static_assert(key == 0x5f5f6774, "Unexpected byte order");++  GHostTime() = default;++  GHostTime(const std::chrono::microseconds tm)+    : time(tm)+  {+  }++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const GHostTime& dgt)+  {+    return discovery::sizeInByteStream(std::move(dgt.time));+  }++  template <typename It>+  friend It toNetworkByteStream(const GHostTime& dgt, It out)+  {+    return discovery::toNetworkByteStream(std::move(dgt.time), std::move(out));+  }++  template <typename It>+  static std::pair<GHostTime, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto result = discovery::Deserialize<chrono::microseconds>::fromNetworkByteStream(+      std::move(begin), std::move(end));+    return make_pair(GHostTime{std::move(result.first)}, std::move(result.second));+  }++  std::chrono::microseconds time;+};++struct PrevGHostTime+{+  static const std::int32_t key = '_pgt';+  static_assert(key == 0x5f706774, "Unexpected byte order");++  PrevGHostTime() = default;++  PrevGHostTime(const std::chrono::microseconds tm)+    : time(tm)+  {+  }++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const PrevGHostTime& dgt)+  {+    return discovery::sizeInByteStream(std::move(dgt.time));+  }++  template <typename It>+  friend It toNetworkByteStream(const PrevGHostTime& pdgt, It out)+  {+    return discovery::toNetworkByteStream(std::move(pdgt.time), std::move(out));+  }++  template <typename It>+  static std::pair<PrevGHostTime, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto result = discovery::Deserialize<chrono::microseconds>::fromNetworkByteStream(+      std::move(begin), std::move(end));+    return make_pair(PrevGHostTime{std::move(result.first)}, std::move(result.second));+  }++  std::chrono::microseconds time;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/PeerState.hpp view
@@ -0,0 +1,90 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/Payload.hpp>+#include <ableton/link/MeasurementEndpointV4.hpp>+#include <ableton/link/NodeState.hpp>++namespace ableton+{+namespace link+{++// A state type for peers. PeerState stores the normal NodeState plus+// additional information (the remote endpoint at which to find its+// ping/pong measurement server).++struct PeerState+{+  using IdType = NodeId;++  IdType ident() const+  {+    return nodeState.ident();+  }++  SessionId sessionId() const+  {+    return nodeState.sessionId;+  }++  Timeline timeline() const+  {+    return nodeState.timeline;+  }++  StartStopState startStopState() const+  {+    return nodeState.startStopState;+  }++  friend bool operator==(const PeerState& lhs, const PeerState& rhs)+  {+    return lhs.nodeState == rhs.nodeState && lhs.endpoint == rhs.endpoint;+  }++  friend auto toPayload(const PeerState& state)+    -> decltype(std::declval<NodeState::Payload>()+                + discovery::makePayload(MeasurementEndpointV4{{}}))+  {+    return toPayload(state.nodeState)+           + discovery::makePayload(MeasurementEndpointV4{state.endpoint});+  }++  template <typename It>+  static PeerState fromPayload(NodeId id, It begin, It end)+  {+    using namespace std;+    auto peerState = PeerState{NodeState::fromPayload(std::move(id), begin, end), {}};++    discovery::parsePayload<MeasurementEndpointV4>(+      std::move(begin), std::move(end), [&peerState](MeasurementEndpointV4 me4) {+        peerState.endpoint = std::move(me4.ep);+      });+    return peerState;+  }++  NodeState nodeState;+  asio::ip::udp::endpoint endpoint;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/Peers.hpp view
@@ -0,0 +1,368 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/PeerState.hpp>+#include <ableton/util/Injected.hpp>+#include <cassert>++namespace ableton+{+namespace link+{++// SessionMembershipCallback is invoked when any change to session+// membership occurs (when any peer joins or leaves a session)+//+// SessionTimelineCallback is invoked with a session id and a timeline+// whenever a new combination of these values is seen+//+// SessionStartStopStateCallback is invoked with a session id and a startStopState+// whenever a new combination of these values is seen++template <typename IoContext,+  typename SessionMembershipCallback,+  typename SessionTimelineCallback,+  typename SessionStartStopStateCallback>+class Peers+{+  // non-movable private implementation type+  struct Impl;++public:+  using Peer = std::pair<PeerState, asio::ip::address>;++  Peers(util::Injected<IoContext> io,+    SessionMembershipCallback membership,+    SessionTimelineCallback timeline,+    SessionStartStopStateCallback startStop)+    : mpImpl(std::make_shared<Impl>(+        std::move(io), std::move(membership), std::move(timeline), std::move(startStop)))+  {+  }++  // The set of peers for a given session, ordered by (peerId, addr).+  // The result will possibly contain multiple entries for the same+  // peer if it is visible through multiple gateways.+  std::vector<Peer> sessionPeers(const SessionId& sid) const+  {+    using namespace std;+    vector<Peer> result;+    auto& peerVec = mpImpl->mPeers;+    copy_if(begin(peerVec), end(peerVec), back_inserter(result), SessionMemberPred{sid});+    return result;+  }++  // Number of individual for a given session.+  std::size_t uniqueSessionPeerCount(const SessionId& sid) const+  {+    using namespace std;+    auto peerVec = sessionPeers(sid);+    auto last = unique(begin(peerVec), end(peerVec),+      [](const Peer& a, const Peer& b) { return a.first.ident() == b.first.ident(); });+    return static_cast<size_t>(distance(begin(peerVec), last));+  }++  void setSessionTimeline(const SessionId& sid, const Timeline& tl)+  {+    // Set the cached timeline for all peers to a new client-specified+    // timeline. When we make a timeline change, we do so+    // optimistically and clients assume that all peers in a session+    // have adopted the newly specified timeline. We must represent+    // this in our cache or else we risk failing to notify about a+    // higher-priority peer timeline that was already seen.+    for (auto& peer : mpImpl->mPeers)+    {+      if (peer.first.sessionId() == sid)+      {+        peer.first.nodeState.timeline = tl;+      }+    }+  }++  // Purge all cached peers that are members of the given session+  void forgetSession(const SessionId& sid)+  {+    using namespace std;+    auto& peerVec = mpImpl->mPeers;+    peerVec.erase(+      remove_if(begin(peerVec), end(peerVec), SessionMemberPred{sid}), end(peerVec));+  }++  void resetPeers()+  {+    mpImpl->mPeers.clear();+  }++  // Observer type that monitors peer discovery on a particular+  // gateway and relays the information to a Peers instance.+  // Models the PeerObserver concept from the discovery module.+  struct GatewayObserver+  {+    using GatewayObserverNodeState = PeerState;+    using GatewayObserverNodeId = NodeId;++    GatewayObserver(std::shared_ptr<Impl> pImpl, asio::ip::address addr)+      : mpImpl(std::move(pImpl))+      , mAddr(std::move(addr))+    {+    }+    GatewayObserver(const GatewayObserver&) = delete;++    GatewayObserver(GatewayObserver&& rhs)+      : mpImpl(std::move(rhs.mpImpl))+      , mAddr(std::move(rhs.mAddr))+    {+    }++    ~GatewayObserver()+    {+      // Check to handle the moved from case+      if (mpImpl)+      {+        mpImpl->gatewayClosed(mAddr);+      }+    }++    // model the PeerObserver concept from discovery+    friend void sawPeer(GatewayObserver& observer, const PeerState& state)+    {+      auto pImpl = observer.mpImpl;+      auto addr = observer.mAddr;+      assert(pImpl);+      pImpl->sawPeerOnGateway(std::move(state), std::move(addr));+    }++    friend void peerLeft(GatewayObserver& observer, const NodeId& id)+    {+      auto pImpl = observer.mpImpl;+      auto addr = observer.mAddr;+      pImpl->peerLeftGateway(std::move(id), std::move(addr));+    }++    friend void peerTimedOut(GatewayObserver& observer, const NodeId& id)+    {+      auto pImpl = observer.mpImpl;+      auto addr = observer.mAddr;+      pImpl->peerLeftGateway(std::move(id), std::move(addr));+    }++    std::shared_ptr<Impl> mpImpl;+    asio::ip::address mAddr;+  };++  // Factory function for the gateway observer+  friend GatewayObserver makeGatewayObserver(Peers& peers, asio::ip::address addr)+  {+    return GatewayObserver{peers.mpImpl, std::move(addr)};+  }++private:+  struct Impl+  {+    Impl(util::Injected<IoContext> io,+      SessionMembershipCallback membership,+      SessionTimelineCallback timeline,+      SessionStartStopStateCallback startStop)+      : mIo(std::move(io))+      , mSessionMembershipCallback(std::move(membership))+      , mSessionTimelineCallback(std::move(timeline))+      , mSessionStartStopStateCallback(std::move(startStop))+    {+    }++    void sawPeerOnGateway(PeerState peerState, asio::ip::address gatewayAddr)+    {+      using namespace std;++      const auto peerSession = peerState.sessionId();+      const auto peerTimeline = peerState.timeline();+      const auto peerStartStopState = peerState.startStopState();++      bool isNewSessionTimeline = !sessionTimelineExists(peerSession, peerTimeline);+      bool isNewSessionStartStopState =+        !sessionStartStopStateExists(peerSession, peerStartStopState);++      auto peer = make_pair(std::move(peerState), std::move(gatewayAddr));+      const auto idRange = equal_range(begin(mPeers), end(mPeers), peer, PeerIdComp{});++      bool didSessionMembershipChange = false;+      if (idRange.first == idRange.second)+      {+        // This peer is not currently known on any gateway+        didSessionMembershipChange = true;+        mPeers.insert(std::move(idRange.first), std::move(peer));+      }+      else+      {+        // We've seen this peer before... does it have a new session?+        didSessionMembershipChange =+          all_of(idRange.first, idRange.second, [&peerSession](const Peer& test) {+            return test.first.sessionId() != peerSession;+          });++        // was it on this gateway?+        const auto addrRange =+          equal_range(idRange.first, idRange.second, peer, AddrComp{});++        if (addrRange.first == addrRange.second)+        {+          // First time on this gateway, add it+          mPeers.insert(std::move(addrRange.first), std::move(peer));+        }+        else+        {+          // We have an entry for this peer on this gateway, update it+          *addrRange.first = std::move(peer);+        }+      }++      // Invoke callbacks outside the critical section+      if (isNewSessionTimeline)+      {+        mSessionTimelineCallback(peerSession, peerTimeline);+      }++      // Pass the start stop state to the Controller after it processed the timeline.+      // A new timeline can cause a session Id change which will prevent processing the+      // new start stop state. By handling the start stop state after the timeline we+      // assure that the start stop state is processed with the correct session Id.+      if (isNewSessionStartStopState)+      {+        mSessionStartStopStateCallback(peerSession, peerStartStopState);+      }++      if (didSessionMembershipChange)+      {+        mSessionMembershipCallback();+      }+    }++    void peerLeftGateway(const NodeId& nodeId, const asio::ip::address& gatewayAddr)+    {+      using namespace std;++      auto it = find_if(begin(mPeers), end(mPeers), [&](const Peer& peer) {+        return peer.first.ident() == nodeId && peer.second == gatewayAddr;+      });++      bool didSessionMembershipChange = false;+      if (it != end(mPeers))+      {+        mPeers.erase(std::move(it));+        didSessionMembershipChange = true;+      }++      if (didSessionMembershipChange)+      {+        mSessionMembershipCallback();+      }+    }++    void gatewayClosed(const asio::ip::address& gatewayAddr)+    {+      using namespace std;++      mPeers.erase(+        remove_if(begin(mPeers), end(mPeers),+          [&gatewayAddr](const Peer& peer) { return peer.second == gatewayAddr; }),+        end(mPeers));++      mSessionMembershipCallback();+    }++    template <typename Predicate>+    bool hasPeerWith(const SessionId& sessionId, Predicate predicate)+    {+      using namespace std;+      return find_if(begin(mPeers), end(mPeers), [&](const Peer& peer) {+        return peer.first.sessionId() == sessionId && predicate(peer.first);+      }) != end(mPeers);+    }++    bool sessionTimelineExists(const SessionId& session, const Timeline& timeline)+    {+      return hasPeerWith(session,+        [&](const PeerState& peerState) { return peerState.timeline() == timeline; });+    }++    bool sessionStartStopStateExists(+      const SessionId& sessionId, const StartStopState& startStopState)+    {+      return hasPeerWith(sessionId, [&](const PeerState& peerState) {+        return peerState.startStopState() == startStopState;+      });+    }++    struct PeerIdComp+    {+      bool operator()(const Peer& lhs, const Peer& rhs) const+      {+        return lhs.first.ident() < rhs.first.ident();+      }+    };++    struct AddrComp+    {+      bool operator()(const Peer& lhs, const Peer& rhs) const+      {+        return lhs.second < rhs.second;+      }+    };++    util::Injected<IoContext> mIo;+    SessionMembershipCallback mSessionMembershipCallback;+    SessionTimelineCallback mSessionTimelineCallback;+    SessionStartStopStateCallback mSessionStartStopStateCallback;+    std::vector<Peer> mPeers; // sorted by peerId, unique by (peerId, addr)+  };++  struct SessionMemberPred+  {+    bool operator()(const Peer& peer) const+    {+      return peer.first.sessionId() == sid;+    }++    const SessionId& sid;+  };++  std::shared_ptr<Impl> mpImpl;+};++template <typename Io,+  typename SessionMembershipCallback,+  typename SessionTimelineCallback,+  typename SessionStartStopStateCallback>+Peers<Io,+  SessionMembershipCallback,+  SessionTimelineCallback,+  SessionStartStopStateCallback>+makePeers(util::Injected<Io> io,+  SessionMembershipCallback membershipCallback,+  SessionTimelineCallback timelineCallback,+  SessionStartStopStateCallback startStopStateCallback)+{+  return {std::move(io), std::move(membershipCallback), std::move(timelineCallback),+    std::move(startStopStateCallback)};+}++} // namespace link+} // namespace ableton
+ link/include/ableton/link/Phase.hpp view
@@ -0,0 +1,100 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/Beats.hpp>+#include <ableton/link/Timeline.hpp>+#include <chrono>++namespace ableton+{+namespace link+{++// Returns a value in the range [0,quantum) corresponding to beats %+// quantum except that negative beat values are handled correctly.+// If the given quantum is zero, returns zero.+inline Beats phase(const Beats beats, const Beats quantum)+{+  if (quantum == Beats{INT64_C(0)})+  {+    return Beats{INT64_C(0)};+  }+  else+  {+    // Handle negative beat values by doing the computation relative to an+    // origin that is on the nearest quantum boundary less than -(abs(x))+    const auto quantumMicros = quantum.microBeats();+    const auto quantumBins = (llabs(beats.microBeats()) + quantumMicros) / quantumMicros;+    const std::int64_t quantumBeats{quantumBins * quantumMicros};+    return (beats + Beats{quantumBeats}) % quantum;+  }+}++// Return the least value greater than x that matches the phase of+// target with respect to the given quantum. If the given quantum+// quantum is 0, x is returned.+inline Beats nextPhaseMatch(const Beats x, const Beats target, const Beats quantum)+{+  const auto desiredPhase = phase(target, quantum);+  const auto xPhase = phase(x, quantum);+  const auto phaseDiff = (desiredPhase - xPhase + quantum) % quantum;+  return x + phaseDiff;+}++// Return the closest value to x that matches the phase of the target+// with respect to the given quantum. The result deviates from x by at+// most quantum/2, but may be less than x.+inline Beats closestPhaseMatch(const Beats x, const Beats target, const Beats quantum)+{+  return nextPhaseMatch(x - Beats{0.5 * quantum.floating()}, target, quantum);+}++// Interprets the given timeline as encoding a quantum boundary at its+// origin. Given such a timeline, returns a phase-encoded beat value+// relative to the given quantum that corresponds to the given+// time. The phase of the resulting beat value can be calculated with+// phase(beats, quantum). The result will deviate by up to +-+// (quantum/2) beats compared to the result of tl.toBeats(time).+inline Beats toPhaseEncodedBeats(+  const Timeline& tl, const std::chrono::microseconds time, const Beats quantum)+{+  const auto beat = tl.toBeats(time);+  return closestPhaseMatch(beat, beat - tl.beatOrigin, quantum);+}++// The inverse of toPhaseEncodedBeats. Given a phase encoded beat+// value from the given timeline and quantum, find the time value that+// it maps to.+inline std::chrono::microseconds fromPhaseEncodedBeats(+  const Timeline& tl, const Beats beat, const Beats quantum)+{+  const auto fromOrigin = beat - tl.beatOrigin;+  const auto originOffset = fromOrigin - phase(fromOrigin, quantum);+  // invert the phase calculation so that it always rounds up in the+  // middle instead of down like closestPhaseMatch. Otherwise we'll+  // end up rounding down twice when a value is at phase quantum/2.+  const auto inversePhaseOffset = closestPhaseMatch(+    quantum - phase(fromOrigin, quantum), quantum - phase(beat, quantum), quantum);+  return tl.fromBeats(tl.beatOrigin + originOffset + quantum - inversePhaseOffset);+}++} // namespace link+} // namespace ableton
+ link/include/ableton/link/PingResponder.hpp view
@@ -0,0 +1,171 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/GhostXForm.hpp>+#include <ableton/link/PayloadEntries.hpp>+#include <ableton/link/SessionId.hpp>+#include <ableton/link/v1/Messages.hpp>+#include <ableton/util/Injected.hpp>+#include <ableton/util/SafeAsyncHandler.hpp>+#include <chrono>+#include <memory>++namespace ableton+{+namespace link+{++template <typename Clock, typename IoContext>+class PingResponder+{+  using IoType = util::Injected<IoContext&>;+  using Socket = typename IoType::type::template Socket<v1::kMaxMessageSize>;++public:+  PingResponder(asio::ip::address_v4 address,+    SessionId sessionId,+    GhostXForm ghostXForm,+    Clock clock,+    IoType io)+    : mIo(io)+    , mpImpl(std::make_shared<Impl>(std::move(address),+        std::move(sessionId),+        std::move(ghostXForm),+        std::move(clock),+        std::move(io)))+  {+    mpImpl->listen();+  }++  PingResponder(const PingResponder&) = delete;+  PingResponder(PingResponder&&) = delete;++  void updateNodeState(const SessionId& sessionId, const GhostXForm& xform)+  {+    mpImpl->mSessionId = std::move(sessionId);+    mpImpl->mGhostXForm = std::move(xform);+  }++  asio::ip::udp::endpoint endpoint() const+  {+    return mpImpl->mSocket.endpoint();+  }++  asio::ip::address address() const+  {+    return endpoint().address();+  }++  Socket socket() const+  {+    return mpImpl->mSocket;+  }++private:+  struct Impl : std::enable_shared_from_this<Impl>+  {+    Impl(asio::ip::address_v4 address,+      SessionId sessionId,+      GhostXForm ghostXForm,+      Clock clock,+      IoType io)+      : mSessionId(std::move(sessionId))+      , mGhostXForm(std::move(ghostXForm))+      , mClock(std::move(clock))+      , mLog(channel(io->log(), "gateway@" + address.to_string()))+      , mSocket(io->template openUnicastSocket<v1::kMaxMessageSize>(address))+    {+    }++    void listen()+    {+      mSocket.receive(util::makeAsyncSafe(this->shared_from_this()));+    }++    // Operator to handle incoming messages on the interface+    template <typename It>+    void operator()(const asio::ip::udp::endpoint& from, const It begin, const It end)+    {+      using namespace discovery;++      // Decode Ping Message+      const auto result = link::v1::parseMessageHeader(begin, end);+      const auto& header = result.first;+      const auto payloadBegin = result.second;++      // Check Payload size+      const auto payloadSize = static_cast<std::size_t>(std::distance(payloadBegin, end));+      const auto maxPayloadSize =+        sizeInByteStream(makePayload(HostTime{}, PrevGHostTime{}));+      if (header.messageType == v1::kPing && payloadSize <= maxPayloadSize)+      {+        debug(mLog) << " Received ping message from " << from;++        try+        {+          reply(std::move(payloadBegin), std::move(end), from);+        }+        catch (const std::runtime_error& err)+        {+          info(mLog) << " Failed to send pong to " << from << ". Reason: " << err.what();+        }+      }+      else+      {+        info(mLog) << " Received invalid Message from " << from << ".";+      }+      listen();+    }++    template <typename It>+    void reply(It begin, It end, const asio::ip::udp::endpoint& to)+    {+      using namespace discovery;++      // Encode Pong Message+      const auto id = SessionMembership{mSessionId};+      const auto currentGt = GHostTime{mGhostXForm.hostToGhost(mClock.micros())};+      const auto pongPayload = makePayload(id, currentGt);++      v1::MessageBuffer pongBuffer;+      const auto pongMsgBegin = std::begin(pongBuffer);+      auto pongMsgEnd = v1::pongMessage(pongPayload, pongMsgBegin);+      // Append ping payload to pong message.+      pongMsgEnd = std::copy(begin, end, pongMsgEnd);++      const auto numBytes =+        static_cast<std::size_t>(std::distance(pongMsgBegin, pongMsgEnd));+      mSocket.send(pongBuffer.data(), numBytes, to);+    }++    SessionId mSessionId;+    GhostXForm mGhostXForm;+    Clock mClock;+    typename IoType::type::Log mLog;+    Socket mSocket;+  };++  IoType mIo;+  std::shared_ptr<Impl> mpImpl;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/SessionId.hpp view
@@ -0,0 +1,63 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/NodeId.hpp>++namespace ableton+{+namespace link+{++// SessionIds occupy the same value space as NodeIds and are+// identified by their founding node.+using SessionId = NodeId;++// A payload entry indicating membership in a particular session+struct SessionMembership+{+  static const std::int32_t key = 'sess';+  static_assert(key == 0x73657373, "Unexpected byte order");++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const SessionMembership& sm)+  {+    return discovery::sizeInByteStream(sm.sessionId);+  }++  template <typename It>+  friend It toNetworkByteStream(const SessionMembership& sm, It out)+  {+    return discovery::toNetworkByteStream(sm.sessionId, std::move(out));+  }++  template <typename It>+  static std::pair<SessionMembership, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto idRes = SessionId::fromNetworkByteStream(std::move(begin), std::move(end));+    return make_pair(SessionMembership{std::move(idRes.first)}, std::move(idRes.second));+  }++  SessionId sessionId;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/SessionState.hpp view
@@ -0,0 +1,115 @@+/* Copyright 2017, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/Optional.hpp>+#include <ableton/link/StartStopState.hpp>+#include <ableton/link/Timeline.hpp>+#include <ableton/link/TripleBuffer.hpp>++namespace ableton+{+namespace link+{++using OptionalTimeline = Optional<Timeline>;+using OptionalStartStopState = Optional<StartStopState>;+using OptionalClientStartStopState = Optional<ClientStartStopState>;++struct SessionState+{+  Timeline timeline;+  StartStopState startStopState;+  GhostXForm ghostXForm;+};++struct ClientState+{+  friend bool operator==(const ClientState& lhs, const ClientState& rhs)+  {+    return std::tie(lhs.timeline, lhs.startStopState)+           == std::tie(rhs.timeline, rhs.startStopState);+  }++  friend bool operator!=(const ClientState& lhs, const ClientState& rhs)+  {+    return !(lhs == rhs);+  }++  Timeline timeline;+  ClientStartStopState startStopState;+};++struct ControllerClientState+{+  ControllerClientState(ClientState state)+    : mState(state)+    , mRtState(state)+  {+  }++  template <typename Fn>+  void update(Fn fn)+  {+    std::unique_lock<std::mutex> lock(mMutex);+    fn(mState);+    mRtState.write(mState);+  }++  ClientState get() const+  {+    std::unique_lock<std::mutex> lock(mMutex);+    return mState;+  }++  ClientState getRt() const+  {+    return mRtState.read();+  }++private:+  mutable std::mutex mMutex;+  ClientState mState;+  mutable TripleBuffer<ClientState> mRtState;+};++struct RtClientState+{+  Timeline timeline;+  ClientStartStopState startStopState;+  std::chrono::microseconds timelineTimestamp;+  std::chrono::microseconds startStopStateTimestamp;+};++struct IncomingClientState+{+  OptionalTimeline timeline;+  OptionalClientStartStopState startStopState;+  std::chrono::microseconds timelineTimestamp;+};++struct ApiState+{+  Timeline timeline;+  ApiStartStopState startStopState;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/Sessions.hpp view
@@ -0,0 +1,301 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/GhostXForm.hpp>+#include <ableton/link/SessionId.hpp>+#include <ableton/link/Timeline.hpp>++namespace ableton+{+namespace link+{++struct SessionMeasurement+{+  GhostXForm xform;+  std::chrono::microseconds timestamp;+};++struct Session+{+  SessionId sessionId;+  Timeline timeline;+  SessionMeasurement measurement;+};++template <typename Peers,+  typename MeasurePeer,+  typename JoinSessionCallback,+  typename IoContext,+  typename Clock>+class Sessions+{+public:+  using Timer = typename util::Injected<IoContext>::type::Timer;++  Sessions(Session init,+    util::Injected<Peers> peers,+    MeasurePeer measure,+    JoinSessionCallback join,+    util::Injected<IoContext> io,+    Clock clock)+    : mPeers(std::move(peers))+    , mMeasure(std::move(measure))+    , mCallback(std::move(join))+    , mCurrent(std::move(init))+    , mIo(std::move(io))+    , mTimer(mIo->makeTimer())+    , mClock(std::move(clock))+  {+  }++  void resetSession(Session session)+  {+    mCurrent = std::move(session);+    mOtherSessions.clear();+  }++  void resetTimeline(Timeline timeline)+  {+    mCurrent.timeline = std::move(timeline);+  }++  // Consider the observed session/timeline pair and return a possibly+  // new timeline that should be used going forward.+  Timeline sawSessionTimeline(SessionId sid, Timeline timeline)+  {+    using namespace std;+    if (sid == mCurrent.sessionId)+    {+      // matches our current session, update the timeline if necessary+      updateTimeline(mCurrent, std::move(timeline));+    }+    else+    {+      auto session = Session{std::move(sid), std::move(timeline), {}};+      const auto range =+        equal_range(begin(mOtherSessions), end(mOtherSessions), session, SessionIdComp{});+      if (range.first == range.second)+      {+        // brand new session, insert it into our list of known+        // sessions and launch a measurement+        launchSessionMeasurement(session);+        mOtherSessions.insert(range.first, std::move(session));+      }+      else+      {+        // we've seen this session before, update its timeline if necessary+        updateTimeline(*range.first, std::move(timeline));+      }+    }+    return mCurrent.timeline;+  }++private:+  void launchSessionMeasurement(Session& session)+  {+    using namespace std;+    auto peers = mPeers->sessionPeers(session.sessionId);+    if (!peers.empty())+    {+      // first criteria: always prefer the founding peer+      const auto it = find_if(begin(peers), end(peers),+        [&session](const Peer& peer) { return session.sessionId == peer.first.ident(); });+      // TODO: second criteria should be degree. We don't have that+      // represented yet so just use the first peer for now+      auto peer = it == end(peers) ? peers.front() : *it;+      // mark that a session is in progress by clearing out the+      // session's timestamp+      session.measurement.timestamp = {};+      mMeasure(std::move(peer), MeasurementResultsHandler{*this, session.sessionId});+    }+  }++  void handleSuccessfulMeasurement(const SessionId& id, GhostXForm xform)+  {+    using namespace std;++    debug(mIo->log()) << "Session " << id << " measurement completed with result "+                      << "(" << xform.slope << ", " << xform.intercept.count() << ")";++    auto measurement = SessionMeasurement{std::move(xform), mClock.micros()};++    if (mCurrent.sessionId == id)+    {+      mCurrent.measurement = std::move(measurement);+      mCallback(mCurrent);+    }+    else+    {+      const auto range = equal_range(+        begin(mOtherSessions), end(mOtherSessions), Session{id, {}, {}}, SessionIdComp{});++      if (range.first != range.second)+      {+        const auto SESSION_EPS = chrono::microseconds{500000};+        // should we join this session?+        const auto hostTime = mClock.micros();+        const auto curGhost = mCurrent.measurement.xform.hostToGhost(hostTime);+        const auto newGhost = measurement.xform.hostToGhost(hostTime);+        // update the measurement for the session entry+        range.first->measurement = std::move(measurement);+        // If session times too close - fall back to session id order+        const auto ghostDiff = newGhost - curGhost;+        if (ghostDiff > SESSION_EPS+            || (std::abs(ghostDiff.count()) < SESSION_EPS.count()+                 && id < mCurrent.sessionId))+        {+          // The new session wins, switch over to it+          auto current = mCurrent;+          mCurrent = std::move(*range.first);+          mOtherSessions.erase(range.first);+          // Put the old current session back into our list of known+          // sessions so that we won't re-measure it+          const auto it = upper_bound(+            begin(mOtherSessions), end(mOtherSessions), current, SessionIdComp{});+          mOtherSessions.insert(it, std::move(current));+          // And notify that we have a new session and make sure that+          // we remeasure it periodically.+          mCallback(mCurrent);+          scheduleRemeasurement();+        }+      }+    }+  }++  void scheduleRemeasurement()+  {+    // set a timer to re-measure the active session after a period+    mTimer.expires_from_now(std::chrono::microseconds{30000000});+    mTimer.async_wait([this](const typename Timer::ErrorCode e) {+      if (!e)+      {+        launchSessionMeasurement(mCurrent);+        scheduleRemeasurement();+      }+    });+  }++  void handleFailedMeasurement(const SessionId& id)+  {+    using namespace std;++    debug(mIo->log()) << "Session " << id << " measurement failed.";++    // if we failed to measure for our current session, schedule a+    // retry in the future. Otherwise, remove the session from our set+    // of known sessions (if it is seen again it will be measured as+    // if new).+    if (mCurrent.sessionId == id)+    {+      scheduleRemeasurement();+    }+    else+    {+      const auto range = equal_range(+        begin(mOtherSessions), end(mOtherSessions), Session{id, {}, {}}, SessionIdComp{});+      if (range.first != range.second)+      {+        mOtherSessions.erase(range.first);+        mPeers->forgetSession(id);+      }+    }+  }++  void updateTimeline(Session& session, Timeline timeline)+  {+    // We use beat origin magnitude to prioritize sessions.+    if (timeline.beatOrigin > session.timeline.beatOrigin)+    {+      debug(mIo->log()) << "Adopting peer timeline (" << timeline.tempo.bpm() << ", "+                        << timeline.beatOrigin.floating() << ", "+                        << timeline.timeOrigin.count() << ")";++      session.timeline = std::move(timeline);+    }+    else+    {+      debug(mIo->log()) << "Rejecting peer timeline with beat origin: "+                        << timeline.beatOrigin.floating()+                        << ". Current timeline beat origin: "+                        << session.timeline.beatOrigin.floating();+    }+  }++  struct MeasurementResultsHandler+  {+    void operator()(GhostXForm xform) const+    {+      Sessions& sessions = mSessions;+      const SessionId& sessionId = mSessionId;+      if (xform == GhostXForm{})+      {+        sessions.handleFailedMeasurement(std::move(sessionId));+      }+      else+      {+        sessions.handleSuccessfulMeasurement(std::move(sessionId), std::move(xform));+      }+    }++    Sessions& mSessions;+    SessionId mSessionId;+  };++  struct SessionIdComp+  {+    bool operator()(const Session& lhs, const Session& rhs) const+    {+      return lhs.sessionId < rhs.sessionId;+    }+  };++  using Peer = typename util::Injected<Peers>::type::Peer;+  util::Injected<Peers> mPeers;+  MeasurePeer mMeasure;+  JoinSessionCallback mCallback;+  Session mCurrent;+  util::Injected<IoContext> mIo;+  Timer mTimer;+  Clock mClock;+  std::vector<Session> mOtherSessions; // sorted/unique by session id+};++template <typename Peers,+  typename MeasurePeer,+  typename JoinSessionCallback,+  typename IoContext,+  typename Clock>+Sessions<Peers, MeasurePeer, JoinSessionCallback, IoContext, Clock> makeSessions(+  Session init,+  util::Injected<Peers> peers,+  MeasurePeer measure,+  JoinSessionCallback join,+  util::Injected<IoContext> io,+  Clock clock)+{+  using namespace std;+  return {std::move(init), std::move(peers), std::move(measure), std::move(join),+    std::move(io), std::move(clock)};+}++} // namespace link+} // namespace ableton
+ link/include/ableton/link/StartStopState.hpp view
@@ -0,0 +1,152 @@+/* Copyright 2017, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/NetworkByteStreamSerializable.hpp>+#include <ableton/link/Beats.hpp>+#include <chrono>+#include <tuple>++namespace ableton+{+namespace link+{++// A tuple of (isPlaying, time) that represents the playing state+// with an according timestamp in microseconds. It also serves as a+// payload entry.++struct StartStopState+{+  static const std::int32_t key = 'stst';+  static_assert(key == 0x73747374, "Unexpected byte order");++  using StartStopStateTuple = std::tuple<bool, Beats, std::chrono::microseconds>;++  StartStopState() = default;++  StartStopState(+    const bool aIsPlaying, const Beats aBeats, const std::chrono::microseconds aTimestamp)+    : isPlaying(aIsPlaying)+    , beats(aBeats)+    , timestamp(aTimestamp)+  {+  }++  friend bool operator==(const StartStopState& lhs, const StartStopState& rhs)+  {+    return std::tie(lhs.isPlaying, lhs.beats, lhs.timestamp)+           == std::tie(rhs.isPlaying, rhs.beats, rhs.timestamp);+  }++  friend bool operator!=(const StartStopState& lhs, const StartStopState& rhs)+  {+    return !(lhs == rhs);+  }++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const StartStopState& state)+  {+    return discovery::sizeInByteStream(state.asTuple());+  }++  template <typename It>+  friend It toNetworkByteStream(const StartStopState& state, It out)+  {+    return discovery::toNetworkByteStream(state.asTuple(), std::move(out));+  }++  template <typename It>+  static std::pair<StartStopState, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    using namespace discovery;+    auto result = Deserialize<StartStopStateTuple>::fromNetworkByteStream(+      std::move(begin), std::move(end));+    auto state =+      StartStopState{get<0>(result.first), get<1>(result.first), get<2>(result.first)};+    return make_pair(std::move(state), std::move(result.second));+  }++  bool isPlaying{false};+  Beats beats{0.};+  std::chrono::microseconds timestamp{0};++private:+  StartStopStateTuple asTuple() const+  {+    return std::make_tuple(isPlaying, beats, timestamp);+  }+};++struct ClientStartStopState+{+  ClientStartStopState() = default;++  ClientStartStopState(const bool aIsPlaying,+    const std::chrono::microseconds aTime,+    const std::chrono::microseconds aTimestamp)+    : isPlaying(aIsPlaying)+    , time(aTime)+    , timestamp(aTimestamp)+  {+  }++  friend bool operator==(const ClientStartStopState& lhs, const ClientStartStopState& rhs)+  {+    return std::tie(lhs.isPlaying, lhs.time, lhs.timestamp)+           == std::tie(rhs.isPlaying, rhs.time, rhs.timestamp);+  }++  friend bool operator!=(const ClientStartStopState& lhs, const ClientStartStopState& rhs)+  {+    return !(lhs == rhs);+  }++  bool isPlaying{false};+  std::chrono::microseconds time{0};+  std::chrono::microseconds timestamp{0};+};++struct ApiStartStopState+{+  ApiStartStopState() = default;++  ApiStartStopState(const bool aIsPlaying, const std::chrono::microseconds aTime)+    : isPlaying(aIsPlaying)+    , time(aTime)+  {+  }++  friend bool operator==(const ApiStartStopState& lhs, const ApiStartStopState& rhs)+  {+    return std::tie(lhs.isPlaying, lhs.time) == std::tie(rhs.isPlaying, rhs.time);+  }++  friend bool operator!=(const ApiStartStopState& lhs, const ApiStartStopState& rhs)+  {+    return !(lhs == rhs);+  }++  bool isPlaying{false};+  std::chrono::microseconds time{0};+};+} // namespace link+} // namespace ableton
+ link/include/ableton/link/Tempo.hpp view
@@ -0,0 +1,125 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/Beats.hpp>+#include <chrono>++namespace ableton+{+namespace link+{++struct Tempo+{+  Tempo() = default;++  // Beats per minute+  explicit Tempo(const double bpm)+    : mValue(bpm)+  {+  }++  Tempo(const std::chrono::microseconds microsPerBeat)+    : mValue(60. * 1e6 / static_cast<double>(microsPerBeat.count()))+  {+  }++  double bpm() const+  {+    return mValue;+  }++  std::chrono::microseconds microsPerBeat() const+  {+    return std::chrono::microseconds{std::llround(60. * 1e6 / bpm())};+  }++  // Given the tempo, convert a time to a beat value+  Beats microsToBeats(const std::chrono::microseconds micros) const+  {+    return Beats{+      static_cast<double>(micros.count()) / static_cast<double>(microsPerBeat().count())};+  }++  // Given the tempo, convert a beat to a time value+  std::chrono::microseconds beatsToMicros(const Beats beats) const+  {+    return std::chrono::microseconds{+      std::llround(beats.floating() * static_cast<double>(microsPerBeat().count()))};+  }++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const Tempo tempo)+  {+    return discovery::sizeInByteStream(tempo.microsPerBeat());+  }++  template <typename It>+  friend It toNetworkByteStream(const Tempo tempo, It out)+  {+    return discovery::toNetworkByteStream(tempo.microsPerBeat(), std::move(out));+  }++  template <typename It>+  static std::pair<Tempo, It> fromNetworkByteStream(It begin, It end)+  {+    auto result =+      discovery::Deserialize<std::chrono::microseconds>::fromNetworkByteStream(+        std::move(begin), std::move(end));+    return std::make_pair(Tempo{std::move(result.first)}, std::move(result.second));+  }++  friend bool operator==(const Tempo lhs, const Tempo rhs)+  {+    return lhs.mValue == rhs.mValue;+  }++  friend bool operator!=(const Tempo lhs, const Tempo rhs)+  {+    return lhs.mValue != rhs.mValue;+  }++  friend bool operator<(const Tempo lhs, const Tempo rhs)+  {+    return lhs.mValue < rhs.mValue;+  }++  friend bool operator>(const Tempo lhs, const Tempo rhs)+  {+    return lhs.mValue > rhs.mValue;+  }++  friend bool operator<=(const Tempo lhs, const Tempo rhs)+  {+    return lhs.mValue <= rhs.mValue;+  }++  friend bool operator>=(const Tempo lhs, const Tempo rhs)+  {+    return lhs.mValue >= rhs.mValue;+  }++private:+  double mValue = 0;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/Timeline.hpp view
@@ -0,0 +1,98 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/NetworkByteStreamSerializable.hpp>+#include <ableton/link/Beats.hpp>+#include <ableton/link/Tempo.hpp>+#include <cmath>+#include <cstdint>+#include <tuple>++namespace ableton+{+namespace link+{++// A tuple of (tempo, beats, time), with integral units+// based on microseconds. This type establishes a bijection between+// beats and wall time, given a valid tempo. It also serves as a+// payload entry.++struct Timeline+{+  static const std::int32_t key = 'tmln';+  static_assert(key == 0x746d6c6e, "Unexpected byte order");++  Beats toBeats(const std::chrono::microseconds time) const+  {+    return beatOrigin + tempo.microsToBeats(time - timeOrigin);+  }++  std::chrono::microseconds fromBeats(const Beats beats) const+  {+    return timeOrigin + tempo.beatsToMicros(beats - beatOrigin);+  }++  friend bool operator==(const Timeline& lhs, const Timeline& rhs)+  {+    return std::tie(lhs.tempo, lhs.beatOrigin, lhs.timeOrigin)+           == std::tie(rhs.tempo, rhs.beatOrigin, rhs.timeOrigin);+  }++  friend bool operator!=(const Timeline& lhs, const Timeline& rhs)+  {+    return !(lhs == rhs);+  }++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const Timeline& tl)+  {+    return discovery::sizeInByteStream(std::tie(tl.tempo, tl.beatOrigin, tl.timeOrigin));+  }++  template <typename It>+  friend It toNetworkByteStream(const Timeline& tl, It out)+  {+    return discovery::toNetworkByteStream(+      std::tie(tl.tempo, tl.beatOrigin, tl.timeOrigin), std::move(out));+  }++  template <typename It>+  static std::pair<Timeline, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    using namespace discovery;+    Timeline timeline;+    auto result =+      Deserialize<tuple<Tempo, Beats, chrono::microseconds>>::fromNetworkByteStream(+        std::move(begin), std::move(end));+    tie(timeline.tempo, timeline.beatOrigin, timeline.timeOrigin) =+      std::move(result.first);+    return make_pair(std::move(timeline), std::move(result.second));+  }++  Tempo tempo;+  Beats beatOrigin;+  std::chrono::microseconds timeOrigin;+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/TripleBuffer.hpp view
@@ -0,0 +1,121 @@+/* Copyright 2022, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */+++#pragma once++#include <ableton/link/Optional.hpp>++#include <array>+#include <atomic>+#include <cassert>+#include <cstdint>++namespace ableton+{+namespace link+{++template <typename T>+struct TripleBuffer+{+public:+  TripleBuffer()+    : mBuffers{{{}, {}, {}}}+  {+    assert(mState.is_lock_free());+  }++  explicit TripleBuffer(const T& initial)+    : mBuffers{{initial, initial, initial}}+  {+    assert(mState.is_lock_free());+  }++  TripleBuffer(const TripleBuffer&) = delete;+  TripleBuffer& operator=(const TripleBuffer&) = delete;++  T read() noexcept+  {+    loadReadBuffer();+    return mBuffers[mReadIndex];+  }++  Optional<T> readNew()+  {+    if (loadReadBuffer())+    {+      return Optional<T>(mBuffers[mReadIndex]);+    }+    return {};+  }++  template <typename U>+  void write(U&& value)+  {+    mBuffers[mWriteIndex] = std::forward<U>(value);++    const auto prevState =+      mState.exchange(makeState(mWriteIndex, true), std::memory_order_acq_rel);++    mWriteIndex = backIndex(prevState);+  }++private:+  bool loadReadBuffer()+  {+    auto state = mState.load(std::memory_order_acquire);+    auto isNew = isNewWrite(state);+    if (isNew)+    {+      const auto prevState =+        mState.exchange(makeState(mReadIndex, false), std::memory_order_acq_rel);++      mReadIndex = backIndex(prevState);+    }+    return isNew;+  }++  using BackingState = uint32_t;++  static constexpr bool isNewWrite(const BackingState state)+  {+    return (state & 0x0000FFFFu) != 0;+  }++  static constexpr uint32_t backIndex(const BackingState state)+  {+    return state >> 16;+  }++  static constexpr BackingState makeState(+    const uint32_t backBufferIndex, const bool isWrite)+  {+    return (backBufferIndex << 16) | uint32_t(isWrite);+  }++  std::atomic<BackingState> mState{makeState(1u, false)}; // Reader and writer+  uint32_t mReadIndex = 0u;                               // Reader only+  uint32_t mWriteIndex = 2u;                              // Writer only++  std::array<T, 3> mBuffers{};+};++} // namespace link+} // namespace ableton
+ link/include/ableton/link/v1/Messages.hpp view
@@ -0,0 +1,138 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/Payload.hpp>+#include <array>++namespace ableton+{+namespace link+{+namespace v1+{++// The maximum size of a message, in bytes+const std::size_t kMaxMessageSize = 512;+// Utility typedef for an array of bytes of maximum message size+using MessageBuffer = std::array<uint8_t, v1::kMaxMessageSize>;++using MessageType = uint8_t;++const MessageType kPing = 1;+const MessageType kPong = 2;++struct MessageHeader+{+  MessageType messageType;++  friend std::uint32_t sizeInByteStream(const MessageHeader& header)+  {+    return discovery::sizeInByteStream(header.messageType);+  }++  template <typename It>+  friend It toNetworkByteStream(const MessageHeader& header, It out)+  {+    return discovery::toNetworkByteStream(header.messageType, std::move(out));+  }++  template <typename It>+  static std::pair<MessageHeader, It> fromNetworkByteStream(It begin, const It end)+  {+    using namespace discovery;++    MessageHeader header;+    std::tie(header.messageType, begin) =+      Deserialize<decltype(header.messageType)>::fromNetworkByteStream(begin, end);++    return std::make_pair(std::move(header), std::move(begin));+  }+};++namespace detail+{++// Types that are only used in the sending/parsing of messages, not+// publicly exposed.+using ProtocolHeader = std::array<char, 8>;+const ProtocolHeader kProtocolHeader = {{'_', 'l', 'i', 'n', 'k', '_', 'v', 1}};++// Must have at least kMaxMessageSize bytes available in the output stream+template <typename Payload, typename It>+It encodeMessage(const MessageType messageType, const Payload& payload, It out)+{+  using namespace std;+  const MessageHeader header = {messageType};+  const auto messageSize =+    kProtocolHeader.size() + sizeInByteStream(header) + sizeInByteStream(payload);++  if (messageSize < kMaxMessageSize)+  {+    return toNetworkByteStream(+      payload, toNetworkByteStream(header,+                 copy(begin(kProtocolHeader), end(kProtocolHeader), std::move(out))));+  }+  else+  {+    throw range_error("Exceeded maximum message size");+  }+}++} // namespace detail++template <typename Payload, typename It>+It pingMessage(const Payload& payload, It out)+{+  return detail::encodeMessage(kPing, payload, std::move(out));+}++template <typename Payload, typename It>+It pongMessage(const Payload& payload, It out)+{+  return detail::encodeMessage(kPong, payload, std::move(out));+}++template <typename It>+std::pair<MessageHeader, It> parseMessageHeader(It bytesBegin, const It bytesEnd)+{+  using ItDiff = typename std::iterator_traits<It>::difference_type;++  MessageHeader header = {};+  const auto protocolHeaderSize = discovery::sizeInByteStream(detail::kProtocolHeader);+  const auto minMessageSize =+    static_cast<ItDiff>(protocolHeaderSize + sizeInByteStream(header));++  // If there are enough bytes in the stream to make a header and if+  // the first bytes in the stream are the protocol header, then+  // proceed to parse the stream.+  if (std::distance(bytesBegin, bytesEnd) >= minMessageSize+      && std::equal(+           begin(detail::kProtocolHeader), end(detail::kProtocolHeader), bytesBegin))+  {+    std::tie(header, bytesBegin) =+      MessageHeader::fromNetworkByteStream(bytesBegin + protocolHeaderSize, bytesEnd);+  }+  return std::make_pair(std::move(header), std::move(bytesBegin));+}++} // namespace v1+} // namespace link+} // namespace ableton
+ link/include/ableton/platforms/Config.hpp view
@@ -0,0 +1,101 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/link/Controller.hpp>+#include <ableton/util/Log.hpp>++#if defined(LINK_PLATFORM_WINDOWS)+#include <ableton/platforms/asio/Context.hpp>+#include <ableton/platforms/stl/Random.hpp>+#include <ableton/platforms/windows/Clock.hpp>+#include <ableton/platforms/windows/ScanIpIfAddrs.hpp>+#if defined(LINK_WINDOWS_SETTHREADDESCRIPTION)+#include <ableton/platforms/windows/ThreadFactory.hpp>+#endif+#elif defined(LINK_PLATFORM_MACOSX)+#include <ableton/platforms/asio/Context.hpp>+#include <ableton/platforms/darwin/Clock.hpp>+#include <ableton/platforms/darwin/ThreadFactory.hpp>+#include <ableton/platforms/posix/ScanIpIfAddrs.hpp>+#include <ableton/platforms/stl/Random.hpp>+#elif defined(LINK_PLATFORM_LINUX)+#include <ableton/platforms/asio/Context.hpp>+#include <ableton/platforms/linux/Clock.hpp>+#include <ableton/platforms/posix/ScanIpIfAddrs.hpp>+#include <ableton/platforms/stl/Random.hpp>+#ifdef __linux__+#include <ableton/platforms/linux/ThreadFactory.hpp>+#endif+#elif defined(ESP_PLATFORM)+#include <ableton/platforms/esp32/Clock.hpp>+#include <ableton/platforms/esp32/Context.hpp>+#include <ableton/platforms/esp32/Random.hpp>+#include <ableton/platforms/esp32/ScanIpIfAddrs.hpp>+#endif++namespace ableton+{+namespace link+{+namespace platform+{++#if defined(LINK_PLATFORM_WINDOWS)+using Clock = platforms::windows::Clock;+using Random = platforms::stl::Random;+#if defined(LINK_WINDOWS_SETTHREADDESCRIPTION)+using IoContext = platforms::asio::Context<platforms::windows::ScanIpIfAddrs,+  util::NullLog,+  platforms::windows::ThreadFactory>;+#else+using IoContext =+  platforms::asio::Context<platforms::windows::ScanIpIfAddrs, util::NullLog>;+#endif++#elif defined(LINK_PLATFORM_MACOSX)+using Clock = platforms::darwin::Clock;+using IoContext = platforms::asio::Context<platforms::posix::ScanIpIfAddrs,+  util::NullLog,+  platforms::darwin::ThreadFactory>;+using Random = platforms::stl::Random;++#elif defined(LINK_PLATFORM_LINUX)+using Clock = platforms::linux::ClockMonotonicRaw;+using Random = platforms::stl::Random;+#ifdef __linux__+using IoContext = platforms::asio::Context<platforms::posix::ScanIpIfAddrs,+  util::NullLog,+  platforms::linux::ThreadFactory>;+#else+using IoContext =+  platforms::asio::Context<platforms::posix::ScanIpIfAddrs, util::NullLog>;+#endif++#elif defined(ESP_PLATFORM)+using Clock = platforms::esp32::Clock;+using IoContext =+  platforms::esp32::Context<platforms::esp32::ScanIpIfAddrs, util::NullLog>;+using Random = platforms::esp32::Random;+#endif++} // namespace platform+} // namespace link+} // namespace ableton
+ link/include/ableton/platforms/asio/AsioTimer.hpp view
@@ -0,0 +1,132 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/util/SafeAsyncHandler.hpp>+#include <functional>++namespace ableton+{+namespace platforms+{+namespace asio+{++// This implementation is based on the boost::asio::system_timer concept.+// Since boost::system_timer doesn't support move semantics, we create a wrapper+// with a unique_ptr to get a movable type. It also handles an inconvenient+// aspect of asio timers, which is that you must explicitly guard against the+// handler firing after cancellation. We handle this by use of the SafeAsyncHandler+// utility. AsioTimer therefore guarantees that a handler will not be called after+// the destruction of the timer, or after the timer has been canceled.++class AsioTimer+{+public:+  using ErrorCode = ::asio::error_code;+  using TimePoint = std::chrono::system_clock::time_point;++  AsioTimer(::asio::io_service& io)+    : mpTimer(new ::asio::system_timer(io))+    , mpAsyncHandler(std::make_shared<AsyncHandler>())+  {+  }++  ~AsioTimer()+  {+    // The timer may not be valid anymore if this instance was moved from+    if (mpTimer != nullptr)+    {+      // Ignore errors during cancellation+      cancel();+    }+  }++  AsioTimer(const AsioTimer&) = delete;+  AsioTimer& operator=(const AsioTimer&) = delete;++  // Enable move construction but not move assignment. Move assignment+  // would get weird - would have to handle outstanding handlers+  AsioTimer(AsioTimer&& rhs)+    : mpTimer(std::move(rhs.mpTimer))+    , mpAsyncHandler(std::move(rhs.mpAsyncHandler))+  {+  }++  void expires_at(std::chrono::system_clock::time_point tp)+  {+    mpTimer->expires_at(std::move(tp));+  }++  template <typename T>+  void expires_from_now(T duration)+  {+    mpTimer->expires_from_now(std::move(duration));+  }++  ErrorCode cancel()+  {+    ErrorCode ec;+    mpTimer->cancel(ec);+    mpAsyncHandler->mpHandler = nullptr;+    return ec;+  }++  template <typename Handler>+  void async_wait(Handler handler)+  {+    *mpAsyncHandler = std::move(handler);+    mpTimer->async_wait(util::makeAsyncSafe(mpAsyncHandler));+  }++  TimePoint now() const+  {+    return std::chrono::system_clock::now();+  }++private:+  struct AsyncHandler+  {+    template <typename Handler>+    AsyncHandler& operator=(Handler handler)+    {+      mpHandler = [handler](ErrorCode ec) { handler(std::move(ec)); };+      return *this;+    }++    void operator()(ErrorCode ec)+    {+      if (mpHandler)+      {+        mpHandler(std::move(ec));+      }+    }++    std::function<void(const ErrorCode)> mpHandler;+  };++  std::unique_ptr<::asio::system_timer> mpTimer;+  std::shared_ptr<AsyncHandler> mpAsyncHandler;+};++} // namespace asio+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/asio/AsioWrapper.hpp view
@@ -0,0 +1,90 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++/*!+ * \brief Wrapper file for AsioStandalone library+ *+ * This file includes all necessary headers from the AsioStandalone library which are used+ * by Link.+ */++#if !defined(ESP_PLATFORM)+#pragma push_macro("ASIO_STANDALONE")+#define ASIO_STANDALONE 1++#pragma push_macro("ASIO_NO_TYPEID")+#define ASIO_NO_TYPEID 1+#endif++#if defined(LINK_PLATFORM_WINDOWS)+#pragma push_macro("INCL_EXTRA_HTON_FUNCTIONS")+#define INCL_EXTRA_HTON_FUNCTIONS 1+#endif++#if defined(WIN32) || defined(_WIN32)+#if !defined(_WIN32_WINNT)+#define _WIN32_WINNT 0x0501+#endif+#endif++#if defined(__clang__)+#pragma clang diagnostic push+#if __has_warning("-Wcomma")+#pragma clang diagnostic ignored "-Wcomma"+#endif+#if __has_warning("-Wshorten-64-to-32")+#pragma clang diagnostic ignored "-Wshorten-64-to-32"+#endif+#if __has_warning("-Wunused-local-typedef")+#pragma clang diagnostic ignored "-Wunused-local-typedef"+#endif+#endif++#if defined(_MSC_VER)+#define _SCL_SECURE_NO_WARNINGS 1+#pragma warning(push, 0)+#pragma warning(disable : 4242)+#pragma warning(disable : 4668)+#pragma warning(disable : 4702)+#pragma warning(disable : 5204)+#pragma warning(disable : 5220)+#endif++#include <asio.hpp>+#include <asio/system_timer.hpp>++#if defined(LINK_PLATFORM_WINDOWS)+#pragma pop_macro("INCL_EXTRA_HTON_FUNCTIONS")+#endif++#if !defined(ESP_PLATFORM)+#pragma pop_macro("ASIO_STANDALONE")+#pragma pop_macro("ASIO_NO_TYPEID")+#endif++#if defined(_MSC_VER)+#pragma warning(pop)+#undef _SCL_SECURE_NO_WARNINGS+#endif++#if defined(__clang__)+#pragma clang diagnostic pop+#endif
+ link/include/ableton/platforms/asio/Context.hpp view
@@ -0,0 +1,196 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/IpV4Interface.hpp>+#include <ableton/platforms/asio/AsioTimer.hpp>+#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/platforms/asio/LockFreeCallbackDispatcher.hpp>+#include <ableton/platforms/asio/Socket.hpp>+#include <thread>+#include <utility>++namespace ableton+{+namespace platforms+{+namespace asio+{+namespace+{++struct ThreadFactory+{+  template <typename Callable, typename... Args>+  static std::thread makeThread(std::string, Callable&& f, Args&&... args)+  {+    return std::thread(std::forward<Callable>(f), std::forward<Args>(args)...);+  }+};++} // namespace++template <typename ScanIpIfAddrs, typename LogT, typename ThreadFactoryT = ThreadFactory>+class Context+{+public:+  using Timer = AsioTimer;+  using Log = LogT;++  template <typename Handler, typename Duration>+  using LockFreeCallbackDispatcher =+    LockFreeCallbackDispatcher<Handler, Duration, ThreadFactoryT>;++  template <std::size_t BufferSize>+  using Socket = asio::Socket<BufferSize>;++  Context()+    : Context(DefaultHandler{})+  {+  }++  template <typename ExceptionHandler>+  explicit Context(ExceptionHandler exceptHandler)+    : mpService(new ::asio::io_service())+    , mpWork(new ::asio::io_service::work(*mpService))+  {+    mThread = ThreadFactoryT::makeThread("Link Main",+      [](::asio::io_service& service, ExceptionHandler handler) {+        for (;;)+        {+          try+          {+            service.run();+            break;+          }+          catch (const typename ExceptionHandler::Exception& exception)+          {+            handler(exception);+          }+        }+      },+      std::ref(*mpService), std::move(exceptHandler));+  }++  Context(const Context&) = delete;++  Context(Context&& rhs)+    : mpService(std::move(rhs.mpService))+    , mpWork(std::move(rhs.mpWork))+    , mThread(std::move(rhs.mThread))+    , mLog(std::move(rhs.mLog))+    , mScanIpIfAddrs(std::move(rhs.mScanIpIfAddrs))+  {+  }++  ~Context()+  {+    if (mpService && mpWork)+    {+      mpWork.reset();+      mThread.join();+    }+  }++  void stop()+  {+    if (mpService && mpWork)+    {+      mpWork.reset();+      mpService->stop();+      mThread.join();+    }+  }+++  template <std::size_t BufferSize>+  Socket<BufferSize> openUnicastSocket(const ::asio::ip::address_v4& addr)+  {+    auto socket = Socket<BufferSize>{*mpService};+    socket.mpImpl->mSocket.set_option(+      ::asio::ip::multicast::enable_loopback(addr.is_loopback()));+    socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr));+    socket.mpImpl->mSocket.bind(::asio::ip::udp::endpoint{addr, 0});+    return socket;+  }++  template <std::size_t BufferSize>+  Socket<BufferSize> openMulticastSocket(const ::asio::ip::address_v4& addr)+  {+    auto socket = Socket<BufferSize>{*mpService};+    socket.mpImpl->mSocket.set_option(::asio::ip::udp::socket::reuse_address(true));+    socket.mpImpl->mSocket.set_option(+      ::asio::socket_base::broadcast(!addr.is_loopback()));+    socket.mpImpl->mSocket.set_option(+      ::asio::ip::multicast::enable_loopback(addr.is_loopback()));+    socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr));+    socket.mpImpl->mSocket.bind({::asio::ip::address::from_string("0.0.0.0"),+      discovery::multicastEndpoint().port()});+    socket.mpImpl->mSocket.set_option(::asio::ip::multicast::join_group(+      discovery::multicastEndpoint().address().to_v4(), addr));+    return socket;+  }++  std::vector<::asio::ip::address> scanNetworkInterfaces()+  {+    return mScanIpIfAddrs();+  }++  Timer makeTimer() const+  {+    return {*mpService};+  }++  Log& log()+  {+    return mLog;+  }++  template <typename Handler>+  void async(Handler handler)+  {+    mpService->post(std::move(handler));+  }++private:+  // Default handler is hidden and defines a hidden exception type+  // that will never be thrown by other code, so it effectively does+  // not catch.+  struct DefaultHandler+  {+    struct Exception+    {+    };++    void operator()(const Exception&)+    {+    }+  };++  std::unique_ptr<::asio::io_service> mpService;+  std::unique_ptr<::asio::io_service::work> mpWork;+  std::thread mThread;+  Log mLog;+  ScanIpIfAddrs mScanIpIfAddrs;+};++} // namespace asio+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp view
@@ -0,0 +1,88 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <atomic>+#include <condition_variable>+#include <thread>++namespace ableton+{+namespace platforms+{+namespace asio+{++// Utility to signal invocation of a callback on another thread in a lock free manner.+// The callback is evoked on a thread owned by the instance of this class.+//+// A condition variable is used to notify a waiting thread, but only if the required+// lock can be acquired immediately. If that fails, we fall back on signaling+// after a timeout. This gives us a guaranteed minimum signaling rate which is defined+// by the fallbackPeriod parameter.++template <typename Callback, typename Duration, typename ThreadFactory>+class LockFreeCallbackDispatcher+{+public:+  LockFreeCallbackDispatcher(Callback callback, Duration fallbackPeriod)+    : mCallback(std::move(callback))+    , mFallbackPeriod(std::move(fallbackPeriod))+    , mRunning(true)+    , mThread(ThreadFactory::makeThread("Link Dispatcher", [this] { run(); }))+  {+  }++  ~LockFreeCallbackDispatcher()+  {+    mRunning = false;+    mCondition.notify_one();+    mThread.join();+  }++  void invoke()+  {+    mCondition.notify_one();+  }++private:+  void run()+  {+    while (mRunning.load())+    {+      {+        std::unique_lock<std::mutex> lock(mMutex);+        mCondition.wait_for(lock, mFallbackPeriod);+      }+      mCallback();+    }+  }++  Callback mCallback;+  Duration mFallbackPeriod;+  std::atomic<bool> mRunning;+  std::mutex mMutex;+  std::condition_variable mCondition;+  std::thread mThread;+};++} // namespace asio+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/asio/Socket.hpp view
@@ -0,0 +1,110 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/util/SafeAsyncHandler.hpp>+#include <array>+#include <cassert>++namespace ableton+{+namespace platforms+{+namespace asio+{++template <std::size_t MaxPacketSize>+struct Socket+{+  Socket(::asio::io_service& io)+    : mpImpl(std::make_shared<Impl>(io))+  {+  }++  Socket(const Socket&) = delete;+  Socket& operator=(const Socket&) = delete;++  Socket(Socket&& rhs)+    : mpImpl(std::move(rhs.mpImpl))+  {+  }++  std::size_t send(const uint8_t* const pData,+    const size_t numBytes,+    const ::asio::ip::udp::endpoint& to)+  {+    assert(numBytes < MaxPacketSize);+    return mpImpl->mSocket.send_to(::asio::buffer(pData, numBytes), to);+  }++  template <typename Handler>+  void receive(Handler handler)+  {+    mpImpl->mHandler = std::move(handler);+    mpImpl->mSocket.async_receive_from(+      ::asio::buffer(mpImpl->mReceiveBuffer, MaxPacketSize), mpImpl->mSenderEndpoint,+      util::makeAsyncSafe(mpImpl));+  }++  ::asio::ip::udp::endpoint endpoint() const+  {+    return mpImpl->mSocket.local_endpoint();+  }++  struct Impl+  {+    Impl(::asio::io_service& io)+      : mSocket(io, ::asio::ip::udp::v4())+    {+    }++    ~Impl()+    {+      // Ignore error codes in shutdown and close as the socket may+      // have already been forcibly closed+      ::asio::error_code ec;+      mSocket.shutdown(::asio::ip::udp::socket::shutdown_both, ec);+      mSocket.close(ec);+    }++    void operator()(const ::asio::error_code& error, const std::size_t numBytes)+    {+      if (!error && numBytes > 0 && numBytes <= MaxPacketSize)+      {+        const auto bufBegin = begin(mReceiveBuffer);+        mHandler(mSenderEndpoint, bufBegin, bufBegin + static_cast<ptrdiff_t>(numBytes));+      }+    }++    ::asio::ip::udp::socket mSocket;+    ::asio::ip::udp::endpoint mSenderEndpoint;+    using Buffer = std::array<uint8_t, MaxPacketSize>;+    Buffer mReceiveBuffer;+    using ByteIt = typename Buffer::const_iterator;+    std::function<void(const ::asio::ip::udp::endpoint&, ByteIt, ByteIt)> mHandler;+  };++  std::shared_ptr<Impl> mpImpl;+};++} // namespace asio+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/asio/Util.hpp view
@@ -0,0 +1,43 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <algorithm>++namespace ableton+{+namespace platforms+{+namespace asio+{++// Utility for making v4 or v6 ip addresses from raw bytes in network byte-order+template <typename AsioAddrType>+AsioAddrType makeAddress(const char* pAddr)+{+  using namespace std;+  typename AsioAddrType::bytes_type bytes;+  copy(pAddr, pAddr + bytes.size(), begin(bytes));+  return AsioAddrType{bytes};+}++} // namespace asio+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/darwin/Clock.hpp view
@@ -0,0 +1,70 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <chrono>+#include <mach/mach_time.h>++namespace ableton+{+namespace platforms+{+namespace darwin+{++struct Clock+{+  using Ticks = std::uint64_t;+  using Micros = std::chrono::microseconds;++  Clock()+  {+    mach_timebase_info_data_t timeInfo;+    mach_timebase_info(&timeInfo);+    // numer / denom gives nanoseconds, we want microseconds+    mTicksToMicros = timeInfo.numer / (timeInfo.denom * 1000.);+  }++  Micros ticksToMicros(const Ticks ticks) const+  {+    return Micros{llround(mTicksToMicros * ticks)};+  }++  Ticks microsToTicks(const Micros micros) const+  {+    return static_cast<Ticks>(micros.count() / mTicksToMicros);+  }++  Ticks ticks() const+  {+    return mach_absolute_time();+  }++  std::chrono::microseconds micros() const+  {+    return ticksToMicros(ticks());+  }++  double mTicksToMicros;+};++} // namespace darwin+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/darwin/Darwin.hpp view
@@ -0,0 +1,30 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++// ntohll and htonll are not defined in 10.7 SDK, so we provide a compatibility macro here++#ifndef ntohll+#define ntohll(x) __DARWIN_OSSwapInt64(x)+#endif++#ifndef htonll+#define htonll(x) __DARWIN_OSSwapInt64(x)+#endif
+ link/include/ableton/platforms/darwin/ThreadFactory.hpp view
@@ -0,0 +1,48 @@+/* Copyright 2021, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <pthread.h>+#include <thread>+#include <utility>++namespace ableton+{+namespace platforms+{+namespace darwin+{++struct ThreadFactory+{+  template <typename Callable, typename... Args>+  static std::thread makeThread(std::string name, Callable&& f, Args&&... args)+  {+    return std::thread{[](std::string name, Callable&& f, Args&&... args) {+                         pthread_setname_np(name.c_str());+                         f(args...);+                       },+      std::move(name), std::forward<Callable>(f), std::forward<Args>(args)...};+  }+};++} // namespace darwin+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/esp32/Clock.hpp view
@@ -0,0 +1,36 @@+/* Copyright 2019, Mathias Bredholt, Torso Electronics, Copenhagen. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ */++#pragma once++#include "esp_timer.h"++namespace ableton+{+namespace platforms+{+namespace esp32+{+struct Clock+{+  std::chrono::microseconds micros() const+  {+    return static_cast<std::chrono::microseconds>(esp_timer_get_time());+  }+};+} // namespace esp32+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/esp32/Context.hpp view
@@ -0,0 +1,228 @@+/* Copyright 2020, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/discovery/IpV4Interface.hpp>+#include <ableton/platforms/asio/AsioTimer.hpp>+#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/platforms/asio/Socket.hpp>+#include <ableton/platforms/esp32/LockFreeCallbackDispatcher.hpp>+#include <driver/timer.h>+#include <freertos/FreeRTOS.h>+#include <freertos/task.h>++namespace ableton+{+namespace platforms+{+namespace esp32+{++template <typename ScanIpIfAddrs, typename LogT>+class Context+{+  class ServiceRunner+  {++    static void run(void* userParams)+    {+      auto runner = static_cast<ServiceRunner*>(userParams);+      for (;;)+      {+        try+        {+          ulTaskNotifyTake(pdTRUE, portMAX_DELAY);+          runner->mpService->poll_one();+        }+        catch (...)+        {+        }+      }+    }++    static void IRAM_ATTR timerIsr(void* userParam)+    {+      static BaseType_t xHigherPriorityTaskWoken = pdFALSE;++      timer_group_clr_intr_status_in_isr(TIMER_GROUP_0, TIMER_1);+      timer_group_enable_alarm_in_isr(TIMER_GROUP_0, TIMER_1);++      vTaskNotifyGiveFromISR(userParam, &xHigherPriorityTaskWoken);+      if (xHigherPriorityTaskWoken)+      {+        portYIELD_FROM_ISR();+      }+    }++  public:+    ServiceRunner()+      : mpService(new ::asio::io_service())+      , mpWork(new ::asio::io_service::work(*mpService))+    {+      xTaskCreatePinnedToCore(run, "link", 8192, this, 2 | portPRIVILEGE_BIT,+        &mTaskHandle, LINK_ESP_TASK_CORE_ID);++      timer_config_t config = {.alarm_en = TIMER_ALARM_EN,+        .counter_en = TIMER_PAUSE,+        .intr_type = TIMER_INTR_LEVEL,+        .counter_dir = TIMER_COUNT_UP,+        .auto_reload = TIMER_AUTORELOAD_EN,+        .divider = 80};++      timer_init(TIMER_GROUP_0, TIMER_1, &config);+      timer_set_counter_value(TIMER_GROUP_0, TIMER_1, 0);+      timer_set_alarm_value(TIMER_GROUP_0, TIMER_1, 100);+      timer_enable_intr(TIMER_GROUP_0, TIMER_1);+      timer_isr_register(TIMER_GROUP_0, TIMER_1, &timerIsr, mTaskHandle, 0, nullptr);++      timer_start(TIMER_GROUP_0, TIMER_1);+    }++    ~ServiceRunner()+    {+      vTaskDelete(mTaskHandle);+    }++    template <typename Handler>+    void async(Handler handler)+    {+      mpService->post(std::move(handler));+    }++    ::asio::io_service& service() const+    {+      return *mpService;+    }++  private:+    TaskHandle_t mTaskHandle;+    std::unique_ptr<::asio::io_service> mpService;+    std::unique_ptr<::asio::io_service::work> mpWork;+  };++public:+  using Timer = ::ableton::platforms::asio::AsioTimer;+  using Log = LogT;++  template <typename Handler, typename Duration>+  using LockFreeCallbackDispatcher = LockFreeCallbackDispatcher<Handler, Duration>;++  template <std::size_t BufferSize>+  using Socket = asio::Socket<BufferSize>;++  Context()+    : Context(DefaultHandler{})+  {+  }++  template <typename ExceptionHandler>+  explicit Context(ExceptionHandler exceptHandler)+  {+  }++  Context(const Context&) = delete;++  Context(Context&& rhs)+    : mLog(std::move(rhs.mLog))+    , mScanIpIfAddrs(std::move(rhs.mScanIpIfAddrs))+  {+  }++  void stop()+  {+  }++  template <std::size_t BufferSize>+  Socket<BufferSize> openUnicastSocket(const ::asio::ip::address_v4& addr)+  {+    auto socket = Socket<BufferSize>{serviceRunner().service()};+    socket.mpImpl->mSocket.set_option(+      ::asio::ip::multicast::enable_loopback(addr.is_loopback()));+    socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr));+    socket.mpImpl->mSocket.bind(::asio::ip::udp::endpoint{addr, 0});+    return socket;+  }++  template <std::size_t BufferSize>+  Socket<BufferSize> openMulticastSocket(const ::asio::ip::address_v4& addr)+  {+    auto socket = Socket<BufferSize>{serviceRunner().service()};+    socket.mpImpl->mSocket.set_option(::asio::ip::udp::socket::reuse_address(true));+    socket.mpImpl->mSocket.set_option(+      ::asio::socket_base::broadcast(!addr.is_loopback()));+    socket.mpImpl->mSocket.set_option(+      ::asio::ip::multicast::enable_loopback(addr.is_loopback()));+    socket.mpImpl->mSocket.set_option(::asio::ip::multicast::outbound_interface(addr));+    socket.mpImpl->mSocket.bind({::asio::ip::address::from_string("0.0.0.0"),+      discovery::multicastEndpoint().port()});+    socket.mpImpl->mSocket.set_option(::asio::ip::multicast::join_group(+      discovery::multicastEndpoint().address().to_v4(), addr));+    return socket;+  }++  std::vector<::asio::ip::address> scanNetworkInterfaces()+  {+    return mScanIpIfAddrs();+  }++  Timer makeTimer() const+  {+    return {serviceRunner().service()};+  }++  Log& log()+  {+    return mLog;+  }++  template <typename Handler>+  void async(Handler handler)+  {+    serviceRunner().service().post(std::move(handler));+  }++private:+  // Default handler is hidden and defines a hidden exception type+  // that will never be thrown by other code, so it effectively does+  // not catch.+  struct DefaultHandler+  {+    struct Exception+    {+    };++    void operator()(const Exception&)+    {+    }+  };++  static ServiceRunner& serviceRunner()+  {+    static ServiceRunner runner;+    return runner;+  }++  Log mLog;+  ScanIpIfAddrs mScanIpIfAddrs;+};++} // namespace esp32+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/esp32/Esp32.hpp view
@@ -0,0 +1,27 @@+/* Copyright 2019, Mathias Bredholt, Torso Electronics, Copenhagen. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ */++#pragma once++#include <endian.h>++#ifndef ntohll+#define ntohll(x) bswap64(x)+#endif++#ifndef htonll+#define htonll(x) bswap64(x)+#endif
+ link/include/ableton/platforms/esp32/LockFreeCallbackDispatcher.hpp view
@@ -0,0 +1,94 @@+/* Copyright 2020, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <atomic>+#include <condition_variable>+#include <freertos/task.h>++namespace ableton+{+namespace platforms+{+namespace esp32+{++// Utility to signal invocation of a callback on another thread in a lock free manner.+// The callback is evoked on a thread owned by the instance of this class.+//+// A condition variable is used to notify a waiting thread, but only if the required+// lock can be acquired immediately. If that fails, we fall back on signaling+// after a timeout. This gives us a guaranteed minimum signaling rate which is defined+// by the fallbackPeriod parameter.++template <typename Callback, typename Duration>+class LockFreeCallbackDispatcher+{+public:+  LockFreeCallbackDispatcher(Callback callback, Duration fallbackPeriod)+    : mCallback(std::move(callback))+    , mFallbackPeriod(std::move(fallbackPeriod))+    , mRunning(true)+  {+    xTaskCreate(run, "link", 4096, this, tskIDLE_PRIORITY, &mTaskHandle);+  }++  ~LockFreeCallbackDispatcher()+  {+    mRunning = false;+    mCondition.notify_one();+    vTaskDelete(mTaskHandle);+  }++  void invoke()+  {+    if (mMutex.try_lock())+    {+      mCondition.notify_one();+      mMutex.unlock();+    }+  }++private:+  static void run(void* userData)+  {+    auto dispatcher = static_cast<LockFreeCallbackDispatcher*>(userData);+    while (dispatcher->mRunning.load())+    {+      {+        std::unique_lock<std::mutex> lock(dispatcher->mMutex);+        dispatcher->mCondition.wait_for(lock, dispatcher->mFallbackPeriod);+      }+      dispatcher->mCallback();+      vTaskDelay(1);+    }+  }++  Callback mCallback;+  Duration mFallbackPeriod;+  std::atomic<bool> mRunning;+  std::mutex mMutex;+  std::condition_variable mCondition;+  TaskHandle_t mTaskHandle;+};++} // namespace esp32+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/esp32/Random.hpp view
@@ -0,0 +1,36 @@+/* Copyright 2019, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ */++#pragma once++namespace ableton+{+namespace platforms+{+namespace esp32+{++struct Random+{+  uint8_t operator()()+  {+    return static_cast<uint8_t>((esp_random() % 93) + 33); // printable ascii chars+  }+};++} // namespace esp32+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp view
@@ -0,0 +1,59 @@+/* Copyright 2020, Ableton AG, Berlin and 2019, Mathias Bredholt, Torso Electronics,+ * Copenhagen. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <arpa/inet.h>+#include <esp_netif.h>+#include <net/if.h>+#include <vector>++namespace ableton+{+namespace platforms+{+namespace esp32+{++// ESP32 implementation of ip interface address scanner+struct ScanIpIfAddrs+{+  std::vector<::asio::ip::address> operator()()+  {+    std::vector<::asio::ip::address> addrs;+    // Get first network interface+    esp_netif_t* esp_netif = esp_netif_next(NULL);+    while (esp_netif)+    {+      // Check if interface is active+      if (esp_netif_is_netif_up(esp_netif))+      {+        esp_netif_ip_info_t ip_info;+        esp_netif_get_ip_info(esp_netif, &ip_info);+        addrs.emplace_back(::asio::ip::address_v4(ntohl(ip_info.ip.addr)));+      }+      // Get next network interface+      esp_netif = esp_netif_next(esp_netif);+    }+    return addrs;+  }+};++} // namespace esp32+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/linux/Clock.hpp view
@@ -0,0 +1,60 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <chrono>+#include <cmath>+#include <ctime>++namespace ableton+{+namespace platforms+{++#ifdef linux+#undef linux+#endif++#if defined(__FreeBSD_kernel__)+#define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC+#endif++namespace linux+{++template <clockid_t CLOCK>+class Clock+{+public:+  std::chrono::microseconds micros() const+  {+    ::timespec ts;+    ::clock_gettime(CLOCK, &ts);+    std::uint64_t ns = ts.tv_sec * 1000000000ULL + ts.tv_nsec;+    return std::chrono::microseconds(ns / 1000ULL);+  }+};++using ClockMonotonic = Clock<CLOCK_MONOTONIC>;+using ClockMonotonicRaw = Clock<CLOCK_MONOTONIC_RAW>;++} // namespace linux+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/linux/Linux.hpp view
@@ -0,0 +1,30 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <byteswap.h>++#ifndef ntohll+#define ntohll(x) bswap_64(x)+#endif++#ifndef htonll+#define htonll(x) bswap_64(x)+#endif
+ link/include/ableton/platforms/linux/ThreadFactory.hpp view
@@ -0,0 +1,45 @@+/* Copyright 2021, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <pthread.h>+#include <thread>++namespace ableton+{+namespace platforms+{+namespace linux+{++struct ThreadFactory+{+  template <typename Callable, typename... Args>+  static std::thread makeThread(std::string name, Callable&& f, Args&&... args)+  {+    auto thread = std::thread(std::forward<Callable>(f), std::forward<Args>(args)...);+    pthread_setname_np(thread.native_handle(), name.c_str());+    return thread;+  }+};++} // namespace linux+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/posix/ScanIpIfAddrs.hpp view
@@ -0,0 +1,110 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/platforms/asio/Util.hpp>+#include <arpa/inet.h>+#include <ifaddrs.h>+#include <net/if.h>+#include <vector>++namespace ableton+{+namespace platforms+{+namespace posix+{+namespace detail+{++// RAII type to make [get,free]ifaddrs function pairs exception safe+class GetIfAddrs+{+public:+  GetIfAddrs()+  {+    if (getifaddrs(&interfaces)) // returns 0 on success+    {+      interfaces = NULL;+    }+  }+  ~GetIfAddrs()+  {+    if (interfaces)+      freeifaddrs(interfaces);+  }++  // RAII must not copy+  GetIfAddrs(GetIfAddrs&) = delete;+  GetIfAddrs& operator=(GetIfAddrs&) = delete;++  template <typename Function>+  void withIfAddrs(Function f)+  {+    if (interfaces)+      f(*interfaces);+  }++private:+  struct ifaddrs* interfaces = NULL;+};++} // namespace detail+++// Posix implementation of ip interface address scanner+struct ScanIpIfAddrs+{+  // Scan active network interfaces and return corresponding addresses+  // for all ip-based interfaces.+  std::vector<::asio::ip::address> operator()()+  {+    std::vector<::asio::ip::address> addrs;++    detail::GetIfAddrs getIfAddrs;+    getIfAddrs.withIfAddrs([&addrs](const struct ifaddrs& interfaces) {+      const struct ifaddrs* interface;+      for (interface = &interfaces; interface; interface = interface->ifa_next)+      {+        auto addr = reinterpret_cast<const struct sockaddr_in*>(interface->ifa_addr);+        if (addr && interface->ifa_flags & IFF_UP)+        {+          if (addr->sin_family == AF_INET)+          {+            auto bytes = reinterpret_cast<const char*>(&addr->sin_addr);+            addrs.emplace_back(asio::makeAddress<::asio::ip::address_v4>(bytes));+          }+          else if (addr->sin_family == AF_INET6)+          {+            auto addr6 = reinterpret_cast<const struct sockaddr_in6*>(addr);+            auto bytes = reinterpret_cast<const char*>(&addr6->sin6_addr);+            addrs.emplace_back(asio::makeAddress<::asio::ip::address_v6>(bytes));+          }+        }+      }+    });+    return addrs;+  }+};++} // namespace posix+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/stl/Clock.hpp view
@@ -0,0 +1,43 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <chrono>++namespace ableton+{+namespace platforms+{+namespace stl+{++struct Clock+{+  std::chrono::microseconds micros() const+  {+    using namespace std::chrono;+    auto nowInMicros = time_point_cast<microseconds>(steady_clock::now());+    return nowInMicros.time_since_epoch();+  }+};++} // namespace stl+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/stl/Random.hpp view
@@ -0,0 +1,51 @@+/* Copyright 2019, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <random>++namespace ableton+{+namespace platforms+{+namespace stl+{++struct Random+{+  Random()+    : gen(rd())+    , dist(33, 126) // printable ascii chars+  {+  }++  uint8_t operator()()+  {+    return static_cast<uint8_t>(dist(gen));+  }++  std::random_device rd;+  std::mt19937 gen;+  std::uniform_int_distribution<unsigned> dist;+};++} // namespace stl+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/windows/Clock.hpp view
@@ -0,0 +1,71 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <chrono>+#include <cstdint>++namespace ableton+{+namespace platforms+{+namespace windows+{++struct Clock+{+  using Ticks = std::int64_t;+  using Micros = std::chrono::microseconds;++  Clock()+  {+    LARGE_INTEGER frequency;+    QueryPerformanceFrequency(&frequency);+    mTicksToMicros = 1.0e6 / static_cast<double>(frequency.QuadPart);+  }++  Micros ticksToMicros(const Ticks ticks) const+  {+    return Micros{llround(mTicksToMicros * static_cast<double>(ticks))};+  }++  Ticks microsToTicks(const Micros micros) const+  {+    return static_cast<Ticks>(static_cast<double>(micros.count()) / mTicksToMicros);+  }++  Ticks ticks() const+  {+    LARGE_INTEGER count;+    QueryPerformanceCounter(&count);+    return count.QuadPart;+  }++  std::chrono::microseconds micros() const+  {+    return ticksToMicros(ticks());+  }++  double mTicksToMicros;+};++} // namespace windows+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/windows/ScanIpIfAddrs.hpp view
@@ -0,0 +1,140 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/platforms/asio/Util.hpp>+#include <iphlpapi.h>+#include <stdio.h>+#include <vector>+#include <winsock2.h>+#include <ws2tcpip.h>++#pragma comment(lib, "iphlpapi.lib")+#pragma comment(lib, "ws2_32.lib")++namespace ableton+{+namespace platforms+{+namespace windows+{+namespace detail+{+// RAII type to make [get,free]ifaddrs function pairs exception safe+class GetIfAddrs+{+public:+  GetIfAddrs()+  {+    const int MAX_TRIES = 3;               // MSFT recommendation+    const int WORKING_BUFFER_SIZE = 15000; // MSFT recommendation++    DWORD adapter_addrs_buffer_size = WORKING_BUFFER_SIZE;+    for (int i = 0; i < MAX_TRIES; i++)+    {+      adapter_addrs = (IP_ADAPTER_ADDRESSES*)malloc(adapter_addrs_buffer_size);+      assert(adapter_addrs);++      DWORD error = ::GetAdaptersAddresses(AF_UNSPEC,+        GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | GAA_FLAG_SKIP_DNS_SERVER+          | GAA_FLAG_SKIP_FRIENDLY_NAME,+        NULL, adapter_addrs, &adapter_addrs_buffer_size);++      if (error == ERROR_SUCCESS)+      {+        break;+      }+      // if buffer too small, use new buffer size in next iteration+      if (error == ERROR_BUFFER_OVERFLOW)+      {+        free(adapter_addrs);+        adapter_addrs = NULL;+        continue;+      }+    }+  }+  ~GetIfAddrs()+  {+    if (adapter_addrs)+      free(adapter_addrs);+  }++  // RAII must not copy+  GetIfAddrs(GetIfAddrs&) = delete;+  GetIfAddrs& operator=(GetIfAddrs&) = delete;++  template <typename Function>+  void withIfAddrs(Function f)+  {+    if (adapter_addrs)+      f(*adapter_addrs);+  }++private:+  IP_ADAPTER_ADDRESSES* adapter_addrs;+  IP_ADAPTER_ADDRESSES* adapter;+};++} // namespace detail++struct ScanIpIfAddrs+{+  // Scan active network interfaces and return corresponding addresses+  // for all ip-based interfaces.+  std::vector<::asio::ip::address> operator()()+  {+    std::vector<::asio::ip::address> addrs;++    detail::GetIfAddrs getIfAddrs;+    getIfAddrs.withIfAddrs([&addrs](const IP_ADAPTER_ADDRESSES& interfaces) {+      const IP_ADAPTER_ADDRESSES* networkInterface;+      for (networkInterface = &interfaces; networkInterface;+           networkInterface = networkInterface->Next)+      {+        for (IP_ADAPTER_UNICAST_ADDRESS* address = networkInterface->FirstUnicastAddress;+             NULL != address; address = address->Next)+        {+          auto family = address->Address.lpSockaddr->sa_family;+          if (AF_INET == family)+          {+            // IPv4+            SOCKADDR_IN* addr4 =+              reinterpret_cast<SOCKADDR_IN*>(address->Address.lpSockaddr);+            auto bytes = reinterpret_cast<const char*>(&addr4->sin_addr);+            addrs.emplace_back(asio::makeAddress<::asio::ip::address_v4>(bytes));+          }+          else if (AF_INET6 == family)+          {+            SOCKADDR_IN6* addr6 =+              reinterpret_cast<SOCKADDR_IN6*>(address->Address.lpSockaddr);+            auto bytes = reinterpret_cast<const char*>(&addr6->sin6_addr);+            addrs.emplace_back(asio::makeAddress<::asio::ip::address_v6>(bytes));+          }+        }+      }+    });+    return addrs;+  }+};++} // namespace windows+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/windows/ThreadFactory.hpp view
@@ -0,0 +1,52 @@+/* Copyright 2021, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <processthreadsapi.h>+#include <thread>+#include <utility>++namespace ableton+{+namespace platforms+{+namespace windows+{++struct ThreadFactory+{+  template <typename Callable, typename... Args>+  static std::thread makeThread(std::string name, Callable&& f, Args&&... args)+  {+    return std::thread(+      [](std::string name, Callable&& f, Args&&... args) {+        assert(name.length() < 20);+        wchar_t nativeName[20];+        mbstowcs(nativeName, name.c_str(), name.length() + 1);+        SetThreadDescription(GetCurrentThread(), nativeName);+        f(args...);+      },+      std::move(name), std::forward<Callable>(f), std::forward<Args>(args)...);+  }+};++} // namespace windows+} // namespace platforms+} // namespace ableton
+ link/include/ableton/platforms/windows/Windows.hpp view
@@ -0,0 +1,32 @@+/* Copyright 2020, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++// ntohll and htonll are not defined for MinGW++#ifdef __MINGW32__+#if __BIG_ENDIAN__+#define htonll(x) (x)+#define ntohll(x) (x)+#else+#define htonll(x) (((uint64_t)htonl((x)&0xFFFFFFFF) << 32) | htonl((x) >> 32))+#define ntohll(x) (((uint64_t)ntohl((x)&0xFFFFFFFF) << 32) | ntohl((x) >> 32))+#endif+#endif
+ link/include/ableton/test/CatchWrapper.hpp view
@@ -0,0 +1,42 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++/*!+ * \brief Wrapper file for Catch library+ *+ * This file includes the Catch header for Link, and also disables some compiler warnings+ * which are specific to that library.+ */++#if defined(_MSC_VER)+#pragma warning(push, 0)+#pragma warning(disable : 4242)+#pragma warning(disable : 4244)+#pragma warning(disable : 4668)+#pragma warning(disable : 4702)+#pragma warning(disable : 5220)+#endif++#include <catch.hpp>++#if defined(_MSC_VER)+#pragma warning(pop)+#endif
+ link/include/ableton/test/serial_io/Context.hpp view
@@ -0,0 +1,109 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/test/serial_io/SchedulerTree.hpp>+#include <ableton/test/serial_io/Timer.hpp>+#include <ableton/util/Log.hpp>+#include <chrono>+#include <memory>++namespace ableton+{+namespace test+{+namespace serial_io+{++class Context+{+public:+  Context(const SchedulerTree::TimePoint& now,+    const std::vector<::asio::ip::address>& ifAddrs,+    std::shared_ptr<SchedulerTree> pScheduler)+    : mNow(now)+    , mIfAddrs(ifAddrs)+    , mpScheduler(std::move(pScheduler))+    , mNextTimerId(0)+  {+  }++  ~Context()+  {+    if (mpScheduler != nullptr)+    {+      // Finish any pending tasks before shutting down+      mpScheduler->run();+    }+  }++  Context(const Context&) = delete;+  Context& operator=(const Context&) = delete;++  Context(Context&& rhs)+    : mNow(rhs.mNow)+    , mIfAddrs(rhs.mIfAddrs)+    , mpScheduler(std::move(rhs.mpScheduler))+    , mLog(std::move(rhs.mLog))+    , mNextTimerId(rhs.mNextTimerId)+  {+  }++  void stop()+  {+  }++  template <typename Handler>+  void async(Handler handler)+  {+    mpScheduler->async(std::move(handler));+  }++  using Timer = serial_io::Timer;++  Timer makeTimer()+  {+    return {mNextTimerId++, mNow, mpScheduler};+  }++  using Log = util::NullLog;++  Log& log()+  {+    return mLog;+  }++  std::vector<::asio::ip::address> scanNetworkInterfaces()+  {+    return mIfAddrs;+  }++private:+  const SchedulerTree::TimePoint& mNow;+  const std::vector<::asio::ip::address>& mIfAddrs;+  std::shared_ptr<SchedulerTree> mpScheduler;+  Log mLog;+  SchedulerTree::TimerId mNextTimerId;+};++} // namespace serial_io+} // namespace test+} // namespace ableton
+ link/include/ableton/test/serial_io/Fixture.hpp view
@@ -0,0 +1,92 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/test/serial_io/Context.hpp>+#include <chrono>+#include <memory>++namespace ableton+{+namespace test+{+namespace serial_io+{++class Fixture+{+public:+  Fixture()+    : mpScheduler(std::make_shared<SchedulerTree>())+    , mNow(std::chrono::milliseconds{123456789})+  {+  }++  ~Fixture()+  {+    flush();+  }++  Fixture(const Fixture&) = delete;+  Fixture& operator=(const Fixture&) = delete;+  Fixture(Fixture&&) = delete;+  Fixture& operator=(Fixture&&) = delete;++  void setNetworkInterfaces(std::vector<::asio::ip::address> ifAddrs)+  {+    mIfAddrs = std::move(ifAddrs);+  }++  Context makeIoContext()+  {+    return {mNow, mIfAddrs, mpScheduler};+  }++  void flush()+  {+    mpScheduler->run();+  }++  template <typename T, typename Rep>+  void advanceTime(std::chrono::duration<T, Rep> duration)+  {+    const auto target = mNow + duration;+    mpScheduler->run();+    auto nextTimer = mpScheduler->nextTimerExpiration();+    while (nextTimer <= target)+    {+      mNow = nextTimer;+      mpScheduler->triggerTimersUntil(mNow);+      mpScheduler->run();+      nextTimer = mpScheduler->nextTimerExpiration();+    }+    mNow = target;+  }++private:+  std::shared_ptr<SchedulerTree> mpScheduler;+  SchedulerTree::TimePoint mNow;+  std::vector<::asio::ip::address> mIfAddrs;+};++} // namespace serial_io+} // namespace test+} // namespace ableton
+ link/include/ableton/test/serial_io/SchedulerTree.hpp view
@@ -0,0 +1,104 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <chrono>+#include <functional>+#include <list>+#include <map>+#include <memory>++namespace ableton+{+namespace test+{+namespace serial_io+{++class SchedulerTree+{+public:+  using TimePoint = std::chrono::system_clock::time_point;+  using TimerId = std::size_t;+  using TimerErrorCode = int;++  void run();++  std::shared_ptr<SchedulerTree> makeChild();++  template <typename Handler>+  void async(Handler handler)+  {+    mPendingHandlers.push_back(std::move(handler));+  }++  template <typename Handler>+  void setTimer(const TimerId timerId, const TimePoint expiration, Handler handler)+  {+    using namespace std;+    mTimers[make_pair(std::move(expiration), timerId)] = std::move(handler);+  }++  void cancelTimer(const TimerId timerId);++  // returns the time that the next timer in the subtree expires+  TimePoint nextTimerExpiration();++  // triggers all timers in the subtree that expire at time t or before+  void triggerTimersUntil(const TimePoint t);++private:+  // returns true if some work was done, false if there was none to do+  bool handlePending();++  // returns the time that the next timer from this node expires+  TimePoint nextOwnTimerExpiration();++  // Traversal function over children that cleans up children that+  // have been destroyed.+  template <typename Fn>+  void withChildren(Fn fn)+  {+    auto it = begin(mChildren);+    while (it != end(mChildren))+    {+      const auto childIt = it++;+      auto pChild = childIt->lock();+      if (pChild)+      {+        fn(*pChild);+      }+      else+      {+        mChildren.erase(childIt);+      }+    }+  }++  using TimerHandler = std::function<void(TimerErrorCode)>;+  using TimerMap = std::map<std::pair<TimePoint, TimerId>, TimerHandler>;+  TimerMap mTimers;+  std::list<std::function<void()>> mPendingHandlers;+  std::list<std::weak_ptr<SchedulerTree>> mChildren;+};++} // namespace serial_io+} // namespace test+} // namespace ableton
+ link/include/ableton/test/serial_io/Timer.hpp view
@@ -0,0 +1,110 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/test/serial_io/SchedulerTree.hpp>++namespace ableton+{+namespace test+{+namespace serial_io+{++struct Timer+{+  using ErrorCode = SchedulerTree::TimerErrorCode;+  using TimePoint = SchedulerTree::TimePoint;++  Timer(const SchedulerTree::TimerId timerId,+    const TimePoint& now,+    std::shared_ptr<SchedulerTree> pScheduler)+    : mId(timerId)+    , mNow(now)+    , mpScheduler(std::move(pScheduler))+  {+  }++  ~Timer()+  {+    if (!mbMovedFrom)+    {+      cancel();+    }+  }++  Timer(const Timer&) = delete;++  Timer(Timer&& rhs)+    : mId(rhs.mId)+    , mNow(rhs.mNow)+    , mExpiration(std::move(rhs.mExpiration))+    , mpScheduler(std::move(rhs.mpScheduler))+  {+    rhs.mbMovedFrom = true;+  }++  void expires_at(const TimePoint t)+  {+    if (t < mNow)+    {+      throw std::runtime_error("Setting timer in the past");+    }+    else+    {+      cancel();+      mExpiration = t;+    }+  }++  template <typename T, typename Rep>+  void expires_from_now(std::chrono::duration<T, Rep> duration)+  {+    expires_at(mNow + duration);+  }++  void cancel()+  {+    auto pScheduler = mpScheduler.lock();+    pScheduler->cancelTimer(mId);+  }++  template <typename Handler>+  void async_wait(Handler handler)+  {+    auto pScheduler = mpScheduler.lock();+    pScheduler->setTimer(mId, mExpiration, std::move(handler));+  }++  TimePoint now() const+  {+    return mNow;+  }++  const SchedulerTree::TimerId mId;+  const TimePoint& mNow;+  TimePoint mExpiration;+  std::weak_ptr<SchedulerTree> mpScheduler;+  bool mbMovedFrom = false;+};++} // namespace serial_io+} // namespace test+} // namespace ableton
+ link/include/ableton/util/Injected.hpp view
@@ -0,0 +1,254 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <memory>++namespace ableton+{+namespace util+{++// Utility type for aiding in dependency injection.++// Base template and implementation for injected valued+template <typename T>+struct Injected+{+  using type = T;++  Injected() = default;++  explicit Injected(T t)+    : val(std::move(t))+  {+  }++  Injected(const Injected&) = default;+  Injected& operator=(const Injected&) = default;++  Injected(Injected&& rhs)+    : val(std::move(rhs.val))+  {+  }++  Injected& operator=(Injected&& rhs)+  {+    val = std::move(rhs.val);+    return *this;+  }++  T* operator->()+  {+    return &val;+  }++  const T* operator->() const+  {+    return &val;+  }++  T& operator*()+  {+    return val;+  }++  const T& operator*() const+  {+    return val;+  }++  T val;+};++// Utility function for injecting values+template <typename T>+Injected<T> injectVal(T t)+{+  return Injected<T>(std::move(t));+}++// Specialization for injected references+template <typename T>+struct Injected<T&>+{+  using type = T;++  explicit Injected(T& t)+    : ref(std::ref(t))+  {+  }++  Injected(const Injected&) = default;+  Injected& operator=(const Injected&) = default;++  Injected(Injected&& rhs)+    : ref(std::move(rhs.ref))+  {+  }++  Injected& operator=(Injected&& rhs)+  {+    ref = std::move(rhs.ref);+    return *this;+  }++  T* operator->()+  {+    return &ref.get();+  }++  const T* operator->() const+  {+    return &ref.get();+  }++  T& operator*()+  {+    return ref;+  }++  const T& operator*() const+  {+    return ref;+  }++  std::reference_wrapper<T> ref;+};++// Utility function for injecting references+template <typename T>+Injected<T&> injectRef(T& t)+{+  return Injected<T&>(t);+}++// Specialization for injected shared_ptr+template <typename T>+struct Injected<std::shared_ptr<T>>+{+  using type = T;++  explicit Injected(std::shared_ptr<T> pT)+    : shared(std::move(pT))+  {+  }++  Injected(const Injected&) = default;+  Injected& operator=(const Injected&) = default;++  Injected(Injected&& rhs)+    : shared(std::move(rhs.shared))+  {+  }++  Injected& operator=(Injected&& rhs)+  {+    shared = std::move(rhs.shared);+    return *this;+  }++  T* operator->()+  {+    return shared.get();+  }++  const T* operator->() const+  {+    return shared.get();+  }++  T& operator*()+  {+    return *shared;+  }++  const T& operator*() const+  {+    return *shared;+  }++  std::shared_ptr<T> shared;+};++// Utility function for injected shared_ptr+template <typename T>+Injected<std::shared_ptr<T>> injectShared(std::shared_ptr<T> shared)+{+  return Injected<std::shared_ptr<T>>(std::move(shared));+}++// Specialization for injected unique_ptr+template <typename T>+struct Injected<std::unique_ptr<T>>+{+  using type = T;++  explicit Injected(std::unique_ptr<T> pT)+    : unique(std::move(pT))+  {+  }++  Injected(const Injected&) = default;+  Injected& operator=(const Injected&) = default;++  Injected(Injected&& rhs)+    : unique(std::move(rhs.unique))+  {+  }++  Injected& operator=(Injected&& rhs)+  {+    unique = std::move(rhs.unique);+    return *this;+  }++  T* operator->()+  {+    return unique.get();+  }++  const T* operator->() const+  {+    return unique.get();+  }++  T& operator*()+  {+    return *unique;+  }++  const T& operator*() const+  {+    return *unique;+  }++  std::unique_ptr<T> unique;+};++// Utility function for injected unique_ptr+template <typename T>+Injected<std::unique_ptr<T>> injectUnique(std::unique_ptr<T> unique)+{+  return Injected<std::unique_ptr<T>>(std::move(unique));+}++} // namespace util+} // namespace ableton
+ link/include/ableton/util/Log.hpp view
@@ -0,0 +1,176 @@+// Copyright: 2014, Ableton AG, Berlin, all rights reserved++#pragma once++#include <ableton/util/Injected.hpp>+#include <iostream>+#include <string>++namespace ableton+{+namespace util+{++// Null object for the Log concept+struct NullLog+{+  template <typename T>+  friend const NullLog& operator<<(const NullLog& log, const T&)+  {+    return log;+  }++  friend const NullLog& debug(const NullLog& log)+  {+    return log;+  }++  friend const NullLog& info(const NullLog& log)+  {+    return log;+  }++  friend const NullLog& warning(const NullLog& log)+  {+    return log;+  }++  friend const NullLog& error(const NullLog& log)+  {+    return log;+  }++  friend NullLog channel(const NullLog&, std::string)+  {+    return {};+  }+};++// std streams-based log+struct StdLog+{+  StdLog(std::string channelName = "")+    : mChannelName(std::move(channelName))+  {+  }++  // Stream type used by std log to prepend the channel name to log messages+  struct StdLogStream+  {+    StdLogStream(std::ostream& ioStream, const std::string& channelName)+      : mpIoStream(&ioStream)+      , mChannelName(channelName)+    {+      ioStream << "[" << mChannelName << "] ";+    }++    StdLogStream(StdLogStream&& rhs)+      : mpIoStream(rhs.mpIoStream)+      , mChannelName(rhs.mChannelName)+    {+      rhs.mpIoStream = nullptr;+    }++    ~StdLogStream()+    {+      if (mpIoStream)+      {+        (*mpIoStream) << "\n";+      }+    }++    template <typename T>+    std::ostream& operator<<(const T& rhs)+    {+      (*mpIoStream) << rhs;+      return *mpIoStream;+    }++    std::ostream* mpIoStream;+    const std::string& mChannelName;+  };++  friend StdLogStream debug(const StdLog& log)+  {+    return {std::clog, log.mChannelName};+  }++  friend StdLogStream info(const StdLog& log)+  {+    return {std::clog, log.mChannelName};+  }++  friend StdLogStream warning(const StdLog& log)+  {+    return {std::clog, log.mChannelName};+  }++  friend StdLogStream error(const StdLog& log)+  {+    return {std::cerr, log.mChannelName};+  }++  friend StdLog channel(const StdLog& log, const std::string& channelName)+  {+    auto compositeName =+      log.mChannelName.empty() ? channelName : log.mChannelName + "::" + channelName;+    return {std::move(compositeName)};+  }++  std::string mChannelName;+};++// Log adapter that adds timestamps+template <typename Log>+struct Timestamped+{+  using InnerLog = typename util::Injected<Log>::type;++  Timestamped() = default;++  Timestamped(util::Injected<Log> log)+    : mLog(std::move(log))+  {+  }++  util::Injected<Log> mLog;++  friend decltype(debug(std::declval<InnerLog>())) debug(const Timestamped& log)+  {+    return log.logTimestamp(debug(*log.mLog));+  }++  friend decltype(info(std::declval<InnerLog>())) info(const Timestamped& log)+  {+    return log.logTimestamp(info(*log.mLog));+  }++  friend decltype(warning(std::declval<InnerLog>())) warning(const Timestamped& log)+  {+    return log.logTimestamp(warning(*log.mLog));+  }++  friend decltype(error(std::declval<InnerLog>())) error(const Timestamped& log)+  {+    return log.logTimestamp(error(*log.mLog));+  }++  friend Timestamped channel(const Timestamped& log, const std::string& channelName)+  {+    return {channel(*log.mLog, channelName)};+  }++  template <typename Stream>+  Stream logTimestamp(Stream&& streamRef) const+  {+    using namespace std::chrono;+    Stream stream = std::forward<Stream>(streamRef);+    stream << "|"+           << duration_cast<milliseconds>(system_clock::now().time_since_epoch()).count()+           << "ms| ";+    return stream;+  }+};++} // namespace util+} // namespace ableton
+ link/include/ableton/util/SafeAsyncHandler.hpp view
@@ -0,0 +1,66 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <memory>++namespace ableton+{+namespace util+{++// A utility handler for passing to async functions that may call the+// handler past the lifetime of the wrapped delegate object.+// The need for this is particularly driven by boost::asio timer+// objects, which explicitly document that they may be called without+// an error code after they have been cancelled. This has led to+// several crashes. This handler wrapper implements a useful idiom for+// avoiding this problem.++template <typename Delegate>+struct SafeAsyncHandler+{+  SafeAsyncHandler(const std::shared_ptr<Delegate>& pDelegate)+    : mpDelegate(pDelegate)+  {+  }++  template <typename... T>+  void operator()(T&&... t) const+  {+    std::shared_ptr<Delegate> pDelegate = mpDelegate.lock();+    if (pDelegate)+    {+      (*pDelegate)(std::forward<T>(t)...);+    }+  }++  std::weak_ptr<Delegate> mpDelegate;+};++// Factory function for easily wrapping a shared_ptr to a handler+template <typename Delegate>+SafeAsyncHandler<Delegate> makeAsyncSafe(const std::shared_ptr<Delegate>& pDelegate)+{+  return {pDelegate};+}++} // namespace util+} // namespace ableton
+ link/include/ableton/util/SampleTiming.hpp view
@@ -0,0 +1,52 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <chrono>++namespace ableton+{+namespace util+{++/*! Utility type to convert between time and sample index given the+ *  time at the beginning of a buffer and the sample rate.+ */+struct SampleTiming+{+  double sampleAtTime(std::chrono::microseconds time) const+  {+    using namespace std::chrono;+    return duration_cast<duration<double>>(time - mBufferBegin).count() * mSampleRate;+  }++  std::chrono::microseconds timeAtSample(const double sample) const+  {+    using namespace std::chrono;+    return mBufferBegin+           + duration_cast<microseconds>(duration<double>{sample / mSampleRate});+  }++  std::chrono::microseconds mBufferBegin;+  double mSampleRate;+};++} // namespace util+} // namespace ableton
+ link/include/ableton/util/test/IoService.hpp view
@@ -0,0 +1,114 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <ableton/util/test/Timer.hpp>++namespace ableton+{+namespace util+{+namespace test+{++struct IoService+{+  // Wrapper around the internal util::test::Timer in the list+  struct Timer+  {+    using ErrorCode = test::Timer::ErrorCode;+    using TimePoint = test::Timer::TimePoint;++    Timer(util::test::Timer* pTimer)+      : mpTimer(pTimer)+    {+    }++    void expires_at(std::chrono::system_clock::time_point t)+    {+      mpTimer->expires_at(t);+    }++    template <typename T, typename Rep>+    void expires_from_now(std::chrono::duration<T, Rep> duration)+    {+      mpTimer->expires_from_now(duration);+    }++    ErrorCode cancel()+    {+      return mpTimer->cancel();+    }++    template <typename Handler>+    void async_wait(Handler handler)+    {+      mpTimer->async_wait(std::move(handler));+    }++    TimePoint now() const+    {+      return mpTimer->now();+    }++    util::test::Timer* mpTimer;+  };++  IoService() = default;++  Timer makeTimer()+  {+    mTimers.emplace_back();+    return Timer{&mTimers.back()};+  }++  template <typename Handler>+  void post(Handler handler)+  {+    mHandlers.emplace_back(std::move(handler));+  }++  template <typename T, typename Rep>+  void advance(std::chrono::duration<T, Rep> duration)+  {+    runHandlers();++    for (auto& timer : mTimers)+    {+      timer.advance(duration);+    }+  }++  void runHandlers()+  {+    for (auto& handler : mHandlers)+    {+      handler();+    }+    mHandlers.clear();+  }++  std::vector<std::function<void()>> mHandlers;+  std::vector<util::test::Timer> mTimers;+};++} // namespace test+} // namespace util+} // namespace ableton
+ link/include/ableton/util/test/Timer.hpp view
@@ -0,0 +1,96 @@+/* Copyright 2016, Ableton AG, Berlin. All rights reserved.+ *+ *  This program is free software: you can redistribute it and/or modify+ *  it under the terms of the GNU General Public License as published by+ *  the Free Software Foundation, either version 2 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 General Public License for more details.+ *+ *  You should have received a copy of the GNU General Public License+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.+ *+ *  If you would like to incorporate Link into a proprietary software application,+ *  please contact <link-devs@ableton.com>.+ */++#pragma once++#include <chrono>+#include <functional>++namespace ableton+{+namespace util+{+namespace test+{++struct Timer+{+  using ErrorCode = int;+  using TimePoint = std::chrono::system_clock::time_point;++  // Initialize timer with an arbitrary large value to simulate the+  // time_since_epoch of a real clock.+  Timer()+    : mNow{std::chrono::milliseconds{123456789}}+  {+  }++  void expires_at(std::chrono::system_clock::time_point t)+  {+    cancel();+    mFireAt = std::move(t);+  }++  template <typename T, typename Rep>+  void expires_from_now(std::chrono::duration<T, Rep> duration)+  {+    cancel();+    mFireAt = now() + duration;+  }++  ErrorCode cancel()+  {+    if (mHandler)+    {+      mHandler(1); // call existing handler with truthy error code+    }+    mHandler = nullptr;+    return 0;+  }++  template <typename Handler>+  void async_wait(Handler handler)+  {+    mHandler = [handler](ErrorCode ec) { handler(ec); };+  }++  std::chrono::system_clock::time_point now() const+  {+    return mNow;+  }++  template <typename T, typename Rep>+  void advance(std::chrono::duration<T, Rep> duration)+  {+    mNow += duration;+    if (mHandler && mFireAt < mNow)+    {+      mHandler(0);+      mHandler = nullptr;+    }+  }++  std::function<void(ErrorCode)> mHandler;+  std::chrono::system_clock::time_point mFireAt;+  std::chrono::system_clock::time_point mNow;+};++} // namespace test+} // namespace util+} // namespace ableton
+ link/modules/asio-standalone/asio/include/asio.hpp view
@@ -0,0 +1,182 @@+//+// asio.hpp+// ~~~~~~~~+//+// Copyright (c) 2003-2020 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/async_result.hpp"+#include "asio/awaitable.hpp"+#include "asio/basic_datagram_socket.hpp"+#include "asio/basic_deadline_timer.hpp"+#include "asio/basic_io_object.hpp"+#include "asio/basic_raw_socket.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_socket.hpp"+#include "asio/basic_streambuf.hpp"+#include "asio/basic_waitable_timer.hpp"+#include "asio/bind_executor.hpp"+#include "asio/buffer.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/co_spawn.hpp"+#include "asio/completion_condition.hpp"+#include "asio/compose.hpp"+#include "asio/connect.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/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/read.hpp"+#include "asio/read_at.hpp"+#include "asio/read_until.hpp"+#include "asio/redirect_error.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/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/write.hpp"+#include "asio/write_at.hpp"++#endif // ASIO_HPP
+ link/modules/asio-standalone/asio/include/asio/any_io_executor.hpp view
@@ -0,0 +1,71 @@+//+// any_io_executor.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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+ */+#if defined(GENERATING_DOCUMENTATION)+typedef execution::any_executor<...> any_io_executor;+#else // 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>+  > any_io_executor;+#endif // defined(GENERATING_DOCUMENTATION)++#endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ANY_IO_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/associated_allocator.hpp view
@@ -0,0 +1,125 @@+//+// associated_allocator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename T, typename E, 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();+  }+};++} // 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>+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>+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)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ASSOCIATED_ALLOCATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/associated_executor.hpp view
@@ -0,0 +1,166 @@+//+// associated_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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/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 {+namespace detail {++template <typename T, typename E, 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();+  }+};++} // 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>+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>+inline typename associated_executor<T, Executor>::type+get_associated_executor(const T& t, const Executor& ex,+    typename enable_if<+      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>+inline typename associated_executor<T,+  typename ExecutionContext::executor_type>::type+get_associated_executor(const T& t, ExecutionContext& ctx,+    typename enable_if<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+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ASSOCIATED_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/async_result.hpp view
@@ -0,0 +1,582 @@+//+// async_result.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_ASYNC_RESULT_HPP+#define ASIO_ASYNC_RESULT_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/detail/push_options.hpp"++namespace asio {++#if defined(ASIO_HAS_CONCEPTS) \+  && defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  && defined(ASIO_HAS_DECLTYPE)++namespace detail {++template <typename T>+struct is_completion_signature : false_type+{+};++template <typename R, typename... Args>+struct is_completion_signature<R(Args...)> : true_type+{+};++template <typename T, typename... Args>+ASIO_CONCEPT callable_with = requires(T t, Args&&... args)+{+  t(static_cast<Args&&>(args)...);+};++template <typename T, typename Signature>+struct is_completion_handler_for : false_type+{+};++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...)>+  : integral_constant<bool, (callable_with<T, Args...>)>+{+};++} // namespace detail++template <typename T>+ASIO_CONCEPT completion_signature =+  detail::is_completion_signature<T>::value;++#define ASIO_COMPLETION_SIGNATURE \+  ::asio::completion_signature++template <typename T, typename Signature>+ASIO_CONCEPT completion_handler_for =+  detail::is_completion_signature<Signature>::value+    && detail::is_completion_handler_for<T, Signature>::value;++#define ASIO_COMPLETION_HANDLER_FOR(s) \+  ::asio::completion_handler_for<s>++#else // defined(ASIO_HAS_CONCEPTS)+      //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   && defined(ASIO_HAS_DECLTYPE)++#define ASIO_COMPLETION_SIGNATURE typename+#define ASIO_COMPLETION_HANDLER_FOR(s) typename++#endif // defined(ASIO_HAS_CONCEPTS)+       //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   && defined(ASIO_HAS_DECLTYPE)++/// An interface for customising the behaviour of an initiating function.+/**+ * The async_result traits class is used for determining:+ *+ * @li the concrete completion handler type to be called at the end of the+ * asynchronous operation;+ *+ * @li the initiating function return type; and+ *+ * @li how the return value of the initiating function is obtained.+ *+ * The trait allows the handler and return types to be determined at the point+ * where the specific completion handler signature is known.+ *+ * This template may be specialised for user-defined completion token types.+ * The primary template assumes that the CompletionToken is the completion+ * handler.+ */+template <typename CompletionToken, ASIO_COMPLETION_SIGNATURE Signature>+class async_result+{+public:+  /// The concrete completion handler type for the specific signature.+  typedef CompletionToken completion_handler_type;++  /// The return type of the initiating function.+  typedef void return_type;++  /// Construct an async result from a given handler.+  /**+   * When using a specalised async_result, the constructor has an opportunity+   * to initialise some state associated with the completion handler, which is+   * then returned from the initiating function.+   */+  explicit async_result(completion_handler_type& h)+  {+    (void)h;+  }++  /// Obtain the value to be returned from the initiating function.+  return_type get()+  {+  }++#if defined(GENERATING_DOCUMENTATION)++  /// Initiate the asynchronous operation that will produce the result, and+  /// obtain the value to be returned from the initiating function.+  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static return_type initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args);++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation,+      ASIO_COMPLETION_HANDLER_FOR(Signature) RawCompletionToken,+      typename... Args>+  static return_type initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+  {+    ASIO_MOVE_CAST(Initiation)(initiation)(+        ASIO_MOVE_CAST(RawCompletionToken)(token),+        ASIO_MOVE_CAST(Args)(args)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation,+      ASIO_COMPLETION_HANDLER_FOR(Signature) RawCompletionToken>+  static return_type initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token)+  {+    ASIO_MOVE_CAST(Initiation)(initiation)(+        ASIO_MOVE_CAST(RawCompletionToken)(token));+  }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, \+      ASIO_COMPLETION_HANDLER_FOR(Signature) RawCompletionToken, \+      ASIO_VARIADIC_TPARAMS(n)> \+  static return_type initiate( \+      ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_MOVE_ARG(RawCompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    ASIO_MOVE_CAST(Initiation)(initiation)( \+        ASIO_MOVE_CAST(RawCompletionToken)(token), \+        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;+};++#if !defined(GENERATING_DOCUMENTATION)++template <ASIO_COMPLETION_SIGNATURE Signature>+class async_result<void, Signature>+{+  // Empty.+};++#endif // !defined(GENERATING_DOCUMENTATION)++/// Helper template to deduce the handler type from a CompletionToken, capture+/// a local copy of the handler, and then create an async_result for the+/// handler.+template <typename CompletionToken, ASIO_COMPLETION_SIGNATURE Signature>+struct async_completion+{+  /// The real handler type to be used for the asynchronous operation.+  typedef typename asio::async_result<+    typename decay<CompletionToken>::type,+      Signature>::completion_handler_type completion_handler_type;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Constructor.+  /**+   * The constructor creates the concrete completion handler and makes the link+   * between the handler and the asynchronous result.+   */+  explicit async_completion(CompletionToken& token)+    : completion_handler(static_cast<typename conditional<+        is_same<CompletionToken, completion_handler_type>::value,+        completion_handler_type&, CompletionToken&&>::type>(token)),+      result(completion_handler)+  {+  }+#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  explicit async_completion(typename decay<CompletionToken>::type& token)+    : completion_handler(token),+      result(completion_handler)+  {+  }++  explicit async_completion(const typename decay<CompletionToken>::type& token)+    : completion_handler(token),+      result(completion_handler)+  {+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// A copy of, or reference to, a real handler object.+#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  typename conditional<+    is_same<CompletionToken, completion_handler_type>::value,+    completion_handler_type&, completion_handler_type>::type completion_handler;+#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  completion_handler_type completion_handler;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// The result of the asynchronous operation's initiating function.+  async_result<typename decay<CompletionToken>::type, Signature> result;+};++namespace detail {++template <typename CompletionToken, typename Signature>+struct async_result_helper+  : async_result<typename decay<CompletionToken>::type, Signature>+{+};++struct async_result_memfns_base+{+  void initiate();+};++template <typename T>+struct async_result_memfns_derived+  : T, async_result_memfns_base+{+};++template <typename T, T>+struct async_result_memfns_check+{+};++template <typename>+char (&async_result_initiate_memfn_helper(...))[2];++template <typename T>+char async_result_initiate_memfn_helper(+    async_result_memfns_check<+      void (async_result_memfns_base::*)(),+      &async_result_memfns_derived<T>::initiate>*);++template <typename CompletionToken, typename Signature>+struct async_result_has_initiate_memfn+  : integral_constant<bool, sizeof(async_result_initiate_memfn_helper<+      async_result<typename decay<CompletionToken>::type, Signature>+    >(0)) != 1>+{+};++} // namespace detail++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_INITFN_RESULT_TYPE(ct, sig) \+  void_or_deduced+#elif defined(_MSC_VER) && (_MSC_VER < 1500)+# define ASIO_INITFN_RESULT_TYPE(ct, sig) \+  typename ::asio::detail::async_result_helper< \+    ct, sig>::return_type+#define ASIO_HANDLER_TYPE(ct, sig) \+  typename ::asio::detail::async_result_helper< \+    ct, sig>::completion_handler_type+#else+# define ASIO_INITFN_RESULT_TYPE(ct, sig) \+  typename ::asio::async_result< \+    typename ::asio::decay<ct>::type, sig>::return_type+#define ASIO_HANDLER_TYPE(ct, sig) \+  typename ::asio::async_result< \+    typename ::asio::decay<ct>::type, sig>::completion_handler_type+#endif++#if defined(GENERATION_DOCUMENTATION)+# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \+  auto+#elif defined(ASIO_HAS_RETURN_TYPE_DEDUCTION)+# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \+  auto+#else+# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \+  ASIO_INITFN_RESULT_TYPE(ct, sig)+#endif++#if defined(GENERATION_DOCUMENTATION)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \+  void_or_deduced+#elif defined(ASIO_HAS_DECLTYPE)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \+  decltype expr+#else+# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \+  ASIO_INITFN_RESULT_TYPE(ct, sig)+#endif++#if defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken,+    completion_signature Signature,+    typename Initiation, typename... Args>+void_or_deduced async_initiate(+    ASIO_MOVE_ARG(Initiation) initiation,+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken),+    ASIO_MOVE_ARG(Args)... args);++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Signature,+    typename Initiation, typename... Args>+inline typename enable_if<+    detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,+    ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signature,+      (async_result<typename decay<CompletionToken>::type,+        Signature>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(),+          declval<ASIO_MOVE_ARG(CompletionToken)>(),+          declval<ASIO_MOVE_ARG(Args)>()...)))>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,+    ASIO_MOVE_ARG(Args)... args)+{+  return async_result<typename decay<CompletionToken>::type,+    Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+      ASIO_MOVE_CAST(CompletionToken)(token),+      ASIO_MOVE_CAST(Args)(args)...);+}++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Signature,+    typename Initiation, typename... Args>+inline typename enable_if<+    !detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,+    ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,+    ASIO_MOVE_ARG(Args)... args)+{+  async_completion<CompletionToken, Signature> completion(token);++  ASIO_MOVE_CAST(Initiation)(initiation)(+      ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,+        Signature))(completion.completion_handler),+      ASIO_MOVE_CAST(Args)(args)...);++  return completion.result.get();+}++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Signature,+    typename Initiation>+inline typename enable_if<+    detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,+    ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signature,+      (async_result<typename decay<CompletionToken>::type,+        Signature>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(),+          declval<ASIO_MOVE_ARG(CompletionToken)>())))>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+  return async_result<typename decay<CompletionToken>::type,+    Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+      ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Signature,+    typename Initiation>+inline typename enable_if<+    !detail::async_result_has_initiate_memfn<CompletionToken, Signature>::value,+    ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+  async_completion<CompletionToken, Signature> completion(token);++  ASIO_MOVE_CAST(Initiation)(initiation)(+      ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,+        Signature))(completion.completion_handler));++  return completion.result.get();+}++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename CompletionToken, \+      ASIO_COMPLETION_SIGNATURE Signature, \+      typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  inline typename enable_if< \+      detail::async_result_has_initiate_memfn< \+        CompletionToken, Signature>::value, \+      ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signature, \+        (async_result<typename decay<CompletionToken>::type, \+          Signature>::initiate(declval<ASIO_MOVE_ARG(Initiation)>(), \+            declval<ASIO_MOVE_ARG(CompletionToken)>(), \+            ASIO_VARIADIC_MOVE_DECLVAL(n))))>::type \+  async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return async_result<typename decay<CompletionToken>::type, \+      Signature>::initiate(ASIO_MOVE_CAST(Initiation)(initiation), \+        ASIO_MOVE_CAST(CompletionToken)(token), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <typename CompletionToken, \+      ASIO_COMPLETION_SIGNATURE Signature, \+      typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  inline typename enable_if< \+      !detail::async_result_has_initiate_memfn< \+        CompletionToken, Signature>::value, \+      ASIO_INITFN_RESULT_TYPE(CompletionToken, Signature)>::type \+  async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    async_completion<CompletionToken, Signature> completion(token); \+  \+    ASIO_MOVE_CAST(Initiation)(initiation)( \+        ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, \+          Signature))(completion.completion_handler), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  \+    return completion.result.get(); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS) \+  && defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  && defined(ASIO_HAS_DECLTYPE)++namespace detail {++template <typename Signature>+struct initiation_archetype+{+  template <completion_handler_for<Signature> CompletionHandler>+  void operator()(CompletionHandler&&) const+  {+  }+};++} // namespace detail++template <typename T, typename Signature>+ASIO_CONCEPT completion_token_for =+  detail::is_completion_signature<Signature>::value+  &&+  requires(T&& t)+  {+    async_initiate<T, Signature>(detail::initiation_archetype<Signature>{}, t);+  };++#define ASIO_COMPLETION_TOKEN_FOR(s) \+  ::asio::completion_token_for<s>++#else // defined(ASIO_HAS_CONCEPTS)+      //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   && defined(ASIO_HAS_DECLTYPE)++#define ASIO_COMPLETION_TOKEN_FOR(s) typename++#endif // defined(ASIO_HAS_CONCEPTS)+       //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   && defined(ASIO_HAS_DECLTYPE)++namespace detail {++template <typename T, typename = void>+struct default_completion_token_impl+{+  typedef void type;+};++template <typename T>+struct default_completion_token_impl<T,+  typename void_type<typename T::default_completion_token_type>::type>+{+  typedef typename T::default_completion_token_type type;+};++} // namespace detail++#if defined(GENERATING_DOCUMENTATION)++/// Traits type used to determine the default completion token type associated+/// with a type (such as an executor).+/**+ * A program may specialise this traits type if the @c T template parameter in+ * the specialisation is a user-defined type.+ *+ * Specialisations of this trait may provide a nested typedef @c type, which is+ * a default-constructible completion token type.+ */+template <typename T>+struct default_completion_token+{+  /// If @c T has a nested type @c default_completion_token_type,+  /// <tt>T::default_completion_token_type</tt>. Otherwise the typedef @c type+  /// is not defined.+  typedef see_below type;+};+#else+template <typename T>+struct default_completion_token+  : detail::default_completion_token_impl<T>+{+};+#endif++#if defined(ASIO_HAS_ALIAS_TEMPLATES)++template <typename T>+using default_completion_token_t = typename default_completion_token<T>::type;++#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++#if defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS)++#define ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(e) \+  = typename ::asio::default_completion_token<e>::type+#define ASIO_DEFAULT_COMPLETION_TOKEN(e) \+  = typename ::asio::default_completion_token<e>::type()++#else // defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS)++#define ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(e)+#define ASIO_DEFAULT_COMPLETION_TOKEN(e)++#endif // defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ASYNC_RESULT_HPP
+ link/modules/asio-standalone/asio/include/asio/awaitable.hpp view
@@ -0,0 +1,133 @@+//+// awaitable.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 "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 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();+  }++  /// 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
+ link/modules/asio-standalone/asio/include/asio/basic_datagram_socket.hpp view
@@ -0,0 +1,1215 @@+//+// basic_datagram_socket.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DATAGRAM_SOCKET_HPP+#define ASIO_BASIC_DATAGRAM_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/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)+#define ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Protocol, typename Executor = any_io_executor>+class basic_datagram_socket;++#endif // !defined(ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)++/// Provides datagram-oriented socket functionality.+/**+ * The basic_datagram_socket class template provides asynchronous and blocking+ * datagram-oriented socket functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Protocol, typename Executor>+class basic_datagram_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_datagram_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_datagram_socket without opening it.+  /**+   * This constructor creates a datagram socket without opening it. The open()+   * function must be called before data can be sent or received on the 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.+   */+  explicit basic_datagram_socket(const executor_type& ex)+    : basic_socket<Protocol, Executor>(ex)+  {+  }++  /// Construct a basic_datagram_socket without opening it.+  /**+   * This constructor creates a datagram socket without opening it. The open()+   * function must be called before data can be sent or received on the 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.+   */+  template <typename ExecutionContext>+  explicit basic_datagram_socket(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(context)+  {+  }++  /// Construct and open a basic_datagram_socket.+  /**+   * This constructor creates and opens a datagram 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.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_datagram_socket(const executor_type& ex, const protocol_type& protocol)+    : basic_socket<Protocol, Executor>(ex, protocol)+  {+  }++  /// Construct and open a basic_datagram_socket.+  /**+   * This constructor creates and opens a datagram 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.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_datagram_socket(ExecutionContext& context,+      const protocol_type& protocol,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(context, protocol)+  {+  }++  /// Construct a basic_datagram_socket, opening it and binding it to the given+  /// local endpoint.+  /**+   * This constructor creates a datagram 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 datagram+   * socket will be bound.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_datagram_socket(const executor_type& ex, const endpoint_type& endpoint)+    : basic_socket<Protocol, Executor>(ex, endpoint)+  {+  }++  /// Construct a basic_datagram_socket, opening it and binding it to the given+  /// local endpoint.+  /**+   * This constructor creates a datagram 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 datagram+   * socket will be bound.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_datagram_socket(ExecutionContext& context,+      const endpoint_type& endpoint,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(context, endpoint)+  {+  }++  /// Construct a basic_datagram_socket on an existing native socket.+  /**+   * This constructor creates a datagram 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_datagram_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_datagram_socket on an existing native socket.+  /**+   * This constructor creates a datagram 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_datagram_socket(ExecutionContext& context,+      const protocol_type& protocol, const native_handle_type& native_socket,+      typename enable_if<+        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_datagram_socket from another.+  /**+   * This constructor moves a datagram socket from one object to another.+   *+   * @param other The other basic_datagram_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_datagram_socket(const executor_type&)+   * constructor.+   */+  basic_datagram_socket(basic_datagram_socket&& other) ASIO_NOEXCEPT+    : basic_socket<Protocol, Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_datagram_socket from another.+  /**+   * This assignment operator moves a datagram socket from one object to+   * another.+   *+   * @param other The other basic_datagram_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_datagram_socket(const executor_type&)+   * constructor.+   */+  basic_datagram_socket& operator=(basic_datagram_socket&& other)+  {+    basic_socket<Protocol, Executor>::operator=(std::move(other));+    return *this;+  }++  /// Move-construct a basic_datagram_socket from a socket of another protocol+  /// type.+  /**+   * This constructor moves a datagram socket from one object to another.+   *+   * @param other The other basic_datagram_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_datagram_socket(const executor_type&)+   * constructor.+   */+  template <typename Protocol1, typename Executor1>+  basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other,+      typename enable_if<+        is_convertible<Protocol1, Protocol>::value+          && is_convertible<Executor1, Executor>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_datagram_socket from a socket of another protocol+  /// type.+  /**+   * This assignment operator moves a datagram socket from one object to+   * another.+   *+   * @param other The other basic_datagram_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_datagram_socket(const executor_type&)+   * constructor.+   */+  template <typename Protocol1, typename Executor1>+  typename enable_if<+    is_convertible<Protocol1, Protocol>::value+      && is_convertible<Executor1, Executor>::value,+    basic_datagram_socket&+  >::type operator=(basic_datagram_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_datagram_socket()+  {+  }++  /// Send some data on a connected socket.+  /**+   * This function is used to send data on the datagram socket. The function+   * call will block until the data has been sent successfully or an error+   * occurs.+   *+   * @param buffers One ore more data buffers to be sent on the socket.+   *+   * @returns The number of bytes sent.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note The send operation can only be used with a connected socket. Use+   * the send_to function to send data on an unconnected datagram socket.+   *+   * @par Example+   * To send a single data buffer use the @ref buffer function as follows:+   * @code socket.send(asio::buffer(data, size)); @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)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().send(+        this->impl_.get_implementation(), buffers, 0, ec);+    asio::detail::throw_error(ec, "send");+    return s;+  }++  /// Send some data on a connected socket.+  /**+   * This function is used to send data on the datagram socket. The function+   * call will block until the data has been sent successfully or an error+   * occurs.+   *+   * @param buffers One ore 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.+   *+   * @note The send operation can only be used with a connected socket. Use+   * the send_to function to send data on an unconnected datagram socket.+   */+  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 a connected socket.+  /**+   * This function is used to send data on the datagram socket. The function+   * call will block until the data has been sent successfully or an 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.+   *+   * @note The send operation can only be used with a connected socket. Use+   * the send_to function to send data on an unconnected datagram socket.+   */+  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 on a connected socket.+  /**+   * This function is used to asynchronously send data on the datagram socket.+   * The function call 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 handler is called.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @note The async_send operation can only be used with a connected socket.+   * Use the async_send_to function to send data on an unconnected datagram+   * socket.+   *+   * @par Example+   * To send a single data buffer use the @ref buffer function as follows:+   * @code+   * socket.async_send(asio::buffer(data, size), 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.+   */+  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_send(const ConstBufferSequence& buffers,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send(this), handler,+        buffers, socket_base::message_flags(0));+  }++  /// Start an asynchronous send on a connected socket.+  /**+   * This function is used to asynchronously send data on the datagram socket.+   * The function call 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 handler is called.+   *+   * @param flags Flags specifying how the send call is to be made.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @note The async_send operation can only be used with a connected socket.+   * Use the async_send_to function to send data on an unconnected datagram+   * socket.+   */+  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_send(const ConstBufferSequence& buffers,+      socket_base::message_flags flags,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send(this), handler, buffers, flags);+  }++  /// Send a datagram to the specified endpoint.+  /**+   * This function is used to send a datagram to the specified remote endpoint.+   * The function call will block until the data has been sent successfully or+   * an error occurs.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   *+   * @param destination The remote endpoint to which the data will be sent.+   *+   * @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+   * asio::ip::udp::endpoint destination(+   *     asio::ip::address::from_string("1.2.3.4"), 12345);+   * socket.send_to(asio::buffer(data, size), destination);+   * @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_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().send_to(+        this->impl_.get_implementation(), buffers, destination, 0, ec);+    asio::detail::throw_error(ec, "send_to");+    return s;+  }++  /// Send a datagram to the specified endpoint.+  /**+   * This function is used to send a datagram to the specified remote endpoint.+   * The function call will block until the data has been sent successfully or+   * an error occurs.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   *+   * @param destination The remote endpoint to which the data will be sent.+   *+   * @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.+   */+  template <typename ConstBufferSequence>+  std::size_t send_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination, socket_base::message_flags flags)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().send_to(+        this->impl_.get_implementation(), buffers, destination, flags, ec);+    asio::detail::throw_error(ec, "send_to");+    return s;+  }++  /// Send a datagram to the specified endpoint.+  /**+   * This function is used to send a datagram to the specified remote endpoint.+   * The function call will block until the data has been sent successfully or+   * an error occurs.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   *+   * @param destination The remote endpoint to which the data will be sent.+   *+   * @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.+   */+  template <typename ConstBufferSequence>+  std::size_t send_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination, socket_base::message_flags flags,+      asio::error_code& ec)+  {+    return this->impl_.get_service().send_to(this->impl_.get_implementation(),+        buffers, destination, flags, ec);+  }++  /// Start an asynchronous send.+  /**+   * This function is used to asynchronously send a datagram to the specified+   * remote endpoint. The function call always returns immediately.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   * 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 handler is called.+   *+   * @param destination The remote endpoint to which the data will be sent.+   * Copies will be made of the endpoint as required.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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 Example+   * To send a single data buffer use the @ref buffer function as follows:+   * @code+   * asio::ip::udp::endpoint destination(+   *     asio::ip::address::from_string("1.2.3.4"), 12345);+   * socket.async_send_to(+   *     asio::buffer(data, size), destination, 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.+   */+  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_send_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send_to(this), handler, buffers,+        destination, socket_base::message_flags(0));+  }++  /// Start an asynchronous send.+  /**+   * This function is used to asynchronously send a datagram to the specified+   * remote endpoint. The function call always returns immediately.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   * 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 handler is called.+   *+   * @param flags Flags specifying how the send call is to be made.+   *+   * @param destination The remote endpoint to which the data will be sent.+   * Copies will be made of the endpoint as required.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   */+  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_send_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination, socket_base::message_flags flags,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send_to(this), handler, buffers, destination, flags);+  }++  /// Receive some data on a connected socket.+  /**+   * This function is used to receive data on the datagram socket. The function+   * call will block until data has been received successfully or an error+   * occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @returns The number of bytes received.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note The receive operation can only be used with a connected socket. Use+   * the receive_from function to receive data on an unconnected datagram+   * socket.+   *+   * @par Example+   * To receive into a single data buffer use the @ref buffer function as+   * follows:+   * @code socket.receive(asio::buffer(data, size)); @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)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive(+        this->impl_.get_implementation(), buffers, 0, 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 datagram socket. The function+   * call will block until data has been received successfully or an error+   * occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @returns The number of bytes received.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note The receive operation can only be used with a connected socket. Use+   * the receive_from function to receive data on an unconnected datagram+   * socket.+   */+  template <typename MutableBufferSequence>+  std::size_t receive(const MutableBufferSequence& buffers,+      socket_base::message_flags flags)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive(+        this->impl_.get_implementation(), buffers, 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 datagram socket. The function+   * call will block until data has been received successfully or an error+   * occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes received.+   *+   * @note The receive operation can only be used with a connected socket. Use+   * the receive_from function to receive data on an unconnected datagram+   * socket.+   */+  template <typename MutableBufferSequence>+  std::size_t receive(const MutableBufferSequence& buffers,+      socket_base::message_flags flags, asio::error_code& ec)+  {+    return this->impl_.get_service().receive(+        this->impl_.get_implementation(), buffers, flags, ec);+  }++  /// Start an asynchronous receive on a connected socket.+  /**+   * This function is used to asynchronously receive data from the datagram+   * socket. The function call 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 handler is called.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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().+   *+   * @note The async_receive operation can only be used with a connected socket.+   * Use the async_receive_from function to receive data on an unconnected+   * datagram socket.+   *+   * @par Example+   * To receive into a single data buffer use the @ref buffer function as+   * follows:+   * @code+   * socket.async_receive(asio::buffer(data, size), 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.+   */+  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_receive(const MutableBufferSequence& buffers,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive(this), handler,+        buffers, socket_base::message_flags(0));+  }++  /// Start an asynchronous receive on a connected socket.+  /**+   * This function is used to asynchronously receive data from the datagram+   * socket. The function call 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 handler is called.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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().+   *+   * @note The async_receive operation can only be used with a connected socket.+   * Use the async_receive_from function to receive data on an unconnected+   * datagram socket.+   */+  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_receive(const MutableBufferSequence& buffers,+      socket_base::message_flags flags,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive(this), handler, buffers, flags);+  }++  /// Receive a datagram with the endpoint of the sender.+  /**+   * This function is used to receive a datagram. The function call will block+   * until data has been received successfully or an error occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the datagram.+   *+   * @returns The number of bytes received.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * To receive into a single data buffer use the @ref buffer function as+   * follows:+   * @code+   * asio::ip::udp::endpoint sender_endpoint;+   * socket.receive_from(+   *     asio::buffer(data, size), sender_endpoint);+   * @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_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive_from(+        this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec);+    asio::detail::throw_error(ec, "receive_from");+    return s;+  }+  +  /// Receive a datagram with the endpoint of the sender.+  /**+   * This function is used to receive a datagram. The function call will block+   * until data has been received successfully or an error occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the datagram.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @returns The number of bytes received.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename MutableBufferSequence>+  std::size_t receive_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint, socket_base::message_flags flags)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive_from(+        this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);+    asio::detail::throw_error(ec, "receive_from");+    return s;+  }+  +  /// Receive a datagram with the endpoint of the sender.+  /**+   * This function is used to receive a datagram. The function call will block+   * until data has been received successfully or an error occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the datagram.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes received.+   */+  template <typename MutableBufferSequence>+  std::size_t receive_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint, socket_base::message_flags flags,+      asio::error_code& ec)+  {+    return this->impl_.get_service().receive_from(+        this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);+  }++  /// Start an asynchronous receive.+  /**+   * This function is used to asynchronously receive a datagram. The function+   * call 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 handler is called.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the datagram. Ownership of the sender_endpoint object+   * is retained by the caller, which must guarantee that it is valid until the+   * handler is called.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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 Example+   * To receive into a single data buffer use the @ref buffer function as+   * follows:+   * @code socket.async_receive_from(+   *     asio::buffer(data, size), sender_endpoint, 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.+   */+  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_receive_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive_from(this), handler, buffers,+        &sender_endpoint, socket_base::message_flags(0));+  }++  /// Start an asynchronous receive.+  /**+   * This function is used to asynchronously receive a datagram. The function+   * call 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 handler is called.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the datagram. Ownership of the sender_endpoint object+   * is retained by the caller, which must guarantee that it is valid until the+   * handler is called.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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().+   */+  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_receive_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint, socket_base::message_flags flags,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive_from(this), handler,+        buffers, &sender_endpoint, flags);+  }++private:+  // Disallow copying and assignment.+  basic_datagram_socket(const basic_datagram_socket&) ASIO_DELETED;+  basic_datagram_socket& operator=(+      const basic_datagram_socket&) ASIO_DELETED;++  class initiate_async_send+  { +  public:+    typedef Executor executor_type;++    explicit initiate_async_send(basic_datagram_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_datagram_socket* self_;+  };++  class initiate_async_send_to+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_send_to(basic_datagram_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, const endpoint_type& destination,+        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_to(+          self_->impl_.get_implementation(), buffers, destination,+          flags, handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_datagram_socket* self_;+  };++  class initiate_async_receive+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_receive(basic_datagram_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 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(+          self_->impl_.get_implementation(), buffers, flags,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_datagram_socket* self_;+  };++  class initiate_async_receive_from+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_receive_from(basic_datagram_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, endpoint_type* sender_endpoint,+        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 ReadHandler.+      ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;++      detail::non_const_lvalue<ReadHandler> handler2(handler);+      self_->impl_.get_service().async_receive_from(+          self_->impl_.get_implementation(), buffers, *sender_endpoint,+          flags, handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_datagram_socket* self_;+  };+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BASIC_DATAGRAM_SOCKET_HPP
+ link/modules/asio-standalone/asio/include/asio/basic_deadline_timer.hpp view
@@ -0,0 +1,693 @@+//+// basic_deadline_timer.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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 always returns immediately.+   *+   * For each call to async_wait(), the supplied handler will be called exactly+   * once. The 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 handler The handler to be called when the timer expires. Copies+   * will be made of the handler as required. The function signature of the+   * 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 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().+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+      void (asio::error_code))+  async_wait(+      ASIO_MOVE_ARG(WaitHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WaitHandler, void (asio::error_code)>(+        initiate_async_wait(this), handler);+  }++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
+ link/modules/asio-standalone/asio/include/asio/basic_io_object.hpp view
@@ -0,0 +1,290 @@+//+// basic_io_object.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/basic_raw_socket.hpp view
@@ -0,0 +1,1206 @@+//+// basic_raw_socket.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_RAW_SOCKET_HPP+#define ASIO_BASIC_RAW_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/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_BASIC_RAW_SOCKET_FWD_DECL)+#define ASIO_BASIC_RAW_SOCKET_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Protocol, typename Executor = any_io_executor>+class basic_raw_socket;++#endif // !defined(ASIO_BASIC_RAW_SOCKET_FWD_DECL)++/// Provides raw-oriented socket functionality.+/**+ * The basic_raw_socket class template provides asynchronous and blocking+ * raw-oriented socket functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Protocol, typename Executor>+class basic_raw_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_raw_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_raw_socket without opening it.+  /**+   * This constructor creates a raw socket without opening it. The open()+   * function must be called before data can be sent or received on the 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.+   */+  explicit basic_raw_socket(const executor_type& ex)+    : basic_socket<Protocol, Executor>(ex)+  {+  }++  /// Construct a basic_raw_socket without opening it.+  /**+   * This constructor creates a raw socket without opening it. The open()+   * function must be called before data can be sent or received on the 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.+   */+  template <typename ExecutionContext>+  explicit basic_raw_socket(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(context)+  {+  }++  /// Construct and open a basic_raw_socket.+  /**+   * This constructor creates and opens a raw 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.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_raw_socket(const executor_type& ex, const protocol_type& protocol)+    : basic_socket<Protocol, Executor>(ex, protocol)+  {+  }++  /// Construct and open a basic_raw_socket.+  /**+   * This constructor creates and opens a raw 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.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_raw_socket(ExecutionContext& context, const protocol_type& protocol,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(context, protocol)+  {+  }++  /// Construct a basic_raw_socket, opening it and binding it to the given+  /// local endpoint.+  /**+   * This constructor creates a raw 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 raw+   * socket will be bound.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_raw_socket(const executor_type& ex, const endpoint_type& endpoint)+    : basic_socket<Protocol, Executor>(ex, endpoint)+  {+  }++  /// Construct a basic_raw_socket, opening it and binding it to the given+  /// local endpoint.+  /**+   * This constructor creates a raw 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 raw+   * socket will be bound.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_raw_socket(ExecutionContext& context, const endpoint_type& endpoint,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(context, endpoint)+  {+  }++  /// Construct a basic_raw_socket on an existing native socket.+  /**+   * This constructor creates a raw 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_raw_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_raw_socket on an existing native socket.+  /**+   * This constructor creates a raw 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_raw_socket(ExecutionContext& context,+      const protocol_type& protocol, const native_handle_type& native_socket,+      typename enable_if<+        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_raw_socket from another.+  /**+   * This constructor moves a raw socket from one object to another.+   *+   * @param other The other basic_raw_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_raw_socket(const executor_type&)+   * constructor.+   */+  basic_raw_socket(basic_raw_socket&& other) ASIO_NOEXCEPT+    : basic_socket<Protocol, Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_raw_socket from another.+  /**+   * This assignment operator moves a raw socket from one object to another.+   *+   * @param other The other basic_raw_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_raw_socket(const executor_type&)+   * constructor.+   */+  basic_raw_socket& operator=(basic_raw_socket&& other)+  {+    basic_socket<Protocol, Executor>::operator=(std::move(other));+    return *this;+  }++  /// Move-construct a basic_raw_socket from a socket of another protocol+  /// type.+  /**+   * This constructor moves a raw socket from one object to another.+   *+   * @param other The other basic_raw_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_raw_socket(const executor_type&)+   * constructor.+   */+  template <typename Protocol1, typename Executor1>+  basic_raw_socket(basic_raw_socket<Protocol1, Executor1>&& other,+      typename enable_if<+        is_convertible<Protocol1, Protocol>::value+          && is_convertible<Executor1, Executor>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_raw_socket from a socket of another protocol type.+  /**+   * This assignment operator moves a raw socket from one object to another.+   *+   * @param other The other basic_raw_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_raw_socket(const executor_type&)+   * constructor.+   */+  template <typename Protocol1, typename Executor1>+  typename enable_if<+    is_convertible<Protocol1, Protocol>::value+      && is_convertible<Executor1, Executor>::value,+    basic_raw_socket&+  >::type operator=(basic_raw_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_raw_socket()+  {+  }++  /// Send some data on a connected socket.+  /**+   * This function is used to send data on the raw socket. The function call+   * will block until the data has been sent successfully or an error occurs.+   *+   * @param buffers One ore more data buffers to be sent on the socket.+   *+   * @returns The number of bytes sent.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note The send operation can only be used with a connected socket. Use+   * the send_to function to send data on an unconnected raw socket.+   *+   * @par Example+   * To send a single data buffer use the @ref buffer function as follows:+   * @code socket.send(asio::buffer(data, size)); @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)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().send(+        this->impl_.get_implementation(), buffers, 0, ec);+    asio::detail::throw_error(ec, "send");+    return s;+  }++  /// Send some data on a connected socket.+  /**+   * This function is used to send data on the raw socket. The function call+   * will block until the data has been sent successfully or an error occurs.+   *+   * @param buffers One ore 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.+   *+   * @note The send operation can only be used with a connected socket. Use+   * the send_to function to send data on an unconnected raw socket.+   */+  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 a connected socket.+  /**+   * This function is used to send data on the raw socket. The function call+   * will block until the data has been sent successfully or an 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.+   *+   * @note The send operation can only be used with a connected socket. Use+   * the send_to function to send data on an unconnected raw socket.+   */+  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 on a connected socket.+  /**+   * This function is used to send data on the raw socket. The function call+   * will block until the data has been sent successfully or an error occurs.+   *+   * @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 handler is called.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @note The async_send operation can only be used with a connected socket.+   * Use the async_send_to function to send data on an unconnected raw+   * socket.+   *+   * @par Example+   * To send a single data buffer use the @ref buffer function as follows:+   * @code+   * socket.async_send(asio::buffer(data, size), 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.+   */+  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_send(const ConstBufferSequence& buffers,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send(this), handler,+        buffers, socket_base::message_flags(0));+  }++  /// Start an asynchronous send on a connected socket.+  /**+   * This function is used to send data on the raw socket. The function call+   * will block until the data has been sent successfully or an error occurs.+   *+   * @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 handler is called.+   *+   * @param flags Flags specifying how the send call is to be made.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @note The async_send operation can only be used with a connected socket.+   * Use the async_send_to function to send data on an unconnected raw+   * socket.+   */+  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_send(const ConstBufferSequence& buffers,+      socket_base::message_flags flags,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send(this), handler, buffers, flags);+  }++  /// Send raw data to the specified endpoint.+  /**+   * This function is used to send raw data to the specified remote endpoint.+   * The function call will block until the data has been sent successfully or+   * an error occurs.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   *+   * @param destination The remote endpoint to which the data will be sent.+   *+   * @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+   * asio::ip::udp::endpoint destination(+   *     asio::ip::address::from_string("1.2.3.4"), 12345);+   * socket.send_to(asio::buffer(data, size), destination);+   * @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_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().send_to(+        this->impl_.get_implementation(), buffers, destination, 0, ec);+    asio::detail::throw_error(ec, "send_to");+    return s;+  }++  /// Send raw data to the specified endpoint.+  /**+   * This function is used to send raw data to the specified remote endpoint.+   * The function call will block until the data has been sent successfully or+   * an error occurs.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   *+   * @param destination The remote endpoint to which the data will be sent.+   *+   * @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.+   */+  template <typename ConstBufferSequence>+  std::size_t send_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination, socket_base::message_flags flags)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().send_to(+        this->impl_.get_implementation(), buffers, destination, flags, ec);+    asio::detail::throw_error(ec, "send_to");+    return s;+  }++  /// Send raw data to the specified endpoint.+  /**+   * This function is used to send raw data to the specified remote endpoint.+   * The function call will block until the data has been sent successfully or+   * an error occurs.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   *+   * @param destination The remote endpoint to which the data will be sent.+   *+   * @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.+   */+  template <typename ConstBufferSequence>+  std::size_t send_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination, socket_base::message_flags flags,+      asio::error_code& ec)+  {+    return this->impl_.get_service().send_to(this->impl_.get_implementation(),+        buffers, destination, flags, ec);+  }++  /// Start an asynchronous send.+  /**+   * This function is used to asynchronously send raw data to the specified+   * remote endpoint. The function call always returns immediately.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   * 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 handler is called.+   *+   * @param destination The remote endpoint to which the data will be sent.+   * Copies will be made of the endpoint as required.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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 Example+   * To send a single data buffer use the @ref buffer function as follows:+   * @code+   * asio::ip::udp::endpoint destination(+   *     asio::ip::address::from_string("1.2.3.4"), 12345);+   * socket.async_send_to(+   *     asio::buffer(data, size), destination, 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.+   */+  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_send_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send_to(this), handler, buffers,+        destination, socket_base::message_flags(0));+  }++  /// Start an asynchronous send.+  /**+   * This function is used to asynchronously send raw data to the specified+   * remote endpoint. The function call always returns immediately.+   *+   * @param buffers One or more data buffers to be sent to the remote endpoint.+   * 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 handler is called.+   *+   * @param flags Flags specifying how the send call is to be made.+   *+   * @param destination The remote endpoint to which the data will be sent.+   * Copies will be made of the endpoint as required.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   */+  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_send_to(const ConstBufferSequence& buffers,+      const endpoint_type& destination, socket_base::message_flags flags,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send_to(this), handler, buffers, destination, flags);+  }++  /// Receive some data on a connected socket.+  /**+   * This function is used to receive data on the raw socket. The function+   * call will block until data has been received successfully or an error+   * occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @returns The number of bytes received.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note The receive operation can only be used with a connected socket. Use+   * the receive_from function to receive data on an unconnected raw+   * socket.+   *+   * @par Example+   * To receive into a single data buffer use the @ref buffer function as+   * follows:+   * @code socket.receive(asio::buffer(data, size)); @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)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive(+        this->impl_.get_implementation(), buffers, 0, 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 raw socket. The function+   * call will block until data has been received successfully or an error+   * occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @returns The number of bytes received.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note The receive operation can only be used with a connected socket. Use+   * the receive_from function to receive data on an unconnected raw+   * socket.+   */+  template <typename MutableBufferSequence>+  std::size_t receive(const MutableBufferSequence& buffers,+      socket_base::message_flags flags)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive(+        this->impl_.get_implementation(), buffers, 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 raw socket. The function+   * call will block until data has been received successfully or an error+   * occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes received.+   *+   * @note The receive operation can only be used with a connected socket. Use+   * the receive_from function to receive data on an unconnected raw+   * socket.+   */+  template <typename MutableBufferSequence>+  std::size_t receive(const MutableBufferSequence& buffers,+      socket_base::message_flags flags, asio::error_code& ec)+  {+    return this->impl_.get_service().receive(+        this->impl_.get_implementation(), buffers, flags, ec);+  }++  /// Start an asynchronous receive on a connected socket.+  /**+   * This function is used to asynchronously receive data from the raw+   * socket. The function call 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 handler is called.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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().+   *+   * @note The async_receive operation can only be used with a connected socket.+   * Use the async_receive_from function to receive data on an unconnected+   * raw socket.+   *+   * @par Example+   * To receive into a single data buffer use the @ref buffer function as+   * follows:+   * @code+   * socket.async_receive(asio::buffer(data, size), 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.+   */+  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_receive(const MutableBufferSequence& buffers,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive(this), handler,+        buffers, socket_base::message_flags(0));+  }++  /// Start an asynchronous receive on a connected socket.+  /**+   * This function is used to asynchronously receive data from the raw+   * socket. The function call 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 handler is called.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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().+   *+   * @note The async_receive operation can only be used with a connected socket.+   * Use the async_receive_from function to receive data on an unconnected+   * raw socket.+   */+  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_receive(const MutableBufferSequence& buffers,+      socket_base::message_flags flags,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive(this), handler, buffers, flags);+  }++  /// Receive raw data with the endpoint of the sender.+  /**+   * This function is used to receive raw data. The function call will block+   * until data has been received successfully or an error occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the data.+   *+   * @returns The number of bytes received.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * To receive into a single data buffer use the @ref buffer function as+   * follows:+   * @code+   * asio::ip::udp::endpoint sender_endpoint;+   * socket.receive_from(+   *     asio::buffer(data, size), sender_endpoint);+   * @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_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive_from(+        this->impl_.get_implementation(), buffers, sender_endpoint, 0, ec);+    asio::detail::throw_error(ec, "receive_from");+    return s;+  }+  +  /// Receive raw data with the endpoint of the sender.+  /**+   * This function is used to receive raw data. The function call will block+   * until data has been received successfully or an error occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the data.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @returns The number of bytes received.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename MutableBufferSequence>+  std::size_t receive_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint, socket_base::message_flags flags)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive_from(+        this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);+    asio::detail::throw_error(ec, "receive_from");+    return s;+  }+  +  /// Receive raw data with the endpoint of the sender.+  /**+   * This function is used to receive raw data. The function call will block+   * until data has been received successfully or an error occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the data.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes received.+   */+  template <typename MutableBufferSequence>+  std::size_t receive_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint, socket_base::message_flags flags,+      asio::error_code& ec)+  {+    return this->impl_.get_service().receive_from(+        this->impl_.get_implementation(), buffers, sender_endpoint, flags, ec);+  }++  /// Start an asynchronous receive.+  /**+   * This function is used to asynchronously receive raw data. The function+   * call 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 handler is called.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the data. Ownership of the sender_endpoint object+   * is retained by the caller, which must guarantee that it is valid until the+   * handler is called.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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 Example+   * To receive into a single data buffer use the @ref buffer function as+   * follows:+   * @code socket.async_receive_from(+   *     asio::buffer(data, size), 0, sender_endpoint, 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.+   */+  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_receive_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive_from(this), handler, buffers,+        &sender_endpoint, socket_base::message_flags(0));+  }++  /// Start an asynchronous receive.+  /**+   * This function is used to asynchronously receive raw data. The function+   * call 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 handler is called.+   *+   * @param sender_endpoint An endpoint object that receives the endpoint of+   * the remote sender of the data. Ownership of the sender_endpoint object+   * is retained by the caller, which must guarantee that it is valid until the+   * handler is called.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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().+   */+  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_receive_from(const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint, socket_base::message_flags flags,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive_from(this), handler,+        buffers, &sender_endpoint, flags);+  }++private:+  // Disallow copying and assignment.+  basic_raw_socket(const basic_raw_socket&) ASIO_DELETED;+  basic_raw_socket& operator=(const basic_raw_socket&) ASIO_DELETED;++  class initiate_async_send+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_send(basic_raw_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_raw_socket* self_;+  };++  class initiate_async_send_to+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_send_to(basic_raw_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, const endpoint_type& destination,+        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_to(+          self_->impl_.get_implementation(), buffers, destination,+          flags, handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_raw_socket* self_;+  };++  class initiate_async_receive+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_receive(basic_raw_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 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(+          self_->impl_.get_implementation(), buffers, flags,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_raw_socket* self_;+  };++  class initiate_async_receive_from+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_receive_from(basic_raw_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, endpoint_type* sender_endpoint,+        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 ReadHandler.+      ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;++      detail::non_const_lvalue<ReadHandler> handler2(handler);+      self_->impl_.get_service().async_receive_from(+          self_->impl_.get_implementation(), buffers, *sender_endpoint,+          flags, handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_raw_socket* self_;+  };+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BASIC_RAW_SOCKET_HPP
+ link/modules/asio-standalone/asio/include/asio/basic_seq_packet_socket.hpp view
@@ -0,0 +1,761 @@+//+// basic_seq_packet_socket.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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.+ */+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 enable_if<+        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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : 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 enable_if<+        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 enable_if<+        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 enable_if<+        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 enable_if<+    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. The function call 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 handler is called.+   *+   * @param flags Flags specifying how the send call is to be made.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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 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.+   */+  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_send(const ConstBufferSequence& buffers,+      socket_base::message_flags flags,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send(this), handler, 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. The function call 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 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 handler is called.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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 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.+   */+  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_receive(const MutableBufferSequence& buffers,+      socket_base::message_flags& out_flags,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive_with_flags(this), handler,+        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. The function call 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 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 handler is called.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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 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.+   */+  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_receive(const MutableBufferSequence& buffers,+      socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive_with_flags(this),+        handler, 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
+ link/modules/asio-standalone/asio/include/asio/basic_serial_port.hpp view
@@ -0,0 +1,907 @@+//+// basic_serial_port.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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/reactive_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::reactive_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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value,+        basic_serial_port+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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.+   * The function call 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 handler is called.+   *+   * @param handler The handler to be called when the write operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @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.+   */+  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 async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_write_some(this), handler, 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.+   * The function call 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 handler is called.+   *+   * @param handler The handler to be called when the read operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @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.+   */+  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 async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_read_some(this), handler, 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::reactive_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
+ link/modules/asio-standalone/asio/include/asio/basic_signal_set.hpp view
@@ -0,0 +1,568 @@+//+// basic_signal_set.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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"++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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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 always returns immediately.+   *+   * For each call to async_wait(), the supplied handler will be called exactly+   * once. The 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 handler The handler to be called when the signal occurs. Copies+   * will be made of the handler as required. The function signature of the+   * 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 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().+   */+  template <+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, int))+      SignalHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(SignalHandler,+      void (asio::error_code, int))+  async_wait(+      ASIO_MOVE_ARG(SignalHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<SignalHandler, void (asio::error_code, int)>(+        initiate_async_wait(this), handler);+  }++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++#endif // ASIO_BASIC_SIGNAL_SET_HPP
+ link/modules/asio-standalone/asio/include/asio/basic_socket.hpp view
@@ -0,0 +1,1894 @@+//+// basic_socket.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_HPP+#define ASIO_BASIC_SOCKET_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/any_io_executor.hpp"+#include "asio/detail/config.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/post.hpp"+#include "asio/socket_base.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/null_socket_service.hpp"+#elif defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_socket_service.hpp"+#else+# include "asio/detail/reactive_socket_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_SOCKET_FWD_DECL)+#define ASIO_BASIC_SOCKET_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Protocol, typename Executor = any_io_executor>+class basic_socket;++#endif // !defined(ASIO_BASIC_SOCKET_FWD_DECL)++/// Provides socket functionality.+/**+ * The basic_socket class template provides functionality that is common to both+ * stream-oriented and datagram-oriented sockets.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Protocol, typename Executor>+class basic_socket+  : public socket_base+{+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_socket<Protocol, Executor1> other;+  };++  /// The native representation of a socket.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#elif defined(ASIO_WINDOWS_RUNTIME)+  typedef typename detail::null_socket_service<+    Protocol>::native_handle_type native_handle_type;+#elif defined(ASIO_HAS_IOCP)+  typedef typename detail::win_iocp_socket_service<+    Protocol>::native_handle_type native_handle_type;+#else+  typedef typename detail::reactive_socket_service<+    Protocol>::native_handle_type native_handle_type;+#endif++  /// The protocol type.+  typedef Protocol protocol_type;++  /// The endpoint type.+  typedef typename Protocol::endpoint endpoint_type;++#if !defined(ASIO_NO_EXTENSIONS)+  /// A basic_socket is always the lowest layer.+  typedef basic_socket<Protocol, Executor> lowest_layer_type;+#endif // !defined(ASIO_NO_EXTENSIONS)++  /// Construct a basic_socket without opening it.+  /**+   * This constructor creates a socket without opening 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_socket(const executor_type& ex)+    : impl_(ex)+  {+  }++  /// Construct a basic_socket without opening it.+  /**+   * This constructor creates a socket without opening 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_socket(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+  }++  /// Construct and open a basic_socket.+  /**+   * This constructor creates and opens a 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.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_socket(const executor_type& ex, const protocol_type& protocol)+    : impl_(ex)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct and open a basic_socket.+  /**+   * This constructor creates and opens a 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.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_socket(ExecutionContext& context, const protocol_type& protocol,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct a basic_socket, opening it and binding it to the given local+  /// endpoint.+  /**+   * This constructor creates a 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 socket will+   * be bound.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_socket(const executor_type& ex, const endpoint_type& endpoint)+    : impl_(ex)+  {+    asio::error_code ec;+    const protocol_type protocol = endpoint.protocol();+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+    impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);+    asio::detail::throw_error(ec, "bind");+  }++  /// Construct a basic_socket, opening it and binding it to the given local+  /// endpoint.+  /**+   * This constructor creates a 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 socket will+   * be bound.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_socket(ExecutionContext& context, const endpoint_type& endpoint,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+    asio::error_code ec;+    const protocol_type protocol = endpoint.protocol();+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+    impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);+    asio::detail::throw_error(ec, "bind");+  }++  /// Construct a basic_socket on an existing native socket.+  /**+   * This constructor creates a 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 A native socket.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_socket(const executor_type& ex, const protocol_type& protocol,+      const native_handle_type& native_socket)+    : impl_(ex)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        protocol, native_socket, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Construct a basic_socket on an existing native socket.+  /**+   * This constructor creates a 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 A native socket.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_socket(ExecutionContext& context, const protocol_type& protocol,+      const native_handle_type& native_socket,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        protocol, native_socket, ec);+    asio::detail::throw_error(ec, "assign");+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_socket from another.+  /**+   * This constructor moves a socket from one object to another.+   *+   * @param other The other basic_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_socket(const executor_type&) constructor.+   */+  basic_socket(basic_socket&& other) ASIO_NOEXCEPT+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_socket from another.+  /**+   * This assignment operator moves a socket from one object to another.+   *+   * @param other The other basic_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_socket(const executor_type&) constructor.+   */+  basic_socket& operator=(basic_socket&& other)+  {+    impl_ = std::move(other.impl_);+    return *this;+  }++  // All sockets have access to each other's implementations.+  template <typename Protocol1, typename Executor1>+  friend class basic_socket;++  /// Move-construct a basic_socket from a socket of another protocol type.+  /**+   * This constructor moves a socket from one object to another.+   *+   * @param other The other basic_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_socket(const executor_type&) constructor.+   */+  template <typename Protocol1, typename Executor1>+  basic_socket(basic_socket<Protocol1, Executor1>&& other,+      typename enable_if<+        is_convertible<Protocol1, Protocol>::value+          && is_convertible<Executor1, Executor>::value+      >::type* = 0)+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_socket from a socket of another protocol type.+  /**+   * This assignment operator moves a socket from one object to another.+   *+   * @param other The other basic_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_socket(const executor_type&) constructor.+   */+  template <typename Protocol1, typename Executor1>+  typename enable_if<+    is_convertible<Protocol1, Protocol>::value+      && is_convertible<Executor1, Executor>::value,+    basic_socket&+  >::type operator=(basic_socket<Protocol1, Executor1> && other)+  {+    basic_socket 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();+  }++#if !defined(ASIO_NO_EXTENSIONS)+  /// Get a reference to the lowest layer.+  /**+   * This function returns a reference to the lowest layer in a stack of+   * layers. Since a basic_socket 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_socket 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;+  }+#endif // !defined(ASIO_NO_EXTENSIONS)++  /// Open the socket using the specified protocol.+  /**+   * This function opens the socket so that it will use the specified protocol.+   *+   * @param protocol An object specifying protocol parameters to be used.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * socket.open(asio::ip::tcp::v4());+   * @endcode+   */+  void open(const protocol_type& protocol = protocol_type())+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Open the socket using the specified protocol.+  /**+   * This function opens the socket so that it will use the specified protocol.+   *+   * @param protocol An object specifying which protocol is to be used.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * asio::error_code ec;+   * socket.open(asio::ip::tcp::v4(), ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID open(const protocol_type& protocol,+      asio::error_code& ec)+  {+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Assign an existing native socket to the socket.+  /*+   * This function opens the socket to hold an existing native socket.+   *+   * @param protocol An object specifying which protocol is to be used.+   *+   * @param native_socket A native socket.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void assign(const protocol_type& protocol,+      const native_handle_type& native_socket)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        protocol, native_socket, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Assign an existing native socket to the socket.+  /*+   * This function opens the socket to hold an existing native socket.+   *+   * @param protocol An object specifying which protocol is to be used.+   *+   * @param native_socket A native socket.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,+      const native_handle_type& native_socket, asio::error_code& ec)+  {+    impl_.get_service().assign(impl_.get_implementation(),+        protocol, native_socket, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Determine whether the socket is open.+  bool is_open() const+  {+    return impl_.get_service().is_open(impl_.get_implementation());+  }++  /// Close the socket.+  /**+   * This function is used to close the socket. Any asynchronous send, receive+   * or connect 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.+   *+   * @note For portable behaviour with respect to graceful closure of a+   * connected socket, call shutdown() before closing the socket.+   */+  void close()+  {+    asio::error_code ec;+    impl_.get_service().close(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "close");+  }++  /// Close the socket.+  /**+   * This function is used to close the socket. Any asynchronous send, receive+   * or connect 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::ip::tcp::socket socket(my_context);+   * ...+   * asio::error_code ec;+   * socket.close(ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   *+   * @note For portable behaviour with respect to graceful closure of a+   * connected socket, call shutdown() before closing the socket.+   */+  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 socket.+  /**+   * This function causes all outstanding asynchronous connect, send and receive+   * operations to finish immediately, and the handlers for cancelled operations+   * will be passed the asio::error::operation_aborted error. Ownership+   * of the native socket 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 socket.+  /**+   * This function causes all outstanding asynchronous connect, send and receive+   * operations to finish immediately, and the handlers for cancelled operations+   * will be passed the asio::error::operation_aborted error. Ownership+   * of the native socket 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 socket representation.+  /**+   * This function may be used to obtain the underlying representation of the+   * socket. This is intended to allow access to native socket 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 socket.+  /**+   * This function causes all outstanding asynchronous connect, send and receive+   * 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 one of the following+   * alternatives:+   *+   * @li Disable asio's I/O completion port backend by defining+   * ASIO_DISABLE_IOCP.+   *+   * @li Use the close() function to simultaneously cancel the outstanding+   * operations and close the socket.+   *+   * 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 socket.+  /**+   * This function causes all outstanding asynchronous connect, send and receive+   * 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 one of the following+   * alternatives:+   *+   * @li Disable asio's I/O completion port backend by defining+   * ASIO_DISABLE_IOCP.+   *+   * @li Use the close() function to simultaneously cancel the outstanding+   * operations and close the socket.+   *+   * 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);+  }++  /// Determine whether the socket is at the out-of-band data mark.+  /**+   * This function is used to check whether the socket input is currently+   * positioned at the out-of-band data mark.+   *+   * @return A bool indicating whether the socket is at the out-of-band data+   * mark.+   *+   * @throws asio::system_error Thrown on failure.+   */+  bool at_mark() const+  {+    asio::error_code ec;+    bool b = impl_.get_service().at_mark(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "at_mark");+    return b;+  }++  /// Determine whether the socket is at the out-of-band data mark.+  /**+   * This function is used to check whether the socket input is currently+   * positioned at the out-of-band data mark.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @return A bool indicating whether the socket is at the out-of-band data+   * mark.+   */+  bool at_mark(asio::error_code& ec) const+  {+    return impl_.get_service().at_mark(impl_.get_implementation(), ec);+  }++  /// Determine the number of bytes available for reading.+  /**+   * This function is used to determine the number of bytes that may be read+   * without blocking.+   *+   * @return The number of bytes that may be read without blocking, or 0 if an+   * error occurs.+   *+   * @throws asio::system_error Thrown on failure.+   */+  std::size_t available() const+  {+    asio::error_code ec;+    std::size_t s = impl_.get_service().available(+        impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "available");+    return s;+  }++  /// Determine the number of bytes available for reading.+  /**+   * This function is used to determine the number of bytes that may be read+   * without blocking.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @return The number of bytes that may be read without blocking, or 0 if an+   * error occurs.+   */+  std::size_t available(asio::error_code& ec) const+  {+    return impl_.get_service().available(impl_.get_implementation(), ec);+  }++  /// Bind the socket to the given local endpoint.+  /**+   * This function binds the socket to the specified endpoint on the local+   * machine.+   *+   * @param endpoint An endpoint on the local machine to which the socket will+   * be bound.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * socket.open(asio::ip::tcp::v4());+   * socket.bind(asio::ip::tcp::endpoint(+   *       asio::ip::tcp::v4(), 12345));+   * @endcode+   */+  void bind(const endpoint_type& endpoint)+  {+    asio::error_code ec;+    impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);+    asio::detail::throw_error(ec, "bind");+  }++  /// Bind the socket to the given local endpoint.+  /**+   * This function binds the socket to the specified endpoint on the local+   * machine.+   *+   * @param endpoint An endpoint on the local machine to which the socket will+   * be bound.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * socket.open(asio::ip::tcp::v4());+   * asio::error_code ec;+   * socket.bind(asio::ip::tcp::endpoint(+   *       asio::ip::tcp::v4(), 12345), ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,+      asio::error_code& ec)+  {+    impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Connect the socket to the specified endpoint.+  /**+   * This function is used to connect a socket to the specified remote endpoint.+   * The function call will block until the connection is successfully made or+   * an error occurs.+   *+   * The socket is automatically opened if it is not already open. If the+   * connect fails, and the socket was automatically opened, the socket is+   * not returned to the closed state.+   *+   * @param peer_endpoint The remote endpoint to which the socket will be+   * connected.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * asio::ip::tcp::endpoint endpoint(+   *     asio::ip::address::from_string("1.2.3.4"), 12345);+   * socket.connect(endpoint);+   * @endcode+   */+  void connect(const endpoint_type& peer_endpoint)+  {+    asio::error_code ec;+    if (!is_open())+    {+      impl_.get_service().open(impl_.get_implementation(),+          peer_endpoint.protocol(), ec);+      asio::detail::throw_error(ec, "connect");+    }+    impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);+    asio::detail::throw_error(ec, "connect");+  }++  /// Connect the socket to the specified endpoint.+  /**+   * This function is used to connect a socket to the specified remote endpoint.+   * The function call will block until the connection is successfully made or+   * an error occurs.+   *+   * The socket is automatically opened if it is not already open. If the+   * connect fails, and the socket was automatically opened, the socket is+   * not returned to the closed state.+   *+   * @param peer_endpoint The remote endpoint to which the socket will be+   * connected.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * asio::ip::tcp::endpoint endpoint(+   *     asio::ip::address::from_string("1.2.3.4"), 12345);+   * asio::error_code ec;+   * socket.connect(endpoint, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID connect(const endpoint_type& peer_endpoint,+      asio::error_code& ec)+  {+    if (!is_open())+    {+      impl_.get_service().open(impl_.get_implementation(),+            peer_endpoint.protocol(), ec);+      if (ec)+      {+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }+    }++    impl_.get_service().connect(impl_.get_implementation(), peer_endpoint, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Start an asynchronous connect.+  /**+   * This function is used to asynchronously connect a socket to the specified+   * remote endpoint. The function call always returns immediately.+   *+   * The socket is automatically opened if it is not already open. If the+   * connect fails, and the socket was automatically opened, the socket is+   * not returned to the closed state.+   *+   * @param peer_endpoint The remote endpoint to which the socket will be+   * connected. Copies will be made of the endpoint object as required.+   *+   * @param handler The handler to be called when the connection operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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 Example+   * @code+   * void connect_handler(const asio::error_code& error)+   * {+   *   if (!error)+   *   {+   *     // Connect succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::socket socket(my_context);+   * asio::ip::tcp::endpoint endpoint(+   *     asio::ip::address::from_string("1.2.3.4"), 12345);+   * socket.async_connect(endpoint, connect_handler);+   * @endcode+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        ConnectHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(ConnectHandler,+      void (asio::error_code))+  async_connect(const endpoint_type& peer_endpoint,+      ASIO_MOVE_ARG(ConnectHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    asio::error_code open_ec;+    if (!is_open())+    {+      const protocol_type protocol = peer_endpoint.protocol();+      impl_.get_service().open(impl_.get_implementation(), protocol, open_ec);+    }++    return async_initiate<ConnectHandler, void (asio::error_code)>(+        initiate_async_connect(this), handler, peer_endpoint, open_ec);+  }++  /// Set an option on the socket.+  /**+   * This function is used to set an option on the socket.+   *+   * @param option The new option value to be set on the socket.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @sa SettableSocketOption @n+   * asio::socket_base::broadcast @n+   * asio::socket_base::do_not_route @n+   * asio::socket_base::keep_alive @n+   * asio::socket_base::linger @n+   * asio::socket_base::receive_buffer_size @n+   * asio::socket_base::receive_low_watermark @n+   * asio::socket_base::reuse_address @n+   * asio::socket_base::send_buffer_size @n+   * asio::socket_base::send_low_watermark @n+   * asio::ip::multicast::join_group @n+   * asio::ip::multicast::leave_group @n+   * asio::ip::multicast::enable_loopback @n+   * asio::ip::multicast::outbound_interface @n+   * asio::ip::multicast::hops @n+   * asio::ip::tcp::no_delay+   *+   * @par Example+   * Setting the IPPROTO_TCP/TCP_NODELAY option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::no_delay option(true);+   * socket.set_option(option);+   * @endcode+   */+  template <typename SettableSocketOption>+  void set_option(const SettableSocketOption& 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 socket.+  /**+   * This function is used to set an option on the socket.+   *+   * @param option The new option value to be set on the socket.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @sa SettableSocketOption @n+   * asio::socket_base::broadcast @n+   * asio::socket_base::do_not_route @n+   * asio::socket_base::keep_alive @n+   * asio::socket_base::linger @n+   * asio::socket_base::receive_buffer_size @n+   * asio::socket_base::receive_low_watermark @n+   * asio::socket_base::reuse_address @n+   * asio::socket_base::send_buffer_size @n+   * asio::socket_base::send_low_watermark @n+   * asio::ip::multicast::join_group @n+   * asio::ip::multicast::leave_group @n+   * asio::ip::multicast::enable_loopback @n+   * asio::ip::multicast::outbound_interface @n+   * asio::ip::multicast::hops @n+   * asio::ip::tcp::no_delay+   *+   * @par Example+   * Setting the IPPROTO_TCP/TCP_NODELAY option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::no_delay option(true);+   * asio::error_code ec;+   * socket.set_option(option, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  template <typename SettableSocketOption>+  ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& 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 socket.+  /**+   * This function is used to get the current value of an option on the socket.+   *+   * @param option The option value to be obtained from the socket.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @sa GettableSocketOption @n+   * asio::socket_base::broadcast @n+   * asio::socket_base::do_not_route @n+   * asio::socket_base::keep_alive @n+   * asio::socket_base::linger @n+   * asio::socket_base::receive_buffer_size @n+   * asio::socket_base::receive_low_watermark @n+   * asio::socket_base::reuse_address @n+   * asio::socket_base::send_buffer_size @n+   * asio::socket_base::send_low_watermark @n+   * asio::ip::multicast::join_group @n+   * asio::ip::multicast::leave_group @n+   * asio::ip::multicast::enable_loopback @n+   * asio::ip::multicast::outbound_interface @n+   * asio::ip::multicast::hops @n+   * asio::ip::tcp::no_delay+   *+   * @par Example+   * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::socket::keep_alive option;+   * socket.get_option(option);+   * bool is_set = option.value();+   * @endcode+   */+  template <typename GettableSocketOption>+  void get_option(GettableSocketOption& 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 socket.+  /**+   * This function is used to get the current value of an option on the socket.+   *+   * @param option The option value to be obtained from the socket.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @sa GettableSocketOption @n+   * asio::socket_base::broadcast @n+   * asio::socket_base::do_not_route @n+   * asio::socket_base::keep_alive @n+   * asio::socket_base::linger @n+   * asio::socket_base::receive_buffer_size @n+   * asio::socket_base::receive_low_watermark @n+   * asio::socket_base::reuse_address @n+   * asio::socket_base::send_buffer_size @n+   * asio::socket_base::send_low_watermark @n+   * asio::ip::multicast::join_group @n+   * asio::ip::multicast::leave_group @n+   * asio::ip::multicast::enable_loopback @n+   * asio::ip::multicast::outbound_interface @n+   * asio::ip::multicast::hops @n+   * asio::ip::tcp::no_delay+   *+   * @par Example+   * Getting the value of the SOL_SOCKET/SO_KEEPALIVE option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::socket::keep_alive option;+   * asio::error_code ec;+   * socket.get_option(option, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * bool is_set = option.value();+   * @endcode+   */+  template <typename GettableSocketOption>+  ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,+      asio::error_code& ec) const+  {+    impl_.get_service().get_option(impl_.get_implementation(), option, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Perform an IO control command on the socket.+  /**+   * This function is used to execute an IO control command on the socket.+   *+   * @param command The IO control command to be performed on the socket.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @sa IoControlCommand @n+   * asio::socket_base::bytes_readable @n+   * asio::socket_base::non_blocking_io+   *+   * @par Example+   * Getting the number of bytes ready to read:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::socket::bytes_readable command;+   * socket.io_control(command);+   * std::size_t bytes_readable = command.get();+   * @endcode+   */+  template <typename IoControlCommand>+  void io_control(IoControlCommand& command)+  {+    asio::error_code ec;+    impl_.get_service().io_control(impl_.get_implementation(), command, ec);+    asio::detail::throw_error(ec, "io_control");+  }++  /// Perform an IO control command on the socket.+  /**+   * This function is used to execute an IO control command on the socket.+   *+   * @param command The IO control command to be performed on the socket.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @sa IoControlCommand @n+   * asio::socket_base::bytes_readable @n+   * asio::socket_base::non_blocking_io+   *+   * @par Example+   * Getting the number of bytes ready to read:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::socket::bytes_readable command;+   * asio::error_code ec;+   * socket.io_control(command, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * std::size_t bytes_readable = command.get();+   * @endcode+   */+  template <typename IoControlCommand>+  ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,+      asio::error_code& ec)+  {+    impl_.get_service().io_control(impl_.get_implementation(), command, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Gets the non-blocking mode of the socket.+  /**+   * @returns @c true if the socket's synchronous operations will fail with+   * asio::error::would_block if they are unable to perform the requested+   * operation immediately. If @c false, synchronous operations will block+   * until complete.+   *+   * @note The non-blocking mode has no effect on the behaviour of asynchronous+   * operations. Asynchronous operations will never fail with the error+   * asio::error::would_block.+   */+  bool non_blocking() const+  {+    return impl_.get_service().non_blocking(impl_.get_implementation());+  }++  /// Sets the non-blocking mode of the socket.+  /**+   * @param mode If @c true, the socket's synchronous operations will fail with+   * asio::error::would_block if they are unable to perform the requested+   * operation immediately. If @c false, synchronous operations will block+   * until complete.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note The non-blocking mode has no effect on the behaviour of asynchronous+   * operations. Asynchronous operations will never fail with the error+   * asio::error::would_block.+   */+  void non_blocking(bool mode)+  {+    asio::error_code ec;+    impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);+    asio::detail::throw_error(ec, "non_blocking");+  }++  /// Sets the non-blocking mode of the socket.+  /**+   * @param mode If @c true, the socket's synchronous operations will fail with+   * asio::error::would_block if they are unable to perform the requested+   * operation immediately. If @c false, synchronous operations will block+   * until complete.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note The non-blocking mode has no effect on the behaviour of asynchronous+   * operations. Asynchronous operations will never fail with the error+   * asio::error::would_block.+   */+  ASIO_SYNC_OP_VOID non_blocking(+      bool mode, asio::error_code& ec)+  {+    impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Gets the non-blocking mode of the native socket implementation.+  /**+   * This function is used to retrieve the non-blocking mode of the underlying+   * native socket. This mode has no effect on the behaviour of the socket+   * object's synchronous operations.+   *+   * @returns @c true if the underlying socket is in non-blocking mode and+   * direct system calls may fail with asio::error::would_block (or the+   * equivalent system error).+   *+   * @note The current non-blocking mode is cached by the socket object.+   * Consequently, the return value may be incorrect if the non-blocking mode+   * was set directly on the native socket.+   *+   * @par Example+   * This function is intended to allow the encapsulation of arbitrary+   * non-blocking system calls as asynchronous operations, in a way that is+   * transparent to the user of the socket object. The following example+   * illustrates how Linux's @c sendfile system call might be encapsulated:+   * @code template <typename Handler>+   * struct sendfile_op+   * {+   *   tcp::socket& sock_;+   *   int fd_;+   *   Handler handler_;+   *   off_t offset_;+   *   std::size_t total_bytes_transferred_;+   *+   *   // Function call operator meeting WriteHandler requirements.+   *   // Used as the handler for the async_write_some operation.+   *   void operator()(asio::error_code ec, std::size_t)+   *   {+   *     // Put the underlying socket into non-blocking mode.+   *     if (!ec)+   *       if (!sock_.native_non_blocking())+   *         sock_.native_non_blocking(true, ec);+   *+   *     if (!ec)+   *     {+   *       for (;;)+   *       {+   *         // Try the system call.+   *         errno = 0;+   *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);+   *         ec = asio::error_code(n < 0 ? errno : 0,+   *             asio::error::get_system_category());+   *         total_bytes_transferred_ += ec ? 0 : n;+   *+   *         // Retry operation immediately if interrupted by signal.+   *         if (ec == asio::error::interrupted)+   *           continue;+   *+   *         // Check if we need to run the operation again.+   *         if (ec == asio::error::would_block+   *             || ec == asio::error::try_again)+   *         {+   *           // We have to wait for the socket to become ready again.+   *           sock_.async_wait(tcp::socket::wait_write, *this);+   *           return;+   *         }+   *+   *         if (ec || n == 0)+   *         {+   *           // An error occurred, or we have reached the end of the file.+   *           // Either way we must exit the loop so we can call the handler.+   *           break;+   *         }+   *+   *         // Loop around to try calling sendfile again.+   *       }+   *     }+   *+   *     // Pass result back to user's handler.+   *     handler_(ec, total_bytes_transferred_);+   *   }+   * };+   *+   * template <typename Handler>+   * void async_sendfile(tcp::socket& sock, int fd, Handler h)+   * {+   *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };+   *   sock.async_wait(tcp::socket::wait_write, op);+   * } @endcode+   */+  bool native_non_blocking() const+  {+    return impl_.get_service().native_non_blocking(impl_.get_implementation());+  }++  /// Sets the non-blocking mode of the native socket implementation.+  /**+   * This function is used to modify the non-blocking mode of the underlying+   * native socket. It has no effect on the behaviour of the socket object's+   * synchronous operations.+   *+   * @param mode If @c true, the underlying socket is put into non-blocking+   * mode and direct system calls may fail with asio::error::would_block+   * (or the equivalent system error).+   *+   * @throws asio::system_error Thrown on failure. If the @c mode is+   * @c false, but the current value of @c non_blocking() is @c true, this+   * function fails with asio::error::invalid_argument, as the+   * combination does not make sense.+   *+   * @par Example+   * This function is intended to allow the encapsulation of arbitrary+   * non-blocking system calls as asynchronous operations, in a way that is+   * transparent to the user of the socket object. The following example+   * illustrates how Linux's @c sendfile system call might be encapsulated:+   * @code template <typename Handler>+   * struct sendfile_op+   * {+   *   tcp::socket& sock_;+   *   int fd_;+   *   Handler handler_;+   *   off_t offset_;+   *   std::size_t total_bytes_transferred_;+   *+   *   // Function call operator meeting WriteHandler requirements.+   *   // Used as the handler for the async_write_some operation.+   *   void operator()(asio::error_code ec, std::size_t)+   *   {+   *     // Put the underlying socket into non-blocking mode.+   *     if (!ec)+   *       if (!sock_.native_non_blocking())+   *         sock_.native_non_blocking(true, ec);+   *+   *     if (!ec)+   *     {+   *       for (;;)+   *       {+   *         // Try the system call.+   *         errno = 0;+   *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);+   *         ec = asio::error_code(n < 0 ? errno : 0,+   *             asio::error::get_system_category());+   *         total_bytes_transferred_ += ec ? 0 : n;+   *+   *         // Retry operation immediately if interrupted by signal.+   *         if (ec == asio::error::interrupted)+   *           continue;+   *+   *         // Check if we need to run the operation again.+   *         if (ec == asio::error::would_block+   *             || ec == asio::error::try_again)+   *         {+   *           // We have to wait for the socket to become ready again.+   *           sock_.async_wait(tcp::socket::wait_write, *this);+   *           return;+   *         }+   *+   *         if (ec || n == 0)+   *         {+   *           // An error occurred, or we have reached the end of the file.+   *           // Either way we must exit the loop so we can call the handler.+   *           break;+   *         }+   *+   *         // Loop around to try calling sendfile again.+   *       }+   *     }+   *+   *     // Pass result back to user's handler.+   *     handler_(ec, total_bytes_transferred_);+   *   }+   * };+   *+   * template <typename Handler>+   * void async_sendfile(tcp::socket& sock, int fd, Handler h)+   * {+   *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };+   *   sock.async_wait(tcp::socket::wait_write, op);+   * } @endcode+   */+  void native_non_blocking(bool mode)+  {+    asio::error_code ec;+    impl_.get_service().native_non_blocking(+        impl_.get_implementation(), mode, ec);+    asio::detail::throw_error(ec, "native_non_blocking");+  }++  /// Sets the non-blocking mode of the native socket implementation.+  /**+   * This function is used to modify the non-blocking mode of the underlying+   * native socket. It has no effect on the behaviour of the socket object's+   * synchronous operations.+   *+   * @param mode If @c true, the underlying socket is put into non-blocking+   * mode and direct system calls may fail with asio::error::would_block+   * (or the equivalent system error).+   *+   * @param ec Set to indicate what error occurred, if any. If the @c mode is+   * @c false, but the current value of @c non_blocking() is @c true, this+   * function fails with asio::error::invalid_argument, as the+   * combination does not make sense.+   *+   * @par Example+   * This function is intended to allow the encapsulation of arbitrary+   * non-blocking system calls as asynchronous operations, in a way that is+   * transparent to the user of the socket object. The following example+   * illustrates how Linux's @c sendfile system call might be encapsulated:+   * @code template <typename Handler>+   * struct sendfile_op+   * {+   *   tcp::socket& sock_;+   *   int fd_;+   *   Handler handler_;+   *   off_t offset_;+   *   std::size_t total_bytes_transferred_;+   *+   *   // Function call operator meeting WriteHandler requirements.+   *   // Used as the handler for the async_write_some operation.+   *   void operator()(asio::error_code ec, std::size_t)+   *   {+   *     // Put the underlying socket into non-blocking mode.+   *     if (!ec)+   *       if (!sock_.native_non_blocking())+   *         sock_.native_non_blocking(true, ec);+   *+   *     if (!ec)+   *     {+   *       for (;;)+   *       {+   *         // Try the system call.+   *         errno = 0;+   *         int n = ::sendfile(sock_.native_handle(), fd_, &offset_, 65536);+   *         ec = asio::error_code(n < 0 ? errno : 0,+   *             asio::error::get_system_category());+   *         total_bytes_transferred_ += ec ? 0 : n;+   *+   *         // Retry operation immediately if interrupted by signal.+   *         if (ec == asio::error::interrupted)+   *           continue;+   *+   *         // Check if we need to run the operation again.+   *         if (ec == asio::error::would_block+   *             || ec == asio::error::try_again)+   *         {+   *           // We have to wait for the socket to become ready again.+   *           sock_.async_wait(tcp::socket::wait_write, *this);+   *           return;+   *         }+   *+   *         if (ec || n == 0)+   *         {+   *           // An error occurred, or we have reached the end of the file.+   *           // Either way we must exit the loop so we can call the handler.+   *           break;+   *         }+   *+   *         // Loop around to try calling sendfile again.+   *       }+   *     }+   *+   *     // Pass result back to user's handler.+   *     handler_(ec, total_bytes_transferred_);+   *   }+   * };+   *+   * template <typename Handler>+   * void async_sendfile(tcp::socket& sock, int fd, Handler h)+   * {+   *   sendfile_op<Handler> op = { sock, fd, h, 0, 0 };+   *   sock.async_wait(tcp::socket::wait_write, op);+   * } @endcode+   */+  ASIO_SYNC_OP_VOID native_non_blocking(+      bool mode, asio::error_code& ec)+  {+    impl_.get_service().native_non_blocking(+        impl_.get_implementation(), mode, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Get the local endpoint of the socket.+  /**+   * This function is used to obtain the locally bound endpoint of the socket.+   *+   * @returns An object that represents the local endpoint of the socket.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint = socket.local_endpoint();+   * @endcode+   */+  endpoint_type local_endpoint() const+  {+    asio::error_code ec;+    endpoint_type ep = impl_.get_service().local_endpoint(+        impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "local_endpoint");+    return ep;+  }++  /// Get the local endpoint of the socket.+  /**+   * This function is used to obtain the locally bound endpoint of the socket.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns An object that represents the local endpoint of the socket.+   * Returns a default-constructed endpoint object if an error occurred.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::error_code ec;+   * asio::ip::tcp::endpoint endpoint = socket.local_endpoint(ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  endpoint_type local_endpoint(asio::error_code& ec) const+  {+    return impl_.get_service().local_endpoint(impl_.get_implementation(), ec);+  }++  /// Get the remote endpoint of the socket.+  /**+   * This function is used to obtain the remote endpoint of the socket.+   *+   * @returns An object that represents the remote endpoint of the socket.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint();+   * @endcode+   */+  endpoint_type remote_endpoint() const+  {+    asio::error_code ec;+    endpoint_type ep = impl_.get_service().remote_endpoint(+        impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "remote_endpoint");+    return ep;+  }++  /// Get the remote endpoint of the socket.+  /**+   * This function is used to obtain the remote endpoint of the socket.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns An object that represents the remote endpoint of the socket.+   * Returns a default-constructed endpoint object if an error occurred.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::error_code ec;+   * asio::ip::tcp::endpoint endpoint = socket.remote_endpoint(ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  endpoint_type remote_endpoint(asio::error_code& ec) const+  {+    return impl_.get_service().remote_endpoint(impl_.get_implementation(), ec);+  }++  /// Disable sends or receives on the socket.+  /**+   * This function is used to disable send operations, receive operations, or+   * both.+   *+   * @param what Determines what types of operation will no longer be allowed.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * Shutting down the send side of the socket:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * socket.shutdown(asio::ip::tcp::socket::shutdown_send);+   * @endcode+   */+  void shutdown(shutdown_type what)+  {+    asio::error_code ec;+    impl_.get_service().shutdown(impl_.get_implementation(), what, ec);+    asio::detail::throw_error(ec, "shutdown");+  }++  /// Disable sends or receives on the socket.+  /**+   * This function is used to disable send operations, receive operations, or+   * both.+   *+   * @param what Determines what types of operation will no longer be allowed.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * Shutting down the send side of the socket:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::error_code ec;+   * socket.shutdown(asio::ip::tcp::socket::shutdown_send, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID shutdown(shutdown_type what,+      asio::error_code& ec)+  {+    impl_.get_service().shutdown(impl_.get_implementation(), what, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Wait for the socket to become ready to read, ready to write, or to have+  /// pending error conditions.+  /**+   * This function is used to perform a blocking wait for a socket to enter+   * a ready to read, write or error condition state.+   *+   * @param w Specifies the desired socket state.+   *+   * @par Example+   * Waiting for a socket to become readable.+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * socket.wait(asio::ip::tcp::socket::wait_read);+   * @endcode+   */+  void wait(wait_type w)+  {+    asio::error_code ec;+    impl_.get_service().wait(impl_.get_implementation(), w, ec);+    asio::detail::throw_error(ec, "wait");+  }++  /// Wait for the socket to become ready to read, ready to write, or to have+  /// pending error conditions.+  /**+   * This function is used to perform a blocking wait for a socket to enter+   * a ready to read, write or error condition state.+   *+   * @param w Specifies the desired socket state.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * Waiting for a socket to become readable.+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::error_code ec;+   * socket.wait(asio::ip::tcp::socket::wait_read, ec);+   * @endcode+   */+  ASIO_SYNC_OP_VOID wait(wait_type w, asio::error_code& ec)+  {+    impl_.get_service().wait(impl_.get_implementation(), w, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Asynchronously wait for the socket to become ready to read, ready to+  /// write, or to have pending error conditions.+  /**+   * This function is used to perform an asynchronous wait for a socket to enter+   * a ready to read, write or error condition state.+   *+   * @param w Specifies the desired socket state.+   *+   * @param handler The handler to be called when the wait operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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 Example+   * @code+   * void wait_handler(const asio::error_code& error)+   * {+   *   if (!error)+   *   {+   *     // Wait succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * socket.async_wait(asio::ip::tcp::socket::wait_read, wait_handler);+   * @endcode+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+      void (asio::error_code))+  async_wait(wait_type w,+      ASIO_MOVE_ARG(WaitHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WaitHandler, void (asio::error_code)>(+        initiate_async_wait(this), handler, w);+  }++protected:+  /// Protected destructor to prevent deletion through this type.+  /**+   * This function destroys the socket, cancelling any outstanding asynchronous+   * operations associated with the socket as if by calling @c cancel.+   */+  ~basic_socket()+  {+  }++#if defined(ASIO_WINDOWS_RUNTIME)+  detail::io_object_impl<+    detail::null_socket_service<Protocol>, Executor> impl_;+#elif defined(ASIO_HAS_IOCP)+  detail::io_object_impl<+    detail::win_iocp_socket_service<Protocol>, Executor> impl_;+#else+  detail::io_object_impl<+    detail::reactive_socket_service<Protocol>, Executor> impl_;+#endif++private:+  // Disallow copying and assignment.+  basic_socket(const basic_socket&) ASIO_DELETED;+  basic_socket& operator=(const basic_socket&) ASIO_DELETED;++  class initiate_async_connect+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_connect(basic_socket* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename ConnectHandler>+    void operator()(ASIO_MOVE_ARG(ConnectHandler) handler,+        const endpoint_type& peer_endpoint,+        const asio::error_code& open_ec) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a ConnectHandler.+      ASIO_CONNECT_HANDLER_CHECK(ConnectHandler, handler) type_check;++      if (open_ec)+      {+          asio::post(self_->impl_.get_executor(),+              asio::detail::bind_handler(+                ASIO_MOVE_CAST(ConnectHandler)(handler), open_ec));+      }+      else+      {+        detail::non_const_lvalue<ConnectHandler> handler2(handler);+        self_->impl_.get_service().async_connect(+            self_->impl_.get_implementation(), peer_endpoint,+            handler2.value, self_->impl_.get_executor());+      }+    }++  private:+    basic_socket* self_;+  };++  class initiate_async_wait+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_wait(basic_socket* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename WaitHandler>+    void operator()(ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) 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(), w,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_socket* self_;+  };+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BASIC_SOCKET_HPP
+ link/modules/asio-standalone/asio/include/asio/basic_socket_acceptor.hpp view
@@ -0,0 +1,2501 @@+//+// basic_socket_acceptor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_ACCEPTOR_HPP+#define ASIO_BASIC_SOCKET_ACCEPTOR_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/basic_socket.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/socket_base.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/null_socket_service.hpp"+#elif defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_socket_service.hpp"+#else+# include "asio/detail/reactive_socket_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_SOCKET_ACCEPTOR_FWD_DECL)+#define ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Protocol, typename Executor = any_io_executor>+class basic_socket_acceptor;++#endif // !defined(ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL)++/// Provides the ability to accept new connections.+/**+ * The basic_socket_acceptor class template is used for accepting new socket+ * connections.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * @par Example+ * Opening a socket acceptor with the SO_REUSEADDR option enabled:+ * @code+ * asio::ip::tcp::acceptor acceptor(my_context);+ * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), port);+ * acceptor.open(endpoint.protocol());+ * acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(true));+ * acceptor.bind(endpoint);+ * acceptor.listen();+ * @endcode+ */+template <typename Protocol, typename Executor>+class basic_socket_acceptor+  : public socket_base+{+public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the acceptor type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The socket type when rebound to the specified executor.+    typedef basic_socket_acceptor<Protocol, Executor1> other;+  };++  /// The native representation of an acceptor.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#elif defined(ASIO_WINDOWS_RUNTIME)+  typedef typename detail::null_socket_service<+    Protocol>::native_handle_type native_handle_type;+#elif defined(ASIO_HAS_IOCP)+  typedef typename detail::win_iocp_socket_service<+    Protocol>::native_handle_type native_handle_type;+#else+  typedef typename detail::reactive_socket_service<+    Protocol>::native_handle_type native_handle_type;+#endif++  /// The protocol type.+  typedef Protocol protocol_type;++  /// The endpoint type.+  typedef typename Protocol::endpoint endpoint_type;++  /// Construct an acceptor without opening it.+  /**+   * This constructor creates an acceptor without opening it to listen for new+   * connections. The open() function must be called before the acceptor can+   * accept new socket connections.+   *+   * @param ex The I/O executor that the acceptor will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * acceptor.+   */+  explicit basic_socket_acceptor(const executor_type& ex)+    : impl_(ex)+  {+  }++  /// Construct an acceptor without opening it.+  /**+   * This constructor creates an acceptor without opening it to listen for new+   * connections. The open() function must be called before the acceptor can+   * accept new socket connections.+   *+   * @param context An execution context which provides the I/O executor that+   * the acceptor will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the acceptor.+   */+  template <typename ExecutionContext>+  explicit basic_socket_acceptor(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+  }++  /// Construct an open acceptor.+  /**+   * This constructor creates an acceptor and automatically opens it.+   *+   * @param ex The I/O executor that the acceptor will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * acceptor.+   *+   * @param protocol An object specifying protocol parameters to be used.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_socket_acceptor(const executor_type& ex, const protocol_type& protocol)+    : impl_(ex)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct an open acceptor.+  /**+   * This constructor creates an acceptor and automatically opens it.+   *+   * @param context An execution context which provides the I/O executor that+   * the acceptor will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the acceptor.+   *+   * @param protocol An object specifying protocol parameters to be used.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_socket_acceptor(ExecutionContext& context,+      const protocol_type& protocol,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct an acceptor opened on the given endpoint.+  /**+   * This constructor creates an acceptor and automatically opens it to listen+   * for new connections on the specified endpoint.+   *+   * @param ex The I/O executor that the acceptor will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * acceptor.+   *+   * @param endpoint An endpoint on the local machine on which the acceptor+   * will listen for new connections.+   *+   * @param reuse_addr Whether the constructor should set the socket option+   * socket_base::reuse_address.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note This constructor is equivalent to the following code:+   * @code+   * basic_socket_acceptor<Protocol> acceptor(my_context);+   * acceptor.open(endpoint.protocol());+   * if (reuse_addr)+   *   acceptor.set_option(socket_base::reuse_address(true));+   * acceptor.bind(endpoint);+   * acceptor.listen();+   * @endcode+   */+  basic_socket_acceptor(const executor_type& ex,+      const endpoint_type& endpoint, bool reuse_addr = true)+    : impl_(ex)+  {+    asio::error_code ec;+    const protocol_type protocol = endpoint.protocol();+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+    if (reuse_addr)+    {+      impl_.get_service().set_option(impl_.get_implementation(),+          socket_base::reuse_address(true), ec);+      asio::detail::throw_error(ec, "set_option");+    }+    impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);+    asio::detail::throw_error(ec, "bind");+    impl_.get_service().listen(impl_.get_implementation(),+        socket_base::max_listen_connections, ec);+    asio::detail::throw_error(ec, "listen");+  }++  /// Construct an acceptor opened on the given endpoint.+  /**+   * This constructor creates an acceptor and automatically opens it to listen+   * for new connections on the specified endpoint.+   *+   * @param context An execution context which provides the I/O executor that+   * the acceptor will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the acceptor.+   *+   * @param endpoint An endpoint on the local machine on which the acceptor+   * will listen for new connections.+   *+   * @param reuse_addr Whether the constructor should set the socket option+   * socket_base::reuse_address.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note This constructor is equivalent to the following code:+   * @code+   * basic_socket_acceptor<Protocol> acceptor(my_context);+   * acceptor.open(endpoint.protocol());+   * if (reuse_addr)+   *   acceptor.set_option(socket_base::reuse_address(true));+   * acceptor.bind(endpoint);+   * acceptor.listen();+   * @endcode+   */+  template <typename ExecutionContext>+  basic_socket_acceptor(ExecutionContext& context,+      const endpoint_type& endpoint, bool reuse_addr = true,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+    asio::error_code ec;+    const protocol_type protocol = endpoint.protocol();+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+    if (reuse_addr)+    {+      impl_.get_service().set_option(impl_.get_implementation(),+          socket_base::reuse_address(true), ec);+      asio::detail::throw_error(ec, "set_option");+    }+    impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);+    asio::detail::throw_error(ec, "bind");+    impl_.get_service().listen(impl_.get_implementation(),+        socket_base::max_listen_connections, ec);+    asio::detail::throw_error(ec, "listen");+  }++  /// Construct a basic_socket_acceptor on an existing native acceptor.+  /**+   * This constructor creates an acceptor object to hold an existing native+   * acceptor.+   *+   * @param ex The I/O executor that the acceptor will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * acceptor.+   *+   * @param protocol An object specifying protocol parameters to be used.+   *+   * @param native_acceptor A native acceptor.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_socket_acceptor(const executor_type& ex,+      const protocol_type& protocol, const native_handle_type& native_acceptor)+    : impl_(ex)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        protocol, native_acceptor, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Construct a basic_socket_acceptor on an existing native acceptor.+  /**+   * This constructor creates an acceptor object to hold an existing native+   * acceptor.+   *+   * @param context An execution context which provides the I/O executor that+   * the acceptor will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the acceptor.+   *+   * @param protocol An object specifying protocol parameters to be used.+   *+   * @param native_acceptor A native acceptor.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_socket_acceptor(ExecutionContext& context,+      const protocol_type& protocol, const native_handle_type& native_acceptor,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        protocol, native_acceptor, ec);+    asio::detail::throw_error(ec, "assign");+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_socket_acceptor from another.+  /**+   * This constructor moves an acceptor from one object to another.+   *+   * @param other The other basic_socket_acceptor 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_socket_acceptor(const executor_type&)+   * constructor.+   */+  basic_socket_acceptor(basic_socket_acceptor&& other) ASIO_NOEXCEPT+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_socket_acceptor from another.+  /**+   * This assignment operator moves an acceptor from one object to another.+   *+   * @param other The other basic_socket_acceptor 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_socket_acceptor(const executor_type&)+   * constructor.+   */+  basic_socket_acceptor& operator=(basic_socket_acceptor&& other)+  {+    impl_ = std::move(other.impl_);+    return *this;+  }++  // All socket acceptors have access to each other's implementations.+  template <typename Protocol1, typename Executor1>+  friend class basic_socket_acceptor;++  /// Move-construct a basic_socket_acceptor from an acceptor of another+  /// protocol type.+  /**+   * This constructor moves an acceptor from one object to another.+   *+   * @param other The other basic_socket_acceptor 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_socket_acceptor(const executor_type&)+   * constructor.+   */+  template <typename Protocol1, typename Executor1>+  basic_socket_acceptor(basic_socket_acceptor<Protocol1, Executor1>&& other,+      typename enable_if<+        is_convertible<Protocol1, Protocol>::value+          && is_convertible<Executor1, Executor>::value+      >::type* = 0)+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_socket_acceptor from an acceptor of another protocol+  /// type.+  /**+   * This assignment operator moves an acceptor from one object to another.+   *+   * @param other The other basic_socket_acceptor 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_socket_acceptor(const executor_type&)+   * constructor.+   */+  template <typename Protocol1, typename Executor1>+  typename enable_if<+    is_convertible<Protocol1, Protocol>::value+      && is_convertible<Executor1, Executor>::value,+    basic_socket_acceptor&+  >::type operator=(basic_socket_acceptor<Protocol1, Executor1>&& other)+  {+    basic_socket_acceptor tmp(std::move(other));+    impl_ = std::move(tmp.impl_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destroys the acceptor.+  /**+   * This function destroys the acceptor, cancelling any outstanding+   * asynchronous operations associated with the acceptor as if by calling+   * @c cancel.+   */+  ~basic_socket_acceptor()+  {+  }++  /// Get the executor associated with the object.+  executor_type get_executor() ASIO_NOEXCEPT+  {+    return impl_.get_executor();+  }++  /// Open the acceptor using the specified protocol.+  /**+   * This function opens the socket acceptor so that it will use the specified+   * protocol.+   *+   * @param protocol An object specifying which protocol is to be used.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * acceptor.open(asio::ip::tcp::v4());+   * @endcode+   */+  void open(const protocol_type& protocol = protocol_type())+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Open the acceptor using the specified protocol.+  /**+   * This function opens the socket acceptor so that it will use the specified+   * protocol.+   *+   * @param protocol An object specifying which protocol is to be used.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * asio::error_code ec;+   * acceptor.open(asio::ip::tcp::v4(), ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID open(const protocol_type& protocol,+      asio::error_code& ec)+  {+    impl_.get_service().open(impl_.get_implementation(), protocol, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Assigns an existing native acceptor to the acceptor.+  /*+   * This function opens the acceptor to hold an existing native acceptor.+   *+   * @param protocol An object specifying which protocol is to be used.+   *+   * @param native_acceptor A native acceptor.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void assign(const protocol_type& protocol,+      const native_handle_type& native_acceptor)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        protocol, native_acceptor, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Assigns an existing native acceptor to the acceptor.+  /*+   * This function opens the acceptor to hold an existing native acceptor.+   *+   * @param protocol An object specifying which protocol is to be used.+   *+   * @param native_acceptor A native acceptor.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID assign(const protocol_type& protocol,+      const native_handle_type& native_acceptor, asio::error_code& ec)+  {+    impl_.get_service().assign(impl_.get_implementation(),+        protocol, native_acceptor, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Determine whether the acceptor is open.+  bool is_open() const+  {+    return impl_.get_service().is_open(impl_.get_implementation());+  }++  /// Bind the acceptor to the given local endpoint.+  /**+   * This function binds the socket acceptor to the specified endpoint on the+   * local machine.+   *+   * @param endpoint An endpoint on the local machine to which the socket+   * acceptor will be bound.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 12345);+   * acceptor.open(endpoint.protocol());+   * acceptor.bind(endpoint);+   * @endcode+   */+  void bind(const endpoint_type& endpoint)+  {+    asio::error_code ec;+    impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);+    asio::detail::throw_error(ec, "bind");+  }++  /// Bind the acceptor to the given local endpoint.+  /**+   * This function binds the socket acceptor to the specified endpoint on the+   * local machine.+   *+   * @param endpoint An endpoint on the local machine to which the socket+   * acceptor will be bound.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * asio::ip::tcp::endpoint endpoint(asio::ip::tcp::v4(), 12345);+   * acceptor.open(endpoint.protocol());+   * asio::error_code ec;+   * acceptor.bind(endpoint, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID bind(const endpoint_type& endpoint,+      asio::error_code& ec)+  {+    impl_.get_service().bind(impl_.get_implementation(), endpoint, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Place the acceptor into the state where it will listen for new+  /// connections.+  /**+   * This function puts the socket acceptor into the state where it may accept+   * new connections.+   *+   * @param backlog The maximum length of the queue of pending connections.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void listen(int backlog = socket_base::max_listen_connections)+  {+    asio::error_code ec;+    impl_.get_service().listen(impl_.get_implementation(), backlog, ec);+    asio::detail::throw_error(ec, "listen");+  }++  /// Place the acceptor into the state where it will listen for new+  /// connections.+  /**+   * This function puts the socket acceptor into the state where it may accept+   * new connections.+   *+   * @param backlog The maximum length of the queue of pending connections.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::error_code ec;+   * acceptor.listen(asio::socket_base::max_listen_connections, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID listen(int backlog, asio::error_code& ec)+  {+    impl_.get_service().listen(impl_.get_implementation(), backlog, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Close the acceptor.+  /**+   * This function is used to close the acceptor. Any asynchronous accept+   * operations will be cancelled immediately.+   *+   * A subsequent call to open() is required before the acceptor can again be+   * used to again perform socket accept operations.+   *+   * @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 acceptor.+  /**+   * This function is used to close the acceptor. Any asynchronous accept+   * operations will be cancelled immediately.+   *+   * A subsequent call to open() is required before the acceptor can again be+   * used to again perform socket accept operations.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::error_code ec;+   * acceptor.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 acceptor.+  /**+   * This function causes all outstanding asynchronous accept operations to+   * finish immediately, and the handlers for cancelled operations will be+   * passed the asio::error::operation_aborted error. Ownership of the+   * native acceptor 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 acceptor.+  /**+   * This function causes all outstanding asynchronous accept operations to+   * finish immediately, and the handlers for cancelled operations will be+   * passed the asio::error::operation_aborted error. Ownership of the+   * native acceptor 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 acceptor representation.+  /**+   * This function may be used to obtain the underlying representation of the+   * acceptor. This is intended to allow access to native acceptor 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 acceptor.+  /**+   * This function causes all outstanding asynchronous connect, send and receive+   * 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 acceptor.+  /**+   * This function causes all outstanding asynchronous connect, send and receive+   * 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);+  }++  /// Set an option on the acceptor.+  /**+   * This function is used to set an option on the acceptor.+   *+   * @param option The new option value to be set on the acceptor.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @sa SettableSocketOption @n+   * asio::socket_base::reuse_address+   * asio::socket_base::enable_connection_aborted+   *+   * @par Example+   * Setting the SOL_SOCKET/SO_REUSEADDR option:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::acceptor::reuse_address option(true);+   * acceptor.set_option(option);+   * @endcode+   */+  template <typename SettableSocketOption>+  void set_option(const SettableSocketOption& 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 acceptor.+  /**+   * This function is used to set an option on the acceptor.+   *+   * @param option The new option value to be set on the acceptor.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @sa SettableSocketOption @n+   * asio::socket_base::reuse_address+   * asio::socket_base::enable_connection_aborted+   *+   * @par Example+   * Setting the SOL_SOCKET/SO_REUSEADDR option:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::acceptor::reuse_address option(true);+   * asio::error_code ec;+   * acceptor.set_option(option, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  template <typename SettableSocketOption>+  ASIO_SYNC_OP_VOID set_option(const SettableSocketOption& 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 acceptor.+  /**+   * This function is used to get the current value of an option on the+   * acceptor.+   *+   * @param option The option value to be obtained from the acceptor.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @sa GettableSocketOption @n+   * asio::socket_base::reuse_address+   *+   * @par Example+   * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::acceptor::reuse_address option;+   * acceptor.get_option(option);+   * bool is_set = option.get();+   * @endcode+   */+  template <typename GettableSocketOption>+  void get_option(GettableSocketOption& 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 acceptor.+  /**+   * This function is used to get the current value of an option on the+   * acceptor.+   *+   * @param option The option value to be obtained from the acceptor.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @sa GettableSocketOption @n+   * asio::socket_base::reuse_address+   *+   * @par Example+   * Getting the value of the SOL_SOCKET/SO_REUSEADDR option:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::acceptor::reuse_address option;+   * asio::error_code ec;+   * acceptor.get_option(option, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * bool is_set = option.get();+   * @endcode+   */+  template <typename GettableSocketOption>+  ASIO_SYNC_OP_VOID get_option(GettableSocketOption& option,+      asio::error_code& ec) const+  {+    impl_.get_service().get_option(impl_.get_implementation(), option, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Perform an IO control command on the acceptor.+  /**+   * This function is used to execute an IO control command on the acceptor.+   *+   * @param command The IO control command to be performed on the acceptor.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @sa IoControlCommand @n+   * asio::socket_base::non_blocking_io+   *+   * @par Example+   * Getting the number of bytes ready to read:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::acceptor::non_blocking_io command(true);+   * socket.io_control(command);+   * @endcode+   */+  template <typename IoControlCommand>+  void io_control(IoControlCommand& command)+  {+    asio::error_code ec;+    impl_.get_service().io_control(impl_.get_implementation(), command, ec);+    asio::detail::throw_error(ec, "io_control");+  }++  /// Perform an IO control command on the acceptor.+  /**+   * This function is used to execute an IO control command on the acceptor.+   *+   * @param command The IO control command to be performed on the acceptor.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @sa IoControlCommand @n+   * asio::socket_base::non_blocking_io+   *+   * @par Example+   * Getting the number of bytes ready to read:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::acceptor::non_blocking_io command(true);+   * asio::error_code ec;+   * socket.io_control(command, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  template <typename IoControlCommand>+  ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,+      asio::error_code& ec)+  {+    impl_.get_service().io_control(impl_.get_implementation(), command, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Gets the non-blocking mode of the acceptor.+  /**+   * @returns @c true if the acceptor's synchronous operations will fail with+   * asio::error::would_block if they are unable to perform the requested+   * operation immediately. If @c false, synchronous operations will block+   * until complete.+   *+   * @note The non-blocking mode has no effect on the behaviour of asynchronous+   * operations. Asynchronous operations will never fail with the error+   * asio::error::would_block.+   */+  bool non_blocking() const+  {+    return impl_.get_service().non_blocking(impl_.get_implementation());+  }++  /// Sets the non-blocking mode of the acceptor.+  /**+   * @param mode If @c true, the acceptor's synchronous operations will fail+   * with asio::error::would_block if they are unable to perform the+   * requested operation immediately. If @c false, synchronous operations will+   * block until complete.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note The non-blocking mode has no effect on the behaviour of asynchronous+   * operations. Asynchronous operations will never fail with the error+   * asio::error::would_block.+   */+  void non_blocking(bool mode)+  {+    asio::error_code ec;+    impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);+    asio::detail::throw_error(ec, "non_blocking");+  }++  /// Sets the non-blocking mode of the acceptor.+  /**+   * @param mode If @c true, the acceptor's synchronous operations will fail+   * with asio::error::would_block if they are unable to perform the+   * requested operation immediately. If @c false, synchronous operations will+   * block until complete.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note The non-blocking mode has no effect on the behaviour of asynchronous+   * operations. Asynchronous operations will never fail with the error+   * asio::error::would_block.+   */+  ASIO_SYNC_OP_VOID non_blocking(+      bool mode, asio::error_code& ec)+  {+    impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Gets the non-blocking mode of the native acceptor implementation.+  /**+   * This function is used to retrieve the non-blocking mode of the underlying+   * native acceptor. This mode has no effect on the behaviour of the acceptor+   * object's synchronous operations.+   *+   * @returns @c true if the underlying acceptor is in non-blocking mode and+   * direct system calls may fail with asio::error::would_block (or the+   * equivalent system error).+   *+   * @note The current non-blocking mode is cached by the acceptor object.+   * Consequently, the return value may be incorrect if the non-blocking mode+   * was set directly on the native acceptor.+   */+  bool native_non_blocking() const+  {+    return impl_.get_service().native_non_blocking(impl_.get_implementation());+  }++  /// Sets the non-blocking mode of the native acceptor implementation.+  /**+   * This function is used to modify the non-blocking mode of the underlying+   * native acceptor. It has no effect on the behaviour of the acceptor object's+   * synchronous operations.+   *+   * @param mode If @c true, the underlying acceptor is put into non-blocking+   * mode and direct system calls may fail with asio::error::would_block+   * (or the equivalent system error).+   *+   * @throws asio::system_error Thrown on failure. If the @c mode is+   * @c false, but the current value of @c non_blocking() is @c true, this+   * function fails with asio::error::invalid_argument, as the+   * combination does not make sense.+   */+  void native_non_blocking(bool mode)+  {+    asio::error_code ec;+    impl_.get_service().native_non_blocking(+        impl_.get_implementation(), mode, ec);+    asio::detail::throw_error(ec, "native_non_blocking");+  }++  /// Sets the non-blocking mode of the native acceptor implementation.+  /**+   * This function is used to modify the non-blocking mode of the underlying+   * native acceptor. It has no effect on the behaviour of the acceptor object's+   * synchronous operations.+   *+   * @param mode If @c true, the underlying acceptor is put into non-blocking+   * mode and direct system calls may fail with asio::error::would_block+   * (or the equivalent system error).+   *+   * @param ec Set to indicate what error occurred, if any. If the @c mode is+   * @c false, but the current value of @c non_blocking() is @c true, this+   * function fails with asio::error::invalid_argument, as the+   * combination does not make sense.+   */+  ASIO_SYNC_OP_VOID native_non_blocking(+      bool mode, asio::error_code& ec)+  {+    impl_.get_service().native_non_blocking(+        impl_.get_implementation(), mode, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Get the local endpoint of the acceptor.+  /**+   * This function is used to obtain the locally bound endpoint of the acceptor.+   *+   * @returns An object that represents the local endpoint of the acceptor.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint();+   * @endcode+   */+  endpoint_type local_endpoint() const+  {+    asio::error_code ec;+    endpoint_type ep = impl_.get_service().local_endpoint(+        impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "local_endpoint");+    return ep;+  }++  /// Get the local endpoint of the acceptor.+  /**+   * This function is used to obtain the locally bound endpoint of the acceptor.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns An object that represents the local endpoint of the acceptor.+   * Returns a default-constructed endpoint object if an error occurred and the+   * error handler did not throw an exception.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::error_code ec;+   * asio::ip::tcp::endpoint endpoint = acceptor.local_endpoint(ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  endpoint_type local_endpoint(asio::error_code& ec) const+  {+    return impl_.get_service().local_endpoint(impl_.get_implementation(), ec);+  }++  /// Wait for the acceptor to become ready to read, ready to write, or to have+  /// pending error conditions.+  /**+   * This function is used to perform a blocking wait for an acceptor to enter+   * a ready to read, write or error condition state.+   *+   * @param w Specifies the desired acceptor state.+   *+   * @par Example+   * Waiting for an acceptor to become readable.+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * acceptor.wait(asio::ip::tcp::acceptor::wait_read);+   * @endcode+   */+  void wait(wait_type w)+  {+    asio::error_code ec;+    impl_.get_service().wait(impl_.get_implementation(), w, ec);+    asio::detail::throw_error(ec, "wait");+  }++  /// Wait for the acceptor to become ready to read, ready to write, or to have+  /// pending error conditions.+  /**+   * This function is used to perform a blocking wait for an acceptor to enter+   * a ready to read, write or error condition state.+   *+   * @param w Specifies the desired acceptor state.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * Waiting for an acceptor to become readable.+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::error_code ec;+   * acceptor.wait(asio::ip::tcp::acceptor::wait_read, ec);+   * @endcode+   */+  ASIO_SYNC_OP_VOID wait(wait_type w, asio::error_code& ec)+  {+    impl_.get_service().wait(impl_.get_implementation(), w, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Asynchronously wait for the acceptor to become ready to read, ready to+  /// write, or to have pending error conditions.+  /**+   * This function is used to perform an asynchronous wait for an acceptor to+   * enter a ready to read, write or error condition state.+   *+   * @param w Specifies the desired acceptor state.+   *+   * @param handler The handler to be called when the wait operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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 Example+   * @code+   * void wait_handler(const asio::error_code& error)+   * {+   *   if (!error)+   *   {+   *     // Wait succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * acceptor.async_wait(+   *     asio::ip::tcp::acceptor::wait_read,+   *     wait_handler);+   * @endcode+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+      void (asio::error_code))+  async_wait(wait_type w,+      ASIO_MOVE_ARG(WaitHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WaitHandler, void (asio::error_code)>(+        initiate_async_wait(this), handler, w);+  }++#if !defined(ASIO_NO_EXTENSIONS)+  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer into the+   * given socket. The function call will block until a new connection has been+   * accepted successfully or an error occurs.+   *+   * @param peer The socket into which the new connection will be accepted.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(my_context);+   * acceptor.accept(socket);+   * @endcode+   */+  template <typename Protocol1, typename Executor1>+  void accept(basic_socket<Protocol1, Executor1>& peer,+      typename enable_if<+        is_convertible<Protocol, Protocol1>::value+      >::type* = 0)+  {+    asio::error_code ec;+    impl_.get_service().accept(impl_.get_implementation(),+        peer, static_cast<endpoint_type*>(0), ec);+    asio::detail::throw_error(ec, "accept");+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer into the+   * given socket. The function call will block until a new connection has been+   * accepted successfully or an error occurs.+   *+   * @param peer The socket into which the new connection will be accepted.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(my_context);+   * asio::error_code ec;+   * acceptor.accept(socket, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  template <typename Protocol1, typename Executor1>+  ASIO_SYNC_OP_VOID accept(+      basic_socket<Protocol1, Executor1>& peer, asio::error_code& ec,+      typename enable_if<+        is_convertible<Protocol, Protocol1>::value+      >::type* = 0)+  {+    impl_.get_service().accept(impl_.get_implementation(),+        peer, static_cast<endpoint_type*>(0), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Start an asynchronous accept.+  /**+   * This function is used to asynchronously accept a new connection into a+   * socket. The function call always returns immediately.+   *+   * @param peer The socket into which the new connection will be accepted.+   * Ownership of the peer object is retained by the caller, which must+   * guarantee that it is valid until the handler is called.+   *+   * @param handler The handler to be called when the accept operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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 Example+   * @code+   * void accept_handler(const asio::error_code& error)+   * {+   *   if (!error)+   *   {+   *     // Accept succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(my_context);+   * acceptor.async_accept(socket, accept_handler);+   * @endcode+   */+  template <typename Protocol1, typename Executor1,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        AcceptHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(AcceptHandler,+      void (asio::error_code))+  async_accept(basic_socket<Protocol1, Executor1>& peer,+      ASIO_MOVE_ARG(AcceptHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),+      typename enable_if<+        is_convertible<Protocol, Protocol1>::value+      >::type* = 0)+  {+    return async_initiate<AcceptHandler, void (asio::error_code)>(+        initiate_async_accept(this), handler,+        &peer, static_cast<endpoint_type*>(0));+  }++  /// Accept a new connection and obtain the endpoint of the peer+  /**+   * This function is used to accept a new connection from a peer into the+   * given socket, and additionally provide the endpoint of the remote peer.+   * The function call will block until a new connection has been accepted+   * successfully or an error occurs.+   *+   * @param peer The socket into which the new connection will be accepted.+   *+   * @param peer_endpoint An endpoint object which will receive the endpoint of+   * the remote peer.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(my_context);+   * asio::ip::tcp::endpoint endpoint;+   * acceptor.accept(socket, endpoint);+   * @endcode+   */+  template <typename Executor1>+  void accept(basic_socket<protocol_type, Executor1>& peer,+      endpoint_type& peer_endpoint)+  {+    asio::error_code ec;+    impl_.get_service().accept(impl_.get_implementation(),+        peer, &peer_endpoint, ec);+    asio::detail::throw_error(ec, "accept");+  }++  /// Accept a new connection and obtain the endpoint of the peer+  /**+   * This function is used to accept a new connection from a peer into the+   * given socket, and additionally provide the endpoint of the remote peer.+   * The function call will block until a new connection has been accepted+   * successfully or an error occurs.+   *+   * @param peer The socket into which the new connection will be accepted.+   *+   * @param peer_endpoint An endpoint object which will receive the endpoint of+   * the remote peer.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(my_context);+   * asio::ip::tcp::endpoint endpoint;+   * asio::error_code ec;+   * acceptor.accept(socket, endpoint, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  template <typename Executor1>+  ASIO_SYNC_OP_VOID accept(basic_socket<protocol_type, Executor1>& peer,+      endpoint_type& peer_endpoint, asio::error_code& ec)+  {+    impl_.get_service().accept(+        impl_.get_implementation(), peer, &peer_endpoint, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Start an asynchronous accept.+  /**+   * This function is used to asynchronously accept a new connection into a+   * socket, and additionally obtain the endpoint of the remote peer. The+   * function call always returns immediately.+   *+   * @param peer The socket into which the new connection will be accepted.+   * Ownership of the peer object is retained by the caller, which must+   * guarantee that it is valid until the handler is called.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written. Ownership of the peer_endpoint object is+   * retained by the caller, which must guarantee that it is valid until the+   * handler is called.+   *+   * @param handler The handler to be called when the accept operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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().+   */+  template <typename Executor1,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        AcceptHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(AcceptHandler,+      void (asio::error_code))+  async_accept(basic_socket<protocol_type, Executor1>& peer,+      endpoint_type& peer_endpoint,+      ASIO_MOVE_ARG(AcceptHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<AcceptHandler, void (asio::error_code)>(+        initiate_async_accept(this), handler, &peer, &peer_endpoint);+  }+#endif // !defined(ASIO_NO_EXTENSIONS)++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @returns A socket object representing the newly accepted connection.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(acceptor.accept());+   * @endcode+   */+  typename Protocol::socket::template rebind_executor<executor_type>::other+  accept()+  {+    asio::error_code ec;+    typename Protocol::socket::template rebind_executor<+      executor_type>::other peer(impl_.get_executor());+    impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);+    asio::detail::throw_error(ec, "accept");+    return peer;+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns On success, a socket object representing the newly accepted+   * connection. On error, a socket object where is_open() is false.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(acceptor.accept(ec));+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  typename Protocol::socket::template rebind_executor<executor_type>::other+  accept(asio::error_code& ec)+  {+    typename Protocol::socket::template rebind_executor<+      executor_type>::other peer(impl_.get_executor());+    impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);+    return peer;+  }++  /// Start an asynchronous accept.+  /**+   * This function is used to asynchronously accept a new connection. The+   * function call always returns immediately.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param handler The handler to be called when the accept operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   // Result of operation.+   *   const asio::error_code& error,+   *   // On success, the newly accepted socket.+   *   typename Protocol::socket::template+   *     rebind_executor<executor_type>::other peer+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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 Example+   * @code+   * void accept_handler(const asio::error_code& error,+   *     asio::ip::tcp::socket peer)+   * {+   *   if (!error)+   *   {+   *     // Accept succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * acceptor.async_accept(accept_handler);+   * @endcode+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          executor_type>::other)) MoveAcceptHandler+            ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+      void (asio::error_code,+        typename Protocol::socket::template+          rebind_executor<executor_type>::other))+  async_accept(+      ASIO_MOVE_ARG(MoveAcceptHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<MoveAcceptHandler,+      void (asio::error_code, typename Protocol::socket::template+        rebind_executor<executor_type>::other)>(+          initiate_async_move_accept(this), handler,+          impl_.get_executor(), static_cast<endpoint_type*>(0),+          static_cast<typename Protocol::socket::template+            rebind_executor<executor_type>::other*>(0));+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param ex The I/O executor object to be used for the newly+   * accepted socket.+   *+   * @returns A socket object representing the newly accepted connection.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(acceptor.accept());+   * @endcode+   */+  template <typename Executor1>+  typename Protocol::socket::template rebind_executor<Executor1>::other+  accept(const Executor1& ex,+      typename enable_if<+        is_executor<Executor1>::value+          || execution::is_executor<Executor1>::value+      >::type* = 0)+  {+    asio::error_code ec;+    typename Protocol::socket::template+      rebind_executor<Executor1>::other peer(ex);+    impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);+    asio::detail::throw_error(ec, "accept");+    return peer;+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param context The I/O execution context object to be used for the newly+   * accepted socket.+   *+   * @returns A socket object representing the newly accepted connection.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(acceptor.accept());+   * @endcode+   */+  template <typename ExecutionContext>+  typename Protocol::socket::template rebind_executor<+      typename ExecutionContext::executor_type>::other+  accept(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+  {+    asio::error_code ec;+    typename Protocol::socket::template rebind_executor<+        typename ExecutionContext::executor_type>::other peer(context);+    impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);+    asio::detail::throw_error(ec, "accept");+    return peer;+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param ex The I/O executor object to be used for the newly accepted+   * socket.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns On success, a socket object representing the newly accepted+   * connection. On error, a socket object where is_open() is false.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec));+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  template <typename Executor1>+  typename Protocol::socket::template rebind_executor<Executor1>::other+  accept(const Executor1& ex, asio::error_code& ec,+      typename enable_if<+        is_executor<Executor1>::value+          || execution::is_executor<Executor1>::value+      >::type* = 0)+  {+    typename Protocol::socket::template+      rebind_executor<Executor1>::other peer(ex);+    impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);+    return peer;+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param context The I/O execution context object to be used for the newly+   * accepted socket.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns On success, a socket object representing the newly accepted+   * connection. On error, a socket object where is_open() is false.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::socket socket(acceptor.accept(my_context2, ec));+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  template <typename ExecutionContext>+  typename Protocol::socket::template rebind_executor<+      typename ExecutionContext::executor_type>::other+  accept(ExecutionContext& context, asio::error_code& ec,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+  {+    typename Protocol::socket::template rebind_executor<+        typename ExecutionContext::executor_type>::other peer(context);+    impl_.get_service().accept(impl_.get_implementation(), peer, 0, ec);+    return peer;+  }++  /// Start an asynchronous accept.+  /**+   * This function is used to asynchronously accept a new connection. The+   * function call always returns immediately.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param ex The I/O executor object to be used for the newly accepted+   * socket.+   *+   * @param handler The handler to be called when the accept operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   typename Protocol::socket::template rebind_executor<+   *     Executor1>::other peer // On success, the newly accepted socket.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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 Example+   * @code+   * void accept_handler(const asio::error_code& error,+   *     asio::ip::tcp::socket peer)+   * {+   *   if (!error)+   *   {+   *     // Accept succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * acceptor.async_accept(my_context2, accept_handler);+   * @endcode+   */+  template <typename Executor1,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          Executor1>::other)) MoveAcceptHandler+            ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+      void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          Executor1>::other))+  async_accept(const Executor1& ex,+      ASIO_MOVE_ARG(MoveAcceptHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),+      typename enable_if<+        is_executor<Executor1>::value+          || execution::is_executor<Executor1>::value+      >::type* = 0)+  {+    typedef typename Protocol::socket::template rebind_executor<+      Executor1>::other other_socket_type;++    return async_initiate<MoveAcceptHandler,+      void (asio::error_code, other_socket_type)>(+        initiate_async_move_accept(this), handler,+        ex, static_cast<endpoint_type*>(0),+        static_cast<other_socket_type*>(0));+  }++  /// Start an asynchronous accept.+  /**+   * This function is used to asynchronously accept a new connection. The+   * function call always returns immediately.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param context The I/O execution context object to be used for the newly+   * accepted socket.+   *+   * @param handler The handler to be called when the accept operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   typename Protocol::socket::template rebind_executor<+   *     typename ExecutionContext::executor_type>::other peer+   *       // On success, the newly accepted socket.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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 Example+   * @code+   * void accept_handler(const asio::error_code& error,+   *     asio::ip::tcp::socket peer)+   * {+   *   if (!error)+   *   {+   *     // Accept succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * acceptor.async_accept(my_context2, accept_handler);+   * @endcode+   */+  template <typename ExecutionContext,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          typename ExecutionContext::executor_type>::other)) MoveAcceptHandler+            ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+      void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          typename ExecutionContext::executor_type>::other))+  async_accept(ExecutionContext& context,+      ASIO_MOVE_ARG(MoveAcceptHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+  {+    typedef typename Protocol::socket::template rebind_executor<+      typename ExecutionContext::executor_type>::other other_socket_type;++    return async_initiate<MoveAcceptHandler,+      void (asio::error_code, other_socket_type)>(+        initiate_async_move_accept(this), handler,+        context.get_executor(), static_cast<endpoint_type*>(0),+        static_cast<other_socket_type*>(0));+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written.+   *+   * @returns A socket object representing the newly accepted connection.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint;+   * asio::ip::tcp::socket socket(acceptor.accept(endpoint));+   * @endcode+   */+  typename Protocol::socket::template rebind_executor<executor_type>::other+  accept(endpoint_type& peer_endpoint)+  {+    asio::error_code ec;+    typename Protocol::socket::template rebind_executor<+      executor_type>::other peer(impl_.get_executor());+    impl_.get_service().accept(impl_.get_implementation(),+        peer, &peer_endpoint, ec);+    asio::detail::throw_error(ec, "accept");+    return peer;+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns On success, a socket object representing the newly accepted+   * connection. On error, a socket object where is_open() is false.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint;+   * asio::ip::tcp::socket socket(acceptor.accept(endpoint, ec));+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  typename Protocol::socket::template rebind_executor<executor_type>::other+  accept(endpoint_type& peer_endpoint, asio::error_code& ec)+  {+    typename Protocol::socket::template rebind_executor<+      executor_type>::other peer(impl_.get_executor());+    impl_.get_service().accept(impl_.get_implementation(),+        peer, &peer_endpoint, ec);+    return peer;+  }++  /// Start an asynchronous accept.+  /**+   * This function is used to asynchronously accept a new connection. The+   * function call always returns immediately.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written. Ownership of the peer_endpoint object is+   * retained by the caller, which must guarantee that it is valid until the+   * handler is called.+   *+   * @param handler The handler to be called when the accept operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   // Result of operation.+   *   const asio::error_code& error,+   *   // On success, the newly accepted socket.+   *   typename Protocol::socket::template+   *     rebind_executor<executor_type>::other peer+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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 Example+   * @code+   * void accept_handler(const asio::error_code& error,+   *     asio::ip::tcp::socket peer)+   * {+   *   if (!error)+   *   {+   *     // Accept succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint;+   * acceptor.async_accept(endpoint, accept_handler);+   * @endcode+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          executor_type>::other)) MoveAcceptHandler+            ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+      void (asio::error_code,+        typename Protocol::socket::template+          rebind_executor<executor_type>::other))+  async_accept(endpoint_type& peer_endpoint,+      ASIO_MOVE_ARG(MoveAcceptHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<MoveAcceptHandler,+      void (asio::error_code, typename Protocol::socket::template+        rebind_executor<executor_type>::other)>(+          initiate_async_move_accept(this), handler,+          impl_.get_executor(), &peer_endpoint,+          static_cast<typename Protocol::socket::template+            rebind_executor<executor_type>::other*>(0));+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param ex The I/O executor object to be used for the newly accepted+   * socket.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written.+   *+   * @returns A socket object representing the newly accepted connection.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint;+   * asio::ip::tcp::socket socket(+   *     acceptor.accept(my_context2, endpoint));+   * @endcode+   */+  template <typename Executor1>+  typename Protocol::socket::template rebind_executor<Executor1>::other+  accept(const Executor1& ex, endpoint_type& peer_endpoint,+      typename enable_if<+        is_executor<Executor1>::value+          || execution::is_executor<Executor1>::value+      >::type* = 0)+  {+    asio::error_code ec;+    typename Protocol::socket::template+        rebind_executor<Executor1>::other peer(ex);+    impl_.get_service().accept(impl_.get_implementation(),+        peer, &peer_endpoint, ec);+    asio::detail::throw_error(ec, "accept");+    return peer;+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param context The I/O execution context object to be used for the newly+   * accepted socket.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written.+   *+   * @returns A socket object representing the newly accepted connection.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint;+   * asio::ip::tcp::socket socket(+   *     acceptor.accept(my_context2, endpoint));+   * @endcode+   */+  template <typename ExecutionContext>+  typename Protocol::socket::template rebind_executor<+      typename ExecutionContext::executor_type>::other+  accept(ExecutionContext& context, endpoint_type& peer_endpoint,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+  {+    asio::error_code ec;+    typename Protocol::socket::template rebind_executor<+        typename ExecutionContext::executor_type>::other peer(context);+    impl_.get_service().accept(impl_.get_implementation(),+        peer, &peer_endpoint, ec);+    asio::detail::throw_error(ec, "accept");+    return peer;+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param ex The I/O executor object to be used for the newly accepted+   * socket.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns On success, a socket object representing the newly accepted+   * connection. On error, a socket object where is_open() is false.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint;+   * asio::ip::tcp::socket socket(+   *     acceptor.accept(my_context2, endpoint, ec));+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  template <typename Executor1>+  typename Protocol::socket::template rebind_executor<Executor1>::other+  accept(const executor_type& ex,+      endpoint_type& peer_endpoint, asio::error_code& ec,+      typename enable_if<+        is_executor<Executor1>::value+          || execution::is_executor<Executor1>::value+      >::type* = 0)+  {+    typename Protocol::socket::template+      rebind_executor<Executor1>::other peer(ex);+    impl_.get_service().accept(impl_.get_implementation(),+        peer, &peer_endpoint, ec);+    return peer;+  }++  /// Accept a new connection.+  /**+   * This function is used to accept a new connection from a peer. The function+   * call will block until a new connection has been accepted successfully or+   * an error occurs.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param context The I/O execution context object to be used for the newly+   * accepted socket.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns On success, a socket object representing the newly accepted+   * connection. On error, a socket object where is_open() is false.+   *+   * @par Example+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint;+   * asio::ip::tcp::socket socket(+   *     acceptor.accept(my_context2, endpoint, ec));+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  template <typename ExecutionContext>+  typename Protocol::socket::template rebind_executor<+      typename ExecutionContext::executor_type>::other+  accept(ExecutionContext& context,+      endpoint_type& peer_endpoint, asio::error_code& ec,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+  {+    typename Protocol::socket::template rebind_executor<+        typename ExecutionContext::executor_type>::other peer(context);+    impl_.get_service().accept(impl_.get_implementation(),+        peer, &peer_endpoint, ec);+    return peer;+  }++  /// Start an asynchronous accept.+  /**+   * This function is used to asynchronously accept a new connection. The+   * function call always returns immediately.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param ex The I/O executor object to be used for the newly accepted+   * socket.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written. Ownership of the peer_endpoint object is+   * retained by the caller, which must guarantee that it is valid until the+   * handler is called.+   *+   * @param handler The handler to be called when the accept operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   typename Protocol::socket::template rebind_executor<+   *     Executor1>::other peer // On success, the newly accepted socket.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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 Example+   * @code+   * void accept_handler(const asio::error_code& error,+   *     asio::ip::tcp::socket peer)+   * {+   *   if (!error)+   *   {+   *     // Accept succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint;+   * acceptor.async_accept(my_context2, endpoint, accept_handler);+   * @endcode+   */+  template <typename Executor1,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          Executor1>::other)) MoveAcceptHandler+            ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+      void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          Executor1>::other))+  async_accept(const Executor1& ex, endpoint_type& peer_endpoint,+      ASIO_MOVE_ARG(MoveAcceptHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),+      typename enable_if<+        is_executor<Executor1>::value+          || execution::is_executor<Executor1>::value+      >::type* = 0)+  {+    typedef typename Protocol::socket::template rebind_executor<+      Executor1>::other other_socket_type;++    return async_initiate<MoveAcceptHandler,+      void (asio::error_code, other_socket_type)>(+        initiate_async_move_accept(this), handler,+        ex, &peer_endpoint,+        static_cast<other_socket_type*>(0));+  }++  /// Start an asynchronous accept.+  /**+   * This function is used to asynchronously accept a new connection. The+   * function call always returns immediately.+   *+   * This overload requires that the Protocol template parameter satisfy the+   * AcceptableProtocol type requirements.+   *+   * @param context The I/O execution context object to be used for the newly+   * accepted socket.+   *+   * @param peer_endpoint An endpoint object into which the endpoint of the+   * remote peer will be written. Ownership of the peer_endpoint object is+   * retained by the caller, which must guarantee that it is valid until the+   * handler is called.+   *+   * @param handler The handler to be called when the accept operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   typename Protocol::socket::template rebind_executor<+   *     typename ExecutionContext::executor_type>::other peer+   *       // On success, the newly accepted socket.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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 Example+   * @code+   * void accept_handler(const asio::error_code& error,+   *     asio::ip::tcp::socket peer)+   * {+   *   if (!error)+   *   {+   *     // Accept succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::ip::tcp::endpoint endpoint;+   * acceptor.async_accept(my_context2, endpoint, accept_handler);+   * @endcode+   */+  template <typename ExecutionContext,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          typename ExecutionContext::executor_type>::other)) MoveAcceptHandler+            ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+      void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          typename ExecutionContext::executor_type>::other))+  async_accept(ExecutionContext& context,+      endpoint_type& peer_endpoint,+      ASIO_MOVE_ARG(MoveAcceptHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+  {+    typedef typename Protocol::socket::template rebind_executor<+      typename ExecutionContext::executor_type>::other other_socket_type;++    return async_initiate<MoveAcceptHandler,+      void (asio::error_code, other_socket_type)>(+        initiate_async_move_accept(this), handler,+        context.get_executor(), &peer_endpoint,+        static_cast<other_socket_type*>(0));+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++private:+  // Disallow copying and assignment.+  basic_socket_acceptor(const basic_socket_acceptor&) ASIO_DELETED;+  basic_socket_acceptor& operator=(+      const basic_socket_acceptor&) ASIO_DELETED;++  class initiate_async_wait+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_wait(basic_socket_acceptor* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename WaitHandler>+    void operator()(ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) 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(), w,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_socket_acceptor* self_;+  };++  class initiate_async_accept+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_accept(basic_socket_acceptor* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename AcceptHandler, typename Protocol1, typename Executor1>+    void operator()(ASIO_MOVE_ARG(AcceptHandler) handler,+        basic_socket<Protocol1, Executor1>* peer,+        endpoint_type* peer_endpoint) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a AcceptHandler.+      ASIO_ACCEPT_HANDLER_CHECK(AcceptHandler, handler) type_check;++      detail::non_const_lvalue<AcceptHandler> handler2(handler);+      self_->impl_.get_service().async_accept(+          self_->impl_.get_implementation(), *peer, peer_endpoint,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_socket_acceptor* self_;+  };++  class initiate_async_move_accept+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_move_accept(basic_socket_acceptor* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename MoveAcceptHandler, typename Executor1, typename Socket>+    void operator()(ASIO_MOVE_ARG(MoveAcceptHandler) handler,+        const Executor1& peer_ex, endpoint_type* peer_endpoint, Socket*) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a MoveAcceptHandler.+      ASIO_MOVE_ACCEPT_HANDLER_CHECK(+          MoveAcceptHandler, handler, Socket) type_check;++      detail::non_const_lvalue<MoveAcceptHandler> handler2(handler);+      self_->impl_.get_service().async_move_accept(+          self_->impl_.get_implementation(), peer_ex, peer_endpoint,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_socket_acceptor* self_;+  };++#if defined(ASIO_WINDOWS_RUNTIME)+  detail::io_object_impl<+    detail::null_socket_service<Protocol>, Executor> impl_;+#elif defined(ASIO_HAS_IOCP)+  detail::io_object_impl<+    detail::win_iocp_socket_service<Protocol>, Executor> impl_;+#else+  detail::io_object_impl<+    detail::reactive_socket_service<Protocol>, Executor> impl_;+#endif+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BASIC_SOCKET_ACCEPTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/basic_socket_iostream.hpp view
@@ -0,0 +1,407 @@+//+// basic_socket_iostream.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/basic_socket_streambuf.hpp view
@@ -0,0 +1,687 @@+//+// basic_socket_streambuf.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/basic_stream_socket.hpp view
@@ -0,0 +1,1053 @@+//+// basic_stream_socket.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SOCKET_HPP+#define ASIO_BASIC_STREAM_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/async_result.hpp"+#include "asio/basic_socket.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_SOCKET_FWD_DECL)+#define ASIO_BASIC_STREAM_SOCKET_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Protocol, typename Executor = any_io_executor>+class basic_stream_socket;++#endif // !defined(ASIO_BASIC_STREAM_SOCKET_FWD_DECL)++/// Provides stream-oriented socket functionality.+/**+ * The basic_stream_socket class template provides asynchronous and blocking+ * stream-oriented socket functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * @par Concepts:+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.+ */+template <typename Protocol, typename Executor>+class basic_stream_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_stream_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_stream_socket without opening it.+  /**+   * This constructor creates a stream 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_stream_socket(const executor_type& ex)+    : basic_socket<Protocol, Executor>(ex)+  {+  }++  /// Construct a basic_stream_socket without opening it.+  /**+   * This constructor creates a stream 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_stream_socket(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(context)+  {+  }++  /// Construct and open a basic_stream_socket.+  /**+   * This constructor creates and opens a stream 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_stream_socket(const executor_type& ex, const protocol_type& protocol)+    : basic_socket<Protocol, Executor>(ex, protocol)+  {+  }++  /// Construct and open a basic_stream_socket.+  /**+   * This constructor creates and opens a stream 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_stream_socket(ExecutionContext& context, const protocol_type& protocol,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(context, protocol)+  {+  }++  /// Construct a basic_stream_socket, opening it and binding it to the given+  /// local endpoint.+  /**+   * This constructor creates a stream 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 stream+   * socket will be bound.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_stream_socket(const executor_type& ex, const endpoint_type& endpoint)+    : basic_socket<Protocol, Executor>(ex, endpoint)+  {+  }++  /// Construct a basic_stream_socket, opening it and binding it to the given+  /// local endpoint.+  /**+   * This constructor creates a stream 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 stream+   * socket will be bound.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(context, endpoint)+  {+  }++  /// Construct a basic_stream_socket on an existing native socket.+  /**+   * This constructor creates a stream 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_stream_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_stream_socket on an existing native socket.+  /**+   * This constructor creates a stream 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_stream_socket(ExecutionContext& context,+      const protocol_type& protocol, const native_handle_type& native_socket,+      typename enable_if<+        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_stream_socket from another.+  /**+   * This constructor moves a stream socket from one object to another.+   *+   * @param other The other basic_stream_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_stream_socket(const executor_type&)+   * constructor.+   */+  basic_stream_socket(basic_stream_socket&& other) ASIO_NOEXCEPT+    : basic_socket<Protocol, Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_stream_socket from another.+  /**+   * This assignment operator moves a stream socket from one object to another.+   *+   * @param other The other basic_stream_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_stream_socket(const executor_type&)+   * constructor.+   */+  basic_stream_socket& operator=(basic_stream_socket&& other)+  {+    basic_socket<Protocol, Executor>::operator=(std::move(other));+    return *this;+  }++  /// Move-construct a basic_stream_socket from a socket of another protocol+  /// type.+  /**+   * This constructor moves a stream socket from one object to another.+   *+   * @param other The other basic_stream_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_stream_socket(const executor_type&)+   * constructor.+   */+  template <typename Protocol1, typename Executor1>+  basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other,+      typename enable_if<+        is_convertible<Protocol1, Protocol>::value+          && is_convertible<Executor1, Executor>::value+      >::type* = 0)+    : basic_socket<Protocol, Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_stream_socket from a socket of another protocol type.+  /**+   * This assignment operator moves a stream socket from one object to another.+   *+   * @param other The other basic_stream_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_stream_socket(const executor_type&)+   * constructor.+   */+  template <typename Protocol1, typename Executor1>+  typename enable_if<+    is_convertible<Protocol1, Protocol>::value+      && is_convertible<Executor1, Executor>::value,+    basic_stream_socket&+  >::type operator=(basic_stream_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_stream_socket()+  {+  }++  /// Send some data on the socket.+  /**+   * This function is used to send data on the stream socket. The function+   * call will block until one or more bytes of the data has been sent+   * successfully, or an until error occurs.+   *+   * @param buffers One or more data buffers to be sent on the socket.+   *+   * @returns The number of bytes sent.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @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.+   *+   * @par Example+   * To send a single data buffer use the @ref buffer function as follows:+   * @code+   * socket.send(asio::buffer(data, size));+   * @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)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().send(+        this->impl_.get_implementation(), buffers, 0, ec);+    asio::detail::throw_error(ec, "send");+    return s;+  }++  /// Send some data on the socket.+  /**+   * This function is used to send data on the stream socket. The function+   * call will block until one or more bytes of 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.+   *+   * @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.+   *+   * @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 stream socket. The function+   * call will block until one or more bytes of 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 stream socket.+   * The function call 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 handler is called.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @note The send 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 send a single data buffer use the @ref buffer function as follows:+   * @code+   * socket.async_send(asio::buffer(data, size), 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.+   */+  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_send(const ConstBufferSequence& buffers,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send(this), handler,+        buffers, socket_base::message_flags(0));+  }++  /// Start an asynchronous send.+  /**+   * This function is used to asynchronously send data on the stream socket.+   * The function call 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 handler is called.+   *+   * @param flags Flags specifying how the send call is to be made.+   *+   * @param handler The handler to be called when the send operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @note The send 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 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.+   */+  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_send(const ConstBufferSequence& buffers,+      socket_base::message_flags flags,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send(this), handler, buffers, flags);+  }++  /// Receive some data on the socket.+  /**+   * This function is used to receive data on the stream socket. The function+   * call will block until one or more bytes of data has been received+   * successfully, or until an error occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @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));+   * @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)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive(+        this->impl_.get_implementation(), buffers, 0, ec);+    asio::detail::throw_error(ec, "receive");+    return s;+  }++  /// Receive some data on the socket.+  /**+   * This function is used to receive data on the stream socket. The function+   * call will block until one or more bytes of data has been received+   * successfully, or until an error occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @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);+   * @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 flags)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().receive(+        this->impl_.get_implementation(), buffers, 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 stream socket. The function+   * call will block until one or more bytes of data has been received+   * successfully, or until an error occurs.+   *+   * @param buffers One or more buffers into which the data will be received.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @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 flags, asio::error_code& ec)+  {+    return this->impl_.get_service().receive(+        this->impl_.get_implementation(), buffers, flags, ec);+  }++  /// Start an asynchronous receive.+  /**+   * This function is used to asynchronously receive data from the stream+   * socket. The function call 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 handler is called.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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().+   *+   * @note The receive operation may not receive 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 received before the asynchronous+   * operation completes.+   *+   * @par Example+   * To receive into a single data buffer use the @ref buffer function as+   * follows:+   * @code+   * socket.async_receive(asio::buffer(data, size), 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.+   */+  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_receive(const MutableBufferSequence& buffers,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive(this), handler,+        buffers, socket_base::message_flags(0));+  }++  /// Start an asynchronous receive.+  /**+   * This function is used to asynchronously receive data from the stream+   * socket. The function call 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 handler is called.+   *+   * @param flags Flags specifying how the receive call is to be made.+   *+   * @param handler The handler to be called when the receive operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the 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 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().+   *+   * @note The receive operation may not receive 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 received before the asynchronous+   * operation completes.+   *+   * @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, 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.+   */+  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_receive(const MutableBufferSequence& buffers,+      socket_base::message_flags flags,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive(this), handler, buffers, flags);+  }++  /// Write some data to the socket.+  /**+   * This function is used to write data to the stream socket. 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 socket.+   *+   * @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+   * socket.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().send(+        this->impl_.get_implementation(), buffers, 0, ec);+    asio::detail::throw_error(ec, "write_some");+    return s;+  }++  /// Write some data to the socket.+  /**+   * This function is used to write data to the stream socket. 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 socket.+   *+   * @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().send(+        this->impl_.get_implementation(), buffers, 0, ec);+  }++  /// Start an asynchronous write.+  /**+   * This function is used to asynchronously write data to the stream socket.+   * The function call always returns immediately.+   *+   * @param buffers One or more data buffers to be written to 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 handler is called.+   *+   * @param handler The handler to be called when the write operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @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+   * socket.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)) 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 async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_send(this), handler,+        buffers, socket_base::message_flags(0));+  }++  /// Read some data from the socket.+  /**+   * This function is used to read data from the stream socket. 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+   * socket.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().receive(+        this->impl_.get_implementation(), buffers, 0, ec);+    asio::detail::throw_error(ec, "read_some");+    return s;+  }++  /// Read some data from the socket.+  /**+   * This function is used to read data from the stream socket. 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().receive(+        this->impl_.get_implementation(), buffers, 0, ec);+  }++  /// Start an asynchronous read.+  /**+   * This function is used to asynchronously read data from the stream socket.+   * The function call 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 handler is called.+   *+   * @param handler The handler to be called when the read operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @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+   * socket.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)) 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 async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_receive(this), handler,+        buffers, socket_base::message_flags(0));+  }++private:+  // Disallow copying and assignment.+  basic_stream_socket(const basic_stream_socket&) ASIO_DELETED;+  basic_stream_socket& operator=(const basic_stream_socket&) ASIO_DELETED;++  class initiate_async_send+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_send(basic_stream_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_stream_socket* self_;+  };++  class initiate_async_receive+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_receive(basic_stream_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 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(+          self_->impl_.get_implementation(), buffers, flags,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_stream_socket* self_;+  };+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BASIC_STREAM_SOCKET_HPP
+ link/modules/asio-standalone/asio/include/asio/basic_streambuf.hpp view
@@ -0,0 +1,452 @@+//+// basic_streambuf.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/basic_streambuf_fwd.hpp view
@@ -0,0 +1,36 @@+//+// basic_streambuf_fwd.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/basic_waitable_timer.hpp view
@@ -0,0 +1,811 @@+//+// basic_waitable_timer.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 &lt;chrono&gt; 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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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_(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 enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(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 enable_if<+          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 enable_if<+    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 always returns immediately.+   *+   * For each call to async_wait(), the supplied handler will be called exactly+   * once. The 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 handler The handler to be called when the timer expires. Copies+   * will be made of the handler as required. The function signature of the+   * 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 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().+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+      void (asio::error_code))+  async_wait(+      ASIO_MOVE_ARG(WaitHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WaitHandler, void (asio::error_code)>(+        initiate_async_wait(this), handler);+  }++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
+ link/modules/asio-standalone/asio/include/asio/bind_executor.hpp view
@@ -0,0 +1,575 @@+//+// bind_executor.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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/associated_allocator.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>+inline executor_binder<typename decay<T>::type, Executor>+bind_executor(const Executor& ex, ASIO_MOVE_ARG(T) t,+    typename enable_if<+      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>+inline executor_binder<typename decay<T>::type,+  typename ExecutionContext::executor_type>+bind_executor(ExecutionContext& ctx, ASIO_MOVE_ARG(T) t,+    typename enable_if<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 {};++template <typename T, typename Executor, typename Signature>+class async_result<executor_binder<T, Executor>, Signature>+{+public:+  typedef executor_binder<+    typename async_result<T, Signature>::completion_handler_type, Executor>+      completion_handler_type;++  typedef typename async_result<T, Signature>::return_type return_type;++  explicit async_result(executor_binder<T, Executor>& b)+    : target_(b.get())+  {+  }++  return_type get()+  {+    return target_.get();+  }++private:+  async_result(const async_result&) ASIO_DELETED;+  async_result& operator=(const async_result&) ASIO_DELETED;++  async_result<T, Signature> target_;+};++template <typename T, typename Executor, typename Allocator>+struct associated_allocator<executor_binder<T, Executor>, Allocator>+{+  typedef typename associated_allocator<T, Allocator>::type type;++  static type get(const executor_binder<T, Executor>& b,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<T, Allocator>::get(b.get(), a);+  }+};++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
+ link/modules/asio-standalone/asio/include/asio/buffer.hpp view
@@ -0,0 +1,2496 @@+//+// buffer.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_HPP+#define ASIO_BUFFER_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 <cstring>+#include <limits>+#include <stdexcept>+#include <string>+#include <vector>+#include "asio/detail/array_fwd.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/string_view.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/detail/type_traits.hpp"++#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1700)+# if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)+#  if !defined(ASIO_DISABLE_BUFFER_DEBUGGING)+#   define ASIO_ENABLE_BUFFER_DEBUGGING+#  endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING)+# endif // defined(_HAS_ITERATOR_DEBUGGING)+#endif // defined(ASIO_MSVC) && (ASIO_MSVC >= 1700)++#if defined(__GNUC__)+# if defined(_GLIBCXX_DEBUG)+#  if !defined(ASIO_DISABLE_BUFFER_DEBUGGING)+#   define ASIO_ENABLE_BUFFER_DEBUGGING+#  endif // !defined(ASIO_DISABLE_BUFFER_DEBUGGING)+# endif // defined(_GLIBCXX_DEBUG)+#endif // defined(__GNUC__)++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+# include "asio/detail/functional.hpp"+#endif // ASIO_ENABLE_BUFFER_DEBUGGING++#if defined(ASIO_HAS_BOOST_WORKAROUND)+# include <boost/detail/workaround.hpp>+# if !defined(__clang__)+#  if BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))+#   define ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND+#  endif // BOOST_WORKAROUND(__BORLANDC__, BOOST_TESTED_AT(0x582))+# elif BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))+#  define ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND+# endif // BOOST_WORKAROUND(__SUNPRO_CC, BOOST_TESTED_AT(0x590))+#endif // defined(ASIO_HAS_BOOST_WORKAROUND)++#if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)+# include "asio/detail/type_traits.hpp"+#endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)++#include "asio/detail/push_options.hpp"++namespace asio {++class mutable_buffer;+class const_buffer;++/// Holds a buffer that can be modified.+/**+ * The mutable_buffer class provides a safe representation of a buffer that can+ * be modified. It does not own the underlying data, and so is cheap to copy or+ * assign.+ *+ * @par Accessing Buffer Contents+ *+ * The contents of a buffer may be accessed using the @c data() and @c size()+ * member functions:+ *+ * @code asio::mutable_buffer b1 = ...;+ * std::size_t s1 = b1.size();+ * unsigned char* p1 = static_cast<unsigned char*>(b1.data());+ * @endcode+ *+ * The @c data() member function permits violations of type safety, so uses of+ * it in application code should be carefully considered.+ */+class mutable_buffer+{+public:+  /// Construct an empty buffer.+  mutable_buffer() ASIO_NOEXCEPT+    : data_(0),+      size_(0)+  {+  }++  /// Construct a buffer to represent a given memory range.+  mutable_buffer(void* data, std::size_t size) ASIO_NOEXCEPT+    : data_(data),+      size_(size)+  {+  }++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+  mutable_buffer(void* data, std::size_t size,+      asio::detail::function<void()> debug_check)+    : data_(data),+      size_(size),+      debug_check_(debug_check)+  {+  }++  const asio::detail::function<void()>& get_debug_check() const+  {+    return debug_check_;+  }+#endif // ASIO_ENABLE_BUFFER_DEBUGGING++  /// Get a pointer to the beginning of the memory range.+  void* data() const ASIO_NOEXCEPT+  {+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    if (size_ && debug_check_)+      debug_check_();+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+    return data_;+  }++  /// Get the size of the memory range.+  std::size_t size() const ASIO_NOEXCEPT+  {+    return size_;+  }++  /// Move the start of the buffer by the specified number of bytes.+  mutable_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT+  {+    std::size_t offset = n < size_ ? n : size_;+    data_ = static_cast<char*>(data_) + offset;+    size_ -= offset;+    return *this;+  }++private:+  void* data_;+  std::size_t size_;++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+  asio::detail::function<void()> debug_check_;+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+};++#if !defined(ASIO_NO_DEPRECATED)++/// (Deprecated: Use mutable_buffer.) Adapts a single modifiable buffer so that+/// it meets the requirements of the MutableBufferSequence concept.+class mutable_buffers_1+  : public mutable_buffer+{+public:+  /// The type for each element in the list of buffers.+  typedef mutable_buffer value_type;++  /// A random-access iterator type that may be used to read elements.+  typedef const mutable_buffer* const_iterator;++  /// Construct to represent a given memory range.+  mutable_buffers_1(void* data, std::size_t size) ASIO_NOEXCEPT+    : mutable_buffer(data, size)+  {+  }++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+  mutable_buffers_1(void* data, std::size_t size,+      asio::detail::function<void()> debug_check)+    : mutable_buffer(data, size, debug_check)+  {+  }+#endif // ASIO_ENABLE_BUFFER_DEBUGGING++  /// Construct to represent a single modifiable buffer.+  explicit mutable_buffers_1(const mutable_buffer& b) ASIO_NOEXCEPT+    : mutable_buffer(b)+  {+  }++  /// Get a random-access iterator to the first element.+  const_iterator begin() const ASIO_NOEXCEPT+  {+    return this;+  }++  /// Get a random-access iterator for one past the last element.+  const_iterator end() const ASIO_NOEXCEPT+  {+    return begin() + 1;+  }+};++#endif // !defined(ASIO_NO_DEPRECATED)++/// Holds a buffer that cannot be modified.+/**+ * The const_buffer class provides a safe representation of a buffer that cannot+ * be modified. It does not own the underlying data, and so is cheap to copy or+ * assign.+ *+ * @par Accessing Buffer Contents+ *+ * The contents of a buffer may be accessed using the @c data() and @c size()+ * member functions:+ *+ * @code asio::const_buffer b1 = ...;+ * std::size_t s1 = b1.size();+ * const unsigned char* p1 = static_cast<const unsigned char*>(b1.data());+ * @endcode+ *+ * The @c data() member function permits violations of type safety, so uses of+ * it in application code should be carefully considered.+ */+class const_buffer+{+public:+  /// Construct an empty buffer.+  const_buffer() ASIO_NOEXCEPT+    : data_(0),+      size_(0)+  {+  }++  /// Construct a buffer to represent a given memory range.+  const_buffer(const void* data, std::size_t size) ASIO_NOEXCEPT+    : data_(data),+      size_(size)+  {+  }++  /// Construct a non-modifiable buffer from a modifiable one.+  const_buffer(const mutable_buffer& b) ASIO_NOEXCEPT+    : data_(b.data()),+      size_(b.size())+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , debug_check_(b.get_debug_check())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+  {+  }++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+  const_buffer(const void* data, std::size_t size,+      asio::detail::function<void()> debug_check)+    : data_(data),+      size_(size),+      debug_check_(debug_check)+  {+  }++  const asio::detail::function<void()>& get_debug_check() const+  {+    return debug_check_;+  }+#endif // ASIO_ENABLE_BUFFER_DEBUGGING++  /// Get a pointer to the beginning of the memory range.+  const void* data() const ASIO_NOEXCEPT+  {+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    if (size_ && debug_check_)+      debug_check_();+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+    return data_;+  }++  /// Get the size of the memory range.+  std::size_t size() const ASIO_NOEXCEPT+  {+    return size_;+  }++  /// Move the start of the buffer by the specified number of bytes.+  const_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT+  {+    std::size_t offset = n < size_ ? n : size_;+    data_ = static_cast<const char*>(data_) + offset;+    size_ -= offset;+    return *this;+  }++private:+  const void* data_;+  std::size_t size_;++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+  asio::detail::function<void()> debug_check_;+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+};++#if !defined(ASIO_NO_DEPRECATED)++/// (Deprecated: Use const_buffer.) Adapts a single non-modifiable buffer so+/// that it meets the requirements of the ConstBufferSequence concept.+class const_buffers_1+  : public const_buffer+{+public:+  /// The type for each element in the list of buffers.+  typedef const_buffer value_type;++  /// A random-access iterator type that may be used to read elements.+  typedef const const_buffer* const_iterator;++  /// Construct to represent a given memory range.+  const_buffers_1(const void* data, std::size_t size) ASIO_NOEXCEPT+    : const_buffer(data, size)+  {+  }++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+  const_buffers_1(const void* data, std::size_t size,+      asio::detail::function<void()> debug_check)+    : const_buffer(data, size, debug_check)+  {+  }+#endif // ASIO_ENABLE_BUFFER_DEBUGGING++  /// Construct to represent a single non-modifiable buffer.+  explicit const_buffers_1(const const_buffer& b) ASIO_NOEXCEPT+    : const_buffer(b)+  {+  }++  /// Get a random-access iterator to the first element.+  const_iterator begin() const ASIO_NOEXCEPT+  {+    return this;+  }++  /// Get a random-access iterator for one past the last element.+  const_iterator end() const ASIO_NOEXCEPT+  {+    return begin() + 1;+  }+};++#endif // !defined(ASIO_NO_DEPRECATED)++/// (Deprecated: Use the socket/descriptor wait() and async_wait() member+/// functions.) An implementation of both the ConstBufferSequence and+/// MutableBufferSequence concepts to represent a null buffer sequence.+class null_buffers+{+public:+  /// The type for each element in the list of buffers.+  typedef mutable_buffer value_type;++  /// A random-access iterator type that may be used to read elements.+  typedef const mutable_buffer* const_iterator;++  /// Get a random-access iterator to the first element.+  const_iterator begin() const ASIO_NOEXCEPT+  {+    return &buf_;+  }++  /// Get a random-access iterator for one past the last element.+  const_iterator end() const ASIO_NOEXCEPT+  {+    return &buf_;+  }++private:+  mutable_buffer buf_;+};++/** @defgroup buffer_sequence_begin asio::buffer_sequence_begin+ *+ * @brief The asio::buffer_sequence_begin function returns an iterator+ * pointing to the first element in a buffer sequence.+ */+/*@{*/++/// Get an iterator to the first element in a buffer sequence.+template <typename MutableBuffer>+inline const mutable_buffer* buffer_sequence_begin(const MutableBuffer& b,+    typename enable_if<+      is_convertible<const MutableBuffer*, const mutable_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT+{+  return static_cast<const mutable_buffer*>(detail::addressof(b));+}++/// Get an iterator to the first element in a buffer sequence.+template <typename ConstBuffer>+inline const const_buffer* buffer_sequence_begin(const ConstBuffer& b,+    typename enable_if<+      is_convertible<const ConstBuffer*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT+{+  return static_cast<const const_buffer*>(detail::addressof(b));+}++#if defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)++/// Get an iterator to the first element in a buffer sequence.+template <typename C>+inline auto buffer_sequence_begin(C& c,+    typename enable_if<+      !is_convertible<const C*, const mutable_buffer*>::value+        && !is_convertible<const C*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())+{+  return c.begin();+}++/// Get an iterator to the first element in a buffer sequence.+template <typename C>+inline auto buffer_sequence_begin(const C& c,+    typename enable_if<+      !is_convertible<const C*, const mutable_buffer*>::value+        && !is_convertible<const C*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())+{+  return c.begin();+}++#else // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)++template <typename C>+inline typename C::iterator buffer_sequence_begin(C& c,+    typename enable_if<+      !is_convertible<const C*, const mutable_buffer*>::value+        && !is_convertible<const C*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT+{+  return c.begin();+}++template <typename C>+inline typename C::const_iterator buffer_sequence_begin(const C& c,+    typename enable_if<+      !is_convertible<const C*, const mutable_buffer*>::value+        && !is_convertible<const C*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT+{+  return c.begin();+}++#endif // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)++/*@}*/++/** @defgroup buffer_sequence_end asio::buffer_sequence_end+ *+ * @brief The asio::buffer_sequence_end function returns an iterator+ * pointing to one past the end element in a buffer sequence.+ */+/*@{*/++/// Get an iterator to one past the end element in a buffer sequence.+template <typename MutableBuffer>+inline const mutable_buffer* buffer_sequence_end(const MutableBuffer& b,+    typename enable_if<+      is_convertible<const MutableBuffer*, const mutable_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT+{+  return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1;+}++/// Get an iterator to one past the end element in a buffer sequence.+template <typename ConstBuffer>+inline const const_buffer* buffer_sequence_end(const ConstBuffer& b,+    typename enable_if<+      is_convertible<const ConstBuffer*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT+{+  return static_cast<const const_buffer*>(detail::addressof(b)) + 1;+}++#if defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)++/// Get an iterator to one past the end element in a buffer sequence.+template <typename C>+inline auto buffer_sequence_end(C& c,+    typename enable_if<+      !is_convertible<const C*, const mutable_buffer*>::value+        && !is_convertible<const C*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())+{+  return c.end();+}++/// Get an iterator to one past the end element in a buffer sequence.+template <typename C>+inline auto buffer_sequence_end(const C& c,+    typename enable_if<+      !is_convertible<const C*, const mutable_buffer*>::value+        && !is_convertible<const C*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())+{+  return c.end();+}++#else // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)++template <typename C>+inline typename C::iterator buffer_sequence_end(C& c,+    typename enable_if<+      !is_convertible<const C*, const mutable_buffer*>::value+        && !is_convertible<const C*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT+{+  return c.end();+}++template <typename C>+inline typename C::const_iterator buffer_sequence_end(const C& c,+    typename enable_if<+      !is_convertible<const C*, const mutable_buffer*>::value+        && !is_convertible<const C*, const const_buffer*>::value+    >::type* = 0) ASIO_NOEXCEPT+{+  return c.end();+}++#endif // defined(ASIO_HAS_DECLTYPE) || defined(GENERATING_DOCUMENTATION)++/*@}*/++namespace detail {++// Tag types used to select appropriately optimised overloads.+struct one_buffer {};+struct multiple_buffers {};++// Helper trait to detect single buffers.+template <typename BufferSequence>+struct buffer_sequence_cardinality :+  conditional<+    is_same<BufferSequence, mutable_buffer>::value+#if !defined(ASIO_NO_DEPRECATED)+      || is_same<BufferSequence, mutable_buffers_1>::value+      || is_same<BufferSequence, const_buffers_1>::value+#endif // !defined(ASIO_NO_DEPRECATED)+      || is_same<BufferSequence, const_buffer>::value,+    one_buffer, multiple_buffers>::type {};++template <typename Iterator>+inline std::size_t buffer_size(one_buffer,+    Iterator begin, Iterator) ASIO_NOEXCEPT+{+  return const_buffer(*begin).size();+}++template <typename Iterator>+inline std::size_t buffer_size(multiple_buffers,+    Iterator begin, Iterator end) ASIO_NOEXCEPT+{+  std::size_t total_buffer_size = 0;++  Iterator iter = begin;+  for (; iter != end; ++iter)+  {+    const_buffer b(*iter);+    total_buffer_size += b.size();+  }++  return total_buffer_size;+}++} // namespace detail++/// Get the total number of bytes in a buffer sequence.+/**+ * The @c buffer_size function determines the total size of all buffers in the+ * buffer sequence, as if computed as follows:+ *+ * @code size_t total_size = 0;+ * auto i = asio::buffer_sequence_begin(buffers);+ * auto end = asio::buffer_sequence_end(buffers);+ * for (; i != end; ++i)+ * {+ *   const_buffer b(*i);+ *   total_size += b.size();+ * }+ * return total_size; @endcode+ *+ * The @c BufferSequence template parameter may meet either of the @c+ * ConstBufferSequence or @c MutableBufferSequence type requirements.+ */+template <typename BufferSequence>+inline std::size_t buffer_size(const BufferSequence& b) ASIO_NOEXCEPT+{+  return detail::buffer_size(+      detail::buffer_sequence_cardinality<BufferSequence>(),+      asio::buffer_sequence_begin(b),+      asio::buffer_sequence_end(b));+}++#if !defined(ASIO_NO_DEPRECATED)++/** @defgroup buffer_cast asio::buffer_cast+ *+ * @brief (Deprecated: Use the @c data() member function.) The+ * asio::buffer_cast function is used to obtain a pointer to the+ * underlying memory region associated with a buffer.+ *+ * @par Examples:+ *+ * To access the memory of a non-modifiable buffer, use:+ * @code asio::const_buffer b1 = ...;+ * const unsigned char* p1 = asio::buffer_cast<const unsigned char*>(b1);+ * @endcode+ *+ * To access the memory of a modifiable buffer, use:+ * @code asio::mutable_buffer b2 = ...;+ * unsigned char* p2 = asio::buffer_cast<unsigned char*>(b2);+ * @endcode+ *+ * The asio::buffer_cast function permits violations of type safety, so+ * uses of it in application code should be carefully considered.+ */+/*@{*/++/// Cast a non-modifiable buffer to a specified pointer to POD type.+template <typename PointerToPodType>+inline PointerToPodType buffer_cast(const mutable_buffer& b) ASIO_NOEXCEPT+{+  return static_cast<PointerToPodType>(b.data());+}++/// Cast a non-modifiable buffer to a specified pointer to POD type.+template <typename PointerToPodType>+inline PointerToPodType buffer_cast(const const_buffer& b) ASIO_NOEXCEPT+{+  return static_cast<PointerToPodType>(b.data());+}++/*@}*/++#endif // !defined(ASIO_NO_DEPRECATED)++/// Create a new modifiable buffer that is offset from the start of another.+/**+ * @relates mutable_buffer+ */+inline mutable_buffer operator+(const mutable_buffer& b,+    std::size_t n) ASIO_NOEXCEPT+{+  std::size_t offset = n < b.size() ? n : b.size();+  char* new_data = static_cast<char*>(b.data()) + offset;+  std::size_t new_size = b.size() - offset;+  return mutable_buffer(new_data, new_size+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , b.get_debug_check()+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new modifiable buffer that is offset from the start of another.+/**+ * @relates mutable_buffer+ */+inline mutable_buffer operator+(std::size_t n,+    const mutable_buffer& b) ASIO_NOEXCEPT+{+  return b + n;+}++/// Create a new non-modifiable buffer that is offset from the start of another.+/**+ * @relates const_buffer+ */+inline const_buffer operator+(const const_buffer& b,+    std::size_t n) ASIO_NOEXCEPT+{+  std::size_t offset = n < b.size() ? n : b.size();+  const char* new_data = static_cast<const char*>(b.data()) + offset;+  std::size_t new_size = b.size() - offset;+  return const_buffer(new_data, new_size+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , b.get_debug_check()+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new non-modifiable buffer that is offset from the start of another.+/**+ * @relates const_buffer+ */+inline const_buffer operator+(std::size_t n,+    const const_buffer& b) ASIO_NOEXCEPT+{+  return b + n;+}++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+namespace detail {++template <typename Iterator>+class buffer_debug_check+{+public:+  buffer_debug_check(Iterator iter)+    : iter_(iter)+  {+  }++  ~buffer_debug_check()+  {+#if defined(ASIO_MSVC) && (ASIO_MSVC == 1400)+    // MSVC 8's string iterator checking may crash in a std::string::iterator+    // object's destructor when the iterator points to an already-destroyed+    // std::string object, unless the iterator is cleared first.+    iter_ = Iterator();+#endif // defined(ASIO_MSVC) && (ASIO_MSVC == 1400)+  }++  void operator()()+  {+    (void)*iter_;+  }++private:+  Iterator iter_;+};++} // namespace detail+#endif // ASIO_ENABLE_BUFFER_DEBUGGING++/** @defgroup buffer asio::buffer+ *+ * @brief The asio::buffer function is used to create a buffer object to+ * represent raw memory, an array of POD elements, a vector of POD elements,+ * or a std::string.+ *+ * A buffer object represents a contiguous region of memory as a 2-tuple+ * consisting of a pointer and size in bytes. A tuple of the form <tt>{void*,+ * size_t}</tt> specifies a mutable (modifiable) region of memory. Similarly, a+ * tuple of the form <tt>{const void*, size_t}</tt> specifies a const+ * (non-modifiable) region of memory. These two forms correspond to the classes+ * mutable_buffer and const_buffer, respectively. To mirror C++'s conversion+ * rules, a mutable_buffer is implicitly convertible to a const_buffer, and the+ * opposite conversion is not permitted.+ *+ * The simplest use case involves reading or writing a single buffer of a+ * specified size:+ *+ * @code sock.send(asio::buffer(data, size)); @endcode+ *+ * In the above example, the return value of asio::buffer meets the+ * requirements of the ConstBufferSequence concept so that it may be directly+ * passed to the socket's write function. A buffer created for modifiable+ * memory also meets the requirements of the MutableBufferSequence concept.+ *+ * An individual buffer may be created from a builtin array, std::vector,+ * std::array or boost::array of POD elements. This helps prevent buffer+ * overruns by automatically determining the size of the buffer:+ *+ * @code char d1[128];+ * size_t bytes_transferred = sock.receive(asio::buffer(d1));+ *+ * std::vector<char> d2(128);+ * bytes_transferred = sock.receive(asio::buffer(d2));+ *+ * std::array<char, 128> d3;+ * bytes_transferred = sock.receive(asio::buffer(d3));+ *+ * boost::array<char, 128> d4;+ * bytes_transferred = sock.receive(asio::buffer(d4)); @endcode+ *+ * In all three cases above, the buffers created are exactly 128 bytes long.+ * Note that a vector is @e never automatically resized when creating or using+ * a buffer. The buffer size is determined using the vector's <tt>size()</tt>+ * member function, and not its capacity.+ *+ * @par Accessing Buffer Contents+ *+ * The contents of a buffer may be accessed using the @c data() and @c size()+ * member functions:+ *+ * @code asio::mutable_buffer b1 = ...;+ * std::size_t s1 = b1.size();+ * unsigned char* p1 = static_cast<unsigned char*>(b1.data());+ *+ * asio::const_buffer b2 = ...;+ * std::size_t s2 = b2.size();+ * const void* p2 = b2.data(); @endcode+ *+ * The @c data() member function permits violations of type safety, so+ * uses of it in application code should be carefully considered.+ *+ * For convenience, a @ref buffer_size function is provided that works with+ * both buffers and buffer sequences (that is, types meeting the+ * ConstBufferSequence or MutableBufferSequence type requirements). In this+ * case, the function returns the total size of all buffers in the sequence.+ *+ * @par Buffer Copying+ *+ * The @ref buffer_copy function may be used to copy raw bytes between+ * individual buffers and buffer sequences.+*+ * In particular, when used with the @ref buffer_size function, the @ref+ * buffer_copy function can be used to linearise a sequence of buffers. For+ * example:+ *+ * @code vector<const_buffer> buffers = ...;+ *+ * vector<unsigned char> data(asio::buffer_size(buffers));+ * asio::buffer_copy(asio::buffer(data), buffers); @endcode+ *+ * Note that @ref buffer_copy is implemented in terms of @c memcpy, and+ * consequently it cannot be used to copy between overlapping memory regions.+ *+ * @par Buffer Invalidation+ *+ * A buffer object does not have any ownership of the memory it refers to. It+ * is the responsibility of the application to ensure the memory region remains+ * valid until it is no longer required for an I/O operation. When the memory+ * is no longer available, the buffer is said to have been invalidated.+ *+ * For the asio::buffer overloads that accept an argument of type+ * std::vector, the buffer objects returned are invalidated by any vector+ * operation that also invalidates all references, pointers and iterators+ * referring to the elements in the sequence (C++ Std, 23.2.4)+ *+ * For the asio::buffer overloads that accept an argument of type+ * std::basic_string, the buffer objects returned are invalidated according to+ * the rules defined for invalidation of references, pointers and iterators+ * referring to elements of the sequence (C++ Std, 21.3).+ *+ * @par Buffer Arithmetic+ *+ * Buffer objects may be manipulated using simple arithmetic in a safe way+ * which helps prevent buffer overruns. Consider an array initialised as+ * follows:+ *+ * @code boost::array<char, 6> a = { 'a', 'b', 'c', 'd', 'e' }; @endcode+ *+ * A buffer object @c b1 created using:+ *+ * @code b1 = asio::buffer(a); @endcode+ *+ * represents the entire array, <tt>{ 'a', 'b', 'c', 'd', 'e' }</tt>. An+ * optional second argument to the asio::buffer function may be used to+ * limit the size, in bytes, of the buffer:+ *+ * @code b2 = asio::buffer(a, 3); @endcode+ *+ * such that @c b2 represents the data <tt>{ 'a', 'b', 'c' }</tt>. Even if the+ * size argument exceeds the actual size of the array, the size of the buffer+ * object created will be limited to the array size.+ *+ * An offset may be applied to an existing buffer to create a new one:+ *+ * @code b3 = b1 + 2; @endcode+ *+ * where @c b3 will set to represent <tt>{ 'c', 'd', 'e' }</tt>. If the offset+ * exceeds the size of the existing buffer, the newly created buffer will be+ * empty.+ *+ * Both an offset and size may be specified to create a buffer that corresponds+ * to a specific range of bytes within an existing buffer:+ *+ * @code b4 = asio::buffer(b1 + 1, 3); @endcode+ *+ * so that @c b4 will refer to the bytes <tt>{ 'b', 'c', 'd' }</tt>.+ *+ * @par Buffers and Scatter-Gather I/O+ *+ * To read or write using multiple buffers (i.e. scatter-gather I/O), multiple+ * buffer objects may be assigned into a container that supports the+ * MutableBufferSequence (for read) or ConstBufferSequence (for write) concepts:+ *+ * @code+ * char d1[128];+ * std::vector<char> d2(128);+ * boost::array<char, 128> d3;+ *+ * boost::array<mutable_buffer, 3> bufs1 = {+ *   asio::buffer(d1),+ *   asio::buffer(d2),+ *   asio::buffer(d3) };+ * bytes_transferred = sock.receive(bufs1);+ *+ * std::vector<const_buffer> bufs2;+ * bufs2.push_back(asio::buffer(d1));+ * bufs2.push_back(asio::buffer(d2));+ * bufs2.push_back(asio::buffer(d3));+ * bytes_transferred = sock.send(bufs2); @endcode+ */+/*@{*/++#if defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)+# define ASIO_MUTABLE_BUFFER mutable_buffer+# define ASIO_CONST_BUFFER const_buffer+#else // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)+# define ASIO_MUTABLE_BUFFER mutable_buffers_1+# define ASIO_CONST_BUFFER const_buffers_1+#endif // defined(ASIO_NO_DEPRECATED) || defined(GENERATING_DOCUMENTATION)++/// Create a new modifiable buffer from an existing buffer.+/**+ * @returns <tt>mutable_buffer(b)</tt>.+ */+inline ASIO_MUTABLE_BUFFER buffer(+    const mutable_buffer& b) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(b);+}++/// Create a new modifiable buffer from an existing buffer.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     b.data(),+ *     min(b.size(), max_size_in_bytes)); @endcode+ */+inline ASIO_MUTABLE_BUFFER buffer(const mutable_buffer& b,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(+      mutable_buffer(b.data(),+        b.size() < max_size_in_bytes+        ? b.size() : max_size_in_bytes+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+        , b.get_debug_check()+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+        ));+}++/// Create a new non-modifiable buffer from an existing buffer.+/**+ * @returns <tt>const_buffer(b)</tt>.+ */+inline ASIO_CONST_BUFFER buffer(+    const const_buffer& b) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(b);+}++/// Create a new non-modifiable buffer from an existing buffer.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     b.data(),+ *     min(b.size(), max_size_in_bytes)); @endcode+ */+inline ASIO_CONST_BUFFER buffer(const const_buffer& b,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(b.data(),+      b.size() < max_size_in_bytes+      ? b.size() : max_size_in_bytes+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , b.get_debug_check()+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new modifiable buffer that represents the given memory range.+/**+ * @returns <tt>mutable_buffer(data, size_in_bytes)</tt>.+ */+inline ASIO_MUTABLE_BUFFER buffer(void* data,+    std::size_t size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(data, size_in_bytes);+}++/// Create a new non-modifiable buffer that represents the given memory range.+/**+ * @returns <tt>const_buffer(data, size_in_bytes)</tt>.+ */+inline ASIO_CONST_BUFFER buffer(const void* data,+    std::size_t size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data, size_in_bytes);+}++/// Create a new modifiable buffer that represents the given POD array.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     static_cast<void*>(data),+ *     N * sizeof(PodType)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N]) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType));+}+ +/// Create a new modifiable buffer that represents the given POD array.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     static_cast<void*>(data),+ *     min(N * sizeof(PodType), max_size_in_bytes)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N],+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(data,+      N * sizeof(PodType) < max_size_in_bytes+      ? N * sizeof(PodType) : max_size_in_bytes);+}+ +/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     static_cast<const void*>(data),+ *     N * sizeof(PodType)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(+    const PodType (&data)[N]) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data, N * sizeof(PodType));+}++/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     static_cast<const void*>(data),+ *     min(N * sizeof(PodType), max_size_in_bytes)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(const PodType (&data)[N],+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data,+      N * sizeof(PodType) < max_size_in_bytes+      ? N * sizeof(PodType) : max_size_in_bytes);+}++#if defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)++// Borland C++ and Sun Studio think the overloads:+//+//   unspecified buffer(boost::array<PodType, N>& array ...);+//+// and+//+//   unspecified buffer(boost::array<const PodType, N>& array ...);+//+// are ambiguous. This will be worked around by using a buffer_types traits+// class that contains typedefs for the appropriate buffer and container+// classes, based on whether PodType is const or non-const.++namespace detail {++template <bool IsConst>+struct buffer_types_base;++template <>+struct buffer_types_base<false>+{+  typedef mutable_buffer buffer_type;+  typedef ASIO_MUTABLE_BUFFER container_type;+};++template <>+struct buffer_types_base<true>+{+  typedef const_buffer buffer_type;+  typedef ASIO_CONST_BUFFER container_type;+};++template <typename PodType>+struct buffer_types+  : public buffer_types_base<is_const<PodType>::value>+{+};++} // namespace detail++template <typename PodType, std::size_t N>+inline typename detail::buffer_types<PodType>::container_type+buffer(boost::array<PodType, N>& data) ASIO_NOEXCEPT+{+  typedef typename asio::detail::buffer_types<PodType>::buffer_type+    buffer_type;+  typedef typename asio::detail::buffer_types<PodType>::container_type+    container_type;+  return container_type(+      buffer_type(data.c_array(), data.size() * sizeof(PodType)));+}++template <typename PodType, std::size_t N>+inline typename detail::buffer_types<PodType>::container_type+buffer(boost::array<PodType, N>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  typedef typename asio::detail::buffer_types<PodType>::buffer_type+    buffer_type;+  typedef typename asio::detail::buffer_types<PodType>::container_type+    container_type;+  return container_type(+      buffer_type(data.c_array(),+        data.size() * sizeof(PodType) < max_size_in_bytes+        ? data.size() * sizeof(PodType) : max_size_in_bytes));+}++#else // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)++/// Create a new modifiable buffer that represents the given POD array.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.data(),+ *     data.size() * sizeof(PodType)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_MUTABLE_BUFFER buffer(+    boost::array<PodType, N>& data) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(+      data.c_array(), data.size() * sizeof(PodType));+}++/// Create a new modifiable buffer that represents the given POD array.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.data(),+ *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_MUTABLE_BUFFER buffer(boost::array<PodType, N>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(data.c_array(),+      data.size() * sizeof(PodType) < max_size_in_bytes+      ? data.size() * sizeof(PodType) : max_size_in_bytes);+}++/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.data(),+ *     data.size() * sizeof(PodType)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(+    boost::array<const PodType, N>& data) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));+}++/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.data(),+ *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(boost::array<const PodType, N>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(),+      data.size() * sizeof(PodType) < max_size_in_bytes+      ? data.size() * sizeof(PodType) : max_size_in_bytes);+}++#endif // defined(ASIO_ENABLE_ARRAY_BUFFER_WORKAROUND)++/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.data(),+ *     data.size() * sizeof(PodType)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(+    const boost::array<PodType, N>& data) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));+}++/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.data(),+ *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(const boost::array<PodType, N>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(),+      data.size() * sizeof(PodType) < max_size_in_bytes+      ? data.size() * sizeof(PodType) : max_size_in_bytes);+}++#if defined(ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)++/// Create a new modifiable buffer that represents the given POD array.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.data(),+ *     data.size() * sizeof(PodType)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_MUTABLE_BUFFER buffer(+    std::array<PodType, N>& data) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType));+}++/// Create a new modifiable buffer that represents the given POD array.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.data(),+ *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_MUTABLE_BUFFER buffer(std::array<PodType, N>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(data.data(),+      data.size() * sizeof(PodType) < max_size_in_bytes+      ? data.size() * sizeof(PodType) : max_size_in_bytes);+}++/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.data(),+ *     data.size() * sizeof(PodType)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(+    std::array<const PodType, N>& data) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));+}++/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.data(),+ *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(std::array<const PodType, N>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(),+      data.size() * sizeof(PodType) < max_size_in_bytes+      ? data.size() * sizeof(PodType) : max_size_in_bytes);+}++/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.data(),+ *     data.size() * sizeof(PodType)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(+    const std::array<PodType, N>& data) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));+}++/// Create a new non-modifiable buffer that represents the given POD array.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.data(),+ *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode+ */+template <typename PodType, std::size_t N>+inline ASIO_CONST_BUFFER buffer(const std::array<PodType, N>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(),+      data.size() * sizeof(PodType) < max_size_in_bytes+      ? data.size() * sizeof(PodType) : max_size_in_bytes);+}++#endif // defined(ASIO_HAS_STD_ARRAY) || defined(GENERATING_DOCUMENTATION)++/// Create a new modifiable buffer that represents the given POD vector.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.size() ? &data[0] : 0,+ *     data.size() * sizeof(PodType)); @endcode+ *+ * @note The buffer is invalidated by any vector operation that would also+ * invalidate iterators.+ */+template <typename PodType, typename Allocator>+inline ASIO_MUTABLE_BUFFER buffer(+    std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(+      data.size() ? &data[0] : 0, data.size() * sizeof(PodType)+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename std::vector<PodType, Allocator>::iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new modifiable buffer that represents the given POD vector.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.size() ? &data[0] : 0,+ *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode+ *+ * @note The buffer is invalidated by any vector operation that would also+ * invalidate iterators.+ */+template <typename PodType, typename Allocator>+inline ASIO_MUTABLE_BUFFER buffer(std::vector<PodType, Allocator>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,+      data.size() * sizeof(PodType) < max_size_in_bytes+      ? data.size() * sizeof(PodType) : max_size_in_bytes+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename std::vector<PodType, Allocator>::iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new non-modifiable buffer that represents the given POD vector.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.size() ? &data[0] : 0,+ *     data.size() * sizeof(PodType)); @endcode+ *+ * @note The buffer is invalidated by any vector operation that would also+ * invalidate iterators.+ */+template <typename PodType, typename Allocator>+inline ASIO_CONST_BUFFER buffer(+    const std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(+      data.size() ? &data[0] : 0, data.size() * sizeof(PodType)+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename std::vector<PodType, Allocator>::const_iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new non-modifiable buffer that represents the given POD vector.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.size() ? &data[0] : 0,+ *     min(data.size() * sizeof(PodType), max_size_in_bytes)); @endcode+ *+ * @note The buffer is invalidated by any vector operation that would also+ * invalidate iterators.+ */+template <typename PodType, typename Allocator>+inline ASIO_CONST_BUFFER buffer(+    const std::vector<PodType, Allocator>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,+      data.size() * sizeof(PodType) < max_size_in_bytes+      ? data.size() * sizeof(PodType) : max_size_in_bytes+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename std::vector<PodType, Allocator>::const_iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new modifiable buffer that represents the given string.+/**+ * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0,+ * data.size() * sizeof(Elem))</tt>.+ *+ * @note The buffer is invalidated by any non-const operation called on the+ * given string object.+ */+template <typename Elem, typename Traits, typename Allocator>+inline ASIO_MUTABLE_BUFFER buffer(+    std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,+      data.size() * sizeof(Elem)+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename std::basic_string<Elem, Traits, Allocator>::iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new modifiable buffer that represents the given string.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.size() ? &data[0] : 0,+ *     min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode+ *+ * @note The buffer is invalidated by any non-const operation called on the+ * given string object.+ */+template <typename Elem, typename Traits, typename Allocator>+inline ASIO_MUTABLE_BUFFER buffer(+    std::basic_string<Elem, Traits, Allocator>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,+      data.size() * sizeof(Elem) < max_size_in_bytes+      ? data.size() * sizeof(Elem) : max_size_in_bytes+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename std::basic_string<Elem, Traits, Allocator>::iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new non-modifiable buffer that represents the given string.+/**+ * @returns <tt>const_buffer(data.data(), data.size() * sizeof(Elem))</tt>.+ *+ * @note The buffer is invalidated by any non-const operation called on the+ * given string object.+ */+template <typename Elem, typename Traits, typename Allocator>+inline ASIO_CONST_BUFFER buffer(+    const std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(Elem)+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename std::basic_string<Elem, Traits, Allocator>::const_iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new non-modifiable buffer that represents the given string.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.data(),+ *     min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode+ *+ * @note The buffer is invalidated by any non-const operation called on the+ * given string object.+ */+template <typename Elem, typename Traits, typename Allocator>+inline ASIO_CONST_BUFFER buffer(+    const std::basic_string<Elem, Traits, Allocator>& data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.data(),+      data.size() * sizeof(Elem) < max_size_in_bytes+      ? data.size() * sizeof(Elem) : max_size_in_bytes+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename std::basic_string<Elem, Traits, Allocator>::const_iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++#if defined(ASIO_HAS_STRING_VIEW) \+  || defined(GENERATING_DOCUMENTATION)++/// Create a new modifiable buffer that represents the given string_view.+/**+ * @returns <tt>mutable_buffer(data.size() ? &data[0] : 0,+ * data.size() * sizeof(Elem))</tt>.+ */+template <typename Elem, typename Traits>+inline ASIO_CONST_BUFFER buffer(+    basic_string_view<Elem, Traits> data) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,+      data.size() * sizeof(Elem)+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename basic_string_view<Elem, Traits>::iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++/// Create a new non-modifiable buffer that represents the given string.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.size() ? &data[0] : 0,+ *     min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode+ */+template <typename Elem, typename Traits>+inline ASIO_CONST_BUFFER buffer(+    basic_string_view<Elem, Traits> data,+    std::size_t max_size_in_bytes) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,+      data.size() * sizeof(Elem) < max_size_in_bytes+      ? data.size() * sizeof(Elem) : max_size_in_bytes+#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+      , detail::buffer_debug_check<+          typename basic_string_view<Elem, Traits>::iterator+        >(data.begin())+#endif // ASIO_ENABLE_BUFFER_DEBUGGING+      );+}++#endif // defined(ASIO_HAS_STRING_VIEW)+       //  || defined(GENERATING_DOCUMENTATION)++/*@}*/++/// Adapt a basic_string to the DynamicBuffer requirements.+/**+ * Requires that <tt>sizeof(Elem) == 1</tt>.+ */+template <typename Elem, typename Traits, typename Allocator>+class dynamic_string_buffer+{+public:+  /// The type used to represent a sequence of constant buffers that refers to+  /// the underlying memory.+  typedef ASIO_CONST_BUFFER const_buffers_type;++  /// The type used to represent a sequence of mutable buffers that refers to+  /// the underlying memory.+  typedef ASIO_MUTABLE_BUFFER mutable_buffers_type;++  /// Construct a dynamic buffer from a string.+  /**+   * @param s The string to be used as backing storage for the dynamic buffer.+   * The object stores a reference to the string and the user is responsible+   * for ensuring that the string object remains valid while the+   * dynamic_string_buffer object, and copies of the object, are in use.+   *+   * @b DynamicBuffer_v1: Any existing data in the string is treated as the+   * dynamic buffer's input sequence.+   *+   * @param maximum_size Specifies a maximum size for the buffer, in bytes.+   */+  explicit dynamic_string_buffer(std::basic_string<Elem, Traits, Allocator>& s,+      std::size_t maximum_size =+        (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT+    : string_(s),+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      size_((std::numeric_limits<std::size_t>::max)()),+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      max_size_(maximum_size)+  {+  }++  /// @b DynamicBuffer_v2: Copy construct a dynamic buffer.+  dynamic_string_buffer(const dynamic_string_buffer& other) ASIO_NOEXCEPT+    : string_(other.string_),+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      size_(other.size_),+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      max_size_(other.max_size_)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move construct a dynamic buffer.+  dynamic_string_buffer(dynamic_string_buffer&& other) ASIO_NOEXCEPT+    : string_(other.string_),+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      size_(other.size_),+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      max_size_(other.max_size_)+  {+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// @b DynamicBuffer_v1: Get the size of the input sequence.+  /// @b DynamicBuffer_v2: Get the current size of the underlying memory.+  /**+   * @returns @b DynamicBuffer_v1 The current size of the input sequence.+   * @b DynamicBuffer_v2: The current size of the underlying string if less than+   * max_size(). Otherwise returns max_size().+   */+  std::size_t size() const ASIO_NOEXCEPT+  {+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+    if (size_ != (std::numeric_limits<std::size_t>::max)())+      return size_;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+    return (std::min)(string_.size(), max_size());+  }++  /// Get the maximum size of the dynamic buffer.+  /**+   * @returns The allowed maximum size of the underlying memory.+   */+  std::size_t max_size() const ASIO_NOEXCEPT+  {+    return max_size_;+  }++  /// Get the maximum size that the buffer may grow to without triggering+  /// reallocation.+  /**+   * @returns The current capacity of the underlying string if less than+   * max_size(). Otherwise returns max_size().+   */+  std::size_t capacity() const ASIO_NOEXCEPT+  {+    return (std::min)(string_.capacity(), max_size());+  }++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  /// @b DynamicBuffer_v1: Get a list of buffers that represents the input+  /// sequence.+  /**+   * @returns An object of type @c const_buffers_type that satisfies+   * ConstBufferSequence requirements, representing the basic_string memory in+   * the input sequence.+   *+   * @note The returned object is invalidated by any @c dynamic_string_buffer+   * or @c basic_string member function that resizes or erases the string.+   */+  const_buffers_type data() const ASIO_NOEXCEPT+  {+    return const_buffers_type(asio::buffer(string_, size_));+  }+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++  /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the+  /// underlying memory.+  /**+   * @param pos Position of the first byte to represent in the buffer sequence+   *+   * @param n The number of bytes to return in the buffer sequence. If the+   * underlying memory is shorter, the buffer sequence represents as many bytes+   * as are available.+   *+   * @returns An object of type @c mutable_buffers_type that satisfies+   * MutableBufferSequence requirements, representing the basic_string memory.+   *+   * @note The returned object is invalidated by any @c dynamic_string_buffer+   * or @c basic_string member function that resizes or erases the string.+   */+  mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT+  {+    return mutable_buffers_type(asio::buffer(+          asio::buffer(string_, max_size_) + pos, n));+  }++  /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the+  /// underlying memory.+  /**+   * @param pos Position of the first byte to represent in the buffer sequence+   *+   * @param n The number of bytes to return in the buffer sequence. If the+   * underlying memory is shorter, the buffer sequence represents as many bytes+   * as are available.+   *+   * @note The returned object is invalidated by any @c dynamic_string_buffer+   * or @c basic_string member function that resizes or erases the string.+   */+  const_buffers_type data(std::size_t pos,+      std::size_t n) const ASIO_NOEXCEPT+  {+    return const_buffers_type(asio::buffer(+          asio::buffer(string_, max_size_) + pos, n));+  }++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  /// @b DynamicBuffer_v1: Get a list of buffers that represents the output+  /// sequence, with the given size.+  /**+   * Ensures that the output sequence can accommodate @c n bytes, resizing the+   * basic_string object as necessary.+   *+   * @returns An object of type @c mutable_buffers_type that satisfies+   * MutableBufferSequence requirements, representing basic_string memory+   * at the start of the output sequence of size @c n.+   *+   * @throws std::length_error If <tt>size() + n > max_size()</tt>.+   *+   * @note The returned object is invalidated by any @c dynamic_string_buffer+   * or @c basic_string member function that modifies the input sequence or+   * output sequence.+   */+  mutable_buffers_type prepare(std::size_t n)+  {+    if (size() > max_size() || max_size() - size() < n)+    {+      std::length_error ex("dynamic_string_buffer too long");+      asio::detail::throw_exception(ex);+    }++    if (size_ == (std::numeric_limits<std::size_t>::max)())+      size_ = string_.size(); // Enable v1 behaviour.++    string_.resize(size_ + n);++    return asio::buffer(asio::buffer(string_) + size_, n);+  }++  /// @b DynamicBuffer_v1: Move bytes from the output sequence to the input+  /// sequence.+  /**+   * @param n The number of bytes to append from the start of the output+   * sequence to the end of the input sequence. The remainder of the output+   * sequence is discarded.+   *+   * 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)+  {+    size_ += (std::min)(n, string_.size() - size_);+    string_.resize(size_);+  }+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++  /// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of+  /// bytes.+  /**+   * Resizes the string to accommodate an additional @c n bytes at the end.+   *+   * @throws std::length_error If <tt>size() + n > max_size()</tt>.+   */+  void grow(std::size_t n)+  {+    if (size() > max_size() || max_size() - size() < n)+    {+      std::length_error ex("dynamic_string_buffer too long");+      asio::detail::throw_exception(ex);+    }++    string_.resize(size() + n);+  }++  /// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number+  /// of bytes.+  /**+   * Erases @c n bytes from the end of the string by resizing the basic_string+   * object. If @c n is greater than the current size of the string, the string+   * is emptied.+   */+  void shrink(std::size_t n)+  {+    string_.resize(n > size() ? 0 : size() - n);+  }++  /// @b DynamicBuffer_v1: Remove characters from the input sequence.+  /// @b DynamicBuffer_v2: Consume the specified number of bytes from the+  /// beginning of the underlying memory.+  /**+   * @b DynamicBuffer_v1: 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.+   *+   * @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the string.+   * If @c n is greater than the current size of the string, the string is+   * emptied.+   */+  void consume(std::size_t n)+  {+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+    if (size_ != (std::numeric_limits<std::size_t>::max)())+    {+      std::size_t consume_length = (std::min)(n, size_);+      string_.erase(0, consume_length);+      size_ -= consume_length;+      return;+    }+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+    string_.erase(0, n);+  }++private:+  std::basic_string<Elem, Traits, Allocator>& string_;+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  std::size_t size_;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  const std::size_t max_size_;+};++/// Adapt a vector to the DynamicBuffer requirements.+/**+ * Requires that <tt>sizeof(Elem) == 1</tt>.+ */+template <typename Elem, typename Allocator>+class dynamic_vector_buffer+{+public:+  /// The type used to represent a sequence of constant buffers that refers to+  /// the underlying memory.+  typedef ASIO_CONST_BUFFER const_buffers_type;++  /// The type used to represent a sequence of mutable buffers that refers to+  /// the underlying memory.+  typedef ASIO_MUTABLE_BUFFER mutable_buffers_type;++  /// Construct a dynamic buffer from a vector.+  /**+   * @param v The vector to be used as backing storage for the dynamic buffer.+   * The object stores a reference to the vector and the user is responsible+   * for ensuring that the vector object remains valid while the+   * dynamic_vector_buffer object, and copies of the object, are in use.+   *+   * @param maximum_size Specifies a maximum size for the buffer, in bytes.+   */+  explicit dynamic_vector_buffer(std::vector<Elem, Allocator>& v,+      std::size_t maximum_size =+        (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT+    : vector_(v),+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      size_((std::numeric_limits<std::size_t>::max)()),+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      max_size_(maximum_size)+  {+  }++  /// @b DynamicBuffer_v2: Copy construct a dynamic buffer.+  dynamic_vector_buffer(const dynamic_vector_buffer& other) ASIO_NOEXCEPT+    : vector_(other.vector_),+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      size_(other.size_),+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      max_size_(other.max_size_)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move construct a dynamic buffer.+  dynamic_vector_buffer(dynamic_vector_buffer&& other) ASIO_NOEXCEPT+    : vector_(other.vector_),+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      size_(other.size_),+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+      max_size_(other.max_size_)+  {+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// @b DynamicBuffer_v1: Get the size of the input sequence.+  /// @b DynamicBuffer_v2: Get the current size of the underlying memory.+  /**+   * @returns @b DynamicBuffer_v1 The current size of the input sequence.+   * @b DynamicBuffer_v2: The current size of the underlying vector if less than+   * max_size(). Otherwise returns max_size().+   */+  std::size_t size() const ASIO_NOEXCEPT+  {+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+    if (size_ != (std::numeric_limits<std::size_t>::max)())+      return size_;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+    return (std::min)(vector_.size(), max_size());+  }++  /// Get the maximum size of the dynamic buffer.+  /**+   * @returns @b DynamicBuffer_v1: The allowed maximum of the sum of the sizes+   * of the input sequence and output sequence. @b DynamicBuffer_v2: The allowed+   * maximum size of the underlying memory.+   */+  std::size_t max_size() const ASIO_NOEXCEPT+  {+    return max_size_;+  }++  /// Get the maximum size that the buffer may grow to without triggering+  /// reallocation.+  /**+   * @returns @b DynamicBuffer_v1: The current total capacity of the buffer,+   * i.e. for both the input sequence and output sequence. @b DynamicBuffer_v2:+   * The current capacity of the underlying vector if less than max_size().+   * Otherwise returns max_size().+   */+  std::size_t capacity() const ASIO_NOEXCEPT+  {+    return (std::min)(vector_.capacity(), max_size());+  }++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  /// @b DynamicBuffer_v1: Get a list of buffers that represents the input+  /// sequence.+  /**+   * @returns An object of type @c const_buffers_type that satisfies+   * ConstBufferSequence requirements, representing the vector memory in the+   * input sequence.+   *+   * @note The returned object is invalidated by any @c dynamic_vector_buffer+   * or @c vector member function that modifies the input sequence or output+   * sequence.+   */+  const_buffers_type data() const ASIO_NOEXCEPT+  {+    return const_buffers_type(asio::buffer(vector_, size_));+  }+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++  /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the+  /// underlying memory.+  /**+   * @param pos Position of the first byte to represent in the buffer sequence+   *+   * @param n The number of bytes to return in the buffer sequence. If the+   * underlying memory is shorter, the buffer sequence represents as many bytes+   * as are available.+   *+   * @returns An object of type @c mutable_buffers_type that satisfies+   * MutableBufferSequence requirements, representing the vector memory.+   *+   * @note The returned object is invalidated by any @c dynamic_vector_buffer+   * or @c vector member function that resizes or erases the vector.+   */+  mutable_buffers_type data(std::size_t pos, std::size_t n) ASIO_NOEXCEPT+  {+    return mutable_buffers_type(asio::buffer(+          asio::buffer(vector_, max_size_) + pos, n));+  }++  /// @b DynamicBuffer_v2: Get a sequence of buffers that represents the+  /// underlying memory.+  /**+   * @param pos Position of the first byte to represent in the buffer sequence+   *+   * @param n The number of bytes to return in the buffer sequence. If the+   * underlying memory is shorter, the buffer sequence represents as many bytes+   * as are available.+   *+   * @note The returned object is invalidated by any @c dynamic_vector_buffer+   * or @c vector member function that resizes or erases the vector.+   */+  const_buffers_type data(std::size_t pos,+      std::size_t n) const ASIO_NOEXCEPT+  {+    return const_buffers_type(asio::buffer(+          asio::buffer(vector_, max_size_) + pos, n));+  }++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  /// @b DynamicBuffer_v1: Get a list of buffers that represents the output+  /// sequence, with the given size.+  /**+   * Ensures that the output sequence can accommodate @c n bytes, resizing the+   * vector object as necessary.+   *+   * @returns An object of type @c mutable_buffers_type that satisfies+   * MutableBufferSequence requirements, representing vector memory at the+   * start of the output sequence of size @c n.+   *+   * @throws std::length_error If <tt>size() + n > max_size()</tt>.+   *+   * @note The returned object is invalidated by any @c dynamic_vector_buffer+   * or @c vector member function that modifies the input sequence or output+   * sequence.+   */+  mutable_buffers_type prepare(std::size_t n)+  {+    if (size () > max_size() || max_size() - size() < n)+    {+      std::length_error ex("dynamic_vector_buffer too long");+      asio::detail::throw_exception(ex);+    }++    if (size_ == (std::numeric_limits<std::size_t>::max)())+      size_ = vector_.size(); // Enable v1 behaviour.++    vector_.resize(size_ + n);++    return asio::buffer(asio::buffer(vector_) + size_, n);+  }++  /// @b DynamicBuffer_v1: Move bytes from the output sequence to the input+  /// sequence.+  /**+   * @param n The number of bytes to append from the start of the output+   * sequence to the end of the input sequence. The remainder of the output+   * sequence is discarded.+   *+   * 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)+  {+    size_ += (std::min)(n, vector_.size() - size_);+    vector_.resize(size_);+  }+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++  /// @b DynamicBuffer_v2: Grow the underlying memory by the specified number of+  /// bytes.+  /**+   * Resizes the vector to accommodate an additional @c n bytes at the end.+   *+   * @throws std::length_error If <tt>size() + n > max_size()</tt>.+   */+  void grow(std::size_t n)+  {+    if (size() > max_size() || max_size() - size() < n)+    {+      std::length_error ex("dynamic_vector_buffer too long");+      asio::detail::throw_exception(ex);+    }++    vector_.resize(size() + n);+  }++  /// @b DynamicBuffer_v2: Shrink the underlying memory by the specified number+  /// of bytes.+  /**+   * Erases @c n bytes from the end of the vector by resizing the vector+   * object. If @c n is greater than the current size of the vector, the vector+   * is emptied.+   */+  void shrink(std::size_t n)+  {+    vector_.resize(n > size() ? 0 : size() - n);+  }++  /// @b DynamicBuffer_v1: Remove characters from the input sequence.+  /// @b DynamicBuffer_v2: Consume the specified number of bytes from the+  /// beginning of the underlying memory.+  /**+   * @b DynamicBuffer_v1: 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.+   *+   * @b DynamicBuffer_v2: Erases @c n bytes from the beginning of the vector.+   * If @c n is greater than the current size of the vector, the vector is+   * emptied.+   */+  void consume(std::size_t n)+  {+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+    if (size_ != (std::numeric_limits<std::size_t>::max)())+    {+      std::size_t consume_length = (std::min)(n, size_);+      vector_.erase(vector_.begin(), vector_.begin() + consume_length);+      size_ -= consume_length;+      return;+    }+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+    vector_.erase(vector_.begin(), vector_.begin() + (std::min)(size(), n));+  }++private:+  std::vector<Elem, Allocator>& vector_;+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  std::size_t size_;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  const std::size_t max_size_;+};++/** @defgroup dynamic_buffer asio::dynamic_buffer+ *+ * @brief The asio::dynamic_buffer function is used to create a+ * dynamically resized buffer from a @c std::basic_string or @c std::vector.+ */+/*@{*/++/// Create a new dynamic buffer that represents the given string.+/**+ * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data)</tt>.+ */+template <typename Elem, typename Traits, typename Allocator>+inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(+    std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT+{+  return dynamic_string_buffer<Elem, Traits, Allocator>(data);+}++/// Create a new dynamic buffer that represents the given string.+/**+ * @returns <tt>dynamic_string_buffer<Elem, Traits, Allocator>(data,+ * max_size)</tt>.+ */+template <typename Elem, typename Traits, typename Allocator>+inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(+    std::basic_string<Elem, Traits, Allocator>& data,+    std::size_t max_size) ASIO_NOEXCEPT+{+  return dynamic_string_buffer<Elem, Traits, Allocator>(data, max_size);+}++/// Create a new dynamic buffer that represents the given vector.+/**+ * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data)</tt>.+ */+template <typename Elem, typename Allocator>+inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(+    std::vector<Elem, Allocator>& data) ASIO_NOEXCEPT+{+  return dynamic_vector_buffer<Elem, Allocator>(data);+}++/// Create a new dynamic buffer that represents the given vector.+/**+ * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data, max_size)</tt>.+ */+template <typename Elem, typename Allocator>+inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(+    std::vector<Elem, Allocator>& data,+    std::size_t max_size) ASIO_NOEXCEPT+{+  return dynamic_vector_buffer<Elem, Allocator>(data, max_size);+}++/*@}*/++/** @defgroup buffer_copy asio::buffer_copy+ *+ * @brief The asio::buffer_copy function is used to copy bytes from a+ * source buffer (or buffer sequence) to a target buffer (or buffer sequence).+ *+ * The @c buffer_copy function is available in two forms:+ *+ * @li A 2-argument form: @c buffer_copy(target, source)+ *+ * @li A 3-argument form: @c buffer_copy(target, source, max_bytes_to_copy)+ *+ * Both forms return the number of bytes actually copied. The number of bytes+ * copied is the lesser of:+ *+ * @li @c buffer_size(target)+ *+ * @li @c buffer_size(source)+ *+ * @li @c If specified, @c max_bytes_to_copy.+ *+ * This prevents buffer overflow, regardless of the buffer sizes used in the+ * copy operation.+ *+ * Note that @ref buffer_copy is implemented in terms of @c memcpy, and+ * consequently it cannot be used to copy between overlapping memory regions.+ */+/*@{*/++namespace detail {++inline std::size_t buffer_copy_1(const mutable_buffer& target,+    const const_buffer& source)+{+  using namespace std; // For memcpy.+  std::size_t target_size = target.size();+  std::size_t source_size = source.size();+  std::size_t n = target_size < source_size ? target_size : source_size;+  if (n > 0)+    memcpy(target.data(), source.data(), n);+  return n;+}++template <typename TargetIterator, typename SourceIterator>+inline std::size_t buffer_copy(one_buffer, one_buffer,+    TargetIterator target_begin, TargetIterator,+    SourceIterator source_begin, SourceIterator) ASIO_NOEXCEPT+{+  return (buffer_copy_1)(*target_begin, *source_begin);+}++template <typename TargetIterator, typename SourceIterator>+inline std::size_t buffer_copy(one_buffer, one_buffer,+    TargetIterator target_begin, TargetIterator,+    SourceIterator source_begin, SourceIterator,+    std::size_t max_bytes_to_copy) ASIO_NOEXCEPT+{+  return (buffer_copy_1)(*target_begin,+      asio::buffer(*source_begin, max_bytes_to_copy));+}++template <typename TargetIterator, typename SourceIterator>+std::size_t buffer_copy(one_buffer, multiple_buffers,+    TargetIterator target_begin, TargetIterator,+    SourceIterator source_begin, SourceIterator source_end,+    std::size_t max_bytes_to_copy+      = (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT+{+  std::size_t total_bytes_copied = 0;+  SourceIterator source_iter = source_begin;++  for (mutable_buffer target_buffer(+        asio::buffer(*target_begin, max_bytes_to_copy));+      target_buffer.size() && source_iter != source_end; ++source_iter)+  {+    const_buffer source_buffer(*source_iter);+    std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);+    total_bytes_copied += bytes_copied;+    target_buffer += bytes_copied;+  }++  return total_bytes_copied;+}++template <typename TargetIterator, typename SourceIterator>+std::size_t buffer_copy(multiple_buffers, one_buffer,+    TargetIterator target_begin, TargetIterator target_end,+    SourceIterator source_begin, SourceIterator,+    std::size_t max_bytes_to_copy+      = (std::numeric_limits<std::size_t>::max)()) ASIO_NOEXCEPT+{+  std::size_t total_bytes_copied = 0;+  TargetIterator target_iter = target_begin;++  for (const_buffer source_buffer(+        asio::buffer(*source_begin, max_bytes_to_copy));+      source_buffer.size() && target_iter != target_end; ++target_iter)+  {+    mutable_buffer target_buffer(*target_iter);+    std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);+    total_bytes_copied += bytes_copied;+    source_buffer += bytes_copied;+  }++  return total_bytes_copied;+}++template <typename TargetIterator, typename SourceIterator>+std::size_t buffer_copy(multiple_buffers, multiple_buffers,+    TargetIterator target_begin, TargetIterator target_end,+    SourceIterator source_begin, SourceIterator source_end) ASIO_NOEXCEPT+{+  std::size_t total_bytes_copied = 0;++  TargetIterator target_iter = target_begin;+  std::size_t target_buffer_offset = 0;++  SourceIterator source_iter = source_begin;+  std::size_t source_buffer_offset = 0;++  while (target_iter != target_end && source_iter != source_end)+  {+    mutable_buffer target_buffer =+      mutable_buffer(*target_iter) + target_buffer_offset;++    const_buffer source_buffer =+      const_buffer(*source_iter) + source_buffer_offset;++    std::size_t bytes_copied = (buffer_copy_1)(target_buffer, source_buffer);+    total_bytes_copied += bytes_copied;++    if (bytes_copied == target_buffer.size())+    {+      ++target_iter;+      target_buffer_offset = 0;+    }+    else+      target_buffer_offset += bytes_copied;++    if (bytes_copied == source_buffer.size())+    {+      ++source_iter;+      source_buffer_offset = 0;+    }+    else+      source_buffer_offset += bytes_copied;+  }++  return total_bytes_copied;+}++template <typename TargetIterator, typename SourceIterator>+std::size_t buffer_copy(multiple_buffers, multiple_buffers,+    TargetIterator target_begin, TargetIterator target_end,+    SourceIterator source_begin, SourceIterator source_end,+    std::size_t max_bytes_to_copy) ASIO_NOEXCEPT+{+  std::size_t total_bytes_copied = 0;++  TargetIterator target_iter = target_begin;+  std::size_t target_buffer_offset = 0;++  SourceIterator source_iter = source_begin;+  std::size_t source_buffer_offset = 0;++  while (total_bytes_copied != max_bytes_to_copy+      && target_iter != target_end && source_iter != source_end)+  {+    mutable_buffer target_buffer =+      mutable_buffer(*target_iter) + target_buffer_offset;++    const_buffer source_buffer =+      const_buffer(*source_iter) + source_buffer_offset;++    std::size_t bytes_copied = (buffer_copy_1)(+        target_buffer, asio::buffer(source_buffer,+          max_bytes_to_copy - total_bytes_copied));+    total_bytes_copied += bytes_copied;++    if (bytes_copied == target_buffer.size())+    {+      ++target_iter;+      target_buffer_offset = 0;+    }+    else+      target_buffer_offset += bytes_copied;++    if (bytes_copied == source_buffer.size())+    {+      ++source_iter;+      source_buffer_offset = 0;+    }+    else+      source_buffer_offset += bytes_copied;+  }++  return total_bytes_copied;+}++} // namespace detail++/// Copies bytes from a source buffer sequence to a target buffer sequence.+/**+ * @param target A modifiable buffer sequence representing the memory regions to+ * which the bytes will be copied.+ *+ * @param source A non-modifiable buffer sequence representing the memory+ * regions from which the bytes will be copied.+ *+ * @returns The number of bytes copied.+ *+ * @note The number of bytes copied is the lesser of:+ *+ * @li @c buffer_size(target)+ *+ * @li @c buffer_size(source)+ *+ * This function is implemented in terms of @c memcpy, and consequently it+ * cannot be used to copy between overlapping memory regions.+ */+template <typename MutableBufferSequence, typename ConstBufferSequence>+inline std::size_t buffer_copy(const MutableBufferSequence& target,+    const ConstBufferSequence& source) ASIO_NOEXCEPT+{+  return detail::buffer_copy(+      detail::buffer_sequence_cardinality<MutableBufferSequence>(),+      detail::buffer_sequence_cardinality<ConstBufferSequence>(),+      asio::buffer_sequence_begin(target),+      asio::buffer_sequence_end(target),+      asio::buffer_sequence_begin(source),+      asio::buffer_sequence_end(source));+}++/// Copies a limited number of bytes from a source buffer sequence to a target+/// buffer sequence.+/**+ * @param target A modifiable buffer sequence representing the memory regions to+ * which the bytes will be copied.+ *+ * @param source A non-modifiable buffer sequence representing the memory+ * regions from which the bytes will be copied.+ *+ * @param max_bytes_to_copy The maximum number of bytes to be copied.+ *+ * @returns The number of bytes copied.+ *+ * @note The number of bytes copied is the lesser of:+ *+ * @li @c buffer_size(target)+ *+ * @li @c buffer_size(source)+ *+ * @li @c max_bytes_to_copy+ *+ * This function is implemented in terms of @c memcpy, and consequently it+ * cannot be used to copy between overlapping memory regions.+ */+template <typename MutableBufferSequence, typename ConstBufferSequence>+inline std::size_t buffer_copy(const MutableBufferSequence& target,+    const ConstBufferSequence& source,+    std::size_t max_bytes_to_copy) ASIO_NOEXCEPT+{+  return detail::buffer_copy(+      detail::buffer_sequence_cardinality<MutableBufferSequence>(),+      detail::buffer_sequence_cardinality<ConstBufferSequence>(),+      asio::buffer_sequence_begin(target),+      asio::buffer_sequence_end(target),+      asio::buffer_sequence_begin(source),+      asio::buffer_sequence_end(source), max_bytes_to_copy);+}++/*@}*/++} // namespace asio++#include "asio/detail/pop_options.hpp"+#include "asio/detail/is_buffer_sequence.hpp"+#include "asio/detail/push_options.hpp"++namespace asio {++/// Trait to determine whether a type satisfies the MutableBufferSequence+/// requirements.+template <typename T>+struct is_mutable_buffer_sequence+#if defined(GENERATING_DOCUMENTATION)+  : integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  : asio::detail::is_buffer_sequence<T, mutable_buffer>+#endif // defined(GENERATING_DOCUMENTATION)+{+};++/// Trait to determine whether a type satisfies the ConstBufferSequence+/// requirements.+template <typename T>+struct is_const_buffer_sequence+#if defined(GENERATING_DOCUMENTATION)+  : integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  : asio::detail::is_buffer_sequence<T, const_buffer>+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+/// Trait to determine whether a type satisfies the DynamicBuffer_v1+/// requirements.+template <typename T>+struct is_dynamic_buffer_v1+#if defined(GENERATING_DOCUMENTATION)+  : integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  : asio::detail::is_dynamic_buffer_v1<T>+#endif // defined(GENERATING_DOCUMENTATION)+{+};+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Trait to determine whether a type satisfies the DynamicBuffer_v2+/// requirements.+template <typename T>+struct is_dynamic_buffer_v2+#if defined(GENERATING_DOCUMENTATION)+  : integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  : asio::detail::is_dynamic_buffer_v2<T>+#endif // defined(GENERATING_DOCUMENTATION)+{+};++/// Trait to determine whether a type satisfies the DynamicBuffer requirements.+/**+ * If @c ASIO_NO_DYNAMIC_BUFFER_V1 is not defined, determines whether the+ * type satisfies the DynamicBuffer_v1 requirements. Otherwise, if @c+ * ASIO_NO_DYNAMIC_BUFFER_V1 is defined, determines whether the type+ * satisfies the DynamicBuffer_v2 requirements.+ */+template <typename T>+struct is_dynamic_buffer+#if defined(GENERATING_DOCUMENTATION)+  : integral_constant<bool, automatically_determined>+#elif defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  : asio::is_dynamic_buffer_v2<T>+#else // defined(ASIO_NO_DYNAMIC_BUFFER_V1)+  : asio::is_dynamic_buffer_v1<T>+#endif // defined(ASIO_NO_DYNAMIC_BUFFER_V1)+{+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BUFFER_HPP
+ link/modules/asio-standalone/asio/include/asio/buffered_read_stream.hpp view
@@ -0,0 +1,253 @@+//+// buffered_read_stream.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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.+  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.+  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.+  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
+ link/modules/asio-standalone/asio/include/asio/buffered_read_stream_fwd.hpp view
@@ -0,0 +1,25 @@+//+// buffered_read_stream_fwd.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/buffered_stream.hpp view
@@ -0,0 +1,279 @@+//+// buffered_stream.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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.+  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.+  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.+  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.+  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
+ link/modules/asio-standalone/asio/include/asio/buffered_stream_fwd.hpp view
@@ -0,0 +1,25 @@+//+// buffered_stream_fwd.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/buffered_write_stream.hpp view
@@ -0,0 +1,245 @@+//+// buffered_write_stream.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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.+  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.+  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.+  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
+ link/modules/asio-standalone/asio/include/asio/buffered_write_stream_fwd.hpp view
@@ -0,0 +1,25 @@+//+// buffered_write_stream_fwd.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/buffers_iterator.hpp view
@@ -0,0 +1,521 @@+//+// buffers_iterator.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/co_spawn.hpp view
@@ -0,0 +1,471 @@+//+// co_spawn.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 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 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+ */+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 enable_if<+      (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 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 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+ */+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 enable_if<+      (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 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 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+ */+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 enable_if<+      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 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 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+ */+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 enable_if<+      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 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 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+ */+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 enable_if<+      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 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 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+ */+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 enable_if<+      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
+ link/modules/asio-standalone/asio/include/asio/completion_condition.hpp view
@@ -0,0 +1,218 @@+//+// completion_condition.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/compose.hpp view
@@ -0,0 +1,136 @@+//+// compose.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/connect.hpp view
@@ -0,0 +1,1076 @@+//+// connect.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_HPP+#define ASIO_CONNECT_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/basic_socket.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail+{+  char (&has_iterator_helper(...))[2];++  template <typename T>+  char has_iterator_helper(T*, typename T::iterator* = 0);++  template <typename T>+  struct has_iterator_typedef+  {+    enum { value = (sizeof((has_iterator_helper)((T*)(0))) == 1) };+  };+} // namespace detail++/// Type trait used to determine whether a type is an endpoint sequence that can+/// be used with with @c connect and @c async_connect.+template <typename T>+struct is_endpoint_sequence+{+#if defined(GENERATING_DOCUMENTATION)+  /// The value member is true if the type may be used as an endpoint sequence.+  static const bool value;+#else+  enum+  {+    value = detail::has_iterator_typedef<T>::value+  };+#endif+};++/**+ * @defgroup connect asio::connect+ *+ * @brief The @c connect function is a composed operation that establishes a+ * socket connection by trying each endpoint in a sequence.+ */+/*@{*/++/// Establishes a socket connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param endpoints A sequence of endpoints.+ *+ * @returns The successfully connected endpoint.+ *+ * @throws asio::system_error Thrown on failure. If the sequence is+ * empty, the associated @c error_code is asio::error::not_found.+ * Otherwise, contains the error from the last connection attempt.+ *+ * @par Example+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::socket s(my_context);+ * asio::connect(s, r.resolve(q)); @endcode+ */+template <typename Protocol, typename Executor, typename EndpointSequence>+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type* = 0);++/// Establishes a socket connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param endpoints A sequence of endpoints.+ *+ * @param ec Set to indicate what error occurred, if any. If the sequence is+ * empty, set to asio::error::not_found. Otherwise, contains the error+ * from the last connection attempt.+ *+ * @returns On success, the successfully connected endpoint. Otherwise, a+ * default-constructed endpoint.+ *+ * @par Example+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::socket s(my_context);+ * asio::error_code ec;+ * asio::connect(s, r.resolve(q), ec);+ * if (ec)+ * {+ *   // An error occurred.+ * } @endcode+ */+template <typename Protocol, typename Executor, typename EndpointSequence>+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints, asio::error_code& ec,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type* = 0);++#if !defined(ASIO_NO_DEPRECATED)+/// (Deprecated: Use range overload.) Establishes a socket connection by trying+/// each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @returns On success, an iterator denoting the successfully connected+ * endpoint. Otherwise, the end iterator.+ *+ * @throws asio::system_error Thrown on failure. If the sequence is+ * empty, the associated @c error_code is asio::error::not_found.+ * Otherwise, contains the error from the last connection attempt.+ *+ * @note This overload assumes that a default constructed object of type @c+ * Iterator represents the end of the sequence. This is a valid assumption for+ * iterator types such as @c asio::ip::tcp::resolver::iterator.+ */+template <typename Protocol, typename Executor, typename Iterator>+Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);++/// (Deprecated: Use range overload.) Establishes a socket connection by trying+/// each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param ec Set to indicate what error occurred, if any. If the sequence is+ * empty, set to asio::error::not_found. Otherwise, contains the error+ * from the last connection attempt.+ *+ * @returns On success, an iterator denoting the successfully connected+ * endpoint. Otherwise, the end iterator.+ *+ * @note This overload assumes that a default constructed object of type @c+ * Iterator represents the end of the sequence. This is a valid assumption for+ * iterator types such as @c asio::ip::tcp::resolver::iterator.+ */+template <typename Protocol, typename Executor, typename Iterator>+Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, asio::error_code& ec,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+#endif // !defined(ASIO_NO_DEPRECATED)++/// Establishes a socket connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param end An iterator pointing to the end of a sequence of endpoints.+ *+ * @returns An iterator denoting the successfully connected endpoint.+ *+ * @throws asio::system_error Thrown on failure. If the sequence is+ * empty, the associated @c error_code is asio::error::not_found.+ * Otherwise, contains the error from the last connection attempt.+ *+ * @par Example+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::resolver::results_type e = r.resolve(q);+ * tcp::socket s(my_context);+ * asio::connect(s, e.begin(), e.end()); @endcode+ */+template <typename Protocol, typename Executor, typename Iterator>+Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, Iterator end);++/// Establishes a socket connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param end An iterator pointing to the end of a sequence of endpoints.+ *+ * @param ec Set to indicate what error occurred, if any. If the sequence is+ * empty, set to asio::error::not_found. Otherwise, contains the error+ * from the last connection attempt.+ *+ * @returns On success, an iterator denoting the successfully connected+ * endpoint. Otherwise, the end iterator.+ *+ * @par Example+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::resolver::results_type e = r.resolve(q);+ * tcp::socket s(my_context);+ * asio::error_code ec;+ * asio::connect(s, e.begin(), e.end(), ec);+ * if (ec)+ * {+ *   // An error occurred.+ * } @endcode+ */+template <typename Protocol, typename Executor, typename Iterator>+Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, Iterator end, asio::error_code& ec);++/// Establishes a socket connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param endpoints A sequence of endpoints.+ *+ * @param connect_condition A function object that is called prior to each+ * connection attempt. The signature of the function object must be:+ * @code bool connect_condition(+ *     const asio::error_code& ec,+ *     const typename Protocol::endpoint& next); @endcode+ * The @c ec parameter contains the result from the most recent connect+ * operation. Before the first connection attempt, @c ec is always set to+ * indicate success. The @c next parameter is the next endpoint to be tried.+ * The function object should return true if the next endpoint should be tried,+ * and false if it should be skipped.+ *+ * @returns The successfully connected endpoint.+ *+ * @throws asio::system_error Thrown on failure. If the sequence is+ * empty, the associated @c error_code is asio::error::not_found.+ * Otherwise, contains the error from the last connection attempt.+ *+ * @par Example+ * The following connect condition function object can be used to output+ * information about the individual connection attempts:+ * @code struct my_connect_condition+ * {+ *   bool operator()(+ *       const asio::error_code& ec,+ *       const::tcp::endpoint& next)+ *   {+ *     if (ec) std::cout << "Error: " << ec.message() << std::endl;+ *     std::cout << "Trying: " << next << std::endl;+ *     return true;+ *   }+ * }; @endcode+ * It would be used with the asio::connect function as follows:+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::socket s(my_context);+ * tcp::endpoint e = asio::connect(s,+ *     r.resolve(q), my_connect_condition());+ * std::cout << "Connected to: " << e << std::endl; @endcode+ */+template <typename Protocol, typename Executor,+    typename EndpointSequence, typename ConnectCondition>+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints, ConnectCondition connect_condition,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type* = 0);++/// Establishes a socket connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param endpoints A sequence of endpoints.+ *+ * @param connect_condition A function object that is called prior to each+ * connection attempt. The signature of the function object must be:+ * @code bool connect_condition(+ *     const asio::error_code& ec,+ *     const typename Protocol::endpoint& next); @endcode+ * The @c ec parameter contains the result from the most recent connect+ * operation. Before the first connection attempt, @c ec is always set to+ * indicate success. The @c next parameter is the next endpoint to be tried.+ * The function object should return true if the next endpoint should be tried,+ * and false if it should be skipped.+ *+ * @param ec Set to indicate what error occurred, if any. If the sequence is+ * empty, set to asio::error::not_found. Otherwise, contains the error+ * from the last connection attempt.+ *+ * @returns On success, the successfully connected endpoint. Otherwise, a+ * default-constructed endpoint.+ *+ * @par Example+ * The following connect condition function object can be used to output+ * information about the individual connection attempts:+ * @code struct my_connect_condition+ * {+ *   bool operator()(+ *       const asio::error_code& ec,+ *       const::tcp::endpoint& next)+ *   {+ *     if (ec) std::cout << "Error: " << ec.message() << std::endl;+ *     std::cout << "Trying: " << next << std::endl;+ *     return true;+ *   }+ * }; @endcode+ * It would be used with the asio::connect function as follows:+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::socket s(my_context);+ * asio::error_code ec;+ * tcp::endpoint e = asio::connect(s,+ *     r.resolve(q), my_connect_condition(), ec);+ * if (ec)+ * {+ *   // An error occurred.+ * }+ * else+ * {+ *   std::cout << "Connected to: " << e << std::endl;+ * } @endcode+ */+template <typename Protocol, typename Executor,+    typename EndpointSequence, typename ConnectCondition>+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints, ConnectCondition connect_condition,+    asio::error_code& ec,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type* = 0);++#if !defined(ASIO_NO_DEPRECATED)+/// (Deprecated: Use range overload.) Establishes a socket connection by trying+/// each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param connect_condition A function object that is called prior to each+ * connection attempt. The signature of the function object must be:+ * @code bool connect_condition(+ *     const asio::error_code& ec,+ *     const typename Protocol::endpoint& next); @endcode+ * The @c ec parameter contains the result from the most recent connect+ * operation. Before the first connection attempt, @c ec is always set to+ * indicate success. The @c next parameter is the next endpoint to be tried.+ * The function object should return true if the next endpoint should be tried,+ * and false if it should be skipped.+ *+ * @returns On success, an iterator denoting the successfully connected+ * endpoint. Otherwise, the end iterator.+ *+ * @throws asio::system_error Thrown on failure. If the sequence is+ * empty, the associated @c error_code is asio::error::not_found.+ * Otherwise, contains the error from the last connection attempt.+ *+ * @note This overload assumes that a default constructed object of type @c+ * Iterator represents the end of the sequence. This is a valid assumption for+ * iterator types such as @c asio::ip::tcp::resolver::iterator.+ */+template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition>+Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, ConnectCondition connect_condition,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);++/// (Deprecated: Use range overload.) Establishes a socket connection by trying+/// each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param connect_condition A function object that is called prior to each+ * connection attempt. The signature of the function object must be:+ * @code bool connect_condition(+ *     const asio::error_code& ec,+ *     const typename Protocol::endpoint& next); @endcode+ * The @c ec parameter contains the result from the most recent connect+ * operation. Before the first connection attempt, @c ec is always set to+ * indicate success. The @c next parameter is the next endpoint to be tried.+ * The function object should return true if the next endpoint should be tried,+ * and false if it should be skipped.+ *+ * @param ec Set to indicate what error occurred, if any. If the sequence is+ * empty, set to asio::error::not_found. Otherwise, contains the error+ * from the last connection attempt.+ *+ * @returns On success, an iterator denoting the successfully connected+ * endpoint. Otherwise, the end iterator.+ *+ * @note This overload assumes that a default constructed object of type @c+ * Iterator represents the end of the sequence. This is a valid assumption for+ * iterator types such as @c asio::ip::tcp::resolver::iterator.+ */+template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition>+Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    ConnectCondition connect_condition, asio::error_code& ec,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+#endif // !defined(ASIO_NO_DEPRECATED)++/// Establishes a socket connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param end An iterator pointing to the end of a sequence of endpoints.+ *+ * @param connect_condition A function object that is called prior to each+ * connection attempt. The signature of the function object must be:+ * @code bool connect_condition(+ *     const asio::error_code& ec,+ *     const typename Protocol::endpoint& next); @endcode+ * The @c ec parameter contains the result from the most recent connect+ * operation. Before the first connection attempt, @c ec is always set to+ * indicate success. The @c next parameter is the next endpoint to be tried.+ * The function object should return true if the next endpoint should be tried,+ * and false if it should be skipped.+ *+ * @returns An iterator denoting the successfully connected endpoint.+ *+ * @throws asio::system_error Thrown on failure. If the sequence is+ * empty, the associated @c error_code is asio::error::not_found.+ * Otherwise, contains the error from the last connection attempt.+ *+ * @par Example+ * The following connect condition function object can be used to output+ * information about the individual connection attempts:+ * @code struct my_connect_condition+ * {+ *   bool operator()(+ *       const asio::error_code& ec,+ *       const::tcp::endpoint& next)+ *   {+ *     if (ec) std::cout << "Error: " << ec.message() << std::endl;+ *     std::cout << "Trying: " << next << std::endl;+ *     return true;+ *   }+ * }; @endcode+ * It would be used with the asio::connect function as follows:+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::resolver::results_type e = r.resolve(q);+ * tcp::socket s(my_context);+ * tcp::resolver::results_type::iterator i = asio::connect(+ *     s, e.begin(), e.end(), my_connect_condition());+ * std::cout << "Connected to: " << i->endpoint() << std::endl; @endcode+ */+template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition>+Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    Iterator end, ConnectCondition connect_condition);++/// Establishes a socket connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c connect member+ * function, once for each endpoint in the sequence, until a connection is+ * successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param end An iterator pointing to the end of a sequence of endpoints.+ *+ * @param connect_condition A function object that is called prior to each+ * connection attempt. The signature of the function object must be:+ * @code bool connect_condition(+ *     const asio::error_code& ec,+ *     const typename Protocol::endpoint& next); @endcode+ * The @c ec parameter contains the result from the most recent connect+ * operation. Before the first connection attempt, @c ec is always set to+ * indicate success. The @c next parameter is the next endpoint to be tried.+ * The function object should return true if the next endpoint should be tried,+ * and false if it should be skipped.+ *+ * @param ec Set to indicate what error occurred, if any. If the sequence is+ * empty, set to asio::error::not_found. Otherwise, contains the error+ * from the last connection attempt.+ *+ * @returns On success, an iterator denoting the successfully connected+ * endpoint. Otherwise, the end iterator.+ *+ * @par Example+ * The following connect condition function object can be used to output+ * information about the individual connection attempts:+ * @code struct my_connect_condition+ * {+ *   bool operator()(+ *       const asio::error_code& ec,+ *       const::tcp::endpoint& next)+ *   {+ *     if (ec) std::cout << "Error: " << ec.message() << std::endl;+ *     std::cout << "Trying: " << next << std::endl;+ *     return true;+ *   }+ * }; @endcode+ * It would be used with the asio::connect function as follows:+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::resolver::results_type e = r.resolve(q);+ * tcp::socket s(my_context);+ * asio::error_code ec;+ * tcp::resolver::results_type::iterator i = asio::connect(+ *     s, e.begin(), e.end(), my_connect_condition());+ * if (ec)+ * {+ *   // An error occurred.+ * }+ * else+ * {+ *   std::cout << "Connected to: " << i->endpoint() << std::endl;+ * } @endcode+ */+template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition>+Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, Iterator end, ConnectCondition connect_condition,+    asio::error_code& ec);++/*@}*/++/**+ * @defgroup async_connect asio::async_connect+ *+ * @brief The @c async_connect function is a composed asynchronous operation+ * that establishes a socket connection by trying each endpoint in a sequence.+ */+/*@{*/++/// Asynchronously establishes a socket connection by trying each endpoint in a+/// sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c async_connect+ * member function, once for each endpoint in the sequence, until a connection+ * is successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param endpoints A sequence of endpoints.+ *+ * @param handler The handler to be called when the connect operation+ * completes. Copies will be made of the handler as required. The function+ * signature of the handler must be:+ * @code void handler(+ *   // Result of operation. if the sequence is empty, set to+ *   // asio::error::not_found. Otherwise, contains the+ *   // error from the last connection attempt.+ *   const asio::error_code& error,+ *+ *   // On success, the successfully connected endpoint.+ *   // Otherwise, a default-constructed endpoint.+ *   const typename Protocol::endpoint& endpoint+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::socket s(my_context);+ *+ * // ...+ *+ * r.async_resolve(q, resolve_handler);+ *+ * // ...+ *+ * void resolve_handler(+ *     const asio::error_code& ec,+ *     tcp::resolver::results_type results)+ * {+ *   if (!ec)+ *   {+ *     asio::async_connect(s, results, connect_handler);+ *   }+ * }+ *+ * // ...+ *+ * void connect_handler(+ *     const asio::error_code& ec,+ *     const tcp::endpoint& endpoint)+ * {+ *   // ...+ * } @endcode+ */+template <typename Protocol, typename Executor, typename EndpointSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      typename Protocol::endpoint)) RangeConnectHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+    void (asio::error_code, typename Protocol::endpoint))+async_connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints,+    ASIO_MOVE_ARG(RangeConnectHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type* = 0);++#if !defined(ASIO_NO_DEPRECATED)+/// (Deprecated: Use range overload.) Asynchronously establishes a socket+/// connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c async_connect+ * member function, once for each endpoint in the sequence, until a connection+ * is successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param handler The handler to be called when the connect operation+ * completes. Copies will be made of the handler as required. The function+ * signature of the handler must be:+ * @code void handler(+ *   // Result of operation. if the sequence is empty, set to+ *   // asio::error::not_found. Otherwise, contains the+ *   // error from the last connection attempt.+ *   const asio::error_code& error,+ *+ *   // On success, an iterator denoting the successfully+ *   // connected endpoint. Otherwise, the end iterator.+ *   Iterator iterator+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note This overload assumes that a default constructed object of type @c+ * Iterator represents the end of the sequence. This is a valid assumption for+ * iterator types such as @c asio::ip::tcp::resolver::iterator.+ */+template <typename Protocol, typename Executor, typename Iterator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      Iterator)) IteratorConnectHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+    void (asio::error_code, Iterator))+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    ASIO_MOVE_ARG(IteratorConnectHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+#endif // !defined(ASIO_NO_DEPRECATED)++/// Asynchronously establishes a socket connection by trying each endpoint in a+/// sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c async_connect+ * member function, once for each endpoint in the sequence, until a connection+ * is successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param end An iterator pointing to the end of a sequence of endpoints.+ *+ * @param handler The handler to be called when the connect operation+ * completes. Copies will be made of the handler as required. The function+ * signature of the handler must be:+ * @code void handler(+ *   // Result of operation. if the sequence is empty, set to+ *   // asio::error::not_found. Otherwise, contains the+ *   // error from the last connection attempt.+ *   const asio::error_code& error,+ *+ *   // On success, an iterator denoting the successfully+ *   // connected endpoint. Otherwise, the end iterator.+ *   Iterator iterator+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * @code std::vector<tcp::endpoint> endpoints = ...;+ * tcp::socket s(my_context);+ * asio::async_connect(s,+ *     endpoints.begin(), endpoints.end(),+ *     connect_handler);+ *+ * // ...+ *+ * void connect_handler(+ *     const asio::error_code& ec,+ *     std::vector<tcp::endpoint>::iterator i)+ * {+ *   // ...+ * } @endcode+ */+template <typename Protocol, typename Executor, typename Iterator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      Iterator)) IteratorConnectHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+    void (asio::error_code, Iterator))+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,+    ASIO_MOVE_ARG(IteratorConnectHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor));++/// Asynchronously establishes a socket connection by trying each endpoint in a+/// sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c async_connect+ * member function, once for each endpoint in the sequence, until a connection+ * is successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param endpoints A sequence of endpoints.+ *+ * @param connect_condition A function object that is called prior to each+ * connection attempt. The signature of the function object must be:+ * @code bool connect_condition(+ *     const asio::error_code& ec,+ *     const typename Protocol::endpoint& next); @endcode+ * The @c ec parameter contains the result from the most recent connect+ * operation. Before the first connection attempt, @c ec is always set to+ * indicate success. The @c next parameter is the next endpoint to be tried.+ * The function object should return true if the next endpoint should be tried,+ * and false if it should be skipped.+ *+ * @param handler The handler to be called when the connect operation+ * completes. Copies will be made of the handler as required. The function+ * signature of the handler must be:+ * @code void handler(+ *   // Result of operation. if the sequence is empty, set to+ *   // asio::error::not_found. Otherwise, contains the+ *   // error from the last connection attempt.+ *   const asio::error_code& error,+ *+ *   // On success, an iterator denoting the successfully+ *   // connected endpoint. Otherwise, the end iterator.+ *   Iterator iterator+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * The following connect condition function object can be used to output+ * information about the individual connection attempts:+ * @code struct my_connect_condition+ * {+ *   bool operator()(+ *       const asio::error_code& ec,+ *       const::tcp::endpoint& next)+ *   {+ *     if (ec) std::cout << "Error: " << ec.message() << std::endl;+ *     std::cout << "Trying: " << next << std::endl;+ *     return true;+ *   }+ * }; @endcode+ * It would be used with the asio::connect function as follows:+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::socket s(my_context);+ *+ * // ...+ *+ * r.async_resolve(q, resolve_handler);+ *+ * // ...+ *+ * void resolve_handler(+ *     const asio::error_code& ec,+ *     tcp::resolver::results_type results)+ * {+ *   if (!ec)+ *   {+ *     asio::async_connect(s, results,+ *         my_connect_condition(),+ *         connect_handler);+ *   }+ * }+ *+ * // ...+ *+ * void connect_handler(+ *     const asio::error_code& ec,+ *     const tcp::endpoint& endpoint)+ * {+ *   if (ec)+ *   {+ *     // An error occurred.+ *   }+ *   else+ *   {+ *     std::cout << "Connected to: " << endpoint << std::endl;+ *   }+ * } @endcode+ */+template <typename Protocol, typename Executor,+    typename EndpointSequence, typename ConnectCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      typename Protocol::endpoint)) RangeConnectHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+    void (asio::error_code, typename Protocol::endpoint))+async_connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints, ConnectCondition connect_condition,+    ASIO_MOVE_ARG(RangeConnectHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type* = 0);++#if !defined(ASIO_NO_DEPRECATED)+/// (Deprecated: Use range overload.) Asynchronously establishes a socket+/// connection by trying each endpoint in a sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c async_connect+ * member function, once for each endpoint in the sequence, until a connection+ * is successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param connect_condition A function object that is called prior to each+ * connection attempt. The signature of the function object must be:+ * @code bool connect_condition(+ *     const asio::error_code& ec,+ *     const typename Protocol::endpoint& next); @endcode+ * The @c ec parameter contains the result from the most recent connect+ * operation. Before the first connection attempt, @c ec is always set to+ * indicate success. The @c next parameter is the next endpoint to be tried.+ * The function object should return true if the next endpoint should be tried,+ * and false if it should be skipped.+ *+ * @param handler The handler to be called when the connect operation+ * completes. Copies will be made of the handler as required. The function+ * signature of the handler must be:+ * @code void handler(+ *   // Result of operation. if the sequence is empty, set to+ *   // asio::error::not_found. Otherwise, contains the+ *   // error from the last connection attempt.+ *   const asio::error_code& error,+ *+ *   // On success, an iterator denoting the successfully+ *   // connected endpoint. Otherwise, the end iterator.+ *   Iterator iterator+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note This overload assumes that a default constructed object of type @c+ * Iterator represents the end of the sequence. This is a valid assumption for+ * iterator types such as @c asio::ip::tcp::resolver::iterator.+ */+template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      Iterator)) IteratorConnectHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+    void (asio::error_code, Iterator))+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    ConnectCondition connect_condition,+    ASIO_MOVE_ARG(IteratorConnectHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+#endif // !defined(ASIO_NO_DEPRECATED)++/// Asynchronously establishes a socket connection by trying each endpoint in a+/// sequence.+/**+ * This function attempts to connect a socket to one of a sequence of+ * endpoints. It does this by repeated calls to the socket's @c async_connect+ * member function, once for each endpoint in the sequence, until a connection+ * is successfully established.+ *+ * @param s The socket to be connected. If the socket is already open, it will+ * be closed.+ *+ * @param begin An iterator pointing to the start of a sequence of endpoints.+ *+ * @param end An iterator pointing to the end of a sequence of endpoints.+ *+ * @param connect_condition A function object that is called prior to each+ * connection attempt. The signature of the function object must be:+ * @code bool connect_condition(+ *     const asio::error_code& ec,+ *     const typename Protocol::endpoint& next); @endcode+ * The @c ec parameter contains the result from the most recent connect+ * operation. Before the first connection attempt, @c ec is always set to+ * indicate success. The @c next parameter is the next endpoint to be tried.+ * The function object should return true if the next endpoint should be tried,+ * and false if it should be skipped.+ *+ * @param handler The handler to be called when the connect operation+ * completes. Copies will be made of the handler as required. The function+ * signature of the handler must be:+ * @code void handler(+ *   // Result of operation. if the sequence is empty, set to+ *   // asio::error::not_found. Otherwise, contains the+ *   // error from the last connection attempt.+ *   const asio::error_code& error,+ *+ *   // On success, an iterator denoting the successfully+ *   // connected endpoint. Otherwise, the end iterator.+ *   Iterator iterator+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * The following connect condition function object can be used to output+ * information about the individual connection attempts:+ * @code struct my_connect_condition+ * {+ *   bool operator()(+ *       const asio::error_code& ec,+ *       const::tcp::endpoint& next)+ *   {+ *     if (ec) std::cout << "Error: " << ec.message() << std::endl;+ *     std::cout << "Trying: " << next << std::endl;+ *     return true;+ *   }+ * }; @endcode+ * It would be used with the asio::connect function as follows:+ * @code tcp::resolver r(my_context);+ * tcp::resolver::query q("host", "service");+ * tcp::socket s(my_context);+ *+ * // ...+ *+ * r.async_resolve(q, resolve_handler);+ *+ * // ...+ *+ * void resolve_handler(+ *     const asio::error_code& ec,+ *     tcp::resolver::iterator i)+ * {+ *   if (!ec)+ *   {+ *     tcp::resolver::iterator end;+ *     asio::async_connect(s, i, end,+ *         my_connect_condition(),+ *         connect_handler);+ *   }+ * }+ *+ * // ...+ *+ * void connect_handler(+ *     const asio::error_code& ec,+ *     tcp::resolver::iterator i)+ * {+ *   if (ec)+ *   {+ *     // An error occurred.+ *   }+ *   else+ *   {+ *     std::cout << "Connected to: " << i->endpoint() << std::endl;+ *   }+ * } @endcode+ */+template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      Iterator)) IteratorConnectHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+    void (asio::error_code, Iterator))+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    Iterator end, ConnectCondition connect_condition,+    ASIO_MOVE_ARG(IteratorConnectHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor));++/*@}*/++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/connect.hpp"++#endif
+ link/modules/asio-standalone/asio/include/asio/coroutine.hpp view
@@ -0,0 +1,328 @@+//+// coroutine.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/deadline_timer.hpp view
@@ -0,0 +1,38 @@+//+// deadline_timer.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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
+ link/modules/asio-standalone/asio/include/asio/defer.hpp view
@@ -0,0 +1,130 @@+//+// defer.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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.+ *+ * This function has the following effects:+ *+ * @li Constructs a function object handler of type @c Handler, initialized+ * with <tt>handler(forward<CompletionToken>(token))</tt>.+ *+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,+ * initializing the object as <tt>result(handler)</tt>.+ *+ * @li Obtains the handler's associated executor object @c ex by performing+ * <tt>get_associated_executor(handler)</tt>.+ *+ * @li Obtains the handler's associated allocator object @c alloc by performing+ * <tt>get_associated_allocator(handler)</tt>.+ *+ * @li Performs <tt>ex.defer(std::move(handler), alloc)</tt>.+ *+ * @li Returns <tt>result.get()</tt>.+ */+template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+    ASIO_MOVE_ARG(CompletionToken) 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.+ *+ * This function has the following effects:+ *+ * @li Constructs a function object handler of type @c Handler, initialized+ * with <tt>handler(forward<CompletionToken>(token))</tt>.+ *+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,+ * initializing the object as <tt>result(handler)</tt>.+ *+ * @li Obtains the handler's associated executor object @c ex1 by performing+ * <tt>get_associated_executor(handler)</tt>.+ *+ * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.+ *+ * @li Obtains the handler's associated allocator object @c alloc by performing+ * <tt>get_associated_allocator(handler)</tt>.+ *+ * @li Constructs a function object @c f with a function call operator that+ * performs <tt>ex1.dispatch(std::move(handler), alloc)</tt> followed by+ * <tt>w.reset()</tt>.+ *+ * @li Performs <tt>Executor(ex).defer(std::move(f), alloc)</tt>.+ *+ * @li Returns <tt>result.get()</tt>.+ */+template <typename Executor,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+      ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+    const Executor& ex,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+    typename enable_if<+      execution::is_executor<Executor>::value || is_executor<Executor>::value+    >::type* = 0);++/// Submits a completion token or function object for execution.+/**+ * @returns <tt>defer(ctx.get_executor(), forward<CompletionToken>(token))</tt>.+ */+template <typename ExecutionContext,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+      ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+        typename ExecutionContext::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+    ExecutionContext& ctx,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename ExecutionContext::executor_type),+    typename enable_if<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
+ link/modules/asio-standalone/asio/include/asio/detached.hpp view
@@ -0,0 +1,112 @@+//+// detached.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 enable_if<+          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
+ link/modules/asio-standalone/asio/include/asio/detail/array.hpp view
@@ -0,0 +1,38 @@+//+// detail/array.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_ARRAY_HPP+#define ASIO_DETAIL_ARRAY_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_ARRAY)+# include <array>+#else // defined(ASIO_HAS_STD_ARRAY)+# include <boost/array.hpp>+#endif // defined(ASIO_HAS_STD_ARRAY)++namespace asio {+namespace detail {++#if defined(ASIO_HAS_STD_ARRAY)+using std::array;+#else // defined(ASIO_HAS_STD_ARRAY)+using boost::array;+#endif // defined(ASIO_HAS_STD_ARRAY)++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_ARRAY_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/array_fwd.hpp view
@@ -0,0 +1,34 @@+//+// detail/array_fwd.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_ARRAY_FWD_HPP+#define ASIO_DETAIL_ARRAY_FWD_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++namespace boost {++template<class T, std::size_t N>+class array;++} // namespace boost++// Standard library components can't be forward declared, so we'll have to+// include the array header. Fortunately, it's fairly lightweight and doesn't+// add significantly to the compile time.+#if defined(ASIO_HAS_STD_ARRAY)+# include <array>+#endif // defined(ASIO_HAS_STD_ARRAY)++#endif // ASIO_DETAIL_ARRAY_FWD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/assert.hpp view
@@ -0,0 +1,32 @@+//+// detail/assert.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_ASSERT_HPP+#define ASIO_DETAIL_ASSERT_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_ASSERT)+# include <boost/assert.hpp>+#else // defined(ASIO_HAS_BOOST_ASSERT)+# include <cassert>+#endif // defined(ASIO_HAS_BOOST_ASSERT)++#if defined(ASIO_HAS_BOOST_ASSERT)+# define ASIO_ASSERT(expr) BOOST_ASSERT(expr)+#else // defined(ASIO_HAS_BOOST_ASSERT)+# define ASIO_ASSERT(expr) assert(expr)+#endif // defined(ASIO_HAS_BOOST_ASSERT)++#endif // ASIO_DETAIL_ASSERT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/atomic_count.hpp view
@@ -0,0 +1,64 @@+//+// detail/atomic_count.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_ATOMIC_COUNT_HPP+#define ASIO_DETAIL_ATOMIC_COUNT_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_THREADS)+// Nothing to include.+#elif defined(ASIO_HAS_STD_ATOMIC)+# include <atomic>+#else // defined(ASIO_HAS_STD_ATOMIC)+# include <boost/detail/atomic_count.hpp>+#endif // defined(ASIO_HAS_STD_ATOMIC)++namespace asio {+namespace detail {++#if !defined(ASIO_HAS_THREADS)+typedef long atomic_count;+inline void increment(atomic_count& a, long b) { a += b; }+inline void ref_count_up(atomic_count& a) { ++a; }+inline bool ref_count_down(atomic_count& a) { return --a == 0; }+#elif defined(ASIO_HAS_STD_ATOMIC)+typedef std::atomic<long> atomic_count;+inline void increment(atomic_count& a, long b) { a += b; }++inline void ref_count_up(atomic_count& a)+{+  a.fetch_add(1, std::memory_order_relaxed);+}++inline bool ref_count_down(atomic_count& a)+{+  if (a.fetch_sub(1, std::memory_order_release) == 1)+  {+    std::atomic_thread_fence(std::memory_order_acquire);+    return true;+  }+  return false;+}+#else // defined(ASIO_HAS_STD_ATOMIC)+typedef boost::detail::atomic_count atomic_count;+inline void increment(atomic_count& a, long b) { while (b > 0) ++a, --b; }+inline void ref_count_up(atomic_count& a) { ++a; }+inline bool ref_count_down(atomic_count& a) { return --a == 0; }+#endif // defined(ASIO_HAS_STD_ATOMIC)++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_ATOMIC_COUNT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/base_from_completion_cond.hpp view
@@ -0,0 +1,69 @@+//+// detail/base_from_completion_cond.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP+#define ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/completion_condition.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename CompletionCondition>+class base_from_completion_cond+{+protected:+  explicit base_from_completion_cond(CompletionCondition& completion_condition)+    : completion_condition_(+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))+  {+  }++  std::size_t check_for_completion(+      const asio::error_code& ec,+      std::size_t total_transferred)+  {+    return detail::adapt_completion_condition_result(+        completion_condition_(ec, total_transferred));+  }++private:+  CompletionCondition completion_condition_;+};++template <>+class base_from_completion_cond<transfer_all_t>+{+protected:+  explicit base_from_completion_cond(transfer_all_t)+  {+  }++  static std::size_t check_for_completion(+      const asio::error_code& ec,+      std::size_t total_transferred)+  {+    return transfer_all_t()(ec, total_transferred);+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_BASE_FROM_COMPLETION_COND_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/bind_handler.hpp view
@@ -0,0 +1,934 @@+//+// detail/bind_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_BIND_HANDLER_HPP+#define ASIO_DETAIL_BIND_HANDLER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename Arg1>+class binder1+{+public:+  template <typename T>+  binder1(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1)+    : handler_(ASIO_MOVE_CAST(T)(handler)),+      arg1_(arg1)+  {+  }++  binder1(Handler& handler, const Arg1& arg1)+    : handler_(ASIO_MOVE_CAST(Handler)(handler)),+      arg1_(arg1)+  {+  }++#if defined(ASIO_HAS_MOVE)+  binder1(const binder1& other)+    : handler_(other.handler_),+      arg1_(other.arg1_)+  {+  }++  binder1(binder1&& other)+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+      arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    handler_(static_cast<const Arg1&>(arg1_));+  }++  void operator()() const+  {+    handler_(arg1_);+  }++//private:+  Handler handler_;+  Arg1 arg1_;+};++template <typename Handler, typename Arg1>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    binder1<Handler, Arg1>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    binder1<Handler, Arg1>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1>+inline bool asio_handler_is_continuation(+    binder1<Handler, Arg1>* this_handler)+{+  return asio_handler_cont_helpers::is_continuation(+      this_handler->handler_);+}++template <typename Function, typename Handler, typename Arg1>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+    binder1<Handler, Arg1>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler, typename Arg1>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+    binder1<Handler, Arg1>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1>+inline binder1<typename decay<Handler>::type, Arg1> bind_handler(+    ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1)+{+  return binder1<typename decay<Handler>::type, Arg1>(0,+      ASIO_MOVE_CAST(Handler)(handler), arg1);+}++template <typename Handler, typename Arg1, typename Arg2>+class binder2+{+public:+  template <typename T>+  binder2(int, ASIO_MOVE_ARG(T) handler,+      const Arg1& arg1, const Arg2& arg2)+    : handler_(ASIO_MOVE_CAST(T)(handler)),+      arg1_(arg1),+      arg2_(arg2)+  {+  }++  binder2(Handler& handler, const Arg1& arg1, const Arg2& arg2)+    : handler_(ASIO_MOVE_CAST(Handler)(handler)),+      arg1_(arg1),+      arg2_(arg2)+  {+  }++#if defined(ASIO_HAS_MOVE)+  binder2(const binder2& other)+    : handler_(other.handler_),+      arg1_(other.arg1_),+      arg2_(other.arg2_)+  {+  }++  binder2(binder2&& other)+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+      arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),+      arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    handler_(static_cast<const Arg1&>(arg1_),+        static_cast<const Arg2&>(arg2_));+  }++  void operator()() const+  {+    handler_(arg1_, arg2_);+  }++//private:+  Handler handler_;+  Arg1 arg1_;+  Arg2 arg2_;+};++template <typename Handler, typename Arg1, typename Arg2>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    binder2<Handler, Arg1, Arg2>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    binder2<Handler, Arg1, Arg2>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2>+inline bool asio_handler_is_continuation(+    binder2<Handler, Arg1, Arg2>* this_handler)+{+  return asio_handler_cont_helpers::is_continuation(+      this_handler->handler_);+}++template <typename Function, typename Handler, typename Arg1, typename Arg2>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+    binder2<Handler, Arg1, Arg2>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler, typename Arg1, typename Arg2>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+    binder2<Handler, Arg1, Arg2>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2>+inline binder2<typename decay<Handler>::type, Arg1, Arg2> bind_handler(+    ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1, const Arg2& arg2)+{+  return binder2<typename decay<Handler>::type, Arg1, Arg2>(0,+      ASIO_MOVE_CAST(Handler)(handler), arg1, arg2);+}++template <typename Handler, typename Arg1, typename Arg2, typename Arg3>+class binder3+{+public:+  template <typename T>+  binder3(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1,+      const Arg2& arg2, const Arg3& arg3)+    : handler_(ASIO_MOVE_CAST(T)(handler)),+      arg1_(arg1),+      arg2_(arg2),+      arg3_(arg3)+  {+  }++  binder3(Handler& handler, const Arg1& arg1,+      const Arg2& arg2, const Arg3& arg3)+    : handler_(ASIO_MOVE_CAST(Handler)(handler)),+      arg1_(arg1),+      arg2_(arg2),+      arg3_(arg3)+  {+  }++#if defined(ASIO_HAS_MOVE)+  binder3(const binder3& other)+    : handler_(other.handler_),+      arg1_(other.arg1_),+      arg2_(other.arg2_),+      arg3_(other.arg3_)+  {+  }++  binder3(binder3&& other)+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+      arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),+      arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)),+      arg3_(ASIO_MOVE_CAST(Arg3)(other.arg3_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    handler_(static_cast<const Arg1&>(arg1_),+        static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_));+  }++  void operator()() const+  {+    handler_(arg1_, arg2_, arg3_);+  }++//private:+  Handler handler_;+  Arg1 arg1_;+  Arg2 arg2_;+  Arg3 arg3_;+};++template <typename Handler, typename Arg1, typename Arg2, typename Arg3>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    binder3<Handler, Arg1, Arg2, Arg3>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2, typename Arg3>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    binder3<Handler, Arg1, Arg2, Arg3>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2, typename Arg3>+inline bool asio_handler_is_continuation(+    binder3<Handler, Arg1, Arg2, Arg3>* this_handler)+{+  return asio_handler_cont_helpers::is_continuation(+      this_handler->handler_);+}++template <typename Function, typename Handler,+    typename Arg1, typename Arg2, typename Arg3>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+    binder3<Handler, Arg1, Arg2, Arg3>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler,+    typename Arg1, typename Arg2, typename Arg3>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+    binder3<Handler, Arg1, Arg2, Arg3>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2, typename Arg3>+inline binder3<typename decay<Handler>::type, Arg1, Arg2, Arg3> bind_handler(+    ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1, const Arg2& arg2,+    const Arg3& arg3)+{+  return binder3<typename decay<Handler>::type, Arg1, Arg2, Arg3>(0,+      ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3);+}++template <typename Handler, typename Arg1,+    typename Arg2, typename Arg3, typename Arg4>+class binder4+{+public:+  template <typename T>+  binder4(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1,+      const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)+    : handler_(ASIO_MOVE_CAST(T)(handler)),+      arg1_(arg1),+      arg2_(arg2),+      arg3_(arg3),+      arg4_(arg4)+  {+  }++  binder4(Handler& handler, const Arg1& arg1,+      const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)+    : handler_(ASIO_MOVE_CAST(Handler)(handler)),+      arg1_(arg1),+      arg2_(arg2),+      arg3_(arg3),+      arg4_(arg4)+  {+  }++#if defined(ASIO_HAS_MOVE)+  binder4(const binder4& other)+    : handler_(other.handler_),+      arg1_(other.arg1_),+      arg2_(other.arg2_),+      arg3_(other.arg3_),+      arg4_(other.arg4_)+  {+  }++  binder4(binder4&& other)+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+      arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),+      arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)),+      arg3_(ASIO_MOVE_CAST(Arg3)(other.arg3_)),+      arg4_(ASIO_MOVE_CAST(Arg4)(other.arg4_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    handler_(static_cast<const Arg1&>(arg1_),+        static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),+        static_cast<const Arg4&>(arg4_));+  }++  void operator()() const+  {+    handler_(arg1_, arg2_, arg3_, arg4_);+  }++//private:+  Handler handler_;+  Arg1 arg1_;+  Arg2 arg2_;+  Arg3 arg3_;+  Arg4 arg4_;+};++template <typename Handler, typename Arg1,+    typename Arg2, typename Arg3, typename Arg4>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1,+    typename Arg2, typename Arg3, typename Arg4>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1,+    typename Arg2, typename Arg3, typename Arg4>+inline bool asio_handler_is_continuation(+    binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)+{+  return asio_handler_cont_helpers::is_continuation(+      this_handler->handler_);+}++template <typename Function, typename Handler, typename Arg1,+    typename Arg2, typename Arg3, typename Arg4>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+    binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler, typename Arg1,+    typename Arg2, typename Arg3, typename Arg4>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+    binder4<Handler, Arg1, Arg2, Arg3, Arg4>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1,+    typename Arg2, typename Arg3, typename Arg4>+inline binder4<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4>+bind_handler(ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1,+    const Arg2& arg2, const Arg3& arg3, const Arg4& arg4)+{+  return binder4<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4>(0,+      ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3, arg4);+}++template <typename Handler, typename Arg1, typename Arg2,+    typename Arg3, typename Arg4, typename Arg5>+class binder5+{+public:+  template <typename T>+  binder5(int, ASIO_MOVE_ARG(T) handler, const Arg1& arg1,+      const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)+    : handler_(ASIO_MOVE_CAST(T)(handler)),+      arg1_(arg1),+      arg2_(arg2),+      arg3_(arg3),+      arg4_(arg4),+      arg5_(arg5)+  {+  }++  binder5(Handler& handler, const Arg1& arg1, const Arg2& arg2,+      const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)+    : handler_(ASIO_MOVE_CAST(Handler)(handler)),+      arg1_(arg1),+      arg2_(arg2),+      arg3_(arg3),+      arg4_(arg4),+      arg5_(arg5)+  {+  }++#if defined(ASIO_HAS_MOVE)+  binder5(const binder5& other)+    : handler_(other.handler_),+      arg1_(other.arg1_),+      arg2_(other.arg2_),+      arg3_(other.arg3_),+      arg4_(other.arg4_),+      arg5_(other.arg5_)+  {+  }++  binder5(binder5&& other)+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+      arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),+      arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_)),+      arg3_(ASIO_MOVE_CAST(Arg3)(other.arg3_)),+      arg4_(ASIO_MOVE_CAST(Arg4)(other.arg4_)),+      arg5_(ASIO_MOVE_CAST(Arg5)(other.arg5_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    handler_(static_cast<const Arg1&>(arg1_),+        static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),+        static_cast<const Arg4&>(arg4_), static_cast<const Arg5&>(arg5_));+  }++  void operator()() const+  {+    handler_(arg1_, arg2_, arg3_, arg4_, arg5_);+  }++//private:+  Handler handler_;+  Arg1 arg1_;+  Arg2 arg2_;+  Arg3 arg3_;+  Arg4 arg4_;+  Arg5 arg5_;+};++template <typename Handler, typename Arg1, typename Arg2,+    typename Arg3, typename Arg4, typename Arg5>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2,+    typename Arg3, typename Arg4, typename Arg5>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2,+    typename Arg3, typename Arg4, typename Arg5>+inline bool asio_handler_is_continuation(+    binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)+{+  return asio_handler_cont_helpers::is_continuation(+      this_handler->handler_);+}++template <typename Function, typename Handler, typename Arg1,+    typename Arg2, typename Arg3, typename Arg4, typename Arg5>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+    binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler, typename Arg1,+    typename Arg2, typename Arg3, typename Arg4, typename Arg5>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+    binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2,+    typename Arg3, typename Arg4, typename Arg5>+inline binder5<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4, Arg5>+bind_handler(ASIO_MOVE_ARG(Handler) handler, const Arg1& arg1,+    const Arg2& arg2, const Arg3& arg3, const Arg4& arg4, const Arg5& arg5)+{+  return binder5<typename decay<Handler>::type, Arg1, Arg2, Arg3, Arg4, Arg5>(0,+      ASIO_MOVE_CAST(Handler)(handler), arg1, arg2, arg3, arg4, arg5);+}++#if defined(ASIO_HAS_MOVE)++template <typename Handler, typename Arg1>+class move_binder1+{+public:+  move_binder1(int, ASIO_MOVE_ARG(Handler) handler,+      ASIO_MOVE_ARG(Arg1) arg1)+    : handler_(ASIO_MOVE_CAST(Handler)(handler)),+      arg1_(ASIO_MOVE_CAST(Arg1)(arg1))+  {+  }++  move_binder1(move_binder1&& other)+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+      arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_))+  {+  }++  void operator()()+  {+    handler_(ASIO_MOVE_CAST(Arg1)(arg1_));+  }++//private:+  Handler handler_;+  Arg1 arg1_;+};++template <typename Handler, typename Arg1>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    move_binder1<Handler, Arg1>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    move_binder1<Handler, Arg1>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1>+inline bool asio_handler_is_continuation(+    move_binder1<Handler, Arg1>* this_handler)+{+  return asio_handler_cont_helpers::is_continuation(+      this_handler->handler_);+}++template <typename Function, typename Handler, typename Arg1>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(ASIO_MOVE_ARG(Function) function,+    move_binder1<Handler, Arg1>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      ASIO_MOVE_CAST(Function)(function), this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2>+class move_binder2+{+public:+  move_binder2(int, ASIO_MOVE_ARG(Handler) handler,+      const Arg1& arg1, ASIO_MOVE_ARG(Arg2) arg2)+    : handler_(ASIO_MOVE_CAST(Handler)(handler)),+      arg1_(arg1),+      arg2_(ASIO_MOVE_CAST(Arg2)(arg2))+  {+  }++  move_binder2(move_binder2&& other)+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+      arg1_(ASIO_MOVE_CAST(Arg1)(other.arg1_)),+      arg2_(ASIO_MOVE_CAST(Arg2)(other.arg2_))+  {+  }++  void operator()()+  {+    handler_(static_cast<const Arg1&>(arg1_),+        ASIO_MOVE_CAST(Arg2)(arg2_));+  }++//private:+  Handler handler_;+  Arg1 arg1_;+  Arg2 arg2_;+};++template <typename Handler, typename Arg1, typename Arg2>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    move_binder2<Handler, Arg1, Arg2>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    move_binder2<Handler, Arg1, Arg2>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Arg1, typename Arg2>+inline bool asio_handler_is_continuation(+    move_binder2<Handler, Arg1, Arg2>* this_handler)+{+  return asio_handler_cont_helpers::is_continuation(+      this_handler->handler_);+}++template <typename Function, typename Handler, typename Arg1, typename Arg2>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(ASIO_MOVE_ARG(Function) function,+    move_binder2<Handler, Arg1, Arg2>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      ASIO_MOVE_CAST(Function)(function), this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++#endif // defined(ASIO_HAS_MOVE)++} // namespace detail++template <typename Handler, typename Arg1, typename Allocator>+struct associated_allocator<detail::binder1<Handler, Arg1>, Allocator>+{+  typedef typename associated_allocator<Handler, Allocator>::type type;++  static type get(const detail::binder1<Handler, Arg1>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+  }+};++template <typename Handler, typename Arg1, typename Arg2, typename Allocator>+struct associated_allocator<detail::binder2<Handler, Arg1, Arg2>, Allocator>+{+  typedef typename associated_allocator<Handler, Allocator>::type type;++  static type get(const detail::binder2<Handler, Arg1, Arg2>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+  }+};++template <typename Handler, typename Arg1, typename Executor>+struct associated_executor<detail::binder1<Handler, Arg1>, Executor>+{+  typedef typename associated_executor<Handler, Executor>::type type;++  static type get(const detail::binder1<Handler, Arg1>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<Handler, Executor>::get(h.handler_, ex);+  }+};++template <typename Handler, typename Arg1, typename Arg2, typename Executor>+struct associated_executor<detail::binder2<Handler, Arg1, Arg2>, Executor>+{+  typedef typename associated_executor<Handler, Executor>::type type;++  static type get(const detail::binder2<Handler, Arg1, Arg2>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<Handler, Executor>::get(h.handler_, ex);+  }+};++#if defined(ASIO_HAS_MOVE)++template <typename Handler, typename Arg1, typename Allocator>+struct associated_allocator<detail::move_binder1<Handler, Arg1>, Allocator>+{+  typedef typename associated_allocator<Handler, Allocator>::type type;++  static type get(const detail::move_binder1<Handler, Arg1>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+  }+};++template <typename Handler, typename Arg1, typename Arg2, typename Allocator>+struct associated_allocator<+    detail::move_binder2<Handler, Arg1, Arg2>, Allocator>+{+  typedef typename associated_allocator<Handler, Allocator>::type type;++  static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+  }+};++template <typename Handler, typename Arg1, typename Executor>+struct associated_executor<detail::move_binder1<Handler, Arg1>, Executor>+{+  typedef typename associated_executor<Handler, Executor>::type type;++  static type get(const detail::move_binder1<Handler, Arg1>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<Handler, Executor>::get(h.handler_, ex);+  }+};++template <typename Handler, typename Arg1, typename Arg2, typename Executor>+struct associated_executor<detail::move_binder2<Handler, Arg1, Arg2>, Executor>+{+  typedef typename associated_executor<Handler, Executor>::type type;++  static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<Handler, Executor>::get(h.handler_, ex);+  }+};++#endif // defined(ASIO_HAS_MOVE)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_BIND_HANDLER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/blocking_executor_op.hpp view
@@ -0,0 +1,107 @@+//+// detail/blocking_executor_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_BLOCKING_EXECUTOR_OP_HPP+#define ASIO_DETAIL_BLOCKING_EXECUTOR_OP_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/event.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/scheduler_operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Operation = scheduler_operation>+class blocking_executor_op_base : public Operation+{+public:+  blocking_executor_op_base(typename Operation::func_type complete_func)+    : Operation(complete_func),+      is_complete_(false)+  {+  }++  void wait()+  {+    asio::detail::mutex::scoped_lock lock(mutex_);+    while (!is_complete_)+      event_.wait(lock);+  }++protected:+  struct do_complete_cleanup+  {+    ~do_complete_cleanup()+    {+      asio::detail::mutex::scoped_lock lock(op_->mutex_);+      op_->is_complete_ = true;+      op_->event_.unlock_and_signal_one_for_destruction(lock);+    }++    blocking_executor_op_base* op_;+  };++private:+  asio::detail::mutex mutex_;+  asio::detail::event event_;+  bool is_complete_;+};++template <typename Handler, typename Operation = scheduler_operation>+class blocking_executor_op : public blocking_executor_op_base<Operation>+{+public:+  blocking_executor_op(Handler& h)+    : blocking_executor_op_base<Operation>(&blocking_executor_op::do_complete),+      handler_(h)+  {+  }++  static void do_complete(void* owner, Operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    blocking_executor_op* o(static_cast<blocking_executor_op*>(base));++    typename blocking_executor_op_base<Operation>::do_complete_cleanup+      on_exit = { o };+    (void)on_exit;++    ASIO_HANDLER_COMPLETION((*o));++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN(());+      asio_handler_invoke_helpers::invoke(o->handler_, o->handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler& handler_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_BLOCKING_EXECUTOR_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/buffer_resize_guard.hpp view
@@ -0,0 +1,66 @@+//+// detail/buffer_resize_guard.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP+#define ASIO_DETAIL_BUFFER_RESIZE_GUARD_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/limits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper class to manage buffer resizing in an exception safe way.+template <typename Buffer>+class buffer_resize_guard+{+public:+  // Constructor.+  buffer_resize_guard(Buffer& buffer)+    : buffer_(buffer),+      old_size_(buffer.size())+  {+  }++  // Destructor rolls back the buffer resize unless commit was called.+  ~buffer_resize_guard()+  {+    if (old_size_ != (std::numeric_limits<size_t>::max)())+    {+      buffer_.resize(old_size_);+    }+  }++  // Commit the resize transaction.+  void commit()+  {+    old_size_ = (std::numeric_limits<size_t>::max)();+  }++private:+  // The buffer being managed.+  Buffer& buffer_;++  // The size of the buffer at the time the guard was constructed.+  size_t old_size_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_BUFFER_RESIZE_GUARD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/buffer_sequence_adapter.hpp view
@@ -0,0 +1,650 @@+//+// detail/buffer_sequence_adapter.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP+#define ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/buffer.hpp"+#include "asio/detail/array_fwd.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class buffer_sequence_adapter_base+{+#if defined(ASIO_WINDOWS_RUNTIME)+public:+  // The maximum number of buffers to support in a single operation.+  enum { max_buffers = 1 };++protected:+  typedef Windows::Storage::Streams::IBuffer^ native_buffer_type;++  ASIO_DECL static void init_native_buffer(+      native_buffer_type& buf,+      const asio::mutable_buffer& buffer);++  ASIO_DECL static void init_native_buffer(+      native_buffer_type& buf,+      const asio::const_buffer& buffer);+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+public:+  // The maximum number of buffers to support in a single operation.+  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };++protected:+  typedef WSABUF native_buffer_type;++  static void init_native_buffer(WSABUF& buf,+      const asio::mutable_buffer& buffer)+  {+    buf.buf = static_cast<char*>(buffer.data());+    buf.len = static_cast<ULONG>(buffer.size());+  }++  static void init_native_buffer(WSABUF& buf,+      const asio::const_buffer& buffer)+  {+    buf.buf = const_cast<char*>(static_cast<const char*>(buffer.data()));+    buf.len = static_cast<ULONG>(buffer.size());+  }+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+public:+  // The maximum number of buffers to support in a single operation.+  enum { max_buffers = 64 < max_iov_len ? 64 : max_iov_len };++protected:+  typedef iovec native_buffer_type;++  static void init_iov_base(void*& base, void* addr)+  {+    base = addr;+  }++  template <typename T>+  static void init_iov_base(T& base, void* addr)+  {+    base = static_cast<T>(addr);+  }++  static void init_native_buffer(iovec& iov,+      const asio::mutable_buffer& buffer)+  {+    init_iov_base(iov.iov_base, buffer.data());+    iov.iov_len = buffer.size();+  }++  static void init_native_buffer(iovec& iov,+      const asio::const_buffer& buffer)+  {+    init_iov_base(iov.iov_base, const_cast<void*>(buffer.data()));+    iov.iov_len = buffer.size();+  }+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+};++// Helper class to translate buffers into the native buffer representation.+template <typename Buffer, typename Buffers>+class buffer_sequence_adapter+  : buffer_sequence_adapter_base+{+public:+  enum { is_single_buffer = false };++  explicit buffer_sequence_adapter(const Buffers& buffer_sequence)+    : count_(0), total_buffer_size_(0)+  {+    buffer_sequence_adapter::init(+        asio::buffer_sequence_begin(buffer_sequence),+        asio::buffer_sequence_end(buffer_sequence));+  }++  native_buffer_type* buffers()+  {+    return buffers_;+  }++  std::size_t count() const+  {+    return count_;+  }++  std::size_t total_size() const+  {+    return total_buffer_size_;+  }++  bool all_empty() const+  {+    return total_buffer_size_ == 0;+  }++  static bool all_empty(const Buffers& buffer_sequence)+  {+    return buffer_sequence_adapter::all_empty(+        asio::buffer_sequence_begin(buffer_sequence),+        asio::buffer_sequence_end(buffer_sequence));+  }++  static void validate(const Buffers& buffer_sequence)+  {+    buffer_sequence_adapter::validate(+        asio::buffer_sequence_begin(buffer_sequence),+        asio::buffer_sequence_end(buffer_sequence));+  }++  static Buffer first(const Buffers& buffer_sequence)+  {+    return buffer_sequence_adapter::first(+        asio::buffer_sequence_begin(buffer_sequence),+        asio::buffer_sequence_end(buffer_sequence));+  }++  enum { linearisation_storage_size = 8192 };++  static Buffer linearise(const Buffers& buffer_sequence,+      const asio::mutable_buffer& storage)+  {+    return buffer_sequence_adapter::linearise(+        asio::buffer_sequence_begin(buffer_sequence),+        asio::buffer_sequence_end(buffer_sequence), storage);+  }++private:+  template <typename Iterator>+  void init(Iterator begin, Iterator end)+  {+    Iterator iter = begin;+    for (; iter != end && count_ < max_buffers; ++iter, ++count_)+    {+      Buffer buffer(*iter);+      init_native_buffer(buffers_[count_], buffer);+      total_buffer_size_ += buffer.size();+    }+  }++  template <typename Iterator>+  static bool all_empty(Iterator begin, Iterator end)+  {+    Iterator iter = begin;+    std::size_t i = 0;+    for (; iter != end && i < max_buffers; ++iter, ++i)+      if (Buffer(*iter).size() > 0)+        return false;+    return true;+  }++  template <typename Iterator>+  static void validate(Iterator begin, Iterator end)+  {+    Iterator iter = begin;+    for (; iter != end; ++iter)+    {+      Buffer buffer(*iter);+      buffer.data();+    }+  }++  template <typename Iterator>+  static Buffer first(Iterator begin, Iterator end)+  {+    Iterator iter = begin;+    for (; iter != end; ++iter)+    {+      Buffer buffer(*iter);+      if (buffer.size() != 0)+        return buffer;+    }+    return Buffer();+  }++  template <typename Iterator>+  static Buffer linearise(Iterator begin, Iterator end,+      const asio::mutable_buffer& storage)+  {+    asio::mutable_buffer unused_storage = storage;+    Iterator iter = begin;+    while (iter != end && unused_storage.size() != 0)+    {+      Buffer buffer(*iter);+      ++iter;+      if (buffer.size() == 0)+        continue;+      if (unused_storage.size() == storage.size())+      {+        if (iter == end)+          return buffer;+        if (buffer.size() >= unused_storage.size())+          return buffer;+      }+      unused_storage += asio::buffer_copy(unused_storage, buffer);+    }+    return Buffer(storage.data(), storage.size() - unused_storage.size());+  }++  native_buffer_type buffers_[max_buffers];+  std::size_t count_;+  std::size_t total_buffer_size_;+};++template <typename Buffer>+class buffer_sequence_adapter<Buffer, asio::mutable_buffer>+  : buffer_sequence_adapter_base+{+public:+  enum { is_single_buffer = true };++  explicit buffer_sequence_adapter(+      const asio::mutable_buffer& buffer_sequence)+  {+    init_native_buffer(buffer_, Buffer(buffer_sequence));+    total_buffer_size_ = buffer_sequence.size();+  }++  native_buffer_type* buffers()+  {+    return &buffer_;+  }++  std::size_t count() const+  {+    return 1;+  }++  std::size_t total_size() const+  {+    return total_buffer_size_;+  }++  bool all_empty() const+  {+    return total_buffer_size_ == 0;+  }++  static bool all_empty(const asio::mutable_buffer& buffer_sequence)+  {+    return buffer_sequence.size() == 0;+  }++  static void validate(const asio::mutable_buffer& buffer_sequence)+  {+    buffer_sequence.data();+  }++  static Buffer first(const asio::mutable_buffer& buffer_sequence)+  {+    return Buffer(buffer_sequence);+  }++  enum { linearisation_storage_size = 1 };++  static Buffer linearise(const asio::mutable_buffer& buffer_sequence,+      const Buffer&)+  {+    return Buffer(buffer_sequence);+  }++private:+  native_buffer_type buffer_;+  std::size_t total_buffer_size_;+};++template <typename Buffer>+class buffer_sequence_adapter<Buffer, asio::const_buffer>+  : buffer_sequence_adapter_base+{+public:+  enum { is_single_buffer = true };++  explicit buffer_sequence_adapter(+      const asio::const_buffer& buffer_sequence)+  {+    init_native_buffer(buffer_, Buffer(buffer_sequence));+    total_buffer_size_ = buffer_sequence.size();+  }++  native_buffer_type* buffers()+  {+    return &buffer_;+  }++  std::size_t count() const+  {+    return 1;+  }++  std::size_t total_size() const+  {+    return total_buffer_size_;+  }++  bool all_empty() const+  {+    return total_buffer_size_ == 0;+  }++  static bool all_empty(const asio::const_buffer& buffer_sequence)+  {+    return buffer_sequence.size() == 0;+  }++  static void validate(const asio::const_buffer& buffer_sequence)+  {+    buffer_sequence.data();+  }++  static Buffer first(const asio::const_buffer& buffer_sequence)+  {+    return Buffer(buffer_sequence);+  }++  enum { linearisation_storage_size = 1 };++  static Buffer linearise(const asio::const_buffer& buffer_sequence,+      const Buffer&)+  {+    return Buffer(buffer_sequence);+  }++private:+  native_buffer_type buffer_;+  std::size_t total_buffer_size_;+};++#if !defined(ASIO_NO_DEPRECATED)++template <typename Buffer>+class buffer_sequence_adapter<Buffer, asio::mutable_buffers_1>+  : buffer_sequence_adapter_base+{+public:+  enum { is_single_buffer = true };++  explicit buffer_sequence_adapter(+      const asio::mutable_buffers_1& buffer_sequence)+  {+    init_native_buffer(buffer_, Buffer(buffer_sequence));+    total_buffer_size_ = buffer_sequence.size();+  }++  native_buffer_type* buffers()+  {+    return &buffer_;+  }++  std::size_t count() const+  {+    return 1;+  }++  std::size_t total_size() const+  {+    return total_buffer_size_;+  }++  bool all_empty() const+  {+    return total_buffer_size_ == 0;+  }++  static bool all_empty(const asio::mutable_buffers_1& buffer_sequence)+  {+    return buffer_sequence.size() == 0;+  }++  static void validate(const asio::mutable_buffers_1& buffer_sequence)+  {+    buffer_sequence.data();+  }++  static Buffer first(const asio::mutable_buffers_1& buffer_sequence)+  {+    return Buffer(buffer_sequence);+  }++  enum { linearisation_storage_size = 1 };++  static Buffer linearise(const asio::mutable_buffers_1& buffer_sequence,+      const Buffer&)+  {+    return Buffer(buffer_sequence);+  }++private:+  native_buffer_type buffer_;+  std::size_t total_buffer_size_;+};++template <typename Buffer>+class buffer_sequence_adapter<Buffer, asio::const_buffers_1>+  : buffer_sequence_adapter_base+{+public:+  enum { is_single_buffer = true };++  explicit buffer_sequence_adapter(+      const asio::const_buffers_1& buffer_sequence)+  {+    init_native_buffer(buffer_, Buffer(buffer_sequence));+    total_buffer_size_ = buffer_sequence.size();+  }++  native_buffer_type* buffers()+  {+    return &buffer_;+  }++  std::size_t count() const+  {+    return 1;+  }++  std::size_t total_size() const+  {+    return total_buffer_size_;+  }++  bool all_empty() const+  {+    return total_buffer_size_ == 0;+  }++  static bool all_empty(const asio::const_buffers_1& buffer_sequence)+  {+    return buffer_sequence.size() == 0;+  }++  static void validate(const asio::const_buffers_1& buffer_sequence)+  {+    buffer_sequence.data();+  }++  static Buffer first(const asio::const_buffers_1& buffer_sequence)+  {+    return Buffer(buffer_sequence);+  }++  enum { linearisation_storage_size = 1 };++  static Buffer linearise(const asio::const_buffers_1& buffer_sequence,+      const Buffer&)+  {+    return Buffer(buffer_sequence);+  }++private:+  native_buffer_type buffer_;+  std::size_t total_buffer_size_;+};++#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Buffer, typename Elem>+class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >+  : buffer_sequence_adapter_base+{+public:+  enum { is_single_buffer = false };++  explicit buffer_sequence_adapter(+      const boost::array<Elem, 2>& buffer_sequence)+  {+    init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));+    init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));+    total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();+  }++  native_buffer_type* buffers()+  {+    return buffers_;+  }++  std::size_t count() const+  {+    return 2;+  }++  std::size_t total_size() const+  {+    return total_buffer_size_;+  }++  bool all_empty() const+  {+    return total_buffer_size_ == 0;+  }++  static bool all_empty(const boost::array<Elem, 2>& buffer_sequence)+  {+    return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;+  }++  static void validate(const boost::array<Elem, 2>& buffer_sequence)+  {+    buffer_sequence[0].data();+    buffer_sequence[1].data();+  }++  static Buffer first(const boost::array<Elem, 2>& buffer_sequence)+  {+    return Buffer(buffer_sequence[0].size() != 0+        ? buffer_sequence[0] : buffer_sequence[1]);+  }++  enum { linearisation_storage_size = 8192 };++  static Buffer linearise(const boost::array<Elem, 2>& buffer_sequence,+      const asio::mutable_buffer& storage)+  {+    if (buffer_sequence[0].size() == 0)+      return Buffer(buffer_sequence[1]);+    if (buffer_sequence[1].size() == 0)+      return Buffer(buffer_sequence[0]);+    return Buffer(storage.data(),+        asio::buffer_copy(storage, buffer_sequence));+  }++private:+  native_buffer_type buffers_[2];+  std::size_t total_buffer_size_;+};++#if defined(ASIO_HAS_STD_ARRAY)++template <typename Buffer, typename Elem>+class buffer_sequence_adapter<Buffer, std::array<Elem, 2> >+  : buffer_sequence_adapter_base+{+public:+  enum { is_single_buffer = false };++  explicit buffer_sequence_adapter(+      const std::array<Elem, 2>& buffer_sequence)+  {+    init_native_buffer(buffers_[0], Buffer(buffer_sequence[0]));+    init_native_buffer(buffers_[1], Buffer(buffer_sequence[1]));+    total_buffer_size_ = buffer_sequence[0].size() + buffer_sequence[1].size();+  }++  native_buffer_type* buffers()+  {+    return buffers_;+  }++  std::size_t count() const+  {+    return 2;+  }++  std::size_t total_size() const+  {+    return total_buffer_size_;+  }++  bool all_empty() const+  {+    return total_buffer_size_ == 0;+  }++  static bool all_empty(const std::array<Elem, 2>& buffer_sequence)+  {+    return buffer_sequence[0].size() == 0 && buffer_sequence[1].size() == 0;+  }++  static void validate(const std::array<Elem, 2>& buffer_sequence)+  {+    buffer_sequence[0].data();+    buffer_sequence[1].data();+  }++  static Buffer first(const std::array<Elem, 2>& buffer_sequence)+  {+    return Buffer(buffer_sequence[0].size() != 0+        ? buffer_sequence[0] : buffer_sequence[1]);+  }++  enum { linearisation_storage_size = 8192 };++  static Buffer linearise(const std::array<Elem, 2>& buffer_sequence,+      const asio::mutable_buffer& storage)+  {+    if (buffer_sequence[0].size() == 0)+      return Buffer(buffer_sequence[1]);+    if (buffer_sequence[1].size() == 0)+      return Buffer(buffer_sequence[0]);+    return Buffer(storage.data(),+        asio::buffer_copy(storage, buffer_sequence));+  }++private:+  native_buffer_type buffers_[2];+  std::size_t total_buffer_size_;+};++#endif // defined(ASIO_HAS_STD_ARRAY)++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/buffer_sequence_adapter.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_BUFFER_SEQUENCE_ADAPTER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/buffered_stream_storage.hpp view
@@ -0,0 +1,126 @@+//+// detail/buffered_stream_storage.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP+#define ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/buffer.hpp"+#include "asio/detail/assert.hpp"+#include <cstddef>+#include <cstring>+#include <vector>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class buffered_stream_storage+{+public:+  // The type of the bytes stored in the buffer.+  typedef unsigned char byte_type;++  // The type used for offsets into the buffer.+  typedef std::size_t size_type;++  // Constructor.+  explicit buffered_stream_storage(std::size_t buffer_capacity)+    : begin_offset_(0),+      end_offset_(0),+      buffer_(buffer_capacity)+  {+  }++  /// Clear the buffer.+  void clear()+  {+    begin_offset_ = 0;+    end_offset_ = 0;+  }++  // Return a pointer to the beginning of the unread data.+  mutable_buffer data()+  {+    return asio::buffer(buffer_) + begin_offset_;+  }++  // Return a pointer to the beginning of the unread data.+  const_buffer data() const+  {+    return asio::buffer(buffer_) + begin_offset_;+  }++  // Is there no unread data in the buffer.+  bool empty() const+  {+    return begin_offset_ == end_offset_;+  }++  // Return the amount of unread data the is in the buffer.+  size_type size() const+  {+    return end_offset_ - begin_offset_;+  }++  // Resize the buffer to the specified length.+  void resize(size_type length)+  {+    ASIO_ASSERT(length <= capacity());+    if (begin_offset_ + length <= capacity())+    {+      end_offset_ = begin_offset_ + length;+    }+    else+    {+      using namespace std; // For memmove.+      memmove(&buffer_[0], &buffer_[0] + begin_offset_, size());+      end_offset_ = length;+      begin_offset_ = 0;+    }+  }++  // Return the maximum size for data in the buffer.+  size_type capacity() const+  {+    return buffer_.size();+  }++  // Consume multiple bytes from the beginning of the buffer.+  void consume(size_type count)+  {+    ASIO_ASSERT(begin_offset_ + count <= end_offset_);+    begin_offset_ += count;+    if (empty())+      clear();+  }++private:+  // The offset to the beginning of the unread data.+  size_type begin_offset_;++  // The offset to the end of the unread data.+  size_type end_offset_;+  +  // The data in the buffer.+  std::vector<byte_type> buffer_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_BUFFERED_STREAM_STORAGE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/bulk_executor_op.hpp view
@@ -0,0 +1,88 @@+//+// detail/bulk_executor_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_BULK_EXECUTOR_OP_HPP+#define ASIO_DETAIL_BULK_EXECUTOR_OP_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/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/scheduler_operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename Alloc,+    typename Operation = scheduler_operation>+class bulk_executor_op : public Operation+{+public:+  ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(bulk_executor_op);++  template <typename H>+  bulk_executor_op(ASIO_MOVE_ARG(H) h,+      const Alloc& allocator, std::size_t i)+    : Operation(&bulk_executor_op::do_complete),+      handler_(ASIO_MOVE_CAST(H)(h)),+      allocator_(allocator),+      index_(i)+  {+  }++  static void do_complete(void* owner, Operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    bulk_executor_op* o(static_cast<bulk_executor_op*>(base));+    Alloc allocator(o->allocator_);+    ptr p = { detail::addressof(allocator), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder1<Handler, std::size_t> handler(o->handler_, o->index_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN(());+      asio_handler_invoke_helpers::invoke(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  Alloc allocator_;+  std::size_t index_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_BULK_EXECUTOR_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/call_stack.hpp view
@@ -0,0 +1,125 @@+//+// detail/call_stack.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CALL_STACK_HPP+#define ASIO_DETAIL_CALL_STACK_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/noncopyable.hpp"+#include "asio/detail/tss_ptr.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper class to determine whether or not the current thread is inside an+// invocation of io_context::run() for a specified io_context object.+template <typename Key, typename Value = unsigned char>+class call_stack+{+public:+  // Context class automatically pushes the key/value pair on to the stack.+  class context+    : private noncopyable+  {+  public:+    // Push the key on to the stack.+    explicit context(Key* k)+      : key_(k),+        next_(call_stack<Key, Value>::top_)+    {+      value_ = reinterpret_cast<unsigned char*>(this);+      call_stack<Key, Value>::top_ = this;+    }++    // Push the key/value pair on to the stack.+    context(Key* k, Value& v)+      : key_(k),+        value_(&v),+        next_(call_stack<Key, Value>::top_)+    {+      call_stack<Key, Value>::top_ = this;+    }++    // Pop the key/value pair from the stack.+    ~context()+    {+      call_stack<Key, Value>::top_ = next_;+    }++    // Find the next context with the same key.+    Value* next_by_key() const+    {+      context* elem = next_;+      while (elem)+      {+        if (elem->key_ == key_)+          return elem->value_;+        elem = elem->next_;+      }+      return 0;+    }++  private:+    friend class call_stack<Key, Value>;++    // The key associated with the context.+    Key* key_;++    // The value associated with the context.+    Value* value_;++    // The next element in the stack.+    context* next_;+  };++  friend class context;++  // Determine whether the specified owner is on the stack. Returns address of+  // key if present, 0 otherwise.+  static Value* contains(Key* k)+  {+    context* elem = top_;+    while (elem)+    {+      if (elem->key_ == k)+        return elem->value_;+      elem = elem->next_;+    }+    return 0;+  }++  // Obtain the value at the top of the stack.+  static Value* top()+  {+    context* elem = top_;+    return elem ? elem->value_ : 0;+  }++private:+  // The top of the stack of calls for the current thread.+  static tss_ptr<context> top_;+};++template <typename Key, typename Value>+tss_ptr<typename call_stack<Key, Value>::context>+call_stack<Key, Value>::top_;++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_CALL_STACK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/chrono.hpp view
@@ -0,0 +1,66 @@+//+// detail/chrono.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CHRONO_HPP+#define ASIO_DETAIL_CHRONO_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_CHRONO)+# include <chrono>+#elif defined(ASIO_HAS_BOOST_CHRONO)+# include <boost/chrono/system_clocks.hpp>+#endif // defined(ASIO_HAS_BOOST_CHRONO)++namespace asio {+namespace chrono {++#if defined(ASIO_HAS_STD_CHRONO)+using std::chrono::duration;+using std::chrono::time_point;+using std::chrono::duration_cast;+using std::chrono::nanoseconds;+using std::chrono::microseconds;+using std::chrono::milliseconds;+using std::chrono::seconds;+using std::chrono::minutes;+using std::chrono::hours;+using std::chrono::time_point_cast;+#if defined(ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)+typedef std::chrono::monotonic_clock steady_clock;+#else // defined(ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)+using std::chrono::steady_clock;+#endif // defined(ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK)+using std::chrono::system_clock;+using std::chrono::high_resolution_clock;+#elif defined(ASIO_HAS_BOOST_CHRONO)+using boost::chrono::duration;+using boost::chrono::time_point;+using boost::chrono::duration_cast;+using boost::chrono::nanoseconds;+using boost::chrono::microseconds;+using boost::chrono::milliseconds;+using boost::chrono::seconds;+using boost::chrono::minutes;+using boost::chrono::hours;+using boost::chrono::time_point_cast;+using boost::chrono::system_clock;+using boost::chrono::steady_clock;+using boost::chrono::high_resolution_clock;+#endif // defined(ASIO_HAS_BOOST_CHRONO)++} // namespace chrono+} // namespace asio++#endif // ASIO_DETAIL_CHRONO_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/chrono_time_traits.hpp view
@@ -0,0 +1,190 @@+//+// detail/chrono_time_traits.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP+#define ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/cstdint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper template to compute the greatest common divisor.+template <int64_t v1, int64_t v2>+struct gcd { enum { value = gcd<v2, v1 % v2>::value }; };++template <int64_t v1>+struct gcd<v1, 0> { enum { value = v1 }; };++// Adapts std::chrono clocks for use with a deadline timer.+template <typename Clock, typename WaitTraits>+struct chrono_time_traits+{+  // The clock type.+  typedef Clock clock_type;++  // The duration type of the clock.+  typedef typename clock_type::duration duration_type;++  // The time point type of the clock.+  typedef typename clock_type::time_point time_type;++  // The period of the clock.+  typedef typename duration_type::period period_type;++  // Get the current time.+  static time_type now()+  {+    return clock_type::now();+  }++  // Add a duration to a time.+  static time_type add(const time_type& t, const duration_type& d)+  {+    const time_type epoch;+    if (t >= epoch)+    {+      if ((time_type::max)() - t < d)+        return (time_type::max)();+    }+    else // t < epoch+    {+      if (-(t - (time_type::min)()) > d)+        return (time_type::min)();+    }++    return t + d;+  }++  // Subtract one time from another.+  static duration_type subtract(const time_type& t1, const time_type& t2)+  {+    const time_type epoch;+    if (t1 >= epoch)+    {+      if (t2 >= epoch)+      {+        return t1 - t2;+      }+      else if (t2 == (time_type::min)())+      {+        return (duration_type::max)();+      }+      else if ((time_type::max)() - t1 < epoch - t2)+      {+        return (duration_type::max)();+      }+      else+      {+        return t1 - t2;+      }+    }+    else // t1 < epoch+    {+      if (t2 < epoch)+      {+        return t1 - t2;+      }+      else if (t1 == (time_type::min)())+      {+        return (duration_type::min)();+      }+      else if ((time_type::max)() - t2 < epoch - t1)+      {+        return (duration_type::min)();+      }+      else+      {+        return -(t2 - t1);+      }+    }+  }++  // Test whether one time is less than another.+  static bool less_than(const time_type& t1, const time_type& t2)+  {+    return t1 < t2;+  }++  // Implement just enough of the posix_time::time_duration interface to supply+  // what the timer_queue requires.+  class posix_time_duration+  {+  public:+    explicit posix_time_duration(const duration_type& d)+      : d_(d)+    {+    }++    int64_t ticks() const+    {+      return d_.count();+    }++    int64_t total_seconds() const+    {+      return duration_cast<1, 1>();+    }++    int64_t total_milliseconds() const+    {+      return duration_cast<1, 1000>();+    }++    int64_t total_microseconds() const+    {+      return duration_cast<1, 1000000>();+    }++  private:+    template <int64_t Num, int64_t Den>+    int64_t duration_cast() const+    {+      const int64_t num1 = period_type::num / gcd<period_type::num, Num>::value;+      const int64_t num2 = Num / gcd<period_type::num, Num>::value;++      const int64_t den1 = period_type::den / gcd<period_type::den, Den>::value;+      const int64_t den2 = Den / gcd<period_type::den, Den>::value;++      const int64_t num = num1 * den2;+      const int64_t den = num2 * den1;++      if (num == 1 && den == 1)+        return ticks();+      else if (num != 1 && den == 1)+        return ticks() * num;+      else if (num == 1 && period_type::den != 1)+        return ticks() / den;+      else+        return ticks() * num / den;+    }++    duration_type d_;+  };++  // Convert to POSIX duration type.+  static posix_time_duration to_posix_duration(const duration_type& d)+  {+    return posix_time_duration(WaitTraits::to_wait_duration(d));+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_CHRONO_TIME_TRAITS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/completion_handler.hpp view
@@ -0,0 +1,88 @@+//+// detail/completion_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_COMPLETION_HANDLER_HPP+#define ASIO_DETAIL_COMPLETION_HANDLER_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/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class completion_handler : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(completion_handler);++  completion_handler(Handler& h, const IoExecutor& io_ex)+    : operation(&completion_handler::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(h)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    completion_handler* h(static_cast<completion_handler*>(base));+    ptr p = { asio::detail::addressof(h->handler_), h, h };++    ASIO_HANDLER_COMPLETION((*h));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          h->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    Handler handler(ASIO_MOVE_CAST(Handler)(h->handler_));+    p.h = asio::detail::addressof(handler);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN(());+      w.complete(handler, handler);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_COMPLETION_HANDLER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/concurrency_hint.hpp view
@@ -0,0 +1,94 @@+//+// detail/concurrency_hint.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CONCURRENCY_HINT_HPP+#define ASIO_DETAIL_CONCURRENCY_HINT_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/noncopyable.hpp"++// The concurrency hint ID and mask are used to identify when a "well-known"+// concurrency hint value has been passed to the io_context.+#define ASIO_CONCURRENCY_HINT_ID 0xA5100000u+#define ASIO_CONCURRENCY_HINT_ID_MASK 0xFFFF0000u++// If set, this bit indicates that the scheduler should perform locking.+#define ASIO_CONCURRENCY_HINT_LOCKING_SCHEDULER 0x1u++// If set, this bit indicates that the reactor should perform locking when+// managing descriptor registrations.+#define ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_REGISTRATION 0x2u++// If set, this bit indicates that the reactor should perform locking for I/O.+#define ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_IO 0x4u++// Helper macro to determine if we have a special concurrency hint.+#define ASIO_CONCURRENCY_HINT_IS_SPECIAL(hint) \+  ((static_cast<unsigned>(hint) \+    & ASIO_CONCURRENCY_HINT_ID_MASK) \+      == ASIO_CONCURRENCY_HINT_ID)++// Helper macro to determine if locking is enabled for a given facility.+#define ASIO_CONCURRENCY_HINT_IS_LOCKING(facility, hint) \+  (((static_cast<unsigned>(hint) \+    & (ASIO_CONCURRENCY_HINT_ID_MASK \+      | ASIO_CONCURRENCY_HINT_LOCKING_ ## facility)) \+        ^ ASIO_CONCURRENCY_HINT_ID) != 0)++// This special concurrency hint disables locking in both the scheduler and+// reactor I/O. This hint has the following restrictions:+//+// - Care must be taken to ensure that all operations on the io_context and any+//   of its associated I/O objects (such as sockets and timers) occur in only+//   one thread at a time.+//+// - Asynchronous resolve operations fail with operation_not_supported.+//+// - If a signal_set is used with the io_context, signal_set objects cannot be+//   used with any other io_context in the program.+#define ASIO_CONCURRENCY_HINT_UNSAFE \+  static_cast<int>(ASIO_CONCURRENCY_HINT_ID)++// This special concurrency hint disables locking in the reactor I/O. This hint+// has the following restrictions:+//+// - Care must be taken to ensure that run functions on the io_context, and all+//   operations on the io_context's associated I/O objects (such as sockets and+//   timers), occur in only one thread at a time.+#define ASIO_CONCURRENCY_HINT_UNSAFE_IO \+  static_cast<int>(ASIO_CONCURRENCY_HINT_ID \+      | ASIO_CONCURRENCY_HINT_LOCKING_SCHEDULER \+      | ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_REGISTRATION)++// The special concurrency hint provides full thread safety.+#define ASIO_CONCURRENCY_HINT_SAFE \+  static_cast<int>(ASIO_CONCURRENCY_HINT_ID \+      | ASIO_CONCURRENCY_HINT_LOCKING_SCHEDULER \+      | ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_REGISTRATION \+      | ASIO_CONCURRENCY_HINT_LOCKING_REACTOR_IO)++// This #define may be overridden at compile time to specify a program-wide+// default concurrency hint, used by the zero-argument io_context constructor.+#if !defined(ASIO_CONCURRENCY_HINT_DEFAULT)+# define ASIO_CONCURRENCY_HINT_DEFAULT -1+#endif // !defined(ASIO_CONCURRENCY_HINT_DEFAULT)++// This #define may be overridden at compile time to specify a program-wide+// concurrency hint, used by the one-argument io_context constructor when+// passed a value of 1.+#if !defined(ASIO_CONCURRENCY_HINT_1)+# define ASIO_CONCURRENCY_HINT_1 1+#endif // !defined(ASIO_CONCURRENCY_HINT_DEFAULT)++#endif // ASIO_DETAIL_CONCURRENCY_HINT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_event.hpp view
@@ -0,0 +1,120 @@+//+// detail/conditionally_enabled_event.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CONDITIONALLY_ENABLED_EVENT_HPP+#define ASIO_DETAIL_CONDITIONALLY_ENABLED_EVENT_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/conditionally_enabled_mutex.hpp"+#include "asio/detail/event.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/null_event.hpp"+#include "asio/detail/scoped_lock.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Mutex adapter used to conditionally enable or disable locking.+class conditionally_enabled_event+  : private noncopyable+{+public:+  // Constructor.+  conditionally_enabled_event()+  {+  }++  // Destructor.+  ~conditionally_enabled_event()+  {+  }++  // Signal the event. (Retained for backward compatibility.)+  void signal(conditionally_enabled_mutex::scoped_lock& lock)+  {+    if (lock.mutex_.enabled_)+      event_.signal(lock);+  }++  // Signal all waiters.+  void signal_all(conditionally_enabled_mutex::scoped_lock& lock)+  {+    if (lock.mutex_.enabled_)+      event_.signal_all(lock);+  }++  // Unlock the mutex and signal one waiter.+  void unlock_and_signal_one(+      conditionally_enabled_mutex::scoped_lock& lock)+  {+    if (lock.mutex_.enabled_)+      event_.unlock_and_signal_one(lock);+  }++  // Unlock the mutex and signal one waiter who may destroy us.+  void unlock_and_signal_one_for_destruction(+      conditionally_enabled_mutex::scoped_lock& lock)+  {+    if (lock.mutex_.enabled_)+      event_.unlock_and_signal_one(lock);+  }++  // If there's a waiter, unlock the mutex and signal it.+  bool maybe_unlock_and_signal_one(+      conditionally_enabled_mutex::scoped_lock& lock)+  {+    if (lock.mutex_.enabled_)+      return event_.maybe_unlock_and_signal_one(lock);+    else+      return false;+  }++  // Reset the event.+  void clear(conditionally_enabled_mutex::scoped_lock& lock)+  {+    if (lock.mutex_.enabled_)+      event_.clear(lock);+  }++  // Wait for the event to become signalled.+  void wait(conditionally_enabled_mutex::scoped_lock& lock)+  {+    if (lock.mutex_.enabled_)+      event_.wait(lock);+    else+      null_event().wait(lock);+  }++  // Timed wait for the event to become signalled.+  bool wait_for_usec(+      conditionally_enabled_mutex::scoped_lock& lock, long usec)+  {+    if (lock.mutex_.enabled_)+      return event_.wait_for_usec(lock, usec);+    else+      return null_event().wait_for_usec(lock, usec);+  }++private:+  asio::detail::event event_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_CONDITIONALLY_ENABLED_EVENT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_mutex.hpp view
@@ -0,0 +1,149 @@+//+// detail/conditionally_enabled_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP+#define ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_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/mutex.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/scoped_lock.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Mutex adapter used to conditionally enable or disable locking.+class conditionally_enabled_mutex+  : private noncopyable+{+public:+  // Helper class to lock and unlock a mutex automatically.+  class scoped_lock+    : private noncopyable+  {+  public:+    // Tag type used to distinguish constructors.+    enum adopt_lock_t { adopt_lock };++    // Constructor adopts a lock that is already held.+    scoped_lock(conditionally_enabled_mutex& m, adopt_lock_t)+      : mutex_(m),+        locked_(m.enabled_)+    {+    }++    // Constructor acquires the lock.+    explicit scoped_lock(conditionally_enabled_mutex& m)+      : mutex_(m)+    {+      if (m.enabled_)+      {+        mutex_.mutex_.lock();+        locked_ = true;+      }+      else+        locked_ = false;+    }++    // Destructor releases the lock.+    ~scoped_lock()+    {+      if (locked_)+        mutex_.mutex_.unlock();+    }++    // Explicitly acquire the lock.+    void lock()+    {+      if (mutex_.enabled_ && !locked_)+      {+        mutex_.mutex_.lock();+        locked_ = true;+      }+    }++    // Explicitly release the lock.+    void unlock()+    {+      if (locked_)+      {+        mutex_.unlock();+        locked_ = false;+      }+    }++    // Test whether the lock is held.+    bool locked() const+    {+      return locked_;+    }++    // Get the underlying mutex.+    asio::detail::mutex& mutex()+    {+      return mutex_.mutex_;+    }++  private:+    friend class conditionally_enabled_event;+    conditionally_enabled_mutex& mutex_;+    bool locked_;+  };++  // Constructor.+  explicit conditionally_enabled_mutex(bool enabled)+    : enabled_(enabled)+  {+  }++  // Destructor.+  ~conditionally_enabled_mutex()+  {+  }++  // Determine whether locking is enabled.+  bool enabled() const+  {+    return enabled_;+  }++  // Lock the mutex.+  void lock()+  {+    if (enabled_)+      mutex_.lock();+  }++  // Unlock the mutex.+  void unlock()+  {+    if (enabled_)+      mutex_.unlock();+  }++private:+  friend class scoped_lock;+  friend class conditionally_enabled_event;+  asio::detail::mutex mutex_;+  const bool enabled_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_CONDITIONALLY_ENABLED_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/config.hpp view
@@ -0,0 +1,1822 @@+//+// detail/config.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CONFIG_HPP+#define ASIO_DETAIL_CONFIG_HPP++// boostify: non-boost code starts here+#if !defined(ASIO_STANDALONE)+# if !defined(ASIO_ENABLE_BOOST)+#  if (__cplusplus >= 201103)+#   define ASIO_STANDALONE 1+#  elif defined(_MSC_VER) && defined(_MSVC_LANG)+#   if (_MSC_VER >= 1900) && (_MSVC_LANG >= 201103)+#    define ASIO_STANDALONE 1+#   endif // (_MSC_VER >= 1900) && (_MSVC_LANG >= 201103)+#  endif // defined(_MSC_VER) && defined(_MSVC_LANG)+# endif // !defined(ASIO_ENABLE_BOOST)+#endif // !defined(ASIO_STANDALONE)++// boostify: non-boost code ends here+#if defined(ASIO_STANDALONE)+# define ASIO_DISABLE_BOOST_ARRAY 1+# define ASIO_DISABLE_BOOST_ASSERT 1+# define ASIO_DISABLE_BOOST_BIND 1+# define ASIO_DISABLE_BOOST_CHRONO 1+# define ASIO_DISABLE_BOOST_DATE_TIME 1+# define ASIO_DISABLE_BOOST_LIMITS 1+# define ASIO_DISABLE_BOOST_REGEX 1+# define ASIO_DISABLE_BOOST_STATIC_CONSTANT 1+# define ASIO_DISABLE_BOOST_THROW_EXCEPTION 1+# define ASIO_DISABLE_BOOST_WORKAROUND 1+#else // defined(ASIO_STANDALONE)+# include <boost/config.hpp>+# include <boost/version.hpp>+# define ASIO_HAS_BOOST_CONFIG 1+#endif // defined(ASIO_STANDALONE)++// Default to a header-only implementation. The user must specifically request+// separate compilation by defining either ASIO_SEPARATE_COMPILATION or+// ASIO_DYN_LINK (as a DLL/shared library implies separate compilation).+#if !defined(ASIO_HEADER_ONLY)+# if !defined(ASIO_SEPARATE_COMPILATION)+#  if !defined(ASIO_DYN_LINK)+#   define ASIO_HEADER_ONLY 1+#  endif // !defined(ASIO_DYN_LINK)+# endif // !defined(ASIO_SEPARATE_COMPILATION)+#endif // !defined(ASIO_HEADER_ONLY)++#if defined(ASIO_HEADER_ONLY)+# define ASIO_DECL inline+#else // defined(ASIO_HEADER_ONLY)+# if defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CODEGEARC__)+// We need to import/export our code only if the user has specifically asked+// for it by defining ASIO_DYN_LINK.+#  if defined(ASIO_DYN_LINK)+// Export if this is our own source, otherwise import.+#   if defined(ASIO_SOURCE)+#    define ASIO_DECL __declspec(dllexport)+#   else // defined(ASIO_SOURCE)+#    define ASIO_DECL __declspec(dllimport)+#   endif // defined(ASIO_SOURCE)+#  endif // defined(ASIO_DYN_LINK)+# endif // defined(_MSC_VER) || defined(__BORLANDC__) || defined(__CODEGEARC__)+#endif // defined(ASIO_HEADER_ONLY)++// If ASIO_DECL isn't defined yet define it now.+#if !defined(ASIO_DECL)+# define ASIO_DECL+#endif // !defined(ASIO_DECL)++// Helper macro for documentation.+#define ASIO_UNSPECIFIED(e) e++// Microsoft Visual C++ detection.+#if !defined(ASIO_MSVC)+# if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_MSVC)+#  define ASIO_MSVC BOOST_MSVC+# elif defined(_MSC_VER) && (defined(__INTELLISENSE__) \+      || (!defined(__MWERKS__) && !defined(__EDG_VERSION__)))+#  define ASIO_MSVC _MSC_VER+# endif // defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_MSVC)+#endif // !defined(ASIO_MSVC)++// Clang / libc++ detection.+#if defined(__clang__)+# if (__cplusplus >= 201103)+#  if __has_include(<__config>)+#   include <__config>+#   if defined(_LIBCPP_VERSION)+#    define ASIO_HAS_CLANG_LIBCXX 1+#   endif // defined(_LIBCPP_VERSION)+#  endif // __has_include(<__config>)+# endif // (__cplusplus >= 201103)+#endif // defined(__clang__)++// Android platform detection.+#if defined(__ANDROID__)+# include <android/api-level.h>+#endif // defined(__ANDROID__)++// Support move construction and assignment on compilers known to allow it.+#if !defined(ASIO_HAS_MOVE)+# if !defined(ASIO_DISABLE_MOVE)+#  if defined(__clang__)+#   if __has_feature(__cxx_rvalue_references__)+#    define ASIO_HAS_MOVE 1+#   endif // __has_feature(__cxx_rvalue_references__)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_MOVE 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_MOVE 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+#  if defined(__INTEL_CXX11_MODE__)+#    if defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)+#      define ASIO_HAS_MOVE 1+#    endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1500)+#    if defined(__ICL) && (__ICL >= 1500)+#      define ASIO_HAS_MOVE 1+#    endif // defined(__ICL) && (__ICL >= 1500)+#  endif // defined(__INTEL_CXX11_MODE__)+# endif // !defined(ASIO_DISABLE_MOVE)+#endif // !defined(ASIO_HAS_MOVE)++// If ASIO_MOVE_CAST isn't defined, and move support is available, define+// * ASIO_MOVE_ARG,+// * ASIO_NONDEDUCED_MOVE_ARG, and+// * ASIO_MOVE_CAST+// to take advantage of rvalue references and perfect forwarding.+#if defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST)+# define ASIO_MOVE_ARG(type) type&&+# define ASIO_MOVE_ARG2(type1, type2) type1, type2&&+# define ASIO_NONDEDUCED_MOVE_ARG(type) type&+# define ASIO_MOVE_CAST(type) static_cast<type&&>+# define ASIO_MOVE_CAST2(type1, type2) static_cast<type1, type2&&>+# define ASIO_MOVE_OR_LVALUE(type) static_cast<type&&>+# define ASIO_MOVE_OR_LVALUE_TYPE(type) type+#endif // defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST)++// If ASIO_MOVE_CAST still isn't defined, default to a C++03-compatible+// implementation. Note that older g++ and MSVC versions don't like it when you+// pass a non-member function through a const reference, so for most compilers+// we'll play it safe and stick with the old approach of passing the handler by+// value.+#if !defined(ASIO_MOVE_CAST)+# if defined(__GNUC__)+#  if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4)+#   define ASIO_MOVE_ARG(type) const type&+#  else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4)+#   define ASIO_MOVE_ARG(type) type+#  endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ > 4)+# elif defined(ASIO_MSVC)+#  if (_MSC_VER >= 1400)+#   define ASIO_MOVE_ARG(type) const type&+#  else // (_MSC_VER >= 1400)+#   define ASIO_MOVE_ARG(type) type+#  endif // (_MSC_VER >= 1400)+# else+#  define ASIO_MOVE_ARG(type) type+# endif+# define ASIO_NONDEDUCED_MOVE_ARG(type) const type&+# define ASIO_MOVE_CAST(type) static_cast<const type&>+# define ASIO_MOVE_CAST2(type1, type2) static_cast<const type1, type2&>+# define ASIO_MOVE_OR_LVALUE(type)+# define ASIO_MOVE_OR_LVALUE_TYPE(type) type&+#endif // !defined(ASIO_MOVE_CAST)++// Support variadic templates on compilers known to allow it.+#if !defined(ASIO_HAS_VARIADIC_TEMPLATES)+# if !defined(ASIO_DISABLE_VARIADIC_TEMPLATES)+#  if defined(__clang__)+#   if __has_feature(__cxx_variadic_templates__)+#    define ASIO_HAS_VARIADIC_TEMPLATES 1+#   endif // __has_feature(__cxx_variadic_templates__)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_VARIADIC_TEMPLATES 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900)+#    define ASIO_HAS_VARIADIC_TEMPLATES 1+#   endif // (_MSC_VER >= 1900)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_VARIADIC_TEMPLATES)+#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)+#if !defined(ASIO_ELLIPSIS)+# if defined(ASIO_HAS_VARIADIC_TEMPLATES)+#  define ASIO_ELLIPSIS ...+# else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#  define ASIO_ELLIPSIS+# endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(ASIO_ELLIPSIS)++// Support deleted functions on compilers known to allow it.+#if !defined(ASIO_DELETED)+# if defined(__GNUC__)+#  if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#   if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#    define ASIO_DELETED = delete+#   endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#  endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+# endif // defined(__GNUC__)+# if defined(__clang__)+#  if __has_feature(__cxx_deleted_functions__)+#   define ASIO_DELETED = delete+#  endif // __has_feature(__cxx_deleted_functions__)+# endif // defined(__clang__)+# if defined(ASIO_MSVC)+#  if (_MSC_VER >= 1900)+#   define ASIO_DELETED = delete+#  endif // (_MSC_VER >= 1900)+# endif // defined(ASIO_MSVC)+# if !defined(ASIO_DELETED)+#  define ASIO_DELETED+# endif // !defined(ASIO_DELETED)+#endif // !defined(ASIO_DELETED)++// Support constexpr on compilers known to allow it.+#if !defined(ASIO_HAS_CONSTEXPR)+# if !defined(ASIO_DISABLE_CONSTEXPR)+#  if defined(__clang__)+#   if __has_feature(__cxx_constexpr__)+#    define ASIO_HAS_CONSTEXPR 1+#   endif // __has_feature(__cxx_constexpr__)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_CONSTEXPR 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900)+#    define ASIO_HAS_CONSTEXPR 1+#   endif // (_MSC_VER >= 1900)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_CONSTEXPR)+#endif // !defined(ASIO_HAS_CONSTEXPR)+#if !defined(ASIO_CONSTEXPR)+# if defined(ASIO_HAS_CONSTEXPR)+#  define ASIO_CONSTEXPR constexpr+# else // defined(ASIO_HAS_CONSTEXPR)+#  define ASIO_CONSTEXPR+# endif // defined(ASIO_HAS_CONSTEXPR)+#endif // !defined(ASIO_CONSTEXPR)+#if !defined(ASIO_STATIC_CONSTEXPR)+# if defined(ASIO_HAS_CONSTEXPR)+#  define ASIO_STATIC_CONSTEXPR(type, assignment) \+    static constexpr type assignment+# else // defined(ASIO_HAS_CONSTEXPR)+#  define ASIO_STATIC_CONSTEXPR(type, assignment) \+    static const type assignment+# endif // defined(ASIO_HAS_CONSTEXPR)+#endif // !defined(ASIO_STATIC_CONSTEXPR)+#if !defined(ASIO_STATIC_CONSTEXPR_DEFAULT_INIT)+# if defined(ASIO_HAS_CONSTEXPR)+#  if defined(__GNUC__)+#   if (__GNUC__ >= 8)+#    define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \+      static constexpr const type name{}+#   else // (__GNUC__ >= 8)+#    define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \+      static const type name+#   endif // (__GNUC__ >= 8)+#  elif defined(ASIO_MSVC)+#   define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \+     static const type name+#  else // defined(ASIO_MSVC)+#   define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \+     static constexpr const type name{}+#  endif // defined(ASIO_MSVC)+# else // defined(ASIO_HAS_CONSTEXPR)+#  define ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(type, name) \+    static const type name+# endif // defined(ASIO_HAS_CONSTEXPR)+#endif // !defined(ASIO_STATIC_CONSTEXPR_DEFAULT_INIT)++// Support noexcept on compilers known to allow it.+#if !defined(ASIO_HAS_NOEXCEPT)+# if !defined(ASIO_DISABLE_NOEXCEPT)+#  if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105300)+#   if !defined(BOOST_NO_NOEXCEPT)+#    define ASIO_HAS_NOEXCEPT 1+#   endif // !defined(BOOST_NO_NOEXCEPT)+#   define ASIO_NOEXCEPT BOOST_NOEXCEPT+#   define ASIO_NOEXCEPT_OR_NOTHROW BOOST_NOEXCEPT_OR_NOTHROW+#   define ASIO_NOEXCEPT_IF(c) BOOST_NOEXCEPT_IF(c)+#  elif defined(__clang__)+#   if __has_feature(__cxx_noexcept__)+#    define ASIO_HAS_NOEXCEPT 1+#   endif // __has_feature(__cxx_noexcept__)+#  elif defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#      define ASIO_HAS_NOEXCEPT 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  elif defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900)+#    define ASIO_HAS_NOEXCEPT 1+#   endif // (_MSC_VER >= 1900)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_NOEXCEPT)+# if !defined(ASIO_NOEXCEPT)+# endif // !defined(ASIO_NOEXCEPT)+# if !defined(ASIO_NOEXCEPT_OR_NOTHROW)+# endif // !defined(ASIO_NOEXCEPT_OR_NOTHROW)+#endif // !defined(ASIO_HAS_NOEXCEPT)+#if !defined(ASIO_NOEXCEPT)+# if defined(ASIO_HAS_NOEXCEPT)+#  define ASIO_NOEXCEPT noexcept(true)+# else // defined(ASIO_HAS_NOEXCEPT)+#  define ASIO_NOEXCEPT+# endif // defined(ASIO_HAS_NOEXCEPT)+#endif // !defined(ASIO_NOEXCEPT)+#if !defined(ASIO_NOEXCEPT_OR_NOTHROW)+# if defined(ASIO_HAS_NOEXCEPT)+#  define ASIO_NOEXCEPT_OR_NOTHROW noexcept(true)+# else // defined(ASIO_HAS_NOEXCEPT)+#  define ASIO_NOEXCEPT_OR_NOTHROW throw()+# endif // defined(ASIO_HAS_NOEXCEPT)+#endif // !defined(ASIO_NOEXCEPT_OR_NOTHROW)+#if !defined(ASIO_NOEXCEPT_IF)+# if defined(ASIO_HAS_NOEXCEPT)+#  define ASIO_NOEXCEPT_IF(c) noexcept(c)+# else // defined(ASIO_HAS_NOEXCEPT)+#  define ASIO_NOEXCEPT_IF(c)+# endif // defined(ASIO_HAS_NOEXCEPT)+#endif // !defined(ASIO_NOEXCEPT_IF)++// Support automatic type deduction on compilers known to support it.+#if !defined(ASIO_HAS_DECLTYPE)+# if !defined(ASIO_DISABLE_DECLTYPE)+#  if defined(__clang__)+#   if __has_feature(__cxx_decltype__)+#    define ASIO_HAS_DECLTYPE 1+#   endif // __has_feature(__cxx_decltype__)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_DECLTYPE 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1800)+#    define ASIO_HAS_DECLTYPE 1+#   endif // (_MSC_VER >= 1800)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_DECLTYPE)+#endif // !defined(ASIO_HAS_DECLTYPE)++// Support alias templates on compilers known to allow it.+#if !defined(ASIO_HAS_ALIAS_TEMPLATES)+# if !defined(ASIO_DISABLE_ALIAS_TEMPLATES)+#  if defined(__clang__)+#   if __has_feature(__cxx_alias_templates__)+#    define ASIO_HAS_ALIAS_TEMPLATES 1+#   endif // __has_feature(__cxx_alias_templates__)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_ALIAS_TEMPLATES 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900)+#    define ASIO_HAS_ALIAS_TEMPLATES 1+#   endif // (_MSC_VER >= 1900)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_ALIAS_TEMPLATES)+#endif // !defined(ASIO_HAS_ALIAS_TEMPLATES)++// Support return type deduction on compilers known to allow it.+#if !defined(ASIO_HAS_RETURN_TYPE_DEDUCTION)+# if !defined(ASIO_DISABLE_RETURN_TYPE_DEDUCTION)+#  if defined(__clang__)+#   if __has_feature(__cxx_return_type_deduction__)+#    define ASIO_HAS_RETURN_TYPE_DEDUCTION 1+#   endif // __has_feature(__cxx_return_type_deduction__)+#  elif (__cplusplus >= 201402)+#   define ASIO_HAS_RETURN_TYPE_DEDUCTION 1+#  elif defined(__cpp_return_type_deduction)+#   if (__cpp_return_type_deduction >= 201304)+#    define ASIO_HAS_RETURN_TYPE_DEDUCTION 1+#   endif // (__cpp_return_type_deduction >= 201304)+#  endif // defined(__cpp_return_type_deduction)+# endif // !defined(ASIO_DISABLE_RETURN_TYPE_DEDUCTION)+#endif // !defined(ASIO_HAS_RETURN_TYPE_DEDUCTION)++// Support default function template arguments on compilers known to allow it.+#if !defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS)+# if !defined(ASIO_DISABLE_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS)+#  if (__cplusplus >= 201103)+#   define ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS 1+#  endif // (__cplusplus >= 201103)+# endif // !defined(ASIO_DISABLE_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS)+#endif // !defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS)++// Support concepts on compilers known to allow them.+#if !defined(ASIO_HAS_CONCEPTS)+# if !defined(ASIO_DISABLE_CONCEPTS)+#  if defined(__cpp_concepts)+#   define ASIO_HAS_CONCEPTS 1+#   if (__cpp_concepts >= 201707)+#    define ASIO_CONCEPT concept+#   else // (__cpp_concepts >= 201707)+#    define ASIO_CONCEPT concept bool+#   endif // (__cpp_concepts >= 201707)+#  endif // defined(__cpp_concepts)+# endif // !defined(ASIO_DISABLE_CONCEPTS)+#endif // !defined(ASIO_HAS_CONCEPTS)++// Support template variables on compilers known to allow it.+#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if !defined(ASIO_DISABLE_VARIABLE_TEMPLATES)+#  if defined(__clang__)+#   if (__cplusplus >= 201402)+#    if __has_feature(__cxx_variable_templates__)+#     define ASIO_HAS_VARIABLE_TEMPLATES 1+#    endif // __has_feature(__cxx_variable_templates__)+#   endif // (__cplusplus >= 201402)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if (__GNUC__ >= 6)+#    if (__cplusplus >= 201402)+#     define ASIO_HAS_VARIABLE_TEMPLATES 1+#    endif // (__cplusplus >= 201402)+#   endif // (__GNUC__ >= 6)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1901)+#    define ASIO_HAS_VARIABLE_TEMPLATES 1+#   endif // (_MSC_VER >= 1901)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_VARIABLE_TEMPLATES)+#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++// Support SFINAEd template variables on compilers known to allow it.+#if !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+# if !defined(ASIO_DISABLE_SFINAE_VARIABLE_TEMPLATES)+#  if defined(__clang__)+#   if (__cplusplus >= 201703)+#    if __has_feature(__cxx_variable_templates__)+#     define ASIO_HAS_SFINAE_VARIABLE_TEMPLATES 1+#    endif // __has_feature(__cxx_variable_templates__)+#   endif // (__cplusplus >= 201703)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 8) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 8)+#    if (__cplusplus >= 201402)+#     define ASIO_HAS_SFINAE_VARIABLE_TEMPLATES 1+#    endif // (__cplusplus >= 201402)+#   endif // ((__GNUC__ == 8) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 8)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1901)+#    define ASIO_HAS_SFINAE_VARIABLE_TEMPLATES 1+#   endif // (_MSC_VER >= 1901)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_SFINAE_VARIABLE_TEMPLATES)+#endif // !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++// Support SFINAE use of constant expressions on compilers known to allow it.+#if !defined(ASIO_HAS_CONSTANT_EXPRESSION_SFINAE)+# if !defined(ASIO_DISABLE_CONSTANT_EXPRESSION_SFINAE)+#  if defined(__clang__)+#   if (__cplusplus >= 201402)+#    define ASIO_HAS_CONSTANT_EXPRESSION_SFINAE 1+#   endif // (__cplusplus >= 201402)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if (__GNUC__ >= 7)+#    if (__cplusplus >= 201402)+#     define ASIO_HAS_CONSTANT_EXPRESSION_SFINAE 1+#    endif // (__cplusplus >= 201402)+#   endif // (__GNUC__ >= 7)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1901)+#    define ASIO_HAS_CONSTANT_EXPRESSION_SFINAE 1+#   endif // (_MSC_VER >= 1901)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_CONSTANT_EXPRESSION_SFINAE)+#endif // !defined(ASIO_HAS_CONSTANT_EXPRESSION_SFINAE)++// Enable workarounds for lack of working expression SFINAE.+#if !defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# if !defined(ASIO_DISABLE_WORKING_EXPRESSION_SFINAE)+#  if !defined(ASIO_MSVC)+#   if (__cplusplus >= 201103)+#    define ASIO_HAS_WORKING_EXPRESSION_SFINAE 1+#   endif // (__cplusplus >= 201103)+#  endif // !defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_WORKING_EXPRESSION_SFINAE)+#endif // !defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++// Support ref-qualified functions on compilers known to allow it.+#if !defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+# if !defined(ASIO_DISABLE_REF_QUALIFIED_FUNCTIONS)+#  if defined(__clang__)+#   if __has_feature(__cxx_reference_qualified_functions__)+#    define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1+#   endif // __has_feature(__cxx_reference_qualified_functions__)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900)+#    define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1+#   endif // (_MSC_VER >= 1900)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_REF_QUALIFIED_FUNCTIONS)+#endif // !defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+# if !defined(ASIO_LVALUE_REF_QUAL)+#  define ASIO_LVALUE_REF_QUAL &+# endif // !defined(ASIO_LVALUE_REF_QUAL)+# if !defined(ASIO_RVALUE_REF_QUAL)+#  define ASIO_RVALUE_REF_QUAL &&+# endif // !defined(ASIO_RVALUE_REF_QUAL)+#else // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+# if !defined(ASIO_LVALUE_REF_QUAL)+#  define ASIO_LVALUE_REF_QUAL+# endif // !defined(ASIO_LVALUE_REF_QUAL)+# if !defined(ASIO_RVALUE_REF_QUAL)+#  define ASIO_RVALUE_REF_QUAL+# endif // !defined(ASIO_RVALUE_REF_QUAL)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++// Standard library support for system errors.+#if !defined(ASIO_HAS_STD_SYSTEM_ERROR)+# if !defined(ASIO_DISABLE_STD_SYSTEM_ERROR)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_SYSTEM_ERROR 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<system_error>)+#     define ASIO_HAS_STD_SYSTEM_ERROR 1+#    endif // __has_include(<system_error>)+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_SYSTEM_ERROR 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_SYSTEM_ERROR 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_SYSTEM_ERROR)+#endif // !defined(ASIO_HAS_STD_SYSTEM_ERROR)++// Compliant C++11 compilers put noexcept specifiers on error_category members.+#if !defined(ASIO_ERROR_CATEGORY_NOEXCEPT)+# if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105300)+#  define ASIO_ERROR_CATEGORY_NOEXCEPT BOOST_NOEXCEPT+# elif defined(__clang__)+#  if __has_feature(__cxx_noexcept__)+#   define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)+#  endif // __has_feature(__cxx_noexcept__)+# elif defined(__GNUC__)+#  if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#   if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)+#   endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#  endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+# elif defined(ASIO_MSVC)+#  if (_MSC_VER >= 1900)+#   define ASIO_ERROR_CATEGORY_NOEXCEPT noexcept(true)+#  endif // (_MSC_VER >= 1900)+# endif // defined(ASIO_MSVC)+# if !defined(ASIO_ERROR_CATEGORY_NOEXCEPT)+#  define ASIO_ERROR_CATEGORY_NOEXCEPT+# endif // !defined(ASIO_ERROR_CATEGORY_NOEXCEPT)+#endif // !defined(ASIO_ERROR_CATEGORY_NOEXCEPT)++// Standard library support for arrays.+#if !defined(ASIO_HAS_STD_ARRAY)+# if !defined(ASIO_DISABLE_STD_ARRAY)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_ARRAY 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<array>)+#     define ASIO_HAS_STD_ARRAY 1+#    endif // __has_include(<array>)+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_ARRAY 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1600)+#    define ASIO_HAS_STD_ARRAY 1+#   endif // (_MSC_VER >= 1600)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_ARRAY)+#endif // !defined(ASIO_HAS_STD_ARRAY)++// Standard library support for shared_ptr and weak_ptr.+#if !defined(ASIO_HAS_STD_SHARED_PTR)+# if !defined(ASIO_DISABLE_STD_SHARED_PTR)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_SHARED_PTR 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_STD_SHARED_PTR 1+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_SHARED_PTR 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1600)+#    define ASIO_HAS_STD_SHARED_PTR 1+#   endif // (_MSC_VER >= 1600)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_SHARED_PTR)+#endif // !defined(ASIO_HAS_STD_SHARED_PTR)++// Standard library support for allocator_arg_t.+#if !defined(ASIO_HAS_STD_ALLOCATOR_ARG)+# if !defined(ASIO_DISABLE_STD_ALLOCATOR_ARG)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_ALLOCATOR_ARG 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_STD_ALLOCATOR_ARG 1+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_ALLOCATOR_ARG 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1600)+#    define ASIO_HAS_STD_ALLOCATOR_ARG 1+#   endif // (_MSC_VER >= 1600)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_ALLOCATOR_ARG)+#endif // !defined(ASIO_HAS_STD_ALLOCATOR_ARG)++// Standard library support for atomic operations.+#if !defined(ASIO_HAS_STD_ATOMIC)+# if !defined(ASIO_DISABLE_STD_ATOMIC)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_ATOMIC 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<atomic>)+#     define ASIO_HAS_STD_ATOMIC 1+#    endif // __has_include(<atomic>)+#   elif defined(__apple_build_version__) && defined(_LIBCPP_VERSION)+#    if (__clang_major__ >= 10)+#     if __has_include(<atomic>)+#      define ASIO_HAS_STD_ATOMIC 1+#     endif // __has_include(<atomic>)+#    endif // (__clang_major__ >= 10)+#   endif // defined(__apple_build_version__) && defined(_LIBCPP_VERSION)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_ATOMIC 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_ATOMIC 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_ATOMIC)+#endif // !defined(ASIO_HAS_STD_ATOMIC)++// Standard library support for chrono. Some standard libraries (such as the+// libstdc++ shipped with gcc 4.6) provide monotonic_clock as per early C++0x+// drafts, rather than the eventually standardised name of steady_clock.+#if !defined(ASIO_HAS_STD_CHRONO)+# if !defined(ASIO_DISABLE_STD_CHRONO)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_CHRONO 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<chrono>)+#     define ASIO_HAS_STD_CHRONO 1+#    endif // __has_include(<chrono>)+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_CHRONO 1+#     if ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6))+#      define ASIO_HAS_STD_CHRONO_MONOTONIC_CLOCK 1+#     endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ == 6))+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_CHRONO 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_CHRONO)+#endif // !defined(ASIO_HAS_STD_CHRONO)++// Boost support for chrono.+#if !defined(ASIO_HAS_BOOST_CHRONO)+# if !defined(ASIO_DISABLE_BOOST_CHRONO)+#  if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 104700)+#   define ASIO_HAS_BOOST_CHRONO 1+#  endif // defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 104700)+# endif // !defined(ASIO_DISABLE_BOOST_CHRONO)+#endif // !defined(ASIO_HAS_BOOST_CHRONO)++// Some form of chrono library is available.+#if !defined(ASIO_HAS_CHRONO)+# if defined(ASIO_HAS_STD_CHRONO) \+    || defined(ASIO_HAS_BOOST_CHRONO)+#  define ASIO_HAS_CHRONO 1+# endif // defined(ASIO_HAS_STD_CHRONO)+        // || defined(ASIO_HAS_BOOST_CHRONO)+#endif // !defined(ASIO_HAS_CHRONO)++// Boost support for the DateTime library.+#if !defined(ASIO_HAS_BOOST_DATE_TIME)+# if !defined(ASIO_DISABLE_BOOST_DATE_TIME)+#  define ASIO_HAS_BOOST_DATE_TIME 1+# endif // !defined(ASIO_DISABLE_BOOST_DATE_TIME)+#endif // !defined(ASIO_HAS_BOOST_DATE_TIME)++// Standard library support for addressof.+#if !defined(ASIO_HAS_STD_ADDRESSOF)+# if !defined(ASIO_DISABLE_STD_ADDRESSOF)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_ADDRESSOF 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_STD_ADDRESSOF 1+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_ADDRESSOF 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_ADDRESSOF 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_ADDRESSOF)+#endif // !defined(ASIO_HAS_STD_ADDRESSOF)++// Standard library support for the function class.+#if !defined(ASIO_HAS_STD_FUNCTION)+# if !defined(ASIO_DISABLE_STD_FUNCTION)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_FUNCTION 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_STD_FUNCTION 1+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_FUNCTION 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_FUNCTION 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_FUNCTION)+#endif // !defined(ASIO_HAS_STD_FUNCTION)++// Standard library support for type traits.+#if !defined(ASIO_HAS_STD_TYPE_TRAITS)+# if !defined(ASIO_DISABLE_STD_TYPE_TRAITS)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_TYPE_TRAITS 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<type_traits>)+#     define ASIO_HAS_STD_TYPE_TRAITS 1+#    endif // __has_include(<type_traits>)+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_TYPE_TRAITS 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_TYPE_TRAITS 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_TYPE_TRAITS)+#endif // !defined(ASIO_HAS_STD_TYPE_TRAITS)++// Standard library support for the nullptr_t type.+#if !defined(ASIO_HAS_NULLPTR)+# if !defined(ASIO_DISABLE_NULLPTR)+#  if defined(__clang__)+#   if __has_feature(__cxx_nullptr__)+#    define ASIO_HAS_NULLPTR 1+#   endif // __has_feature(__cxx_nullptr__)+#  elif defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_NULLPTR 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_NULLPTR 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_NULLPTR)+#endif // !defined(ASIO_HAS_NULLPTR)++// Standard library support for the C++11 allocator additions.+#if !defined(ASIO_HAS_CXX11_ALLOCATORS)+# if !defined(ASIO_DISABLE_CXX11_ALLOCATORS)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_CXX11_ALLOCATORS 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_CXX11_ALLOCATORS 1+#   endif // (__cplusplus >= 201103)+#  elif defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_CXX11_ALLOCATORS 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1800)+#    define ASIO_HAS_CXX11_ALLOCATORS 1+#   endif // (_MSC_VER >= 1800)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_CXX11_ALLOCATORS)+#endif // !defined(ASIO_HAS_CXX11_ALLOCATORS)++// Standard library support for the cstdint header.+#if !defined(ASIO_HAS_CSTDINT)+# if !defined(ASIO_DISABLE_CSTDINT)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_CSTDINT 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_CSTDINT 1+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_CSTDINT 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_CSTDINT 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_CSTDINT)+#endif // !defined(ASIO_HAS_CSTDINT)++// Standard library support for the thread class.+#if !defined(ASIO_HAS_STD_THREAD)+# if !defined(ASIO_DISABLE_STD_THREAD)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_THREAD 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<thread>)+#     define ASIO_HAS_STD_THREAD 1+#    endif // __has_include(<thread>)+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_THREAD 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_THREAD 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_THREAD)+#endif // !defined(ASIO_HAS_STD_THREAD)++// Standard library support for the mutex and condition variable classes.+#if !defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)+# if !defined(ASIO_DISABLE_STD_MUTEX_AND_CONDVAR)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<mutex>)+#     define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1+#    endif // __has_include(<mutex>)+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_MUTEX_AND_CONDVAR)+#endif // !defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)++// Standard library support for the call_once function.+#if !defined(ASIO_HAS_STD_CALL_ONCE)+# if !defined(ASIO_DISABLE_STD_CALL_ONCE)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_CALL_ONCE 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<mutex>)+#     define ASIO_HAS_STD_CALL_ONCE 1+#    endif // __has_include(<mutex>)+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_CALL_ONCE 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_CALL_ONCE 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_CALL_ONCE)+#endif // !defined(ASIO_HAS_STD_CALL_ONCE)++// Standard library support for futures.+#if !defined(ASIO_HAS_STD_FUTURE)+# if !defined(ASIO_DISABLE_STD_FUTURE)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_FUTURE 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<future>)+#     define ASIO_HAS_STD_FUTURE 1+#    endif // __has_include(<future>)+#   endif // (__cplusplus >= 201103)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_FUTURE 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_FUTURE 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_FUTURE)+#endif // !defined(ASIO_HAS_STD_FUTURE)++// Standard library support for std::string_view.+#if !defined(ASIO_HAS_STD_STRING_VIEW)+# if !defined(ASIO_DISABLE_STD_STRING_VIEW)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    if (__cplusplus >= 201402)+#     if __has_include(<string_view>)+#      define ASIO_HAS_STD_STRING_VIEW 1+#     endif // __has_include(<string_view>)+#    endif // (__cplusplus >= 201402)+#   else // defined(ASIO_HAS_CLANG_LIBCXX)+#    if (__cplusplus >= 201703)+#     if __has_include(<string_view>)+#      define ASIO_HAS_STD_STRING_VIEW 1+#     endif // __has_include(<string_view>)+#    endif // (__cplusplus >= 201703)+#   endif // defined(ASIO_HAS_CLANG_LIBCXX)+#  elif defined(__GNUC__)+#   if (__GNUC__ >= 7)+#    if (__cplusplus >= 201703)+#     define ASIO_HAS_STD_STRING_VIEW 1+#    endif // (__cplusplus >= 201703)+#   endif // (__GNUC__ >= 7)+#  elif defined(ASIO_MSVC)+#   if (_MSC_VER >= 1910 && _MSVC_LANG >= 201703)+#    define ASIO_HAS_STD_STRING_VIEW 1+#   endif // (_MSC_VER >= 1910 && _MSVC_LANG >= 201703)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_STRING_VIEW)+#endif // !defined(ASIO_HAS_STD_STRING_VIEW)++// Standard library support for std::experimental::string_view.+#if !defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)+# if !defined(ASIO_DISABLE_STD_EXPERIMENTAL_STRING_VIEW)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    if (_LIBCPP_VERSION < 7000)+#     if (__cplusplus >= 201402)+#      if __has_include(<experimental/string_view>)+#       define ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1+#      endif // __has_include(<experimental/string_view>)+#     endif // (__cplusplus >= 201402)+#    endif // (_LIBCPP_VERSION < 7000)+#   else // defined(ASIO_HAS_CLANG_LIBCXX)+#    if (__cplusplus >= 201402)+#     if __has_include(<experimental/string_view>)+#      define ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1+#     endif // __has_include(<experimental/string_view>)+#    endif // (__cplusplus >= 201402)+#   endif // // defined(ASIO_HAS_CLANG_LIBCXX)+#  endif // defined(__clang__)+#  if defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201402)+#     define ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1+#    endif // (__cplusplus >= 201402)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+# endif // !defined(ASIO_DISABLE_STD_EXPERIMENTAL_STRING_VIEW)+#endif // !defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)++// Standard library has a string_view that we can use.+#if !defined(ASIO_HAS_STRING_VIEW)+# if !defined(ASIO_DISABLE_STRING_VIEW)+#  if defined(ASIO_HAS_STD_STRING_VIEW)+#   define ASIO_HAS_STRING_VIEW 1+#  elif defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)+#   define ASIO_HAS_STRING_VIEW 1+#  endif // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)+# endif // !defined(ASIO_DISABLE_STRING_VIEW)+#endif // !defined(ASIO_HAS_STRING_VIEW)++// Standard library support for iostream move construction and assignment.+#if !defined(ASIO_HAS_STD_IOSTREAM_MOVE)+# if !defined(ASIO_DISABLE_STD_IOSTREAM_MOVE)+#  if defined(__GNUC__)+#   if (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_IOSTREAM_MOVE 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_IOSTREAM_MOVE 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_IOSTREAM_MOVE)+#endif // !defined(ASIO_HAS_STD_IOSTREAM_MOVE)++// Standard library has invoke_result (which supersedes result_of).+#if !defined(ASIO_HAS_STD_INVOKE_RESULT)+# if !defined(ASIO_DISABLE_STD_INVOKE_RESULT)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1911 && _MSVC_LANG >= 201703)+#    define ASIO_HAS_STD_INVOKE_RESULT 1+#   endif // (_MSC_VER >= 1911 && _MSVC_LANG >= 201703)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_INVOKE_RESULT)+#endif // !defined(ASIO_HAS_STD_INVOKE_RESULT)++// Standard library support for std::exception_ptr and std::current_exception.+#if !defined(ASIO_HAS_STD_EXCEPTION_PTR)+# if !defined(ASIO_DISABLE_STD_EXCEPTION_PTR)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_EXCEPTION_PTR 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_STD_EXCEPTION_PTR 1+#   endif // (__cplusplus >= 201103)+#  elif defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_EXCEPTION_PTR 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1800)+#    define ASIO_HAS_STD_EXCEPTION_PTR 1+#   endif // (_MSC_VER >= 1800)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_EXCEPTION_PTR)+#endif // !defined(ASIO_HAS_STD_EXCEPTION_PTR)++// Standard library support for std::nested_exception.+#if !defined(ASIO_HAS_STD_NESTED_EXCEPTION)+# if !defined(ASIO_DISABLE_STD_NESTED_EXCEPTION)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_NESTED_EXCEPTION 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_STD_NESTED_EXCEPTION 1+#   endif // (__cplusplus >= 201103)+#  elif defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_NESTED_EXCEPTION 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900)+#    define ASIO_HAS_STD_NESTED_EXCEPTION 1+#   endif // (_MSC_VER >= 1900)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_NESTED_EXCEPTION)+#endif // !defined(ASIO_HAS_STD_NESTED_EXCEPTION)++// Standard library support for std::any.+#if !defined(ASIO_HAS_STD_ANY)+# if !defined(ASIO_DISABLE_STD_ANY)+#  if defined(__clang__)+#   if (__cplusplus >= 201703)+#    if __has_include(<any>)+#     define ASIO_HAS_STD_ANY 1+#    endif // __has_include(<any>)+#   endif // (__cplusplus >= 201703)+#  elif defined(__GNUC__)+#   if (__GNUC__ >= 7)+#    if (__cplusplus >= 201703)+#     define ASIO_HAS_STD_ANY 1+#    endif // (__cplusplus >= 201703)+#   endif // (__GNUC__ >= 7)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703)+#    define ASIO_HAS_STD_ANY 1+#   endif // (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_ANY)+#endif // !defined(ASIO_HAS_STD_ANY)++// Standard library support for std::source_location.+#if !defined(ASIO_HAS_STD_SOURCE_LOCATION)+# if !defined(ASIO_DISABLE_STD_SOURCE_LOCATION)+// ...+# endif // !defined(ASIO_DISABLE_STD_SOURCE_LOCATION)+#endif // !defined(ASIO_HAS_STD_SOURCE_LOCATION)++// Standard library support for std::experimental::source_location.+#if !defined(ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION)+# if !defined(ASIO_DISABLE_STD_EXPERIMENTAL_SOURCE_LOCATION)+#  if defined(__GNUC__)+#   if (__cplusplus >= 201709)+#    if __has_include(<experimental/source_location>)+#     define ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION 1+#    endif // __has_include(<experimental/source_location>)+#   endif // (__cplusplus >= 201709)+#  endif // defined(__GNUC__)+# endif // !defined(ASIO_DISABLE_STD_EXPERIMENTAL_SOURCE_LOCATION)+#endif // !defined(ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION)++// Standard library has a source_location that we can use.+#if !defined(ASIO_HAS_SOURCE_LOCATION)+# if !defined(ASIO_DISABLE_SOURCE_LOCATION)+#  if defined(ASIO_HAS_STD_SOURCE_LOCATION)+#   define ASIO_HAS_SOURCE_LOCATION 1+#  elif defined(ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION)+#   define ASIO_HAS_SOURCE_LOCATION 1+#  endif // defined(ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION)+# endif // !defined(ASIO_DISABLE_SOURCE_LOCATION)+#endif // !defined(ASIO_HAS_SOURCE_LOCATION)++// Windows App target. Windows but with a limited API.+#if !defined(ASIO_WINDOWS_APP)+# if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0603)+#  include <winapifamily.h>+#  if (WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) \+       || WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_TV_TITLE)) \+   && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)+#   define ASIO_WINDOWS_APP 1+#  endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)+         // && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)+# endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0603)+#endif // !defined(ASIO_WINDOWS_APP)++// Legacy WinRT target. Windows App is preferred.+#if !defined(ASIO_WINDOWS_RUNTIME)+# if !defined(ASIO_WINDOWS_APP)+#  if defined(__cplusplus_winrt)+#   include <winapifamily.h>+#   if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP) \+    && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)+#    define ASIO_WINDOWS_RUNTIME 1+#   endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)+          // && !WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)+#  endif // defined(__cplusplus_winrt)+# endif // !defined(ASIO_WINDOWS_APP)+#endif // !defined(ASIO_WINDOWS_RUNTIME)++// Windows target. Excludes WinRT but includes Windows App targets.+#if !defined(ASIO_WINDOWS)+# if !defined(ASIO_WINDOWS_RUNTIME)+#  if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS)+#   define ASIO_WINDOWS 1+#  elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__)+#   define ASIO_WINDOWS 1+#  elif defined(ASIO_WINDOWS_APP)+#   define ASIO_WINDOWS 1+#  endif // defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_WINDOWS)+# endif // !defined(ASIO_WINDOWS_RUNTIME)+#endif // !defined(ASIO_WINDOWS)++// Windows: target OS version.+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# if !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)+#  if defined(_MSC_VER) || (defined(__BORLANDC__) && !defined(__clang__))+#   pragma message( \+  "Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately. For example:\n"\+  "- add -D_WIN32_WINNT=0x0601 to the compiler command line; or\n"\+  "- add _WIN32_WINNT=0x0601 to your project's Preprocessor Definitions.\n"\+  "Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).")+#  else // defined(_MSC_VER) || (defined(__BORLANDC__) && !defined(__clang__))+#   warning Please define _WIN32_WINNT or _WIN32_WINDOWS appropriately.+#   warning For example, add -D_WIN32_WINNT=0x0601 to the compiler command line.+#   warning Assuming _WIN32_WINNT=0x0601 (i.e. Windows 7 target).+#  endif // defined(_MSC_VER) || (defined(__BORLANDC__) && !defined(__clang__))+#  define _WIN32_WINNT 0x0601+# endif // !defined(_WIN32_WINNT) && !defined(_WIN32_WINDOWS)+# if defined(_MSC_VER)+#  if defined(_WIN32) && !defined(WIN32)+#   if !defined(_WINSOCK2API_)+#    define WIN32 // Needed for correct types in winsock2.h+#   else // !defined(_WINSOCK2API_)+#    error Please define the macro WIN32 in your compiler options+#   endif // !defined(_WINSOCK2API_)+#  endif // defined(_WIN32) && !defined(WIN32)+# endif // defined(_MSC_VER)+# if defined(__BORLANDC__)+#  if defined(__WIN32__) && !defined(WIN32)+#   if !defined(_WINSOCK2API_)+#    define WIN32 // Needed for correct types in winsock2.h+#   else // !defined(_WINSOCK2API_)+#    error Please define the macro WIN32 in your compiler options+#   endif // !defined(_WINSOCK2API_)+#  endif // defined(__WIN32__) && !defined(WIN32)+# endif // defined(__BORLANDC__)+# if defined(__CYGWIN__)+#  if !defined(__USE_W32_SOCKETS)+#   error You must add -D__USE_W32_SOCKETS to your compiler options.+#  endif // !defined(__USE_W32_SOCKETS)+# endif // defined(__CYGWIN__)+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++// Windows: minimise header inclusion.+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# if !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)+#  if !defined(WIN32_LEAN_AND_MEAN)+#   define WIN32_LEAN_AND_MEAN+#  endif // !defined(WIN32_LEAN_AND_MEAN)+# endif // !defined(ASIO_NO_WIN32_LEAN_AND_MEAN)+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++// Windows: suppress definition of "min" and "max" macros.+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# if !defined(ASIO_NO_NOMINMAX)+#  if !defined(NOMINMAX)+#   define NOMINMAX 1+#  endif // !defined(NOMINMAX)+# endif // !defined(ASIO_NO_NOMINMAX)+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++// Windows: IO Completion Ports.+#if !defined(ASIO_HAS_IOCP)+# if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+#  if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)+#   if !defined(UNDER_CE) && !defined(ASIO_WINDOWS_APP)+#    if !defined(ASIO_DISABLE_IOCP)+#     define ASIO_HAS_IOCP 1+#    endif // !defined(ASIO_DISABLE_IOCP)+#   endif // !defined(UNDER_CE) && !defined(ASIO_WINDOWS_APP)+#  endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0400)+# endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+#endif // !defined(ASIO_HAS_IOCP)++// On POSIX (and POSIX-like) platforms we need to include unistd.h in order to+// get access to the various platform feature macros, e.g. to be able to test+// for threads support.+#if !defined(ASIO_HAS_UNISTD_H)+# if !defined(ASIO_HAS_BOOST_CONFIG)+#  if defined(unix) \+   || defined(__unix) \+   || defined(_XOPEN_SOURCE) \+   || defined(_POSIX_SOURCE) \+   || (defined(__MACH__) && defined(__APPLE__)) \+   || defined(__FreeBSD__) \+   || defined(__NetBSD__) \+   || defined(__OpenBSD__) \+   || defined(__linux__) \+   || defined(__HAIKU__)+#   define ASIO_HAS_UNISTD_H 1+#  endif+# endif // !defined(ASIO_HAS_BOOST_CONFIG)+#endif // !defined(ASIO_HAS_UNISTD_H)+#if defined(ASIO_HAS_UNISTD_H)+# include <unistd.h>+#endif // defined(ASIO_HAS_UNISTD_H)++// Linux: epoll, eventfd and timerfd.+#if defined(__linux__)+# include <linux/version.h>+# if !defined(ASIO_HAS_EPOLL)+#  if !defined(ASIO_DISABLE_EPOLL)+#   if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)+#    define ASIO_HAS_EPOLL 1+#   endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,45)+#  endif // !defined(ASIO_DISABLE_EPOLL)+# endif // !defined(ASIO_HAS_EPOLL)+# if !defined(ASIO_HAS_EVENTFD)+#  if !defined(ASIO_DISABLE_EVENTFD)+#   if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)+#    define ASIO_HAS_EVENTFD 1+#   endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,22)+#  endif // !defined(ASIO_DISABLE_EVENTFD)+# endif // !defined(ASIO_HAS_EVENTFD)+# if !defined(ASIO_HAS_TIMERFD)+#  if defined(ASIO_HAS_EPOLL)+#   if (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)+#    define ASIO_HAS_TIMERFD 1+#   endif // (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 8)+#  endif // defined(ASIO_HAS_EPOLL)+# endif // !defined(ASIO_HAS_TIMERFD)+#endif // defined(__linux__)++// Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue.+#if (defined(__MACH__) && defined(__APPLE__)) \+  || defined(__FreeBSD__) \+  || defined(__NetBSD__) \+  || defined(__OpenBSD__)+# if !defined(ASIO_HAS_KQUEUE)+#  if !defined(ASIO_DISABLE_KQUEUE)+#   define ASIO_HAS_KQUEUE 1+#  endif // !defined(ASIO_DISABLE_KQUEUE)+# endif // !defined(ASIO_HAS_KQUEUE)+#endif // (defined(__MACH__) && defined(__APPLE__))+       //   || defined(__FreeBSD__)+       //   || defined(__NetBSD__)+       //   || defined(__OpenBSD__)++// Solaris: /dev/poll.+#if defined(__sun)+# if !defined(ASIO_HAS_DEV_POLL)+#  if !defined(ASIO_DISABLE_DEV_POLL)+#   define ASIO_HAS_DEV_POLL 1+#  endif // !defined(ASIO_DISABLE_DEV_POLL)+# endif // !defined(ASIO_HAS_DEV_POLL)+#endif // defined(__sun)++// Serial ports.+#if !defined(ASIO_HAS_SERIAL_PORT)+# if defined(ASIO_HAS_IOCP) \+  || !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+#  if !defined(__SYMBIAN32__)+#   if !defined(ASIO_DISABLE_SERIAL_PORT)+#    define ASIO_HAS_SERIAL_PORT 1+#   endif // !defined(ASIO_DISABLE_SERIAL_PORT)+#  endif // !defined(__SYMBIAN32__)+# endif // defined(ASIO_HAS_IOCP)+        //   || !defined(ASIO_WINDOWS)+        //   && !defined(ASIO_WINDOWS_RUNTIME)+        //   && !defined(__CYGWIN__)+#endif // !defined(ASIO_HAS_SERIAL_PORT)++// Windows: stream handles.+#if !defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)+# if !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE)+#  if defined(ASIO_HAS_IOCP)+#   define ASIO_HAS_WINDOWS_STREAM_HANDLE 1+#  endif // defined(ASIO_HAS_IOCP)+# endif // !defined(ASIO_DISABLE_WINDOWS_STREAM_HANDLE)+#endif // !defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)++// Windows: random access handles.+#if !defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)+# if !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)+#  if defined(ASIO_HAS_IOCP)+#   define ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE 1+#  endif // defined(ASIO_HAS_IOCP)+# endif // !defined(ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE)+#endif // !defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)++// Windows: object handles.+#if !defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE)+# if !defined(ASIO_DISABLE_WINDOWS_OBJECT_HANDLE)+#  if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+#   if !defined(UNDER_CE) && !defined(ASIO_WINDOWS_APP)+#    define ASIO_HAS_WINDOWS_OBJECT_HANDLE 1+#   endif // !defined(UNDER_CE) && !defined(ASIO_WINDOWS_APP)+#  endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# endif // !defined(ASIO_DISABLE_WINDOWS_OBJECT_HANDLE)+#endif // !defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE)++// Windows: OVERLAPPED wrapper.+#if !defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR)+# if !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)+#  if defined(ASIO_HAS_IOCP)+#   define ASIO_HAS_WINDOWS_OVERLAPPED_PTR 1+#  endif // defined(ASIO_HAS_IOCP)+# endif // !defined(ASIO_DISABLE_WINDOWS_OVERLAPPED_PTR)+#endif // !defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR)++// POSIX: stream-oriented file descriptors.+#if !defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)+# if !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)+#  if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+#   define ASIO_HAS_POSIX_STREAM_DESCRIPTOR 1+#  endif // !defined(ASIO_WINDOWS)+         //   && !defined(ASIO_WINDOWS_RUNTIME)+         //   && !defined(__CYGWIN__)+# endif // !defined(ASIO_DISABLE_POSIX_STREAM_DESCRIPTOR)+#endif // !defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)++// UNIX domain sockets.+#if !defined(ASIO_HAS_LOCAL_SOCKETS)+# if !defined(ASIO_DISABLE_LOCAL_SOCKETS)+#  if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+#   define ASIO_HAS_LOCAL_SOCKETS 1+#  endif // !defined(ASIO_WINDOWS)+         //   && !defined(ASIO_WINDOWS_RUNTIME)+         //   && !defined(__CYGWIN__)+# endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS)+#endif // !defined(ASIO_HAS_LOCAL_SOCKETS)++// Can use sigaction() instead of signal().+#if !defined(ASIO_HAS_SIGACTION)+# if !defined(ASIO_DISABLE_SIGACTION)+#  if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+#   define ASIO_HAS_SIGACTION 1+#  endif // !defined(ASIO_WINDOWS)+         //   && !defined(ASIO_WINDOWS_RUNTIME)+         //   && !defined(__CYGWIN__)+# endif // !defined(ASIO_DISABLE_SIGACTION)+#endif // !defined(ASIO_HAS_SIGACTION)++// Can use signal().+#if !defined(ASIO_HAS_SIGNAL)+# if !defined(ASIO_DISABLE_SIGNAL)+#  if !defined(UNDER_CE)+#   define ASIO_HAS_SIGNAL 1+#  endif // !defined(UNDER_CE)+# endif // !defined(ASIO_DISABLE_SIGNAL)+#endif // !defined(ASIO_HAS_SIGNAL)++// Can use getaddrinfo() and getnameinfo().+#if !defined(ASIO_HAS_GETADDRINFO)+# if !defined(ASIO_DISABLE_GETADDRINFO)+#  if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+#   if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0501)+#    define ASIO_HAS_GETADDRINFO 1+#   elif defined(UNDER_CE)+#    define ASIO_HAS_GETADDRINFO 1+#   endif // defined(UNDER_CE)+#  elif defined(__MACH__) && defined(__APPLE__)+#   if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)+#    if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)+#     define ASIO_HAS_GETADDRINFO 1+#    endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 1050)+#   else // defined(__MAC_OS_X_VERSION_MIN_REQUIRED)+#    define ASIO_HAS_GETADDRINFO 1+#   endif // defined(__MAC_OS_X_VERSION_MIN_REQUIRED)+#  else // defined(__MACH__) && defined(__APPLE__)+#   define ASIO_HAS_GETADDRINFO 1+#  endif // defined(__MACH__) && defined(__APPLE__)+# endif // !defined(ASIO_DISABLE_GETADDRINFO)+#endif // !defined(ASIO_HAS_GETADDRINFO)++// Whether standard iostreams are disabled.+#if !defined(ASIO_NO_IOSTREAM)+# if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_NO_IOSTREAM)+#  define ASIO_NO_IOSTREAM 1+# endif // !defined(BOOST_NO_IOSTREAM)+#endif // !defined(ASIO_NO_IOSTREAM)++// Whether exception handling is disabled.+#if !defined(ASIO_NO_EXCEPTIONS)+# if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_NO_EXCEPTIONS)+#  define ASIO_NO_EXCEPTIONS 1+# endif // !defined(BOOST_NO_EXCEPTIONS)+#endif // !defined(ASIO_NO_EXCEPTIONS)++// Whether the typeid operator is supported.+#if !defined(ASIO_NO_TYPEID)+# if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_NO_TYPEID)+#  define ASIO_NO_TYPEID 1+# endif // !defined(BOOST_NO_TYPEID)+#endif // !defined(ASIO_NO_TYPEID)++// Threads.+#if !defined(ASIO_HAS_THREADS)+# if !defined(ASIO_DISABLE_THREADS)+#  if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_THREADS)+#   define ASIO_HAS_THREADS 1+#  elif defined(__GNUC__) && !defined(__MINGW32__) \+     && !defined(linux) && !defined(__linux) && !defined(__linux__)+#   define ASIO_HAS_THREADS 1+#  elif defined(_MT) || defined(__MT__)+#   define ASIO_HAS_THREADS 1+#  elif defined(_REENTRANT)+#   define ASIO_HAS_THREADS 1+#  elif defined(__APPLE__)+#   define ASIO_HAS_THREADS 1+#  elif defined(__HAIKU__)+#   define ASIO_HAS_THREADS 1+#  elif defined(_POSIX_THREADS) && (_POSIX_THREADS + 0 >= 0)+#   define ASIO_HAS_THREADS 1+#  elif defined(_PTHREADS)+#   define ASIO_HAS_THREADS 1+#  endif // defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_THREADS)+# endif // !defined(ASIO_DISABLE_THREADS)+#endif // !defined(ASIO_HAS_THREADS)++// POSIX threads.+#if !defined(ASIO_HAS_PTHREADS)+# if defined(ASIO_HAS_THREADS)+#  if defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS)+#   define ASIO_HAS_PTHREADS 1+#  elif defined(_POSIX_THREADS) && (_POSIX_THREADS + 0 >= 0)+#   define ASIO_HAS_PTHREADS 1+#  elif defined(__HAIKU__)+#   define ASIO_HAS_PTHREADS 1+#  endif // defined(ASIO_HAS_BOOST_CONFIG) && defined(BOOST_HAS_PTHREADS)+# endif // defined(ASIO_HAS_THREADS)+#endif // !defined(ASIO_HAS_PTHREADS)++// Helper to prevent macro expansion.+#define ASIO_PREVENT_MACRO_SUBSTITUTION++// Helper to define in-class constants.+#if !defined(ASIO_STATIC_CONSTANT)+# if !defined(ASIO_DISABLE_BOOST_STATIC_CONSTANT)+#  define ASIO_STATIC_CONSTANT(type, assignment) \+    BOOST_STATIC_CONSTANT(type, assignment)+# else // !defined(ASIO_DISABLE_BOOST_STATIC_CONSTANT)+#  define ASIO_STATIC_CONSTANT(type, assignment) \+    static const type assignment+# endif // !defined(ASIO_DISABLE_BOOST_STATIC_CONSTANT)+#endif // !defined(ASIO_STATIC_CONSTANT)++// Boost array library.+#if !defined(ASIO_HAS_BOOST_ARRAY)+# if !defined(ASIO_DISABLE_BOOST_ARRAY)+#  define ASIO_HAS_BOOST_ARRAY 1+# endif // !defined(ASIO_DISABLE_BOOST_ARRAY)+#endif // !defined(ASIO_HAS_BOOST_ARRAY)++// Boost assert macro.+#if !defined(ASIO_HAS_BOOST_ASSERT)+# if !defined(ASIO_DISABLE_BOOST_ASSERT)+#  define ASIO_HAS_BOOST_ASSERT 1+# endif // !defined(ASIO_DISABLE_BOOST_ASSERT)+#endif // !defined(ASIO_HAS_BOOST_ASSERT)++// Boost limits header.+#if !defined(ASIO_HAS_BOOST_LIMITS)+# if !defined(ASIO_DISABLE_BOOST_LIMITS)+#  define ASIO_HAS_BOOST_LIMITS 1+# endif // !defined(ASIO_DISABLE_BOOST_LIMITS)+#endif // !defined(ASIO_HAS_BOOST_LIMITS)++// Boost throw_exception function.+#if !defined(ASIO_HAS_BOOST_THROW_EXCEPTION)+# if !defined(ASIO_DISABLE_BOOST_THROW_EXCEPTION)+#  define ASIO_HAS_BOOST_THROW_EXCEPTION 1+# endif // !defined(ASIO_DISABLE_BOOST_THROW_EXCEPTION)+#endif // !defined(ASIO_HAS_BOOST_THROW_EXCEPTION)++// Boost regex library.+#if !defined(ASIO_HAS_BOOST_REGEX)+# if !defined(ASIO_DISABLE_BOOST_REGEX)+#  define ASIO_HAS_BOOST_REGEX 1+# endif // !defined(ASIO_DISABLE_BOOST_REGEX)+#endif // !defined(ASIO_HAS_BOOST_REGEX)++// Boost bind function.+#if !defined(ASIO_HAS_BOOST_BIND)+# if !defined(ASIO_DISABLE_BOOST_BIND)+#  define ASIO_HAS_BOOST_BIND 1+# endif // !defined(ASIO_DISABLE_BOOST_BIND)+#endif // !defined(ASIO_HAS_BOOST_BIND)++// Boost's BOOST_WORKAROUND macro.+#if !defined(ASIO_HAS_BOOST_WORKAROUND)+# if !defined(ASIO_DISABLE_BOOST_WORKAROUND)+#  define ASIO_HAS_BOOST_WORKAROUND 1+# endif // !defined(ASIO_DISABLE_BOOST_WORKAROUND)+#endif // !defined(ASIO_HAS_BOOST_WORKAROUND)++// Microsoft Visual C++'s secure C runtime library.+#if !defined(ASIO_HAS_SECURE_RTL)+# if !defined(ASIO_DISABLE_SECURE_RTL)+#  if defined(ASIO_MSVC) \+    && (ASIO_MSVC >= 1400) \+    && !defined(UNDER_CE)+#   define ASIO_HAS_SECURE_RTL 1+#  endif // defined(ASIO_MSVC)+         // && (ASIO_MSVC >= 1400)+         // && !defined(UNDER_CE)+# endif // !defined(ASIO_DISABLE_SECURE_RTL)+#endif // !defined(ASIO_HAS_SECURE_RTL)++// Handler hooking. Disabled for ancient Borland C++ and gcc compilers.+#if !defined(ASIO_HAS_HANDLER_HOOKS)+# if !defined(ASIO_DISABLE_HANDLER_HOOKS)+#  if defined(__GNUC__)+#   if (__GNUC__ >= 3)+#    define ASIO_HAS_HANDLER_HOOKS 1+#   endif // (__GNUC__ >= 3)+#  elif !defined(__BORLANDC__) || defined(__clang__)+#   define ASIO_HAS_HANDLER_HOOKS 1+#  endif // !defined(__BORLANDC__) || defined(__clang__)+# endif // !defined(ASIO_DISABLE_HANDLER_HOOKS)+#endif // !defined(ASIO_HAS_HANDLER_HOOKS)++// Support for the __thread keyword extension.+#if !defined(ASIO_DISABLE_THREAD_KEYWORD_EXTENSION)+# if defined(__linux__)+#  if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))+#   if ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)+#    if !defined(__INTEL_COMPILER) && !defined(__ICL) \+       && !(defined(__clang__) && defined(__ANDROID__))+#     define ASIO_HAS_THREAD_KEYWORD_EXTENSION 1+#     define ASIO_THREAD_KEYWORD __thread+#    elif defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100)+#     define ASIO_HAS_THREAD_KEYWORD_EXTENSION 1+#    endif // defined(__INTEL_COMPILER) && (__INTEL_COMPILER >= 1100)+           // && !(defined(__clang__) && defined(__ANDROID__))+#   endif // ((__GNUC__ == 3) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 3)+#  endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))+# endif // defined(__linux__)+# if defined(ASIO_MSVC) && defined(ASIO_WINDOWS_RUNTIME)+#  if (_MSC_VER >= 1700)+#   define ASIO_HAS_THREAD_KEYWORD_EXTENSION 1+#   define ASIO_THREAD_KEYWORD __declspec(thread)+#  endif // (_MSC_VER >= 1700)+# endif // defined(ASIO_MSVC) && defined(ASIO_WINDOWS_RUNTIME)+#endif // !defined(ASIO_DISABLE_THREAD_KEYWORD_EXTENSION)+#if !defined(ASIO_THREAD_KEYWORD)+# define ASIO_THREAD_KEYWORD __thread+#endif // !defined(ASIO_THREAD_KEYWORD)++// Support for POSIX ssize_t typedef.+#if !defined(ASIO_DISABLE_SSIZE_T)+# if defined(__linux__) \+   || (defined(__MACH__) && defined(__APPLE__))+#  define ASIO_HAS_SSIZE_T 1+# endif // defined(__linux__)+        //   || (defined(__MACH__) && defined(__APPLE__))+#endif // !defined(ASIO_DISABLE_SSIZE_T)++// Helper macros to manage transition away from error_code return values.+#if defined(ASIO_NO_DEPRECATED)+# define ASIO_SYNC_OP_VOID void+# define ASIO_SYNC_OP_VOID_RETURN(e) return+#else // defined(ASIO_NO_DEPRECATED)+# define ASIO_SYNC_OP_VOID asio::error_code+# define ASIO_SYNC_OP_VOID_RETURN(e) return e+#endif // defined(ASIO_NO_DEPRECATED)++// Newer gcc, clang need special treatment to suppress unused typedef warnings.+#if defined(__clang__)+# if defined(__apple_build_version__)+#  if (__clang_major__ >= 7)+#   define ASIO_UNUSED_TYPEDEF __attribute__((__unused__))+#  endif // (__clang_major__ >= 7)+# elif ((__clang_major__ == 3) && (__clang_minor__ >= 6)) \+    || (__clang_major__ > 3)+#  define ASIO_UNUSED_TYPEDEF __attribute__((__unused__))+# endif // ((__clang_major__ == 3) && (__clang_minor__ >= 6))+        //   || (__clang_major__ > 3)+#elif defined(__GNUC__)+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#  define ASIO_UNUSED_TYPEDEF __attribute__((__unused__))+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#endif // defined(__GNUC__)+#if !defined(ASIO_UNUSED_TYPEDEF)+# define ASIO_UNUSED_TYPEDEF+#endif // !defined(ASIO_UNUSED_TYPEDEF)++// Some versions of gcc generate spurious warnings about unused variables.+#if defined(__GNUC__)+# if (__GNUC__ >= 4)+#  define ASIO_UNUSED_VARIABLE __attribute__((__unused__))+# endif // (__GNUC__ >= 4)+#endif // defined(__GNUC__)+#if !defined(ASIO_UNUSED_VARIABLE)+# define ASIO_UNUSED_VARIABLE+#endif // !defined(ASIO_UNUSED_VARIABLE)++// Support the co_await keyword on compilers known to allow it.+#if !defined(ASIO_HAS_CO_AWAIT)+# if !defined(ASIO_DISABLE_CO_AWAIT)+#  if defined(ASIO_MSVC)+#   if (_MSC_FULL_VER >= 190023506)+#    if defined(_RESUMABLE_FUNCTIONS_SUPPORTED)+#     define ASIO_HAS_CO_AWAIT 1+#    endif // defined(_RESUMABLE_FUNCTIONS_SUPPORTED)+#   endif // (_MSC_FULL_VER >= 190023506)+#  endif // defined(ASIO_MSVC)+#  if defined(__clang__)+#   if (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)+#    if __has_include(<experimental/coroutine>)+#     define ASIO_HAS_CO_AWAIT 1+#    endif // __has_include(<experimental/coroutine>)+#   endif // (__cplusplus >= 201703) && (__cpp_coroutines >= 201703)+#  elif defined(__GNUC__)+#   if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902)+#    if __has_include(<coroutine>)+#     define ASIO_HAS_CO_AWAIT 1+#    endif // __has_include(<coroutine>)+#   endif // (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902)+#  endif // defined(__GNUC__)+# endif // !defined(ASIO_DISABLE_CO_AWAIT)+#endif // !defined(ASIO_HAS_CO_AWAIT)++// Standard library support for coroutines.+#if !defined(ASIO_HAS_STD_COROUTINE)+# if !defined(ASIO_DISABLE_STD_COROUTINE)+#  if defined(__GNUC__)+#   if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902)+#    if __has_include(<coroutine>)+#     define ASIO_HAS_STD_COROUTINE 1+#    endif // __has_include(<coroutine>)+#   endif // (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902)+#  endif // defined(__GNUC__)+# endif // !defined(ASIO_DISABLE_STD_COROUTINE)+#endif // !defined(ASIO_HAS_STD_COROUTINE)++// Compiler support for the the [[nodiscard]] attribute.+#if !defined(ASIO_NODISCARD)+# if defined(__has_cpp_attribute)+#  if __has_cpp_attribute(nodiscard)+#   if (__cplusplus >= 201703)+#    define ASIO_NODISCARD [[nodiscard]]+#   endif // (__cplusplus >= 201703)+#  endif // __has_cpp_attribute(nodiscard)+# endif // defined(__has_cpp_attribute)+#endif // !defined(ASIO_NODISCARD)+#if !defined(ASIO_NODISCARD)+# define ASIO_NODISCARD+#endif // !defined(ASIO_NODISCARD)++#endif // ASIO_DETAIL_CONFIG_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/consuming_buffers.hpp view
@@ -0,0 +1,414 @@+//+// detail/consuming_buffers.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CONSUMING_BUFFERS_HPP+#define ASIO_DETAIL_CONSUMING_BUFFERS_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/buffer.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/limits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper template to determine the maximum number of prepared buffers.+template <typename Buffers>+struct prepared_buffers_max+{+  enum { value = buffer_sequence_adapter_base::max_buffers };+};++template <typename Elem, std::size_t N>+struct prepared_buffers_max<boost::array<Elem, N> >+{+  enum { value = N };+};++#if defined(ASIO_HAS_STD_ARRAY)++template <typename Elem, std::size_t N>+struct prepared_buffers_max<std::array<Elem, N> >+{+  enum { value = N };+};++#endif // defined(ASIO_HAS_STD_ARRAY)++// A buffer sequence used to represent a subsequence of the buffers.+template <typename Buffer, std::size_t MaxBuffers>+struct prepared_buffers+{+  typedef Buffer value_type;+  typedef const Buffer* const_iterator;++  enum { max_buffers = MaxBuffers < 16 ? MaxBuffers : 16 };++  prepared_buffers() : count(0) {}+  const_iterator begin() const { return elems; }+  const_iterator end() const { return elems + count; }++  Buffer elems[max_buffers];+  std::size_t count;+};++// A proxy for a sub-range in a list of buffers.+template <typename Buffer, typename Buffers, typename Buffer_Iterator>+class consuming_buffers+{+public:+  typedef prepared_buffers<Buffer, prepared_buffers_max<Buffers>::value>+    prepared_buffers_type;++  // Construct to represent the entire list of buffers.+  explicit consuming_buffers(const Buffers& buffers)+    : buffers_(buffers),+      total_consumed_(0),+      next_elem_(0),+      next_elem_offset_(0)+  {+    using asio::buffer_size;+    total_size_ = buffer_size(buffers);+  }++  // Determine if we are at the end of the buffers.+  bool empty() const+  {+    return total_consumed_ >= total_size_;+  }++  // Get the buffer for a single transfer, with a size.+  prepared_buffers_type prepare(std::size_t max_size)+  {+    prepared_buffers_type result;++    Buffer_Iterator next = asio::buffer_sequence_begin(buffers_);+    Buffer_Iterator end = asio::buffer_sequence_end(buffers_);++    std::advance(next, next_elem_);+    std::size_t elem_offset = next_elem_offset_;+    while (next != end && max_size > 0 && (result.count) < result.max_buffers)+    {+      Buffer next_buf = Buffer(*next) + elem_offset;+      result.elems[result.count] = asio::buffer(next_buf, max_size);+      max_size -= result.elems[result.count].size();+      elem_offset = 0;+      if (result.elems[result.count].size() > 0)+        ++result.count;+      ++next;+    }++    return result;+  }++  // Consume the specified number of bytes from the buffers.+  void consume(std::size_t size)+  {+    total_consumed_ += size;++    Buffer_Iterator next = asio::buffer_sequence_begin(buffers_);+    Buffer_Iterator end = asio::buffer_sequence_end(buffers_);++    std::advance(next, next_elem_);+    while (next != end && size > 0)+    {+      Buffer next_buf = Buffer(*next) + next_elem_offset_;+      if (size < next_buf.size())+      {+        next_elem_offset_ += size;+        size = 0;+      }+      else+      {+        size -= next_buf.size();+        next_elem_offset_ = 0;+        ++next_elem_;+        ++next;+      }+    }+  }++  // Get the total number of bytes consumed from the buffers.+  std::size_t total_consumed() const+  {+    return total_consumed_;+  }++private:+  Buffers buffers_;+  std::size_t total_size_;+  std::size_t total_consumed_;+  std::size_t next_elem_;+  std::size_t next_elem_offset_;+};++// Base class of all consuming_buffers specialisations for single buffers.+template <typename Buffer>+class consuming_single_buffer+{+public:+  // Construct to represent the entire list of buffers.+  template <typename Buffer1>+  explicit consuming_single_buffer(const Buffer1& buffer)+    : buffer_(buffer),+      total_consumed_(0)+  {+  }++  // Determine if we are at the end of the buffers.+  bool empty() const+  {+    return total_consumed_ >= buffer_.size();+  }++  // Get the buffer for a single transfer, with a size.+  Buffer prepare(std::size_t max_size)+  {+    return asio::buffer(buffer_ + total_consumed_, max_size);+  }++  // Consume the specified number of bytes from the buffers.+  void consume(std::size_t size)+  {+    total_consumed_ += size;+  }++  // Get the total number of bytes consumed from the buffers.+  std::size_t total_consumed() const+  {+    return total_consumed_;+  }++private:+  Buffer buffer_;+  std::size_t total_consumed_;+};++template <>+class consuming_buffers<mutable_buffer, mutable_buffer, const mutable_buffer*>+  : public consuming_single_buffer<ASIO_MUTABLE_BUFFER>+{+public:+  explicit consuming_buffers(const mutable_buffer& buffer)+    : consuming_single_buffer<ASIO_MUTABLE_BUFFER>(buffer)+  {+  }+};++template <>+class consuming_buffers<const_buffer, mutable_buffer, const mutable_buffer*>+  : public consuming_single_buffer<ASIO_CONST_BUFFER>+{+public:+  explicit consuming_buffers(const mutable_buffer& buffer)+    : consuming_single_buffer<ASIO_CONST_BUFFER>(buffer)+  {+  }+};++template <>+class consuming_buffers<const_buffer, const_buffer, const const_buffer*>+  : public consuming_single_buffer<ASIO_CONST_BUFFER>+{+public:+  explicit consuming_buffers(const const_buffer& buffer)+    : consuming_single_buffer<ASIO_CONST_BUFFER>(buffer)+  {+  }+};++#if !defined(ASIO_NO_DEPRECATED)++template <>+class consuming_buffers<mutable_buffer,+    mutable_buffers_1, const mutable_buffer*>+  : public consuming_single_buffer<ASIO_MUTABLE_BUFFER>+{+public:+  explicit consuming_buffers(const mutable_buffers_1& buffer)+    : consuming_single_buffer<ASIO_MUTABLE_BUFFER>(buffer)+  {+  }+};++template <>+class consuming_buffers<const_buffer, mutable_buffers_1, const mutable_buffer*>+  : public consuming_single_buffer<ASIO_CONST_BUFFER>+{+public:+  explicit consuming_buffers(const mutable_buffers_1& buffer)+    : consuming_single_buffer<ASIO_CONST_BUFFER>(buffer)+  {+  }+};++template <>+class consuming_buffers<const_buffer, const_buffers_1, const const_buffer*>+  : public consuming_single_buffer<ASIO_CONST_BUFFER>+{+public:+  explicit consuming_buffers(const const_buffers_1& buffer)+    : consuming_single_buffer<ASIO_CONST_BUFFER>(buffer)+  {+  }+};++#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Buffer, typename Elem>+class consuming_buffers<Buffer, boost::array<Elem, 2>,+    typename boost::array<Elem, 2>::const_iterator>+{+public:+  // Construct to represent the entire list of buffers.+  explicit consuming_buffers(const boost::array<Elem, 2>& buffers)+    : buffers_(buffers),+      total_consumed_(0)+  {+  }++  // Determine if we are at the end of the buffers.+  bool empty() const+  {+    return total_consumed_ >=+      Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();+  }++  // Get the buffer for a single transfer, with a size.+  boost::array<Buffer, 2> prepare(std::size_t max_size)+  {+    boost::array<Buffer, 2> result = {{+      Buffer(buffers_[0]), Buffer(buffers_[1]) }};+    std::size_t buffer0_size = result[0].size();+    result[0] = asio::buffer(result[0] + total_consumed_, max_size);+    result[1] = asio::buffer(+        result[1] + (total_consumed_ < buffer0_size+          ? 0 : total_consumed_ - buffer0_size),+        max_size - result[0].size());+    return result;+  }++  // Consume the specified number of bytes from the buffers.+  void consume(std::size_t size)+  {+    total_consumed_ += size;+  }++  // Get the total number of bytes consumed from the buffers.+  std::size_t total_consumed() const+  {+    return total_consumed_;+  }++private:+  boost::array<Elem, 2> buffers_;+  std::size_t total_consumed_;+};++#if defined(ASIO_HAS_STD_ARRAY)++template <typename Buffer, typename Elem>+class consuming_buffers<Buffer, std::array<Elem, 2>,+    typename std::array<Elem, 2>::const_iterator>+{+public:+  // Construct to represent the entire list of buffers.+  explicit consuming_buffers(const std::array<Elem, 2>& buffers)+    : buffers_(buffers),+      total_consumed_(0)+  {+  }++  // Determine if we are at the end of the buffers.+  bool empty() const+  {+    return total_consumed_ >=+      Buffer(buffers_[0]).size() + Buffer(buffers_[1]).size();+  }++  // Get the buffer for a single transfer, with a size.+  std::array<Buffer, 2> prepare(std::size_t max_size)+  {+    std::array<Buffer, 2> result = {{+      Buffer(buffers_[0]), Buffer(buffers_[1]) }};+    std::size_t buffer0_size = result[0].size();+    result[0] = asio::buffer(result[0] + total_consumed_, max_size);+    result[1] = asio::buffer(+        result[1] + (total_consumed_ < buffer0_size+          ? 0 : total_consumed_ - buffer0_size),+        max_size - result[0].size());+    return result;+  }++  // Consume the specified number of bytes from the buffers.+  void consume(std::size_t size)+  {+    total_consumed_ += size;+  }++  // Get the total number of bytes consumed from the buffers.+  std::size_t total_consumed() const+  {+    return total_consumed_;+  }++private:+  std::array<Elem, 2> buffers_;+  std::size_t total_consumed_;+};++#endif // defined(ASIO_HAS_STD_ARRAY)++// Specialisation for null_buffers to ensure that the null_buffers type is+// always passed through to the underlying read or write operation.+template <typename Buffer>+class consuming_buffers<Buffer, null_buffers, const mutable_buffer*>+  : public asio::null_buffers+{+public:+  consuming_buffers(const null_buffers&)+  {+    // No-op.+  }++  bool empty()+  {+    return false;+  }++  null_buffers prepare(std::size_t)+  {+    return null_buffers();+  }++  void consume(std::size_t)+  {+    // No-op.+  }++  std::size_t total_consumed() const+  {+    return 0;+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_CONSUMING_BUFFERS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/cstddef.hpp view
@@ -0,0 +1,31 @@+//+// detail/cstddef.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CSTDDEF_HPP+#define ASIO_DETAIL_CSTDDEF_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <cstddef>++namespace asio {++#if defined(ASIO_HAS_NULLPTR)+using std::nullptr_t;+#else // defined(ASIO_HAS_NULLPTR)+struct nullptr_t {};+#endif // defined(ASIO_HAS_NULLPTR)++} // namespace asio++#endif // ASIO_DETAIL_CSTDDEF_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/cstdint.hpp view
@@ -0,0 +1,60 @@+//+// detail/cstdint.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_CSTDINT_HPP+#define ASIO_DETAIL_CSTDINT_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_CSTDINT)+# include <cstdint>+#else // defined(ASIO_HAS_CSTDINT)+# include <boost/cstdint.hpp>+#endif // defined(ASIO_HAS_CSTDINT)++namespace asio {++#if defined(ASIO_HAS_CSTDINT)+using std::int16_t;+using std::int_least16_t;+using std::uint16_t;+using std::uint_least16_t;+using std::int32_t;+using std::int_least32_t;+using std::uint32_t;+using std::uint_least32_t;+using std::int64_t;+using std::int_least64_t;+using std::uint64_t;+using std::uint_least64_t;+using std::uintmax_t;+#else // defined(ASIO_HAS_CSTDINT)+using boost::int16_t;+using boost::int_least16_t;+using boost::uint16_t;+using boost::uint_least16_t;+using boost::int32_t;+using boost::int_least32_t;+using boost::uint32_t;+using boost::uint_least32_t;+using boost::int64_t;+using boost::int_least64_t;+using boost::uint64_t;+using boost::uint_least64_t;+using boost::uintmax_t;+#endif // defined(ASIO_HAS_CSTDINT)++} // namespace asio++#endif // ASIO_DETAIL_CSTDINT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/date_time_fwd.hpp view
@@ -0,0 +1,34 @@+//+// detail/date_time_fwd.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_DATE_TIME_FWD_HPP+#define ASIO_DETAIL_DATE_TIME_FWD_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++namespace boost {+namespace date_time {++template<class T, class TimeSystem>+class base_time;++} // namespace date_time+namespace posix_time {++class ptime;++} // namespace posix_time+} // namespace boost++#endif // ASIO_DETAIL_DATE_TIME_FWD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/deadline_timer_service.hpp view
@@ -0,0 +1,295 @@+//+// detail/deadline_timer_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP+#define ASIO_DETAIL_DEADLINE_TIMER_SERVICE_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/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/timer_queue.hpp"+#include "asio/detail/timer_queue_ptime.hpp"+#include "asio/detail/timer_scheduler.hpp"+#include "asio/detail/wait_handler.hpp"+#include "asio/detail/wait_op.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)+# include <chrono>+# include <thread>+#endif // defined(ASIO_WINDOWS_RUNTIME)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Time_Traits>+class deadline_timer_service+  : public execution_context_service_base<deadline_timer_service<Time_Traits> >+{+public:+  // The time type.+  typedef typename Time_Traits::time_type time_type;++  // The duration type.+  typedef typename Time_Traits::duration_type duration_type;++  // The implementation type of the timer. This type is dependent on the+  // underlying implementation of the timer service.+  struct implementation_type+    : private asio::detail::noncopyable+  {+    time_type expiry;+    bool might_have_pending_waits;+    typename timer_queue<Time_Traits>::per_timer_data timer_data;+  };++  // Constructor.+  deadline_timer_service(execution_context& context)+    : execution_context_service_base<+        deadline_timer_service<Time_Traits> >(context),+      scheduler_(asio::use_service<timer_scheduler>(context))+  {+    scheduler_.init_task();+    scheduler_.add_timer_queue(timer_queue_);+  }++  // Destructor.+  ~deadline_timer_service()+  {+    scheduler_.remove_timer_queue(timer_queue_);+  }++  // Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+  }++  // Construct a new timer implementation.+  void construct(implementation_type& impl)+  {+    impl.expiry = time_type();+    impl.might_have_pending_waits = false;+  }++  // Destroy a timer implementation.+  void destroy(implementation_type& impl)+  {+    asio::error_code ec;+    cancel(impl, ec);+  }++  // Move-construct a new timer implementation.+  void move_construct(implementation_type& impl,+      implementation_type& other_impl)+  {+    scheduler_.move_timer(timer_queue_, impl.timer_data, other_impl.timer_data);++    impl.expiry = other_impl.expiry;+    other_impl.expiry = time_type();++    impl.might_have_pending_waits = other_impl.might_have_pending_waits;+    other_impl.might_have_pending_waits = false;+  }++  // Move-assign from another timer implementation.+  void move_assign(implementation_type& impl,+      deadline_timer_service& other_service,+      implementation_type& other_impl)+  {+    if (this != &other_service)+      if (impl.might_have_pending_waits)+        scheduler_.cancel_timer(timer_queue_, impl.timer_data);++    other_service.scheduler_.move_timer(other_service.timer_queue_,+        impl.timer_data, other_impl.timer_data);++    impl.expiry = other_impl.expiry;+    other_impl.expiry = time_type();++    impl.might_have_pending_waits = other_impl.might_have_pending_waits;+    other_impl.might_have_pending_waits = false;+  }++  // Move-construct a new timer implementation.+  void converting_move_construct(implementation_type& impl,+      deadline_timer_service&, implementation_type& other_impl)+  {+    move_construct(impl, other_impl);+  }++  // Move-assign from another timer implementation.+  void converting_move_assign(implementation_type& impl,+      deadline_timer_service& other_service,+      implementation_type& other_impl)+  {+    move_assign(impl, other_service, other_impl);+  }++  // Cancel any asynchronous wait operations associated with the timer.+  std::size_t cancel(implementation_type& impl, asio::error_code& ec)+  {+    if (!impl.might_have_pending_waits)+    {+      ec = asio::error_code();+      return 0;+    }++    ASIO_HANDLER_OPERATION((scheduler_.context(),+          "deadline_timer", &impl, 0, "cancel"));++    std::size_t count = scheduler_.cancel_timer(timer_queue_, impl.timer_data);+    impl.might_have_pending_waits = false;+    ec = asio::error_code();+    return count;+  }++  // Cancels one asynchronous wait operation associated with the timer.+  std::size_t cancel_one(implementation_type& impl,+      asio::error_code& ec)+  {+    if (!impl.might_have_pending_waits)+    {+      ec = asio::error_code();+      return 0;+    }++    ASIO_HANDLER_OPERATION((scheduler_.context(),+          "deadline_timer", &impl, 0, "cancel_one"));++    std::size_t count = scheduler_.cancel_timer(+        timer_queue_, impl.timer_data, 1);+    if (count == 0)+      impl.might_have_pending_waits = false;+    ec = asio::error_code();+    return count;+  }++  // Get the expiry time for the timer as an absolute time.+  time_type expiry(const implementation_type& impl) const+  {+    return impl.expiry;+  }++  // Get the expiry time for the timer as an absolute time.+  time_type expires_at(const implementation_type& impl) const+  {+    return impl.expiry;+  }++  // Get the expiry time for the timer relative to now.+  duration_type expires_from_now(const implementation_type& impl) const+  {+    return Time_Traits::subtract(this->expiry(impl), Time_Traits::now());+  }++  // Set the expiry time for the timer as an absolute time.+  std::size_t expires_at(implementation_type& impl,+      const time_type& expiry_time, asio::error_code& ec)+  {+    std::size_t count = cancel(impl, ec);+    impl.expiry = expiry_time;+    ec = asio::error_code();+    return count;+  }++  // Set the expiry time for the timer relative to now.+  std::size_t expires_after(implementation_type& impl,+      const duration_type& expiry_time, asio::error_code& ec)+  {+    return expires_at(impl,+        Time_Traits::add(Time_Traits::now(), expiry_time), ec);+  }++  // Set the expiry time for the timer relative to now.+  std::size_t expires_from_now(implementation_type& impl,+      const duration_type& expiry_time, asio::error_code& ec)+  {+    return expires_at(impl,+        Time_Traits::add(Time_Traits::now(), expiry_time), ec);+  }++  // Perform a blocking wait on the timer.+  void wait(implementation_type& impl, asio::error_code& ec)+  {+    time_type now = Time_Traits::now();+    ec = asio::error_code();+    while (Time_Traits::less_than(now, impl.expiry) && !ec)+    {+      this->do_wait(Time_Traits::to_posix_duration(+            Time_Traits::subtract(impl.expiry, now)), ec);+      now = Time_Traits::now();+    }+  }++  // Start an asynchronous wait on the timer.+  template <typename Handler, typename IoExecutor>+  void async_wait(implementation_type& impl,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef wait_handler<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(handler, io_ex);++    impl.might_have_pending_waits = true;++    ASIO_HANDLER_CREATION((scheduler_.context(),+          *p.p, "deadline_timer", &impl, 0, "async_wait"));++    scheduler_.schedule_timer(timer_queue_, impl.expiry, impl.timer_data, p.p);+    p.v = p.p = 0;+  }++private:+  // Helper function to wait given a duration type. The duration type should+  // either be of type boost::posix_time::time_duration, or implement the+  // required subset of its interface.+  template <typename Duration>+  void do_wait(const Duration& timeout, asio::error_code& ec)+  {+#if defined(ASIO_WINDOWS_RUNTIME)+    std::this_thread::sleep_for(+        std::chrono::seconds(timeout.total_seconds())+        + std::chrono::microseconds(timeout.total_microseconds()));+    ec = asio::error_code();+#else // defined(ASIO_WINDOWS_RUNTIME)+    ::timeval tv;+    tv.tv_sec = timeout.total_seconds();+    tv.tv_usec = timeout.total_microseconds() % 1000000;+    socket_ops::select(0, 0, 0, 0, &tv, ec);+#endif // defined(ASIO_WINDOWS_RUNTIME)+  }++  // The queue of timers.+  timer_queue<Time_Traits> timer_queue_;++  // The object that schedules and executes timers. Usually a reactor.+  timer_scheduler& scheduler_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_DEADLINE_TIMER_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/dependent_type.hpp view
@@ -0,0 +1,36 @@+//+// detail/dependent_type.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_DEPENDENT_TYPE_HPP+#define ASIO_DETAIL_DEPENDENT_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 {+namespace detail {++template <typename DependsOn, typename T>+struct dependent_type+{+  typedef T type;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_DEPENDENT_TYPE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/descriptor_ops.hpp view
@@ -0,0 +1,139 @@+//+// detail/descriptor_ops.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_DESCRIPTOR_OPS_HPP+#define ASIO_DETAIL_DESCRIPTOR_OPS_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_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)++#include <cstddef>+#include "asio/error.hpp"+#include "asio/error_code.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {+namespace descriptor_ops {++// Descriptor state bits.+enum+{+  // The user wants a non-blocking descriptor.+  user_set_non_blocking = 1,++  // The descriptor has been set non-blocking.+  internal_non_blocking = 2,++  // Helper "state" used to determine whether the descriptor is non-blocking.+  non_blocking = user_set_non_blocking | internal_non_blocking,++  // The descriptor may have been dup()-ed.+  possible_dup = 4+};++typedef unsigned char state_type;++inline void get_last_error(+    asio::error_code& ec, bool is_error_condition)+{+  if (!is_error_condition)+  {+    ec.assign(0, ec.category());+  }+  else+  {+    ec = asio::error_code(errno,+        asio::error::get_system_category());+  }+}++ASIO_DECL int open(const char* path, int flags,+    asio::error_code& ec);++ASIO_DECL int close(int d, state_type& state,+    asio::error_code& ec);++ASIO_DECL bool set_user_non_blocking(int d,+    state_type& state, bool value, asio::error_code& ec);++ASIO_DECL bool set_internal_non_blocking(int d,+    state_type& state, bool value, asio::error_code& ec);++typedef iovec buf;++ASIO_DECL std::size_t sync_read(int d, state_type state, buf* bufs,+    std::size_t count, bool all_empty, asio::error_code& ec);++ASIO_DECL std::size_t sync_read1(int d, state_type state, void* data,+    std::size_t size, asio::error_code& ec);++ASIO_DECL bool non_blocking_read(int d, buf* bufs, std::size_t count,+    asio::error_code& ec, std::size_t& bytes_transferred);++ASIO_DECL bool non_blocking_read1(int d, void* data, std::size_t size,+    asio::error_code& ec, std::size_t& bytes_transferred);++ASIO_DECL std::size_t sync_write(int d, state_type state,+    const buf* bufs, std::size_t count, bool all_empty,+    asio::error_code& ec);++ASIO_DECL std::size_t sync_write1(int d, state_type state,+    const void* data, std::size_t size, asio::error_code& ec);++ASIO_DECL bool non_blocking_write(int d,+    const buf* bufs, std::size_t count,+    asio::error_code& ec, std::size_t& bytes_transferred);++ASIO_DECL bool non_blocking_write1(int d,+    const void* data, std::size_t size,+    asio::error_code& ec, std::size_t& bytes_transferred);++ASIO_DECL int ioctl(int d, state_type& state, long cmd,+    ioctl_arg_type* arg, asio::error_code& ec);++ASIO_DECL int fcntl(int d, int cmd, asio::error_code& ec);++ASIO_DECL int fcntl(int d, int cmd,+    long arg, asio::error_code& ec);++ASIO_DECL int poll_read(int d,+    state_type state, asio::error_code& ec);++ASIO_DECL int poll_write(int d,+    state_type state, asio::error_code& ec);++ASIO_DECL int poll_error(int d,+    state_type state, asio::error_code& ec);++} // namespace descriptor_ops+} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/descriptor_ops.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)++#endif // ASIO_DETAIL_DESCRIPTOR_OPS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/descriptor_read_op.hpp view
@@ -0,0 +1,148 @@+//+// detail/descriptor_read_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP+#define ASIO_DETAIL_DESCRIPTOR_READ_OP_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_WINDOWS) && !defined(__CYGWIN__)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class descriptor_read_op_base : public reactor_op+{+public:+  descriptor_read_op_base(const asio::error_code& success_ec,+      int descriptor, const MutableBufferSequence& buffers,+      func_type complete_func)+    : reactor_op(success_ec,+        &descriptor_read_op_base::do_perform, complete_func),+      descriptor_(descriptor),+      buffers_(buffers)+  {+  }++  static status do_perform(reactor_op* base)+  {+    descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base));++    typedef buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs_type;++    status result;+    if (bufs_type::is_single_buffer)+    {+      result = descriptor_ops::non_blocking_read1(o->descriptor_,+          bufs_type::first(o->buffers_).data(),+          bufs_type::first(o->buffers_).size(),+          o->ec_, o->bytes_transferred_) ? done : not_done;+    }+    else+    {+      bufs_type bufs(o->buffers_);+      result = descriptor_ops::non_blocking_read(o->descriptor_,+          bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_)+        ? done : not_done;+    }++    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_read",+          o->ec_, o->bytes_transferred_));++    return result;+  }++private:+  int descriptor_;+  MutableBufferSequence buffers_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class descriptor_read_op+  : public descriptor_read_op_base<MutableBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(descriptor_read_op);++  descriptor_read_op(const asio::error_code& success_ec,+      int descriptor, const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+    : descriptor_read_op_base<MutableBufferSequence>(success_ec,+        descriptor, buffers, &descriptor_read_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    descriptor_read_op* o(static_cast<descriptor_read_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++#endif // ASIO_DETAIL_DESCRIPTOR_READ_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/descriptor_write_op.hpp view
@@ -0,0 +1,148 @@+//+// detail/descriptor_write_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP+#define ASIO_DETAIL_DESCRIPTOR_WRITE_OP_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_WINDOWS) && !defined(__CYGWIN__)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence>+class descriptor_write_op_base : public reactor_op+{+public:+  descriptor_write_op_base(const asio::error_code& success_ec,+      int descriptor, const ConstBufferSequence& buffers,+      func_type complete_func)+    : reactor_op(success_ec,+        &descriptor_write_op_base::do_perform, complete_func),+      descriptor_(descriptor),+      buffers_(buffers)+  {+  }++  static status do_perform(reactor_op* base)+  {+    descriptor_write_op_base* o(static_cast<descriptor_write_op_base*>(base));++    typedef buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs_type;++    status result;+    if (bufs_type::is_single_buffer)+    {+      result = descriptor_ops::non_blocking_write1(o->descriptor_,+          bufs_type::first(o->buffers_).data(),+          bufs_type::first(o->buffers_).size(),+          o->ec_, o->bytes_transferred_) ? done : not_done;+    }+    else+    {+      bufs_type bufs(o->buffers_);+      result = descriptor_ops::non_blocking_write(o->descriptor_,+          bufs.buffers(), bufs.count(), o->ec_, o->bytes_transferred_)+        ? done : not_done;+    }++    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_write",+          o->ec_, o->bytes_transferred_));++    return result;+  }++private:+  int descriptor_;+  ConstBufferSequence buffers_;+};++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class descriptor_write_op+  : public descriptor_write_op_base<ConstBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(descriptor_write_op);++  descriptor_write_op(const asio::error_code& success_ec,+      int descriptor, const ConstBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+    : descriptor_write_op_base<ConstBufferSequence>(success_ec,+        descriptor, buffers, &descriptor_write_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    descriptor_write_op* o(static_cast<descriptor_write_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++#endif // ASIO_DETAIL_DESCRIPTOR_WRITE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/dev_poll_reactor.hpp view
@@ -0,0 +1,218 @@+//+// detail/dev_poll_reactor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_DEV_POLL_REACTOR_HPP+#define ASIO_DETAIL_DEV_POLL_REACTOR_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_DEV_POLL)++#include <cstddef>+#include <vector>+#include <sys/devpoll.h>+#include "asio/detail/hash_map.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/reactor_op_queue.hpp"+#include "asio/detail/select_interrupter.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/timer_queue_base.hpp"+#include "asio/detail/timer_queue_set.hpp"+#include "asio/detail/wait_op.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class dev_poll_reactor+  : public execution_context_service_base<dev_poll_reactor>+{+public:+  enum op_types { read_op = 0, write_op = 1,+    connect_op = 1, except_op = 2, max_ops = 3 };++  // Per-descriptor data.+  struct per_descriptor_data+  {+  };++  // Constructor.+  ASIO_DECL dev_poll_reactor(asio::execution_context& ctx);++  // Destructor.+  ASIO_DECL ~dev_poll_reactor();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Recreate internal descriptors following a fork.+  ASIO_DECL void notify_fork(+      asio::execution_context::fork_event fork_ev);++  // Initialise the task.+  ASIO_DECL void init_task();++  // Register a socket with the reactor. Returns 0 on success, system error+  // code on failure.+  ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&);++  // Register a descriptor with an associated single operation. Returns 0 on+  // success, system error code on failure.+  ASIO_DECL int register_internal_descriptor(+      int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op);++  // Move descriptor registration from one descriptor_data object to another.+  ASIO_DECL void move_descriptor(socket_type descriptor,+      per_descriptor_data& target_descriptor_data,+      per_descriptor_data& source_descriptor_data);++  // Post a reactor operation for immediate completion.+  void post_immediate_completion(reactor_op* op, bool is_continuation)+  {+    scheduler_.post_immediate_completion(op, is_continuation);+  }++  // Start a new operation. The reactor operation will be performed when the+  // given descriptor is flagged as ready, or an error has occurred.+  ASIO_DECL void start_op(int op_type, socket_type descriptor,+      per_descriptor_data&, reactor_op* op,+      bool is_continuation, bool allow_speculative);++  // Cancel all operations associated with the given descriptor. The+  // handlers associated with the descriptor will be invoked with the+  // operation_aborted error.+  ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&);++  // Cancel any operations that are running against the descriptor and remove+  // its registration from the reactor. The reactor resources associated with+  // the descriptor must be released by calling cleanup_descriptor_data.+  ASIO_DECL void deregister_descriptor(socket_type descriptor,+      per_descriptor_data&, bool closing);++  // Remove the descriptor's registration from the reactor. The reactor+  // resources associated with the descriptor must be released by calling+  // cleanup_descriptor_data.+  ASIO_DECL void deregister_internal_descriptor(+      socket_type descriptor, per_descriptor_data&);++  // Perform any post-deregistration cleanup tasks associated with the+  // descriptor data.+  ASIO_DECL void cleanup_descriptor_data(per_descriptor_data&);++  // Add a new timer queue to the reactor.+  template <typename Time_Traits>+  void add_timer_queue(timer_queue<Time_Traits>& queue);++  // Remove a timer queue from the reactor.+  template <typename Time_Traits>+  void remove_timer_queue(timer_queue<Time_Traits>& queue);++  // Schedule a new operation in the given timer queue to expire at the+  // specified absolute time.+  template <typename Time_Traits>+  void schedule_timer(timer_queue<Time_Traits>& queue,+      const typename Time_Traits::time_type& time,+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);++  // Cancel the timer operations associated with the given token. Returns the+  // number of operations that have been posted or dispatched.+  template <typename Time_Traits>+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& timer,+      std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++  // Move the timer operations associated with the given timer.+  template <typename Time_Traits>+  void move_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& target,+      typename timer_queue<Time_Traits>::per_timer_data& source);++  // Run /dev/poll once until interrupted or events are ready to be dispatched.+  ASIO_DECL void run(long usec, op_queue<operation>& ops);++  // Interrupt the select loop.+  ASIO_DECL void interrupt();++private:+  // Create the /dev/poll file descriptor. Throws an exception if the descriptor+  // cannot be created.+  ASIO_DECL static int do_dev_poll_create();++  // Helper function to add a new timer queue.+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);++  // Helper function to remove a timer queue.+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);++  // Get the timeout value for the /dev/poll DP_POLL operation. The timeout+  // value is returned as a number of milliseconds. A return value of -1+  // indicates that the poll should block indefinitely.+  ASIO_DECL int get_timeout(int msec);++  // Cancel all operations associated with the given descriptor. The do_cancel+  // function of the handler objects will be invoked. This function does not+  // acquire the dev_poll_reactor's mutex.+  ASIO_DECL void cancel_ops_unlocked(socket_type descriptor,+      const asio::error_code& ec);++  // Add a pending event entry for the given descriptor.+  ASIO_DECL ::pollfd& add_pending_event_change(int descriptor);++  // The scheduler implementation used to post completions.+  scheduler& scheduler_;++  // Mutex to protect access to internal data.+  asio::detail::mutex mutex_;++  // The /dev/poll file descriptor.+  int dev_poll_fd_;++  // Vector of /dev/poll events waiting to be written to the descriptor.+  std::vector< ::pollfd> pending_event_changes_;++  // Hash map to associate a descriptor with a pending event change index.+  hash_map<int, std::size_t> pending_event_change_index_;++  // The interrupter is used to break a blocking DP_POLL operation.+  select_interrupter interrupter_;++  // The queues of read, write and except operations.+  reactor_op_queue<socket_type> op_queue_[max_ops];++  // The timer queues.+  timer_queue_set timer_queues_;++  // Whether the service has been shut down.+  bool shutdown_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/dev_poll_reactor.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/dev_poll_reactor.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_DEV_POLL)++#endif // ASIO_DETAIL_DEV_POLL_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/epoll_reactor.hpp view
@@ -0,0 +1,266 @@+//+// detail/epoll_reactor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_EPOLL_REACTOR_HPP+#define ASIO_DETAIL_EPOLL_REACTOR_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_EPOLL)++#include "asio/detail/atomic_count.hpp"+#include "asio/detail/conditionally_enabled_mutex.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/object_pool.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/select_interrupter.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/timer_queue_base.hpp"+#include "asio/detail/timer_queue_set.hpp"+#include "asio/detail/wait_op.hpp"+#include "asio/execution_context.hpp"++#if defined(ASIO_HAS_TIMERFD)+# include <sys/timerfd.h>+#endif // defined(ASIO_HAS_TIMERFD)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class epoll_reactor+  : public execution_context_service_base<epoll_reactor>+{+private:+  // The mutex type used by this reactor.+  typedef conditionally_enabled_mutex mutex;++public:+  enum op_types { read_op = 0, write_op = 1,+    connect_op = 1, except_op = 2, max_ops = 3 };++  // Per-descriptor queues.+  class descriptor_state : operation+  {+    friend class epoll_reactor;+    friend class object_pool_access;++    descriptor_state* next_;+    descriptor_state* prev_;++    mutex mutex_;+    epoll_reactor* reactor_;+    int descriptor_;+    uint32_t registered_events_;+    op_queue<reactor_op> op_queue_[max_ops];+    bool try_speculative_[max_ops];+    bool shutdown_;++    ASIO_DECL descriptor_state(bool locking);+    void set_ready_events(uint32_t events) { task_result_ = events; }+    void add_ready_events(uint32_t events) { task_result_ |= events; }+    ASIO_DECL operation* perform_io(uint32_t events);+    ASIO_DECL static void do_complete(+        void* owner, operation* base,+        const asio::error_code& ec, std::size_t bytes_transferred);+  };++  // Per-descriptor data.+  typedef descriptor_state* per_descriptor_data;++  // Constructor.+  ASIO_DECL epoll_reactor(asio::execution_context& ctx);++  // Destructor.+  ASIO_DECL ~epoll_reactor();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Recreate internal descriptors following a fork.+  ASIO_DECL void notify_fork(+      asio::execution_context::fork_event fork_ev);++  // Initialise the task.+  ASIO_DECL void init_task();++  // Register a socket with the reactor. Returns 0 on success, system error+  // code on failure.+  ASIO_DECL int register_descriptor(socket_type descriptor,+      per_descriptor_data& descriptor_data);++  // Register a descriptor with an associated single operation. Returns 0 on+  // success, system error code on failure.+  ASIO_DECL int register_internal_descriptor(+      int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op);++  // Move descriptor registration from one descriptor_data object to another.+  ASIO_DECL void move_descriptor(socket_type descriptor,+      per_descriptor_data& target_descriptor_data,+      per_descriptor_data& source_descriptor_data);++  // Post a reactor operation for immediate completion.+  void post_immediate_completion(reactor_op* op, bool is_continuation)+  {+    scheduler_.post_immediate_completion(op, is_continuation);+  }++  // Start a new operation. The reactor operation will be performed when the+  // given descriptor is flagged as ready, or an error has occurred.+  ASIO_DECL void start_op(int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op,+      bool is_continuation, bool allow_speculative);++  // Cancel all operations associated with the given descriptor. The+  // handlers associated with the descriptor will be invoked with the+  // operation_aborted error.+  ASIO_DECL void cancel_ops(socket_type descriptor,+      per_descriptor_data& descriptor_data);++  // Cancel any operations that are running against the descriptor and remove+  // its registration from the reactor. The reactor resources associated with+  // the descriptor must be released by calling cleanup_descriptor_data.+  ASIO_DECL void deregister_descriptor(socket_type descriptor,+      per_descriptor_data& descriptor_data, bool closing);++  // Remove the descriptor's registration from the reactor. The reactor+  // resources associated with the descriptor must be released by calling+  // cleanup_descriptor_data.+  ASIO_DECL void deregister_internal_descriptor(+      socket_type descriptor, per_descriptor_data& descriptor_data);++  // Perform any post-deregistration cleanup tasks associated with the+  // descriptor data.+  ASIO_DECL void cleanup_descriptor_data(+      per_descriptor_data& descriptor_data);++  // Add a new timer queue to the reactor.+  template <typename Time_Traits>+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue);++  // Remove a timer queue from the reactor.+  template <typename Time_Traits>+  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue);++  // Schedule a new operation in the given timer queue to expire at the+  // specified absolute time.+  template <typename Time_Traits>+  void schedule_timer(timer_queue<Time_Traits>& queue,+      const typename Time_Traits::time_type& time,+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);++  // Cancel the timer operations associated with the given token. Returns the+  // number of operations that have been posted or dispatched.+  template <typename Time_Traits>+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& timer,+      std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++  // Move the timer operations associated with the given timer.+  template <typename Time_Traits>+  void move_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& target,+      typename timer_queue<Time_Traits>::per_timer_data& source);++  // Run epoll once until interrupted or events are ready to be dispatched.+  ASIO_DECL void run(long usec, op_queue<operation>& ops);++  // Interrupt the select loop.+  ASIO_DECL void interrupt();++private:+  // The hint to pass to epoll_create to size its data structures.+  enum { epoll_size = 20000 };++  // Create the epoll file descriptor. Throws an exception if the descriptor+  // cannot be created.+  ASIO_DECL static int do_epoll_create();++  // Create the timerfd file descriptor. Does not throw.+  ASIO_DECL static int do_timerfd_create();++  // Allocate a new descriptor state object.+  ASIO_DECL descriptor_state* allocate_descriptor_state();++  // Free an existing descriptor state object.+  ASIO_DECL void free_descriptor_state(descriptor_state* s);++  // Helper function to add a new timer queue.+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);++  // Helper function to remove a timer queue.+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);++  // Called to recalculate and update the timeout.+  ASIO_DECL void update_timeout();++  // Get the timeout value for the epoll_wait call. The timeout value is+  // returned as a number of milliseconds. A return value of -1 indicates+  // that epoll_wait should block indefinitely.+  ASIO_DECL int get_timeout(int msec);++#if defined(ASIO_HAS_TIMERFD)+  // Get the timeout value for the timer descriptor. The return value is the+  // flag argument to be used when calling timerfd_settime.+  ASIO_DECL int get_timeout(itimerspec& ts);+#endif // defined(ASIO_HAS_TIMERFD)++  // The scheduler implementation used to post completions.+  scheduler& scheduler_;++  // Mutex to protect access to internal data.+  mutex mutex_;++  // The interrupter is used to break a blocking epoll_wait call.+  select_interrupter interrupter_;++  // The epoll file descriptor.+  int epoll_fd_;++  // The timer file descriptor.+  int timer_fd_;++  // The timer queues.+  timer_queue_set timer_queues_;++  // Whether the service has been shut down.+  bool shutdown_;++  // Mutex to protect access to the registered descriptors.+  mutex registered_descriptors_mutex_;++  // Keep track of all registered descriptors.+  object_pool<descriptor_state> registered_descriptors_;++  // Helper class to do post-perform_io cleanup.+  struct perform_io_cleanup_on_block_exit;+  friend struct perform_io_cleanup_on_block_exit;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/epoll_reactor.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/epoll_reactor.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_EPOLL)++#endif // ASIO_DETAIL_EPOLL_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/event.hpp view
@@ -0,0 +1,48 @@+//+// detail/event.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_EVENT_HPP+#define ASIO_DETAIL_EVENT_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_THREADS)+# include "asio/detail/null_event.hpp"+#elif defined(ASIO_WINDOWS)+# include "asio/detail/win_event.hpp"+#elif defined(ASIO_HAS_PTHREADS)+# include "asio/detail/posix_event.hpp"+#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)+# include "asio/detail/std_event.hpp"+#else+# error Only Windows, POSIX and std::condition_variable are supported!+#endif++namespace asio {+namespace detail {++#if !defined(ASIO_HAS_THREADS)+typedef null_event event;+#elif defined(ASIO_WINDOWS)+typedef win_event event;+#elif defined(ASIO_HAS_PTHREADS)+typedef posix_event event;+#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)+typedef std_event event;+#endif++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_EVENT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/eventfd_select_interrupter.hpp view
@@ -0,0 +1,83 @@+//+// detail/eventfd_select_interrupter.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP+#define ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_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_EVENTFD)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class eventfd_select_interrupter+{+public:+  // Constructor.+  ASIO_DECL eventfd_select_interrupter();++  // Destructor.+  ASIO_DECL ~eventfd_select_interrupter();++  // Recreate the interrupter's descriptors. Used after a fork.+  ASIO_DECL void recreate();++  // Interrupt the select call.+  ASIO_DECL void interrupt();++  // Reset the select interrupter. Returns true if the reset was successful.+  ASIO_DECL bool reset();++  // Get the read descriptor to be passed to select.+  int read_descriptor() const+  {+    return read_descriptor_;+  }++private:+  // Open the descriptors. Throws on error.+  ASIO_DECL void open_descriptors();++  // Close the descriptors.+  ASIO_DECL void close_descriptors();++  // The read end of a connection used to interrupt the select call. This file+  // descriptor is passed to select such that when it is time to stop, a single+  // 64bit value will be written on the other end of the connection and this+  // descriptor will become readable.+  int read_descriptor_;++  // The write end of a connection used to interrupt the select call. A single+  // 64bit non-zero value may be written to this to wake up the select which is+  // waiting for the other end to become readable. This descriptor will only+  // differ from the read descriptor when a pipe is used.+  int write_descriptor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/eventfd_select_interrupter.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_EVENTFD)++#endif // ASIO_DETAIL_EVENTFD_SELECT_INTERRUPTER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/executor_function.hpp view
@@ -0,0 +1,203 @@+//+// detail/executor_function.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_EXECUTOR_FUNCTION_HPP+#define ASIO_DETAIL_EXECUTOR_FUNCTION_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/handler_alloc_helpers.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_HAS_MOVE)++// Lightweight, move-only function object wrapper.+class executor_function+{+public:+  template <typename F, typename Alloc>+  explicit executor_function(F f, const Alloc& a)+  {+    // Allocate and construct an object to wrap the function.+    typedef impl<F, Alloc> impl_type;+    typename impl_type::ptr p = {+      detail::addressof(a), impl_type::ptr::allocate(a), 0 };+    impl_ = new (p.v) impl_type(ASIO_MOVE_CAST(F)(f), a);+    p.v = 0;+  }++  executor_function(executor_function&& other) ASIO_NOEXCEPT+    : impl_(other.impl_)+  {+    other.impl_ = 0;+  }++  ~executor_function()+  {+    if (impl_)+      impl_->complete_(impl_, false);+  }++  void operator()()+  {+    if (impl_)+    {+      impl_base* i = impl_;+      impl_ = 0;+      i->complete_(i, true);+    }+  }++private:+  // Base class for polymorphic function implementations.+  struct impl_base+  {+    void (*complete_)(impl_base*, bool);+  };++  // Polymorphic function implementation.+  template <typename Function, typename Alloc>+  struct impl : impl_base+  {+    ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(+        thread_info_base::executor_function_tag, impl);++    template <typename F>+    impl(ASIO_MOVE_ARG(F) f, const Alloc& a)+      : function_(ASIO_MOVE_CAST(F)(f)),+        allocator_(a)+    {+      complete_ = &executor_function::complete<Function, Alloc>;+    }++    Function function_;+    Alloc allocator_;+  };++  // Helper to complete function invocation.+  template <typename Function, typename Alloc>+  static void complete(impl_base* base, bool call)+  {+    // Take ownership of the function object.+    impl<Function, Alloc>* i(static_cast<impl<Function, Alloc>*>(base));+    Alloc allocator(i->allocator_);+    typename impl<Function, Alloc>::ptr p = {+      detail::addressof(allocator), i, i };++    // Make a copy of the function so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the function may be the true owner of the memory+    // associated with the function. Consequently, a local copy of the function+    // is required to ensure that any owning sub-object remains valid until+    // after we have deallocated the memory here.+    Function function(ASIO_MOVE_CAST(Function)(i->function_));+    p.reset();++    // Make the upcall if required.+    if (call)+    {+      function();+    }+  }++  impl_base* impl_;+};++#else // defined(ASIO_HAS_MOVE)++// Not so lightweight, copyable function object wrapper.+class executor_function+{+public:+  template <typename F, typename Alloc>+  explicit executor_function(const F& f, const Alloc&)+    : impl_(new impl<typename decay<F>::type>(f))+  {+  }++  void operator()()+  {+    impl_->complete_(impl_.get());+  }++private:+  // Base class for polymorphic function implementations.+  struct impl_base+  {+    void (*complete_)(impl_base*);+  };++  // Polymorphic function implementation.+  template <typename F>+  struct impl : impl_base+  {+    impl(const F& f)+      : function_(f)+    {+      complete_ = &executor_function::complete<F>;+    }++    F function_;+  };++  // Helper to complete function invocation.+  template <typename F>+  static void complete(impl_base* i)+  {+    static_cast<impl<F>*>(i)->function_();+  }++  shared_ptr<impl_base> impl_;+};++#endif // defined(ASIO_HAS_MOVE)++// Lightweight, non-owning, copyable function object wrapper.+class executor_function_view+{+public:+  template <typename F>+  explicit executor_function_view(F& f) ASIO_NOEXCEPT+    : complete_(&executor_function_view::complete<F>),+      function_(&f)+  {+  }++  void operator()()+  {+    complete_(function_);+  }++private:+  // Helper to complete function invocation.+  template <typename F>+  static void complete(void* f)+  {+    (*static_cast<F*>(f))();+  }++  void (*complete_)(void*);+  void* function_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_EXECUTOR_FUNCTION_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/executor_op.hpp view
@@ -0,0 +1,84 @@+//+// detail/executor_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_EXECUTOR_OP_HPP+#define ASIO_DETAIL_EXECUTOR_OP_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/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/scheduler_operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename Alloc,+    typename Operation = scheduler_operation>+class executor_op : public Operation+{+public:+  ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(executor_op);++  template <typename H>+  executor_op(ASIO_MOVE_ARG(H) h, const Alloc& allocator)+    : Operation(&executor_op::do_complete),+      handler_(ASIO_MOVE_CAST(H)(h)),+      allocator_(allocator)+  {+  }++  static void do_complete(void* owner, Operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    executor_op* o(static_cast<executor_op*>(base));+    Alloc allocator(o->allocator_);+    ptr p = { detail::addressof(allocator), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    Handler handler(ASIO_MOVE_CAST(Handler)(o->handler_));+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN(());+      asio_handler_invoke_helpers::invoke(handler, handler);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  Alloc allocator_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_EXECUTOR_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/fd_set_adapter.hpp view
@@ -0,0 +1,39 @@+//+// detail/fd_set_adapter.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_FD_SET_ADAPTER_HPP+#define ASIO_DETAIL_FD_SET_ADAPTER_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_WINDOWS_RUNTIME)++#include "asio/detail/posix_fd_set_adapter.hpp"+#include "asio/detail/win_fd_set_adapter.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+typedef win_fd_set_adapter fd_set_adapter;+#else+typedef posix_fd_set_adapter fd_set_adapter;+#endif++} // namespace detail+} // namespace asio++#endif // !defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_FD_SET_ADAPTER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/fenced_block.hpp view
@@ -0,0 +1,80 @@+//+// detail/fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_FENCED_BLOCK_HPP+#define ASIO_DETAIL_FENCED_BLOCK_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_THREADS) \+  || defined(ASIO_DISABLE_FENCED_BLOCK)+# include "asio/detail/null_fenced_block.hpp"+#elif defined(ASIO_HAS_STD_ATOMIC)+# include "asio/detail/std_fenced_block.hpp"+#elif defined(__MACH__) && defined(__APPLE__)+# include "asio/detail/macos_fenced_block.hpp"+#elif defined(__sun)+# include "asio/detail/solaris_fenced_block.hpp"+#elif defined(__GNUC__) && defined(__arm__) \+  && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)+# include "asio/detail/gcc_arm_fenced_block.hpp"+#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))+# include "asio/detail/gcc_hppa_fenced_block.hpp"+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))+# include "asio/detail/gcc_x86_fenced_block.hpp"+#elif defined(__GNUC__) \+  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \+  && !defined(__INTEL_COMPILER) && !defined(__ICL) \+  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)+# include "asio/detail/gcc_sync_fenced_block.hpp"+#elif defined(ASIO_WINDOWS) && !defined(UNDER_CE)+# include "asio/detail/win_fenced_block.hpp"+#else+# include "asio/detail/null_fenced_block.hpp"+#endif++namespace asio {+namespace detail {++#if !defined(ASIO_HAS_THREADS) \+  || defined(ASIO_DISABLE_FENCED_BLOCK)+typedef null_fenced_block fenced_block;+#elif defined(ASIO_HAS_STD_ATOMIC)+typedef std_fenced_block fenced_block;+#elif defined(__MACH__) && defined(__APPLE__)+typedef macos_fenced_block fenced_block;+#elif defined(__sun)+typedef solaris_fenced_block fenced_block;+#elif defined(__GNUC__) && defined(__arm__) \+  && !defined(__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4)+typedef gcc_arm_fenced_block fenced_block;+#elif defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))+typedef gcc_hppa_fenced_block fenced_block;+#elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))+typedef gcc_x86_fenced_block fenced_block;+#elif defined(__GNUC__) \+  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \+  && !defined(__INTEL_COMPILER) && !defined(__ICL) \+  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)+typedef gcc_sync_fenced_block fenced_block;+#elif defined(ASIO_WINDOWS) && !defined(UNDER_CE)+typedef win_fenced_block fenced_block;+#else+typedef null_fenced_block fenced_block;+#endif++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/functional.hpp view
@@ -0,0 +1,38 @@+//+// detail/functional.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_FUNCTIONAL_HPP+#define ASIO_DETAIL_FUNCTIONAL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <functional>++#if !defined(ASIO_HAS_STD_FUNCTION)+# include <boost/function.hpp>+#endif // !defined(ASIO_HAS_STD_FUNCTION)++namespace asio {+namespace detail {++#if defined(ASIO_HAS_STD_FUNCTION)+using std::function;+#else // defined(ASIO_HAS_STD_FUNCTION)+using boost::function;+#endif // defined(ASIO_HAS_STD_FUNCTION)++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_FUNCTIONAL_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/future.hpp view
@@ -0,0 +1,33 @@+//+// detail/future.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_FUTURE_HPP+#define ASIO_DETAIL_FUTURE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#if defined(ASIO_HAS_STD_FUTURE)+# include <future>+// Even though the future header is available, libstdc++ may not implement the+// std::future class itself. However, we need to have already included the+// future header to reliably test for _GLIBCXX_HAS_GTHREADS.+# if defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX)+#  if defined(_GLIBCXX_HAS_GTHREADS)+#   define ASIO_HAS_STD_FUTURE_CLASS 1+#  endif // defined(_GLIBCXX_HAS_GTHREADS)+# else // defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX)+#  define ASIO_HAS_STD_FUTURE_CLASS 1+# endif // defined(__GNUC__) && !defined(ASIO_HAS_CLANG_LIBCXX)+#endif // defined(ASIO_HAS_STD_FUTURE)++#endif // ASIO_DETAIL_FUTURE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/gcc_arm_fenced_block.hpp view
@@ -0,0 +1,91 @@+//+// detail/gcc_arm_fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP+#define ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(__GNUC__) && defined(__arm__)++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class gcc_arm_fenced_block+  : private noncopyable+{+public:+  enum half_t { half };+  enum full_t { full };++  // Constructor for a half fenced block.+  explicit gcc_arm_fenced_block(half_t)+  {+  }++  // Constructor for a full fenced block.+  explicit gcc_arm_fenced_block(full_t)+  {+    barrier();+  }++  // Destructor.+  ~gcc_arm_fenced_block()+  {+    barrier();+  }++private:+  static void barrier()+  {+#if defined(__ARM_ARCH_4__) \+    || defined(__ARM_ARCH_4T__) \+    || defined(__ARM_ARCH_5__) \+    || defined(__ARM_ARCH_5E__) \+    || defined(__ARM_ARCH_5T__) \+    || defined(__ARM_ARCH_5TE__) \+    || defined(__ARM_ARCH_5TEJ__) \+    || defined(__ARM_ARCH_6__) \+    || defined(__ARM_ARCH_6J__) \+    || defined(__ARM_ARCH_6K__) \+    || defined(__ARM_ARCH_6Z__) \+    || defined(__ARM_ARCH_6ZK__) \+    || defined(__ARM_ARCH_6T2__)+# if defined(__thumb__)+    // This is just a placeholder and almost certainly not sufficient.+    __asm__ __volatile__ ("" : : : "memory");+# else // defined(__thumb__)+    int a = 0, b = 0;+    __asm__ __volatile__ ("swp %0, %1, [%2]"+        : "=&r"(a) : "r"(1), "r"(&b) : "memory", "cc");+# endif // defined(__thumb__)+#else+    // ARMv7 and later.+    __asm__ __volatile__ ("dmb" : : : "memory");+#endif+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(__GNUC__) && defined(__arm__)++#endif // ASIO_DETAIL_GCC_ARM_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/gcc_hppa_fenced_block.hpp view
@@ -0,0 +1,68 @@+//+// detail/gcc_hppa_fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP+#define ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class gcc_hppa_fenced_block+  : private noncopyable+{+public:+  enum half_t { half };+  enum full_t { full };++  // Constructor for a half fenced block.+  explicit gcc_hppa_fenced_block(half_t)+  {+  }++  // Constructor for a full fenced block.+  explicit gcc_hppa_fenced_block(full_t)+  {+    barrier();+  }++  // Destructor.+  ~gcc_hppa_fenced_block()+  {+    barrier();+  }++private:+  static void barrier()+  {+    // This is just a placeholder and almost certainly not sufficient.+    __asm__ __volatile__ ("" : : : "memory");+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(__GNUC__) && (defined(__hppa) || defined(__hppa__))++#endif // ASIO_DETAIL_GCC_HPPA_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/gcc_sync_fenced_block.hpp view
@@ -0,0 +1,65 @@+//+// detail/gcc_sync_fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP+#define ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(__GNUC__) \+  && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)) \+  && !defined(__INTEL_COMPILER) && !defined(__ICL) \+  && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class gcc_sync_fenced_block+  : private noncopyable+{+public:+  enum half_or_full_t { half, full };++  // Constructor.+  explicit gcc_sync_fenced_block(half_or_full_t)+    : value_(0)+  {+    __sync_lock_test_and_set(&value_, 1);+  }++  // Destructor.+  ~gcc_sync_fenced_block()+  {+    __sync_lock_release(&value_);+  }++private:+  int value_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(__GNUC__)+       // && ((__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4))+       // && !defined(__INTEL_COMPILER) && !defined(__ICL)+       // && !defined(__ICC) && !defined(__ECC) && !defined(__PATHSCALE__)++#endif // ASIO_DETAIL_GCC_SYNC_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/gcc_x86_fenced_block.hpp view
@@ -0,0 +1,99 @@+//+// detail/gcc_x86_fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP+#define ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class gcc_x86_fenced_block+  : private noncopyable+{+public:+  enum half_t { half };+  enum full_t { full };++  // Constructor for a half fenced block.+  explicit gcc_x86_fenced_block(half_t)+  {+  }++  // Constructor for a full fenced block.+  explicit gcc_x86_fenced_block(full_t)+  {+    lbarrier();+  }++  // Destructor.+  ~gcc_x86_fenced_block()+  {+    sbarrier();+  }++private:+  static int barrier()+  {+    int r = 0, m = 1;+    __asm__ __volatile__ (+        "xchgl %0, %1" :+        "=r"(r), "=m"(m) :+        "0"(1), "m"(m) :+        "memory", "cc");+    return r;+  }++  static void lbarrier()+  {+#if defined(__SSE2__)+# if (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL)+    __builtin_ia32_lfence();+# else // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL)+    __asm__ __volatile__ ("lfence" ::: "memory");+# endif // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL)+#else // defined(__SSE2__)+    barrier();+#endif // defined(__SSE2__)+  }++  static void sbarrier()+  {+#if defined(__SSE2__)+# if (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL)+    __builtin_ia32_sfence();+# else // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL)+    __asm__ __volatile__ ("sfence" ::: "memory");+# endif // (__GNUC__ >= 4) && !defined(__INTEL_COMPILER) && !defined(__ICL)+#else // defined(__SSE2__)+    barrier();+#endif // defined(__SSE2__)+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__))++#endif // ASIO_DETAIL_GCC_X86_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/global.hpp view
@@ -0,0 +1,52 @@+//+// detail/global.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_GLOBAL_HPP+#define ASIO_DETAIL_GLOBAL_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_THREADS)+# include "asio/detail/null_global.hpp"+#elif defined(ASIO_WINDOWS)+# include "asio/detail/win_global.hpp"+#elif defined(ASIO_HAS_PTHREADS)+# include "asio/detail/posix_global.hpp"+#elif defined(ASIO_HAS_STD_CALL_ONCE)+# include "asio/detail/std_global.hpp"+#else+# error Only Windows, POSIX and std::call_once are supported!+#endif++namespace asio {+namespace detail {++template <typename T>+inline T& global()+{+#if !defined(ASIO_HAS_THREADS)+  return null_global<T>();+#elif defined(ASIO_WINDOWS)+  return win_global<T>();+#elif defined(ASIO_HAS_PTHREADS)+  return posix_global<T>();+#elif defined(ASIO_HAS_STD_CALL_ONCE)+  return std_global<T>();+#endif+}++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_GLOBAL_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/handler_alloc_helpers.hpp view
@@ -0,0 +1,284 @@+//+// detail/handler_alloc_helpers.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP+#define ASIO_DETAIL_HANDLER_ALLOC_HELPERS_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/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/detail/thread_info_base.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/handler_alloc_hook.hpp"++#include "asio/detail/push_options.hpp"++// Calls to asio_handler_allocate and asio_handler_deallocate must be made from+// a namespace that does not contain any overloads of these functions. The+// asio_handler_alloc_helpers namespace is defined here for that purpose.+namespace asio_handler_alloc_helpers {++#if defined(ASIO_NO_DEPRECATED)+template <typename Handler>+inline void error_if_hooks_are_defined(Handler& h)+{+  using asio::asio_handler_allocate;+  // If you get an error here it is because some of your handlers still+  // overload asio_handler_allocate, but this hook is no longer used.+  (void)static_cast<asio::asio_handler_allocate_is_no_longer_used>(+    asio_handler_allocate(static_cast<std::size_t>(0),+      asio::detail::addressof(h)));++  using asio::asio_handler_deallocate;+  // If you get an error here it is because some of your handlers still+  // overload asio_handler_deallocate, but this hook is no longer used.+  (void)static_cast<asio::asio_handler_deallocate_is_no_longer_used>(+    asio_handler_deallocate(static_cast<void*>(0),+      static_cast<std::size_t>(0), asio::detail::addressof(h)));+}+#endif // defined(ASIO_NO_DEPRECATED)++template <typename Handler>+inline void* allocate(std::size_t s, Handler& h)+{+#if !defined(ASIO_HAS_HANDLER_HOOKS)+  return ::operator new(s);+#elif defined(ASIO_NO_DEPRECATED)+  // The asio_handler_allocate hook is no longer used to obtain memory.+  (void)&error_if_hooks_are_defined<Handler>;+  (void)h;+#if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+  return asio::detail::thread_info_base::allocate(+      asio::detail::thread_context::thread_call_stack::top(), s);+#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+  return ::operator new(size);+#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+#else+  using asio::asio_handler_allocate;+  return asio_handler_allocate(s, asio::detail::addressof(h));+#endif+}++template <typename Handler>+inline void deallocate(void* p, std::size_t s, Handler& h)+{+#if !defined(ASIO_HAS_HANDLER_HOOKS)+  ::operator delete(p);+#elif defined(ASIO_NO_DEPRECATED)+  // The asio_handler_allocate hook is no longer used to obtain memory.+  (void)&error_if_hooks_are_defined<Handler>;+  (void)h;+#if !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+  asio::detail::thread_info_base::deallocate(+      asio::detail::thread_context::thread_call_stack::top(), p, s);+#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+  (void)s;+  ::operator delete(p);+#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+#else+  using asio::asio_handler_deallocate;+  asio_handler_deallocate(p, s, asio::detail::addressof(h));+#endif+}++} // namespace asio_handler_alloc_helpers++namespace asio {+namespace detail {++template <typename Handler, typename T>+class hook_allocator+{+public:+  typedef T value_type;++  template <typename U>+  struct rebind+  {+    typedef hook_allocator<Handler, U> other;+  };++  explicit hook_allocator(Handler& h)+    : handler_(h)+  {+  }++  template <typename U>+  hook_allocator(const hook_allocator<Handler, U>& a)+    : handler_(a.handler_)+  {+  }++  T* allocate(std::size_t n)+  {+    return static_cast<T*>(+        asio_handler_alloc_helpers::allocate(sizeof(T) * n, handler_));+  }++  void deallocate(T* p, std::size_t n)+  {+    asio_handler_alloc_helpers::deallocate(p, sizeof(T) * n, handler_);+  }++//private:+  Handler& handler_;+};++template <typename Handler>+class hook_allocator<Handler, void>+{+public:+  typedef void value_type;++  template <typename U>+  struct rebind+  {+    typedef hook_allocator<Handler, U> other;+  };++  explicit hook_allocator(Handler& h)+    : handler_(h)+  {+  }++  template <typename U>+  hook_allocator(const hook_allocator<Handler, U>& a)+    : handler_(a.handler_)+  {+  }++//private:+  Handler& handler_;+};++template <typename Handler, typename Allocator>+struct get_hook_allocator+{+  typedef Allocator type;++  static type get(Handler&, const Allocator& a)+  {+    return a;+  }+};++template <typename Handler, typename T>+struct get_hook_allocator<Handler, std::allocator<T> >+{+  typedef hook_allocator<Handler, T> type;++  static type get(Handler& handler, const std::allocator<T>&)+  {+    return type(handler);+  }+};++} // namespace detail+} // namespace asio++#define ASIO_DEFINE_HANDLER_PTR(op) \+  struct ptr \+  { \+    Handler* h; \+    op* v; \+    op* p; \+    ~ptr() \+    { \+      reset(); \+    } \+    static op* allocate(Handler& handler) \+    { \+      typedef typename ::asio::associated_allocator< \+        Handler>::type associated_allocator_type; \+      typedef typename ::asio::detail::get_hook_allocator< \+        Handler, associated_allocator_type>::type hook_allocator_type; \+      ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \+            ::asio::detail::get_hook_allocator< \+              Handler, associated_allocator_type>::get( \+                handler, ::asio::get_associated_allocator(handler))); \+      return a.allocate(1); \+    } \+    void reset() \+    { \+      if (p) \+      { \+        p->~op(); \+        p = 0; \+      } \+      if (v) \+      { \+        typedef typename ::asio::associated_allocator< \+          Handler>::type associated_allocator_type; \+        typedef typename ::asio::detail::get_hook_allocator< \+          Handler, associated_allocator_type>::type hook_allocator_type; \+        ASIO_REBIND_ALLOC(hook_allocator_type, op) a( \+              ::asio::detail::get_hook_allocator< \+                Handler, associated_allocator_type>::get( \+                  *h, ::asio::get_associated_allocator(*h))); \+        a.deallocate(static_cast<op*>(v), 1); \+        v = 0; \+      } \+    } \+  } \+  /**/++#define ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR(purpose, op) \+  struct ptr \+  { \+    const Alloc* a; \+    void* v; \+    op* p; \+    ~ptr() \+    { \+      reset(); \+    } \+    static op* allocate(const Alloc& a) \+    { \+      typedef typename ::asio::detail::get_recycling_allocator< \+        Alloc, purpose>::type recycling_allocator_type; \+      ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \+            ::asio::detail::get_recycling_allocator< \+              Alloc, purpose>::get(a)); \+      return a1.allocate(1); \+    } \+    void reset() \+    { \+      if (p) \+      { \+        p->~op(); \+        p = 0; \+      } \+      if (v) \+      { \+        typedef typename ::asio::detail::get_recycling_allocator< \+          Alloc, purpose>::type recycling_allocator_type; \+        ASIO_REBIND_ALLOC(recycling_allocator_type, op) a1( \+              ::asio::detail::get_recycling_allocator< \+                Alloc, purpose>::get(*a)); \+        a1.deallocate(static_cast<op*>(v), 1); \+        v = 0; \+      } \+    } \+  } \+  /**/++#define ASIO_DEFINE_HANDLER_ALLOCATOR_PTR(op) \+  ASIO_DEFINE_TAGGED_HANDLER_ALLOCATOR_PTR( \+      ::asio::detail::thread_info_base::default_tag, op ) \+  /**/++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_HANDLER_ALLOC_HELPERS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/handler_cont_helpers.hpp view
@@ -0,0 +1,45 @@+//+// detail/handler_cont_helpers.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP+#define ASIO_DETAIL_HANDLER_CONT_HELPERS_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/memory.hpp"+#include "asio/handler_continuation_hook.hpp"++#include "asio/detail/push_options.hpp"++// Calls to asio_handler_is_continuation must be made from a namespace that+// does not contain overloads of this function. This namespace is defined here+// for that purpose.+namespace asio_handler_cont_helpers {++template <typename Context>+inline bool is_continuation(Context& context)+{+#if !defined(ASIO_HAS_HANDLER_HOOKS)+  return false;+#else+  using asio::asio_handler_is_continuation;+  return asio_handler_is_continuation(+      asio::detail::addressof(context));+#endif+}++} // namespace asio_handler_cont_helpers++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_HANDLER_CONT_HELPERS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/handler_invoke_helpers.hpp view
@@ -0,0 +1,80 @@+//+// detail/handler_invoke_helpers.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP+#define ASIO_DETAIL_HANDLER_INVOKE_HELPERS_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/memory.hpp"+#include "asio/handler_invoke_hook.hpp"++#include "asio/detail/push_options.hpp"++// Calls to asio_handler_invoke must be made from a namespace that does not+// contain overloads of this function. The asio_handler_invoke_helpers+// namespace is defined here for that purpose.+namespace asio_handler_invoke_helpers {++#if defined(ASIO_NO_DEPRECATED)+template <typename Function, typename Context>+inline void error_if_hook_is_defined(Function& function, Context& context)+{+  using asio::asio_handler_invoke;+  // If you get an error here it is because some of your handlers still+  // overload asio_handler_invoke, but this hook is no longer used.+  (void)static_cast<asio::asio_handler_invoke_is_no_longer_used>(+    asio_handler_invoke(function, asio::detail::addressof(context)));+}+#endif // defined(ASIO_NO_DEPRECATED)++template <typename Function, typename Context>+inline void invoke(Function& function, Context& context)+{+#if !defined(ASIO_HAS_HANDLER_HOOKS)+  Function tmp(function);+  tmp();+#elif defined(ASIO_NO_DEPRECATED)+  // The asio_handler_invoke hook is no longer used to invoke the function.+  (void)&error_if_hook_is_defined<Function, Context>;+  (void)context;+  function();+#else+  using asio::asio_handler_invoke;+  asio_handler_invoke(function, asio::detail::addressof(context));+#endif+}++template <typename Function, typename Context>+inline void invoke(const Function& function, Context& context)+{+#if !defined(ASIO_HAS_HANDLER_HOOKS)+  Function tmp(function);+  tmp();+#elif defined(ASIO_NO_DEPRECATED)+  // The asio_handler_invoke hook is no longer used to invoke the function.+  (void)&error_if_hook_is_defined<const Function, Context>;+  (void)context;+  Function tmp(function);+  tmp();+#else+  using asio::asio_handler_invoke;+  asio_handler_invoke(function, asio::detail::addressof(context));+#endif+}++} // namespace asio_handler_invoke_helpers++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_HANDLER_INVOKE_HELPERS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/handler_tracking.hpp view
@@ -0,0 +1,264 @@+//+// detail/handler_tracking.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_HANDLER_TRACKING_HPP+#define ASIO_DETAIL_HANDLER_TRACKING_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++namespace asio {++class execution_context;++} // namespace asio++#if defined(ASIO_CUSTOM_HANDLER_TRACKING)+# include ASIO_CUSTOM_HANDLER_TRACKING+#elif defined(ASIO_ENABLE_HANDLER_TRACKING)+# include "asio/error_code.hpp"+# include "asio/detail/cstdint.hpp"+# include "asio/detail/static_mutex.hpp"+# include "asio/detail/tss_ptr.hpp"+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_CUSTOM_HANDLER_TRACKING)++// The user-specified header must define the following macros:+// - ASIO_INHERIT_TRACKED_HANDLER+// - ASIO_ALSO_INHERIT_TRACKED_HANDLER+// - ASIO_HANDLER_TRACKING_INIT+// - ASIO_HANDLER_CREATION(args)+// - ASIO_HANDLER_COMPLETION(args)+// - ASIO_HANDLER_INVOCATION_BEGIN(args)+// - ASIO_HANDLER_INVOCATION_END+// - ASIO_HANDLER_OPERATION(args)+// - ASIO_HANDLER_REACTOR_REGISTRATION(args)+// - ASIO_HANDLER_REACTOR_DEREGISTRATION(args)+// - ASIO_HANDLER_REACTOR_READ_EVENT+// - ASIO_HANDLER_REACTOR_WRITE_EVENT+// - ASIO_HANDLER_REACTOR_ERROR_EVENT+// - ASIO_HANDLER_REACTOR_EVENTS(args)+// - ASIO_HANDLER_REACTOR_OPERATION(args)++# if !defined(ASIO_ENABLE_HANDLER_TRACKING)+#  define ASIO_ENABLE_HANDLER_TRACKING 1+# endif /// !defined(ASIO_ENABLE_HANDLER_TRACKING)++#elif defined(ASIO_ENABLE_HANDLER_TRACKING)++class handler_tracking+{+public:+  class completion;++  // Base class for objects containing tracked handlers.+  class tracked_handler+  {+  private:+    // Only the handler_tracking class will have access to the id.+    friend class handler_tracking;+    friend class completion;+    uint64_t id_;++  protected:+    // Constructor initialises with no id.+    tracked_handler() : id_(0) {}++    // Prevent deletion through this type.+    ~tracked_handler() {}+  };++  // Initialise the tracking system.+  ASIO_DECL static void init();++  class location+  {+  public:+    // Constructor adds a location to the stack.+    ASIO_DECL explicit location(const char* file,+        int line, const char* func);++    // Destructor removes a location from the stack.+    ASIO_DECL ~location();++  private:+    // Disallow copying and assignment.+    location(const location&) ASIO_DELETED;+    location& operator=(const location&) ASIO_DELETED;++    friend class handler_tracking;+    const char* file_;+    int line_;+    const char* func_;+    location* next_;+  };++  // Record the creation of a tracked handler.+  ASIO_DECL static void creation(+      execution_context& context, tracked_handler& h,+      const char* object_type, void* object,+      uintmax_t native_handle, const char* op_name);++  class completion+  {+  public:+    // Constructor records that handler is to be invoked with no arguments.+    ASIO_DECL explicit completion(const tracked_handler& h);++    // Destructor records only when an exception is thrown from the handler, or+    // if the memory is being freed without the handler having been invoked.+    ASIO_DECL ~completion();++    // Records that handler is to be invoked with no arguments.+    ASIO_DECL void invocation_begin();++    // Records that handler is to be invoked with one arguments.+    ASIO_DECL void invocation_begin(const asio::error_code& ec);++    // Constructor records that handler is to be invoked with two arguments.+    ASIO_DECL void invocation_begin(+        const asio::error_code& ec, std::size_t bytes_transferred);++    // Constructor records that handler is to be invoked with two arguments.+    ASIO_DECL void invocation_begin(+        const asio::error_code& ec, int signal_number);++    // Constructor records that handler is to be invoked with two arguments.+    ASIO_DECL void invocation_begin(+        const asio::error_code& ec, const char* arg);++    // Record that handler invocation has ended.+    ASIO_DECL void invocation_end();++  private:+    friend class handler_tracking;+    uint64_t id_;+    bool invoked_;+    completion* next_;+  };++  // Record an operation that is not directly associated with a handler.+  ASIO_DECL static void operation(execution_context& context,+      const char* object_type, void* object,+      uintmax_t native_handle, const char* op_name);++  // Record that a descriptor has been registered with the reactor.+  ASIO_DECL static void reactor_registration(execution_context& context,+      uintmax_t native_handle, uintmax_t registration);++  // Record that a descriptor has been deregistered from the reactor.+  ASIO_DECL static void reactor_deregistration(execution_context& context,+      uintmax_t native_handle, uintmax_t registration);++  // Record a reactor-based operation that is associated with a handler.+  ASIO_DECL static void reactor_events(execution_context& context,+      uintmax_t registration, unsigned events);++  // Record a reactor-based operation that is associated with a handler.+  ASIO_DECL static void reactor_operation(+      const tracked_handler& h, const char* op_name,+      const asio::error_code& ec);++  // Record a reactor-based operation that is associated with a handler.+  ASIO_DECL static void reactor_operation(+      const tracked_handler& h, const char* op_name,+      const asio::error_code& ec, std::size_t bytes_transferred);++  // Write a line of output.+  ASIO_DECL static void write_line(const char* format, ...);++private:+  struct tracking_state;+  ASIO_DECL static tracking_state* get_state();+};++# define ASIO_INHERIT_TRACKED_HANDLER \+  : public asio::detail::handler_tracking::tracked_handler++# define ASIO_ALSO_INHERIT_TRACKED_HANDLER \+  , public asio::detail::handler_tracking::tracked_handler++# define ASIO_HANDLER_TRACKING_INIT \+  asio::detail::handler_tracking::init()++# define ASIO_HANDLER_LOCATION(args) \+  asio::detail::handler_tracking::location tracked_location args++# define ASIO_HANDLER_CREATION(args) \+  asio::detail::handler_tracking::creation args++# define ASIO_HANDLER_COMPLETION(args) \+  asio::detail::handler_tracking::completion tracked_completion args++# define ASIO_HANDLER_INVOCATION_BEGIN(args) \+  tracked_completion.invocation_begin args++# define ASIO_HANDLER_INVOCATION_END \+  tracked_completion.invocation_end()++# define ASIO_HANDLER_OPERATION(args) \+  asio::detail::handler_tracking::operation args++# define ASIO_HANDLER_REACTOR_REGISTRATION(args) \+  asio::detail::handler_tracking::reactor_registration args++# define ASIO_HANDLER_REACTOR_DEREGISTRATION(args) \+  asio::detail::handler_tracking::reactor_deregistration args++# define ASIO_HANDLER_REACTOR_READ_EVENT 1+# define ASIO_HANDLER_REACTOR_WRITE_EVENT 2+# define ASIO_HANDLER_REACTOR_ERROR_EVENT 4++# define ASIO_HANDLER_REACTOR_EVENTS(args) \+  asio::detail::handler_tracking::reactor_events args++# define ASIO_HANDLER_REACTOR_OPERATION(args) \+  asio::detail::handler_tracking::reactor_operation args++#else // defined(ASIO_ENABLE_HANDLER_TRACKING)++# define ASIO_INHERIT_TRACKED_HANDLER+# define ASIO_ALSO_INHERIT_TRACKED_HANDLER+# define ASIO_HANDLER_TRACKING_INIT (void)0+# define ASIO_HANDLER_LOCATION(loc) (void)0+# define ASIO_HANDLER_CREATION(args) (void)0+# define ASIO_HANDLER_COMPLETION(args) (void)0+# define ASIO_HANDLER_INVOCATION_BEGIN(args) (void)0+# define ASIO_HANDLER_INVOCATION_END (void)0+# define ASIO_HANDLER_OPERATION(args) (void)0+# define ASIO_HANDLER_REACTOR_REGISTRATION(args) (void)0+# define ASIO_HANDLER_REACTOR_DEREGISTRATION(args) (void)0+# define ASIO_HANDLER_REACTOR_READ_EVENT 0+# define ASIO_HANDLER_REACTOR_WRITE_EVENT 0+# define ASIO_HANDLER_REACTOR_ERROR_EVENT 0+# define ASIO_HANDLER_REACTOR_EVENTS(args) (void)0+# define ASIO_HANDLER_REACTOR_OPERATION(args) (void)0++#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/handler_tracking.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_HANDLER_TRACKING_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/handler_type_requirements.hpp view
@@ -0,0 +1,556 @@+//+// detail/handler_type_requirements.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP+#define ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++// Older versions of gcc have difficulty compiling the sizeof expressions where+// we test the handler type requirements. We'll disable checking of handler type+// requirements for those compilers, but otherwise enable it by default.+#if !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)+# if !defined(__GNUC__) || (__GNUC__ >= 4)+#  define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS 1+# endif // !defined(__GNUC__) || (__GNUC__ >= 4)+#endif // !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)++// With C++0x we can use a combination of enhanced SFINAE and static_assert to+// generate better template error messages. As this technique is not yet widely+// portable, we'll only enable it for tested compilers.+#if !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)+# if defined(__GNUC__)+#  if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+#   if defined(__GXX_EXPERIMENTAL_CXX0X__)+#    define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1+#   endif // defined(__GXX_EXPERIMENTAL_CXX0X__)+#  endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+# endif // defined(__GNUC__)+# if defined(ASIO_MSVC)+#  if (_MSC_VER >= 1600)+#   define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1+#  endif // (_MSC_VER >= 1600)+# endif // defined(ASIO_MSVC)+# if defined(__clang__)+#  if __has_feature(__cxx_static_assert__)+#   define ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT 1+#  endif // __has_feature(cxx_static_assert)+# endif // defined(__clang__)+#endif // !defined(ASIO_DISABLE_HANDLER_TYPE_REQUIREMENTS)++#if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)+# include "asio/async_result.hpp"+#endif // defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)++namespace asio {+namespace detail {++#if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)++# if defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)++template <typename Handler>+auto zero_arg_copyable_handler_test(Handler h, void*)+  -> decltype(+    sizeof(Handler(static_cast<const Handler&>(h))),+    ((h)()),+    char(0));++template <typename Handler>+char (&zero_arg_copyable_handler_test(Handler, ...))[2];++template <typename Handler, typename Arg1>+auto one_arg_handler_test(Handler h, Arg1* a1)+  -> decltype(+    sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),+    ((h)(*a1)),+    char(0));++template <typename Handler>+char (&one_arg_handler_test(Handler h, ...))[2];++template <typename Handler, typename Arg1, typename Arg2>+auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)+  -> decltype(+    sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),+    ((h)(*a1, *a2)),+    char(0));++template <typename Handler>+char (&two_arg_handler_test(Handler, ...))[2];++template <typename Handler, typename Arg1, typename Arg2>+auto two_arg_move_handler_test(Handler h, Arg1* a1, Arg2* a2)+  -> decltype(+    sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),+    ((h)(*a1, ASIO_MOVE_CAST(Arg2)(*a2))),+    char(0));++template <typename Handler>+char (&two_arg_move_handler_test(Handler, ...))[2];++#  define ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg) \+     static_assert(expr, msg);++# else // defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)++#  define ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT(expr, msg)++# endif // defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS_ASSERT)++template <typename T> T& lvref();+template <typename T> T& lvref(T);+template <typename T> const T& clvref();+template <typename T> const T& clvref(T);+#if defined(ASIO_HAS_MOVE)+template <typename T> T rvref();+template <typename T> T rvref(T);+#else // defined(ASIO_HAS_MOVE)+template <typename T> const T& rvref();+template <typename T> const T& rvref(T);+#endif // defined(ASIO_HAS_MOVE)+template <typename T> char argbyv(T);++template <int>+struct handler_type_requirements+{+};++#define ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void()) asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::zero_arg_copyable_handler_test( \+          asio::detail::clvref< \+            asio_true_handler_type>(), 0)) == 1, \+      "CompletionHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::clvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()(), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_READ_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code, std::size_t)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::two_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0), \+          static_cast<const std::size_t*>(0))) == 1, \+      "ReadHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>(), \+            asio::detail::lvref<const std::size_t>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_WRITE_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code, std::size_t)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::two_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0), \+          static_cast<const std::size_t*>(0))) == 1, \+      "WriteHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>(), \+            asio::detail::lvref<const std::size_t>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_ACCEPT_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::one_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0))) == 1, \+      "AcceptHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_MOVE_ACCEPT_HANDLER_CHECK( \+    handler_type, handler, socket_type) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code, socket_type)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::two_arg_move_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0), \+          static_cast<socket_type*>(0))) == 1, \+      "MoveAcceptHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>(), \+            asio::detail::rvref<socket_type>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_CONNECT_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::one_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0))) == 1, \+      "ConnectHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_RANGE_CONNECT_HANDLER_CHECK( \+    handler_type, handler, endpoint_type) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code, endpoint_type)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::two_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0), \+          static_cast<const endpoint_type*>(0))) == 1, \+      "RangeConnectHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>(), \+            asio::detail::lvref<const endpoint_type>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \+    handler_type, handler, iter_type) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code, iter_type)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::two_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0), \+          static_cast<const iter_type*>(0))) == 1, \+      "IteratorConnectHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>(), \+            asio::detail::lvref<const iter_type>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_RESOLVE_HANDLER_CHECK( \+    handler_type, handler, range_type) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code, range_type)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::two_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0), \+          static_cast<const range_type*>(0))) == 1, \+      "ResolveHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>(), \+            asio::detail::lvref<const range_type>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_WAIT_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::one_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0))) == 1, \+      "WaitHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_SIGNAL_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code, int)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::two_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0), \+          static_cast<const int*>(0))) == 1, \+      "SignalHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>(), \+            asio::detail::lvref<const int>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_HANDSHAKE_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::one_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0))) == 1, \+      "HandshakeHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code, std::size_t)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::two_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0), \+          static_cast<const std::size_t*>(0))) == 1, \+      "BufferedHandshakeHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+          asio::detail::lvref<const asio::error_code>(), \+          asio::detail::lvref<const std::size_t>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#define ASIO_SHUTDOWN_HANDLER_CHECK( \+    handler_type, handler) \+  \+  typedef ASIO_HANDLER_TYPE(handler_type, \+      void(asio::error_code)) \+    asio_true_handler_type; \+  \+  ASIO_HANDLER_TYPE_REQUIREMENTS_ASSERT( \+      sizeof(asio::detail::one_arg_handler_test( \+          asio::detail::rvref< \+            asio_true_handler_type>(), \+          static_cast<const asio::error_code*>(0))) == 1, \+      "ShutdownHandler type requirements not met") \+  \+  typedef asio::detail::handler_type_requirements< \+      sizeof( \+        asio::detail::argbyv( \+          asio::detail::rvref< \+            asio_true_handler_type>())) + \+      sizeof( \+        asio::detail::lvref< \+          asio_true_handler_type>()( \+            asio::detail::lvref<const asio::error_code>()), \+        char(0))> ASIO_UNUSED_TYPEDEF++#else // !defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)++#define ASIO_LEGACY_COMPLETION_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_READ_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_WRITE_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_ACCEPT_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_MOVE_ACCEPT_HANDLER_CHECK( \+    handler_type, handler, socket_type) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_CONNECT_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_RANGE_CONNECT_HANDLER_CHECK( \+    handler_type, handler, iter_type) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_ITERATOR_CONNECT_HANDLER_CHECK( \+    handler_type, handler, iter_type) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_RESOLVE_HANDLER_CHECK( \+    handler_type, handler, iter_type) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_WAIT_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_SIGNAL_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_HANDSHAKE_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#define ASIO_SHUTDOWN_HANDLER_CHECK( \+    handler_type, handler) \+  typedef int ASIO_UNUSED_TYPEDEF++#endif // !defined(ASIO_ENABLE_HANDLER_TYPE_REQUIREMENTS)++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_HANDLER_TYPE_REQUIREMENTS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/handler_work.hpp view
@@ -0,0 +1,438 @@+//+// detail/handler_work.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_HANDLER_WORK_HPP+#define ASIO_DETAIL_HANDLER_WORK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_executor.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/allocator.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/execution/execute.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/outstanding_work.hpp"+#include "asio/executor_work_guard.hpp"+#include "asio/prefer.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++class executor;+class io_context;++namespace execution {++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename...> class any_executor;++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename, typename, typename, typename, typename,+    typename, typename, typename, typename> class any_executor;++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace execution+namespace detail {++template <typename Executor, typename CandidateExecutor = void,+    typename IoContext = io_context,+    typename PolymorphicExecutor = executor, typename = void>+class handler_work_base+{+public:+  explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT+    : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+  {+  }++  template <typename OtherExecutor>+  handler_work_base(const Executor& ex,+      const OtherExecutor&) ASIO_NOEXCEPT+    : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+  {+  }++  handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT+    : executor_(other.executor_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(executor_type)(other.executor_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  bool owns_work() const ASIO_NOEXCEPT+  {+    return true;+  }++  template <typename Function, typename Handler>+  void dispatch(Function& function, Handler& handler)+  {+    execution::execute(+        asio::prefer(executor_,+          execution::blocking.possibly,+          execution::allocator((get_associated_allocator)(handler))),+        ASIO_MOVE_CAST(Function)(function));+  }++private:+  typedef typename decay<+      typename prefer_result<Executor,+        execution::outstanding_work_t::tracked_t+      >::type+    >::type executor_type;++  executor_type executor_;+};++template <typename Executor, typename CandidateExecutor,+    typename IoContext, typename PolymorphicExecutor>+class handler_work_base<Executor, CandidateExecutor,+    IoContext, PolymorphicExecutor,+    typename enable_if<+      !execution::is_executor<Executor>::value+        && (!is_same<Executor, PolymorphicExecutor>::value+          || !is_same<CandidateExecutor, void>::value)+    >::type>+{+public:+  explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT+    : executor_(ex),+      owns_work_(true)+  {+    executor_.on_work_started();+  }++  handler_work_base(const Executor& ex,+      const Executor& candidate) ASIO_NOEXCEPT+    : executor_(ex),+      owns_work_(ex != candidate)+  {+    if (owns_work_)+      executor_.on_work_started();+  }++  template <typename OtherExecutor>+  handler_work_base(const Executor& ex,+      const OtherExecutor&) ASIO_NOEXCEPT+    : executor_(ex),+      owns_work_(true)+  {+    executor_.on_work_started();+  }++  handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT+    : executor_(other.executor_),+      owns_work_(other.owns_work_)+  {+    if (owns_work_)+      executor_.on_work_started();+  }++#if defined(ASIO_HAS_MOVE)+  handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)),+      owns_work_(other.owns_work_)+  {+    other.owns_work_ = false;+  }+#endif // defined(ASIO_HAS_MOVE)++  ~handler_work_base()+  {+    if (owns_work_)+      executor_.on_work_finished();+  }++  bool owns_work() const ASIO_NOEXCEPT+  {+    return owns_work_;+  }++  template <typename Function, typename Handler>+  void dispatch(Function& function, Handler& handler)+  {+    executor_.dispatch(ASIO_MOVE_CAST(Function)(function),+        asio::get_associated_allocator(handler));+  }++private:+  Executor executor_;+  bool owns_work_;+};++template <typename Executor, typename IoContext, typename PolymorphicExecutor>+class handler_work_base<Executor, void, IoContext, PolymorphicExecutor,+    typename enable_if<+      is_same<+        Executor,+        typename IoContext::executor_type+      >::value+    >::type>+{+public:+  explicit handler_work_base(const Executor&)+  {+  }++  bool owns_work() const ASIO_NOEXCEPT+  {+    return false;+  }++  template <typename Function, typename Handler>+  void dispatch(Function& function, Handler& handler)+  {+    // When using a native implementation, I/O completion handlers are+    // already dispatched according to the execution context's executor's+    // rules. We can call the function directly.+    asio_handler_invoke_helpers::invoke(function, handler);+  }+};++template <typename Executor, typename IoContext>+class handler_work_base<Executor, void, IoContext, Executor>+{+public:+  explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT+#if !defined(ASIO_NO_TYPEID)+    : executor_(+        ex.target_type() == typeid(typename IoContext::executor_type)+          ? Executor() : ex)+#else // !defined(ASIO_NO_TYPEID)+    : executor_(ex)+#endif // !defined(ASIO_NO_TYPEID)+  {+    if (executor_)+      executor_.on_work_started();+  }++  handler_work_base(const Executor& ex,+      const Executor& candidate) ASIO_NOEXCEPT+    : executor_(ex != candidate ? ex : Executor())+  {+    if (executor_)+      executor_.on_work_started();+  }++  template <typename OtherExecutor>+  handler_work_base(const Executor& ex,+      const OtherExecutor&) ASIO_NOEXCEPT+    : executor_(ex)+  {+    executor_.on_work_started();+  }++  handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT+    : executor_(other.executor_)+  {+    if (executor_)+      executor_.on_work_started();+  }++#if defined(ASIO_HAS_MOVE)+  handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(Executor)(other.executor_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  ~handler_work_base()+  {+    if (executor_)+      executor_.on_work_finished();+  }++  bool owns_work() const ASIO_NOEXCEPT+  {+    return !!executor_;+  }++  template <typename Function, typename Handler>+  void dispatch(Function& function, Handler& handler)+  {+    executor_.dispatch(ASIO_MOVE_CAST(Function)(function),+        asio::get_associated_allocator(handler));+  }++private:+  Executor executor_;+};++template <+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)+    typename... SupportableProperties,+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+    typename T1, typename T2, typename T3, typename T4, typename T5,+    typename T6, typename T7, typename T8, typename T9,+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+    typename IoContext, typename PolymorphicExecutor>+class handler_work_base<+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)+    execution::any_executor<SupportableProperties...>,+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+    execution::any_executor<T1, T2, T3, T4, T5, T6, T7, T8, T9>,+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+    void, IoContext, PolymorphicExecutor>+{+public:+  typedef+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)+    execution::any_executor<SupportableProperties...>+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+    execution::any_executor<T1, T2, T3, T4, T5, T6, T7, T8, T9>+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+    executor_type;++  explicit handler_work_base(const executor_type& ex) ASIO_NOEXCEPT+#if !defined(ASIO_NO_TYPEID)+    : executor_(+        ex.target_type() == typeid(typename IoContext::executor_type)+          ? executor_type()+          : asio::prefer(ex, execution::outstanding_work.tracked))+#else // !defined(ASIO_NO_TYPEID)+    : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+#endif // !defined(ASIO_NO_TYPEID)+  {+  }++  handler_work_base(const executor_type& ex,+      const executor_type& candidate) ASIO_NOEXCEPT+    : executor_(ex != candidate ? ex : executor_type())+  {+  }++  template <typename OtherExecutor>+  handler_work_base(const executor_type& ex,+      const OtherExecutor&) ASIO_NOEXCEPT+    : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+  {+  }++  handler_work_base(const handler_work_base& other) ASIO_NOEXCEPT+    : executor_(other.executor_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  handler_work_base(handler_work_base&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(executor_type)(other.executor_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  bool owns_work() const ASIO_NOEXCEPT+  {+    return !!executor_;+  }++  template <typename Function, typename Handler>+  void dispatch(Function& function, Handler& handler)+  {+    execution::execute(+        asio::prefer(executor_,+          execution::blocking.possibly,+          execution::allocator((get_associated_allocator)(handler))),+        ASIO_MOVE_CAST(Function)(function));+  }++private:+  executor_type executor_;+};++template <typename Handler, typename IoExecutor, typename = void>+class handler_work :+  handler_work_base<IoExecutor>,+  handler_work_base<typename associated_executor<+      Handler, IoExecutor>::type, IoExecutor>+{+public:+  typedef handler_work_base<IoExecutor> base1_type;+  typedef handler_work_base<typename associated_executor<+    Handler, IoExecutor>::type, IoExecutor> base2_type;++  handler_work(Handler& handler, const IoExecutor& io_ex) ASIO_NOEXCEPT+    : base1_type(io_ex),+      base2_type(asio::get_associated_executor(handler, io_ex), io_ex)+  {+  }++  template <typename Function>+  void complete(Function& function, Handler& handler)+  {+    if (!base1_type::owns_work() && !base2_type::owns_work())+    {+      // When using a native implementation, I/O completion handlers are+      // already dispatched according to the execution context's executor's+      // rules. We can call the function directly.+      asio_handler_invoke_helpers::invoke(function, handler);+    }+    else+    {+      base2_type::dispatch(function, handler);+    }+  }+};++template <typename Handler, typename IoExecutor>+class handler_work<+    Handler, IoExecutor,+    typename enable_if<+      is_same<+        typename associated_executor<Handler,+          IoExecutor>::asio_associated_executor_is_unspecialised,+        void+      >::value+    >::type> : handler_work_base<IoExecutor>+{+public:+  typedef handler_work_base<IoExecutor> base1_type;++  handler_work(Handler&, const IoExecutor& io_ex) ASIO_NOEXCEPT+    : base1_type(io_ex)+  {+  }++  template <typename Function>+  void complete(Function& function, Handler& handler)+  {+    if (!base1_type::owns_work())+    {+      // When using a native implementation, I/O completion handlers are+      // already dispatched according to the execution context's executor's+      // rules. We can call the function directly.+      asio_handler_invoke_helpers::invoke(function, handler);+    }+    else+    {+      base1_type::dispatch(function, handler);+    }+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_HANDLER_WORK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/hash_map.hpp view
@@ -0,0 +1,331 @@+//+// detail/hash_map.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_HASH_MAP_HPP+#define ASIO_DETAIL_HASH_MAP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <list>+#include <utility>+#include "asio/detail/assert.hpp"+#include "asio/detail/noncopyable.hpp"++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# include "asio/detail/socket_types.hpp"+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++inline std::size_t calculate_hash_value(int i)+{+  return static_cast<std::size_t>(i);+}++inline std::size_t calculate_hash_value(void* p)+{+  return reinterpret_cast<std::size_t>(p)+    + (reinterpret_cast<std::size_t>(p) >> 3);+}++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+inline std::size_t calculate_hash_value(SOCKET s)+{+  return static_cast<std::size_t>(s);+}+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++// Note: assumes K and V are POD types.+template <typename K, typename V>+class hash_map+  : private noncopyable+{+public:+  // The type of a value in the map.+  typedef std::pair<K, V> value_type;++  // The type of a non-const iterator over the hash map.+  typedef typename std::list<value_type>::iterator iterator;++  // The type of a const iterator over the hash map.+  typedef typename std::list<value_type>::const_iterator const_iterator;++  // Constructor.+  hash_map()+    : size_(0),+      buckets_(0),+      num_buckets_(0)+  {+  }++  // Destructor.+  ~hash_map()+  {+    delete[] buckets_;+  }++  // Get an iterator for the beginning of the map.+  iterator begin()+  {+    return values_.begin();+  }++  // Get an iterator for the beginning of the map.+  const_iterator begin() const+  {+    return values_.begin();+  }++  // Get an iterator for the end of the map.+  iterator end()+  {+    return values_.end();+  }++  // Get an iterator for the end of the map.+  const_iterator end() const+  {+    return values_.end();+  }++  // Check whether the map is empty.+  bool empty() const+  {+    return values_.empty();+  }++  // Find an entry in the map.+  iterator find(const K& k)+  {+    if (num_buckets_)+    {+      size_t bucket = calculate_hash_value(k) % num_buckets_;+      iterator it = buckets_[bucket].first;+      if (it == values_.end())+        return values_.end();+      iterator end_it = buckets_[bucket].last;+      ++end_it;+      while (it != end_it)+      {+        if (it->first == k)+          return it;+        ++it;+      }+    }+    return values_.end();+  }++  // Find an entry in the map.+  const_iterator find(const K& k) const+  {+    if (num_buckets_)+    {+      size_t bucket = calculate_hash_value(k) % num_buckets_;+      const_iterator it = buckets_[bucket].first;+      if (it == values_.end())+        return it;+      const_iterator end_it = buckets_[bucket].last;+      ++end_it;+      while (it != end_it)+      {+        if (it->first == k)+          return it;+        ++it;+      }+    }+    return values_.end();+  }++  // Insert a new entry into the map.+  std::pair<iterator, bool> insert(const value_type& v)+  {+    if (size_ + 1 >= num_buckets_)+      rehash(hash_size(size_ + 1));+    size_t bucket = calculate_hash_value(v.first) % num_buckets_;+    iterator it = buckets_[bucket].first;+    if (it == values_.end())+    {+      buckets_[bucket].first = buckets_[bucket].last =+        values_insert(values_.end(), v);+      ++size_;+      return std::pair<iterator, bool>(buckets_[bucket].last, true);+    }+    iterator end_it = buckets_[bucket].last;+    ++end_it;+    while (it != end_it)+    {+      if (it->first == v.first)+        return std::pair<iterator, bool>(it, false);+      ++it;+    }+    buckets_[bucket].last = values_insert(end_it, v);+    ++size_;+    return std::pair<iterator, bool>(buckets_[bucket].last, true);+  }++  // Erase an entry from the map.+  void erase(iterator it)+  {+    ASIO_ASSERT(it != values_.end());+    ASIO_ASSERT(num_buckets_ != 0);++    size_t bucket = calculate_hash_value(it->first) % num_buckets_;+    bool is_first = (it == buckets_[bucket].first);+    bool is_last = (it == buckets_[bucket].last);+    if (is_first && is_last)+      buckets_[bucket].first = buckets_[bucket].last = values_.end();+    else if (is_first)+      ++buckets_[bucket].first;+    else if (is_last)+      --buckets_[bucket].last;++    values_erase(it);+    --size_;+  }++  // Erase a key from the map.+  void erase(const K& k)+  {+    iterator it = find(k);+    if (it != values_.end())+      erase(it);+  }++  // Remove all entries from the map.+  void clear()+  {+    // Clear the values.+    values_.clear();+    size_ = 0;++    // Initialise all buckets to empty.+    iterator end_it = values_.end();+    for (size_t i = 0; i < num_buckets_; ++i)+      buckets_[i].first = buckets_[i].last = end_it;+  }++private:+  // Calculate the hash size for the specified number of elements.+  static std::size_t hash_size(std::size_t num_elems)+  {+    static std::size_t sizes[] =+    {+#if defined(ASIO_HASH_MAP_BUCKETS)+      ASIO_HASH_MAP_BUCKETS+#else // ASIO_HASH_MAP_BUCKETS+      3, 13, 23, 53, 97, 193, 389, 769, 1543, 3079, 6151, 12289, 24593,+      49157, 98317, 196613, 393241, 786433, 1572869, 3145739, 6291469,+      12582917, 25165843+#endif // ASIO_HASH_MAP_BUCKETS+    };+    const std::size_t nth_size = sizeof(sizes) / sizeof(std::size_t) - 1;+    for (std::size_t i = 0; i < nth_size; ++i)+      if (num_elems < sizes[i])+        return sizes[i];+    return sizes[nth_size];+  }++  // Re-initialise the hash from the values already contained in the list.+  void rehash(std::size_t num_buckets)+  {+    if (num_buckets == num_buckets_)+      return;+    ASIO_ASSERT(num_buckets != 0);++    iterator end_iter = values_.end();++    // Update number of buckets and initialise all buckets to empty.+    bucket_type* tmp = new bucket_type[num_buckets];+    delete[] buckets_;+    buckets_ = tmp;+    num_buckets_ = num_buckets;+    for (std::size_t i = 0; i < num_buckets_; ++i)+      buckets_[i].first = buckets_[i].last = end_iter;++    // Put all values back into the hash.+    iterator iter = values_.begin();+    while (iter != end_iter)+    {+      std::size_t bucket = calculate_hash_value(iter->first) % num_buckets_;+      if (buckets_[bucket].last == end_iter)+      {+        buckets_[bucket].first = buckets_[bucket].last = iter++;+      }+      else if (++buckets_[bucket].last == iter)+      {+        ++iter;+      }+      else+      {+        values_.splice(buckets_[bucket].last, values_, iter++);+        --buckets_[bucket].last;+      }+    }+  }++  // Insert an element into the values list by splicing from the spares list,+  // if a spare is available, and otherwise by inserting a new element.+  iterator values_insert(iterator it, const value_type& v)+  {+    if (spares_.empty())+    {+      return values_.insert(it, v);+    }+    else+    {+      spares_.front() = v;+      values_.splice(it, spares_, spares_.begin());+      return --it;+    }+  }++  // Erase an element from the values list by splicing it to the spares list.+  void values_erase(iterator it)+  {+    *it = value_type();+    spares_.splice(spares_.begin(), values_, it);+  }++  // The number of elements in the hash.+  std::size_t size_;++  // The list of all values in the hash map.+  std::list<value_type> values_;++  // The list of spare nodes waiting to be recycled. Assumes that POD types only+  // are stored in the hash map.+  std::list<value_type> spares_;++  // The type for a bucket in the hash table.+  struct bucket_type+  {+    iterator first;+    iterator last;+  };++  // The buckets in the hash.+  bucket_type* buckets_;++  // The number of buckets in the hash.+  std::size_t num_buckets_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_HASH_MAP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp view
@@ -0,0 +1,118 @@+//+// detail/impl/buffer_sequence_adapter.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP+#define ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)++#include <robuffer.h>+#include <windows.storage.streams.h>+#include <wrl/implements.h>+#include "asio/detail/buffer_sequence_adapter.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class winrt_buffer_impl :+  public Microsoft::WRL::RuntimeClass<+    Microsoft::WRL::RuntimeClassFlags<+      Microsoft::WRL::RuntimeClassType::WinRtClassicComMix>,+    ABI::Windows::Storage::Streams::IBuffer,+    Windows::Storage::Streams::IBufferByteAccess>+{+public:+  explicit winrt_buffer_impl(const asio::const_buffer& b)+  {+    bytes_ = const_cast<byte*>(static_cast<const byte*>(b.data()));+    length_ = b.size();+    capacity_ = b.size();+  }++  explicit winrt_buffer_impl(const asio::mutable_buffer& b)+  {+    bytes_ = static_cast<byte*>(b.data());+    length_ = 0;+    capacity_ = b.size();+  }++  ~winrt_buffer_impl()+  {+  }++  STDMETHODIMP Buffer(byte** value)+  {+    *value = bytes_;+    return S_OK;+  }++  STDMETHODIMP get_Capacity(UINT32* value)+  {+    *value = capacity_;+    return S_OK;+  }++  STDMETHODIMP get_Length(UINT32 *value)+  {+    *value = length_;+    return S_OK;+  }++  STDMETHODIMP put_Length(UINT32 value)+  {+    if (value > capacity_)+      return E_INVALIDARG;+    length_ = value;+    return S_OK;+  }++private:+  byte* bytes_;+  UINT32 length_;+  UINT32 capacity_;+};++void buffer_sequence_adapter_base::init_native_buffer(+    buffer_sequence_adapter_base::native_buffer_type& buf,+    const asio::mutable_buffer& buffer)+{+  std::memset(&buf, 0, sizeof(native_buffer_type));+  Microsoft::WRL::ComPtr<IInspectable> insp+    = Microsoft::WRL::Make<winrt_buffer_impl>(buffer);+  buf = reinterpret_cast<Windows::Storage::Streams::IBuffer^>(insp.Get());+}++void buffer_sequence_adapter_base::init_native_buffer(+    buffer_sequence_adapter_base::native_buffer_type& buf,+    const asio::const_buffer& buffer)+{+  std::memset(&buf, 0, sizeof(native_buffer_type));+  Microsoft::WRL::ComPtr<IInspectable> insp+    = Microsoft::WRL::Make<winrt_buffer_impl>(buffer);+  Platform::Object^ buf_obj = reinterpret_cast<Platform::Object^>(insp.Get());+  buf = reinterpret_cast<Windows::Storage::Streams::IBuffer^>(insp.Get());+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_IMPL_BUFFER_SEQUENCE_ADAPTER_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/descriptor_ops.ipp view
@@ -0,0 +1,608 @@+//+// detail/impl/descriptor_ops.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP+#define ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <cerrno>+#include "asio/detail/descriptor_ops.hpp"+#include "asio/error.hpp"++#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {+namespace descriptor_ops {++int open(const char* path, int flags, asio::error_code& ec)+{+  int result = ::open(path, flags);+  get_last_error(ec, result < 0);+  return result;+}++int close(int d, state_type& state, asio::error_code& ec)+{+  int result = 0;+  if (d != -1)+  {+    result = ::close(d);+    get_last_error(ec, result < 0);++    if (result != 0+        && (ec == asio::error::would_block+          || ec == asio::error::try_again))+    {+      // According to UNIX Network Programming Vol. 1, it is possible for+      // close() to fail with EWOULDBLOCK under certain circumstances. What+      // isn't clear is the state of the descriptor after this error. The one+      // current OS where this behaviour is seen, Windows, says that the socket+      // remains open. Therefore we'll put the descriptor back into blocking+      // mode and have another attempt at closing it.+#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+      int flags = ::fcntl(d, F_GETFL, 0);+      if (flags >= 0)+        ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);+#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+      ioctl_arg_type arg = 0;+      ::ioctl(d, FIONBIO, &arg);+#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+      state &= ~non_blocking;++      result = ::close(d);+      get_last_error(ec, result < 0);+    }+  }++  return result;+}++bool set_user_non_blocking(int d, state_type& state,+    bool value, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return false;+  }++#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+  int result = ::fcntl(d, F_GETFL, 0);+  get_last_error(ec, result < 0);+  if (result >= 0)+  {+    int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));+    result = ::fcntl(d, F_SETFL, flag);+    get_last_error(ec, result < 0);+  }+#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+  ioctl_arg_type arg = (value ? 1 : 0);+  int result = ::ioctl(d, FIONBIO, &arg);+  get_last_error(ec, result < 0);+#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)++  if (result >= 0)+  {+    if (value)+      state |= user_set_non_blocking;+    else+    {+      // Clearing the user-set non-blocking mode always overrides any+      // internally-set non-blocking flag. Any subsequent asynchronous+      // operations will need to re-enable non-blocking I/O.+      state &= ~(user_set_non_blocking | internal_non_blocking);+    }+    return true;+  }++  return false;+}++bool set_internal_non_blocking(int d, state_type& state,+    bool value, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return false;+  }++  if (!value && (state & user_set_non_blocking))+  {+    // It does not make sense to clear the internal non-blocking flag if the+    // user still wants non-blocking behaviour. Return an error and let the+    // caller figure out whether to update the user-set non-blocking flag.+    ec = asio::error::invalid_argument;+    return false;+  }++#if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+  int result = ::fcntl(d, F_GETFL, 0);+  get_last_error(ec, result < 0);+  if (result >= 0)+  {+    int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));+    result = ::fcntl(d, F_SETFL, flag);+    get_last_error(ec, result < 0);+  }+#else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+  ioctl_arg_type arg = (value ? 1 : 0);+  int result = ::ioctl(d, FIONBIO, &arg);+  get_last_error(ec, result < 0);+#endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)++  if (result >= 0)+  {+    if (value)+      state |= internal_non_blocking;+    else+      state &= ~internal_non_blocking;+    return true;+  }++  return false;+}++std::size_t sync_read(int d, state_type state, buf* bufs,+    std::size_t count, bool all_empty, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // A request to read 0 bytes on a stream is a no-op.+  if (all_empty)+  {+    ec.assign(0, ec.category());+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count));+    get_last_error(ec, bytes < 0);++    // Check if operation succeeded.+    if (bytes > 0)+      return bytes;++    // Check for EOF.+    if (bytes == 0)+    {+      ec = asio::error::eof;+      return 0;+    }++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for descriptor to become ready.+    if (descriptor_ops::poll_read(d, 0, ec) < 0)+      return 0;+  }+}++std::size_t sync_read1(int d, state_type state, void* data,+    std::size_t size, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // A request to read 0 bytes on a stream is a no-op.+  if (size == 0)+  {+    ec.assign(0, ec.category());+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = ::read(d, data, size);+    get_last_error(ec, bytes < 0);++    // Check if operation succeeded.+    if (bytes > 0)+      return bytes;++    // Check for EOF.+    if (bytes == 0)+    {+      ec = asio::error::eof;+      return 0;+    }++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for descriptor to become ready.+    if (descriptor_ops::poll_read(d, 0, ec) < 0)+      return 0;+  }+}++bool non_blocking_read(int d, buf* bufs, std::size_t count,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  for (;;)+  {+    // Read some data.+    signed_size_type bytes = ::readv(d, bufs, static_cast<int>(count));+    get_last_error(ec, bytes < 0);++    // Check for end of stream.+    if (bytes == 0)+    {+      ec = asio::error::eof;+      return true;+    }++    // Check if operation succeeded.+    if (bytes > 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++bool non_blocking_read1(int d, void* data, std::size_t size,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  for (;;)+  {+    // Read some data.+    signed_size_type bytes = ::read(d, data, size);+    get_last_error(ec, bytes < 0);++    // Check for end of stream.+    if (bytes == 0)+    {+      ec = asio::error::eof;+      return true;+    }++    // Check if operation succeeded.+    if (bytes > 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++std::size_t sync_write(int d, state_type state, const buf* bufs,+    std::size_t count, bool all_empty, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // A request to write 0 bytes on a stream is a no-op.+  if (all_empty)+  {+    ec.assign(0, ec.category());+    return 0;+  }++  // Write some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count));+    get_last_error(ec, bytes < 0);++    // Check if operation succeeded.+    if (bytes > 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for descriptor to become ready.+    if (descriptor_ops::poll_write(d, 0, ec) < 0)+      return 0;+  }+}++std::size_t sync_write1(int d, state_type state, const void* data,+    std::size_t size, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // A request to write 0 bytes on a stream is a no-op.+  if (size == 0)+  {+    ec.assign(0, ec.category());+    return 0;+  }++  // Write some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = ::write(d, data, size);+    get_last_error(ec, bytes < 0);++    // Check if operation succeeded.+    if (bytes > 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for descriptor to become ready.+    if (descriptor_ops::poll_write(d, 0, ec) < 0)+      return 0;+  }+}++bool non_blocking_write(int d, const buf* bufs, std::size_t count,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  for (;;)+  {+    // Write some data.+    signed_size_type bytes = ::writev(d, bufs, static_cast<int>(count));+    get_last_error(ec, bytes < 0);++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++bool non_blocking_write1(int d, const void* data, std::size_t size,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  for (;;)+  {+    // Write some data.+    signed_size_type bytes = ::write(d, data, size);+    get_last_error(ec, bytes < 0);++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++int ioctl(int d, state_type& state, long cmd,+    ioctl_arg_type* arg, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return -1;+  }++  int result = ::ioctl(d, cmd, arg);+  get_last_error(ec, result < 0);++  if (result >= 0)+  {+    // When updating the non-blocking mode we always perform the ioctl syscall,+    // even if the flags would otherwise indicate that the descriptor is+    // already in the correct state. This ensures that the underlying+    // descriptor is put into the state that has been requested by the user. If+    // the ioctl syscall was successful then we need to update the flags to+    // match.+    if (cmd == static_cast<long>(FIONBIO))+    {+      if (*arg)+      {+        state |= user_set_non_blocking;+      }+      else+      {+        // Clearing the non-blocking mode always overrides any internally-set+        // non-blocking flag. Any subsequent asynchronous operations will need+        // to re-enable non-blocking I/O.+        state &= ~(user_set_non_blocking | internal_non_blocking);+      }+    }+  }++  return result;+}++int fcntl(int d, int cmd, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return -1;+  }++  int result = ::fcntl(d, cmd);+  get_last_error(ec, result < 0);+  return result;+}++int fcntl(int d, int cmd, long arg, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return -1;+  }++  int result = ::fcntl(d, cmd, arg);+  get_last_error(ec, result < 0);+  return result;+}++int poll_read(int d, state_type state, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return -1;+  }++  pollfd fds;+  fds.fd = d;+  fds.events = POLLIN;+  fds.revents = 0;+  int timeout = (state & user_set_non_blocking) ? 0 : -1;+  int result = ::poll(&fds, 1, timeout);+  get_last_error(ec, result < 0);+  if (result == 0)+    if (state & user_set_non_blocking)+      ec = asio::error::would_block;+  return result;+}++int poll_write(int d, state_type state, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return -1;+  }++  pollfd fds;+  fds.fd = d;+  fds.events = POLLOUT;+  fds.revents = 0;+  int timeout = (state & user_set_non_blocking) ? 0 : -1;+  int result = ::poll(&fds, 1, timeout);+  get_last_error(ec, result < 0);+  if (result == 0)+    if (state & user_set_non_blocking)+      ec = asio::error::would_block;+  return result;+}++int poll_error(int d, state_type state, asio::error_code& ec)+{+  if (d == -1)+  {+    ec = asio::error::bad_descriptor;+    return -1;+  }++  pollfd fds;+  fds.fd = d;+  fds.events = POLLPRI | POLLERR | POLLHUP;+  fds.revents = 0;+  int timeout = (state & user_set_non_blocking) ? 0 : -1;+  int result = ::poll(&fds, 1, timeout);+  get_last_error(ec, result < 0);+  if (result == 0)+    if (state & user_set_non_blocking)+      ec = asio::error::would_block;+  return result;+}++} // namespace descriptor_ops+} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)++#endif // ASIO_DETAIL_IMPL_DESCRIPTOR_OPS_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.hpp view
@@ -0,0 +1,91 @@+//+// detail/impl/dev_poll_reactor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP+#define ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_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_DEV_POLL)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Time_Traits>+void dev_poll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_add_timer_queue(queue);+}++template <typename Time_Traits>+void dev_poll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_remove_timer_queue(queue);+}++template <typename Time_Traits>+void dev_poll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,+    const typename Time_Traits::time_type& time,+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  if (shutdown_)+  {+    scheduler_.post_immediate_completion(op, false);+    return;+  }++  bool earliest = queue.enqueue_timer(time, timer, op);+  scheduler_.work_started();+  if (earliest)+    interrupter_.interrupt();+}++template <typename Time_Traits>+std::size_t dev_poll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& timer,+    std::size_t max_cancelled)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+  return n;+}++template <typename Time_Traits>+void dev_poll_reactor::move_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& target,+    typename timer_queue<Time_Traits>::per_timer_data& source)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer(target, ops);+  queue.move_timer(target, source);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_DEV_POLL)++#endif // ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.ipp view
@@ -0,0 +1,446 @@+//+// detail/impl/dev_poll_reactor.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP+#define ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP++#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_DEV_POLL)++#include "asio/detail/dev_poll_reactor.hpp"+#include "asio/detail/assert.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++dev_poll_reactor::dev_poll_reactor(asio::execution_context& ctx)+  : asio::detail::execution_context_service_base<dev_poll_reactor>(ctx),+    scheduler_(use_service<scheduler>(ctx)),+    mutex_(),+    dev_poll_fd_(do_dev_poll_create()),+    interrupter_(),+    shutdown_(false)+{+  // Add the interrupter's descriptor to /dev/poll.+  ::pollfd ev = { 0, 0, 0 };+  ev.fd = interrupter_.read_descriptor();+  ev.events = POLLIN | POLLERR;+  ev.revents = 0;+  ::write(dev_poll_fd_, &ev, sizeof(ev));+}++dev_poll_reactor::~dev_poll_reactor()+{+  shutdown();+  ::close(dev_poll_fd_);+}++void dev_poll_reactor::shutdown()+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  shutdown_ = true;+  lock.unlock();++  op_queue<operation> ops;++  for (int i = 0; i < max_ops; ++i)+    op_queue_[i].get_all_operations(ops);++  timer_queues_.get_all_timers(ops);++  scheduler_.abandon_operations(ops);+} ++void dev_poll_reactor::notify_fork(+    asio::execution_context::fork_event fork_ev)+{+  if (fork_ev == asio::execution_context::fork_child)+  {+    detail::mutex::scoped_lock lock(mutex_);++    if (dev_poll_fd_ != -1)+      ::close(dev_poll_fd_);+    dev_poll_fd_ = -1;+    dev_poll_fd_ = do_dev_poll_create();++    interrupter_.recreate();++    // Add the interrupter's descriptor to /dev/poll.+    ::pollfd ev = { 0, 0, 0 };+    ev.fd = interrupter_.read_descriptor();+    ev.events = POLLIN | POLLERR;+    ev.revents = 0;+    ::write(dev_poll_fd_, &ev, sizeof(ev));++    // Re-register all descriptors with /dev/poll. The changes will be written+    // to the /dev/poll descriptor the next time the reactor is run.+    for (int i = 0; i < max_ops; ++i)+    {+      reactor_op_queue<socket_type>::iterator iter = op_queue_[i].begin();+      reactor_op_queue<socket_type>::iterator end = op_queue_[i].end();+      for (; iter != end; ++iter)+      {+        ::pollfd& pending_ev = add_pending_event_change(iter->first);+        pending_ev.events |= POLLERR | POLLHUP;+        switch (i)+        {+        case read_op: pending_ev.events |= POLLIN; break;+        case write_op: pending_ev.events |= POLLOUT; break;+        case except_op: pending_ev.events |= POLLPRI; break;+        default: break;+        }+      }+    }+    interrupter_.interrupt();+  }+}++void dev_poll_reactor::init_task()+{+  scheduler_.init_task();+}++int dev_poll_reactor::register_descriptor(socket_type, per_descriptor_data&)+{+  return 0;+}++int dev_poll_reactor::register_internal_descriptor(int op_type,+    socket_type descriptor, per_descriptor_data&, reactor_op* op)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  op_queue_[op_type].enqueue_operation(descriptor, op);+  ::pollfd& ev = add_pending_event_change(descriptor);+  ev.events = POLLERR | POLLHUP;+  switch (op_type)+  {+  case read_op: ev.events |= POLLIN; break;+  case write_op: ev.events |= POLLOUT; break;+  case except_op: ev.events |= POLLPRI; break;+  default: break;+  }+  interrupter_.interrupt();++  return 0;+}++void dev_poll_reactor::move_descriptor(socket_type,+    dev_poll_reactor::per_descriptor_data&,+    dev_poll_reactor::per_descriptor_data&)+{+}++void dev_poll_reactor::start_op(int op_type, socket_type descriptor,+    dev_poll_reactor::per_descriptor_data&, reactor_op* op,+    bool is_continuation, bool allow_speculative)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  if (shutdown_)+  {+    post_immediate_completion(op, is_continuation);+    return;+  }++  if (allow_speculative)+  {+    if (op_type != read_op || !op_queue_[except_op].has_operation(descriptor))+    {+      if (!op_queue_[op_type].has_operation(descriptor))+      {+        if (op->perform())+        {+          lock.unlock();+          scheduler_.post_immediate_completion(op, is_continuation);+          return;+        }+      }+    }+  }++  bool first = op_queue_[op_type].enqueue_operation(descriptor, op);+  scheduler_.work_started();+  if (first)+  {+    ::pollfd& ev = add_pending_event_change(descriptor);+    ev.events = POLLERR | POLLHUP;+    if (op_type == read_op+        || op_queue_[read_op].has_operation(descriptor))+      ev.events |= POLLIN;+    if (op_type == write_op+        || op_queue_[write_op].has_operation(descriptor))+      ev.events |= POLLOUT;+    if (op_type == except_op+        || op_queue_[except_op].has_operation(descriptor))+      ev.events |= POLLPRI;+    interrupter_.interrupt();+  }+}++void dev_poll_reactor::cancel_ops(socket_type descriptor,+    dev_poll_reactor::per_descriptor_data&)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);+}++void dev_poll_reactor::deregister_descriptor(socket_type descriptor,+    dev_poll_reactor::per_descriptor_data&, bool)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  // Remove the descriptor from /dev/poll.+  ::pollfd& ev = add_pending_event_change(descriptor);+  ev.events = POLLREMOVE;+  interrupter_.interrupt();++  // Cancel any outstanding operations associated with the descriptor.+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);+}++void dev_poll_reactor::deregister_internal_descriptor(+    socket_type descriptor, dev_poll_reactor::per_descriptor_data&)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  // Remove the descriptor from /dev/poll. Since this function is only called+  // during a fork, we can apply the change immediately.+  ::pollfd ev = { 0, 0, 0 };+  ev.fd = descriptor;+  ev.events = POLLREMOVE;+  ev.revents = 0;+  ::write(dev_poll_fd_, &ev, sizeof(ev));++  // Destroy all operations associated with the descriptor.+  op_queue<operation> ops;+  asio::error_code ec;+  for (int i = 0; i < max_ops; ++i)+    op_queue_[i].cancel_operations(descriptor, ops, ec);+}++void dev_poll_reactor::cleanup_descriptor_data(+    dev_poll_reactor::per_descriptor_data&)+{+}++void dev_poll_reactor::run(long usec, op_queue<operation>& ops)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  // We can return immediately if there's no work to do and the reactor is+  // not supposed to block.+  if (usec == 0 && op_queue_[read_op].empty() && op_queue_[write_op].empty()+      && op_queue_[except_op].empty() && timer_queues_.all_empty())+    return;++  // Write the pending event registration changes to the /dev/poll descriptor.+  std::size_t events_size = sizeof(::pollfd) * pending_event_changes_.size();+  if (events_size > 0)+  {+    errno = 0;+    int result = ::write(dev_poll_fd_,+        &pending_event_changes_[0], events_size);+    if (result != static_cast<int>(events_size))+    {+      asio::error_code ec = asio::error_code(+          errno, asio::error::get_system_category());+      for (std::size_t i = 0; i < pending_event_changes_.size(); ++i)+      {+        int descriptor = pending_event_changes_[i].fd;+        for (int j = 0; j < max_ops; ++j)+          op_queue_[j].cancel_operations(descriptor, ops, ec);+      }+    }+    pending_event_changes_.clear();+    pending_event_change_index_.clear();+  }++  // Calculate timeout.+  int timeout;+  if (usec == 0)+    timeout = 0;+  else+  {+    timeout = (usec < 0) ? -1 : ((usec - 1) / 1000 + 1);+    timeout = get_timeout(timeout);+  }+  lock.unlock();++  // Block on the /dev/poll descriptor.+  ::pollfd events[128] = { { 0, 0, 0 } };+  ::dvpoll dp = { 0, 0, 0 };+  dp.dp_fds = events;+  dp.dp_nfds = 128;+  dp.dp_timeout = timeout;+  int num_events = ::ioctl(dev_poll_fd_, DP_POLL, &dp);++  lock.lock();++  // Dispatch the waiting events.+  for (int i = 0; i < num_events; ++i)+  {+    int descriptor = events[i].fd;+    if (descriptor == interrupter_.read_descriptor())+    {+      interrupter_.reset();+    }+    else+    {+      bool more_reads = false;+      bool more_writes = false;+      bool more_except = false;++      // Exception operations must be processed first to ensure that any+      // out-of-band data is read before normal data.+      if (events[i].events & (POLLPRI | POLLERR | POLLHUP))+        more_except =+          op_queue_[except_op].perform_operations(descriptor, ops);+      else+        more_except = op_queue_[except_op].has_operation(descriptor);++      if (events[i].events & (POLLIN | POLLERR | POLLHUP))+        more_reads = op_queue_[read_op].perform_operations(descriptor, ops);+      else+        more_reads = op_queue_[read_op].has_operation(descriptor);++      if (events[i].events & (POLLOUT | POLLERR | POLLHUP))+        more_writes = op_queue_[write_op].perform_operations(descriptor, ops);+      else+        more_writes = op_queue_[write_op].has_operation(descriptor);++      if ((events[i].events & (POLLERR | POLLHUP)) != 0+            && !more_except && !more_reads && !more_writes)+      {+        // If we have an event and no operations associated with the+        // descriptor then we need to delete the descriptor from /dev/poll.+        // The poll operation can produce POLLHUP or POLLERR events when there+        // is no operation pending, so if we do not remove the descriptor we+        // can end up in a tight polling loop.+        ::pollfd ev = { 0, 0, 0 };+        ev.fd = descriptor;+        ev.events = POLLREMOVE;+        ev.revents = 0;+        ::write(dev_poll_fd_, &ev, sizeof(ev));+      }+      else+      {+        ::pollfd ev = { 0, 0, 0 };+        ev.fd = descriptor;+        ev.events = POLLERR | POLLHUP;+        if (more_reads)+          ev.events |= POLLIN;+        if (more_writes)+          ev.events |= POLLOUT;+        if (more_except)+          ev.events |= POLLPRI;+        ev.revents = 0;+        int result = ::write(dev_poll_fd_, &ev, sizeof(ev));+        if (result != sizeof(ev))+        {+          asio::error_code ec(errno,+              asio::error::get_system_category());+          for (int j = 0; j < max_ops; ++j)+            op_queue_[j].cancel_operations(descriptor, ops, ec);+        }+      }+    }+  }+  timer_queues_.get_ready_timers(ops);+}++void dev_poll_reactor::interrupt()+{+  interrupter_.interrupt();+}++int dev_poll_reactor::do_dev_poll_create()+{+  int fd = ::open("/dev/poll", O_RDWR);+  if (fd == -1)+  {+    asio::error_code ec(errno,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "/dev/poll");+  }+  return fd;+}++void dev_poll_reactor::do_add_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.insert(&queue);+}++void dev_poll_reactor::do_remove_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.erase(&queue);+}++int dev_poll_reactor::get_timeout(int msec)+{+  // By default we will wait no longer than 5 minutes. This will ensure that+  // any changes to the system clock are detected after no longer than this.+  const int max_msec = 5 * 60 * 1000;+  return timer_queues_.wait_duration_msec(+      (msec < 0 || max_msec < msec) ? max_msec : msec);+}++void dev_poll_reactor::cancel_ops_unlocked(socket_type descriptor,+    const asio::error_code& ec)+{+  bool need_interrupt = false;+  op_queue<operation> ops;+  for (int i = 0; i < max_ops; ++i)+    need_interrupt = op_queue_[i].cancel_operations(+        descriptor, ops, ec) || need_interrupt;+  scheduler_.post_deferred_completions(ops);+  if (need_interrupt)+    interrupter_.interrupt();+}++::pollfd& dev_poll_reactor::add_pending_event_change(int descriptor)+{+  hash_map<int, std::size_t>::iterator iter+    = pending_event_change_index_.find(descriptor);+  if (iter == pending_event_change_index_.end())+  {+    std::size_t index = pending_event_changes_.size();+    pending_event_changes_.reserve(pending_event_changes_.size() + 1);+    pending_event_change_index_.insert(std::make_pair(descriptor, index));+    pending_event_changes_.push_back(::pollfd());+    pending_event_changes_[index].fd = descriptor;+    pending_event_changes_[index].revents = 0;+    return pending_event_changes_[index];+  }+  else+  {+    return pending_event_changes_[iter->second];+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_DEV_POLL)++#endif // ASIO_DETAIL_IMPL_DEV_POLL_REACTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.hpp view
@@ -0,0 +1,89 @@+//+// detail/impl/epoll_reactor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP+#define ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if defined(ASIO_HAS_EPOLL)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Time_Traits>+void epoll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_add_timer_queue(queue);+}++template <typename Time_Traits>+void epoll_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_remove_timer_queue(queue);+}++template <typename Time_Traits>+void epoll_reactor::schedule_timer(timer_queue<Time_Traits>& queue,+    const typename Time_Traits::time_type& time,+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)+{+  mutex::scoped_lock lock(mutex_);++  if (shutdown_)+  {+    scheduler_.post_immediate_completion(op, false);+    return;+  }++  bool earliest = queue.enqueue_timer(time, timer, op);+  scheduler_.work_started();+  if (earliest)+    update_timeout();+}++template <typename Time_Traits>+std::size_t epoll_reactor::cancel_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& timer,+    std::size_t max_cancelled)+{+  mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+  return n;+}++template <typename Time_Traits>+void epoll_reactor::move_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& target,+    typename timer_queue<Time_Traits>::per_timer_data& source)+{+  mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer(target, ops);+  queue.move_timer(target, source);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_EPOLL)++#endif // ASIO_DETAIL_IMPL_EPOLL_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.ipp view
@@ -0,0 +1,787 @@+//+// detail/impl/epoll_reactor.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP+#define ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP++#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_EPOLL)++#include <cstddef>+#include <sys/epoll.h>+#include "asio/detail/epoll_reactor.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#if defined(ASIO_HAS_TIMERFD)+# include <sys/timerfd.h>+#endif // defined(ASIO_HAS_TIMERFD)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++epoll_reactor::epoll_reactor(asio::execution_context& ctx)+  : execution_context_service_base<epoll_reactor>(ctx),+    scheduler_(use_service<scheduler>(ctx)),+    mutex_(ASIO_CONCURRENCY_HINT_IS_LOCKING(+          REACTOR_REGISTRATION, scheduler_.concurrency_hint())),+    interrupter_(),+    epoll_fd_(do_epoll_create()),+    timer_fd_(do_timerfd_create()),+    shutdown_(false),+    registered_descriptors_mutex_(mutex_.enabled())+{+  // Add the interrupter's descriptor to epoll.+  epoll_event ev = { 0, { 0 } };+  ev.events = EPOLLIN | EPOLLERR | EPOLLET;+  ev.data.ptr = &interrupter_;+  epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);+  interrupter_.interrupt();++  // Add the timer descriptor to epoll.+  if (timer_fd_ != -1)+  {+    ev.events = EPOLLIN | EPOLLERR;+    ev.data.ptr = &timer_fd_;+    epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);+  }+}++epoll_reactor::~epoll_reactor()+{+  if (epoll_fd_ != -1)+    close(epoll_fd_);+  if (timer_fd_ != -1)+    close(timer_fd_);+}++void epoll_reactor::shutdown()+{+  mutex::scoped_lock lock(mutex_);+  shutdown_ = true;+  lock.unlock();++  op_queue<operation> ops;++  while (descriptor_state* state = registered_descriptors_.first())+  {+    for (int i = 0; i < max_ops; ++i)+      ops.push(state->op_queue_[i]);+    state->shutdown_ = true;+    registered_descriptors_.free(state);+  }++  timer_queues_.get_all_timers(ops);++  scheduler_.abandon_operations(ops);+}++void epoll_reactor::notify_fork(+    asio::execution_context::fork_event fork_ev)+{+  if (fork_ev == asio::execution_context::fork_child)+  {+    if (epoll_fd_ != -1)+      ::close(epoll_fd_);+    epoll_fd_ = -1;+    epoll_fd_ = do_epoll_create();++    if (timer_fd_ != -1)+      ::close(timer_fd_);+    timer_fd_ = -1;+    timer_fd_ = do_timerfd_create();++    interrupter_.recreate();++    // Add the interrupter's descriptor to epoll.+    epoll_event ev = { 0, { 0 } };+    ev.events = EPOLLIN | EPOLLERR | EPOLLET;+    ev.data.ptr = &interrupter_;+    epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, interrupter_.read_descriptor(), &ev);+    interrupter_.interrupt();++    // Add the timer descriptor to epoll.+    if (timer_fd_ != -1)+    {+      ev.events = EPOLLIN | EPOLLERR;+      ev.data.ptr = &timer_fd_;+      epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, timer_fd_, &ev);+    }++    update_timeout();++    // Re-register all descriptors with epoll.+    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);+    for (descriptor_state* state = registered_descriptors_.first();+        state != 0; state = state->next_)+    {+      ev.events = state->registered_events_;+      ev.data.ptr = state;+      int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, state->descriptor_, &ev);+      if (result != 0)+      {+        asio::error_code ec(errno,+            asio::error::get_system_category());+        asio::detail::throw_error(ec, "epoll re-registration");+      }+    }+  }+}++void epoll_reactor::init_task()+{+  scheduler_.init_task();+}++int epoll_reactor::register_descriptor(socket_type descriptor,+    epoll_reactor::per_descriptor_data& descriptor_data)+{+  descriptor_data = allocate_descriptor_state();++  ASIO_HANDLER_REACTOR_REGISTRATION((+        context(), static_cast<uintmax_t>(descriptor),+        reinterpret_cast<uintmax_t>(descriptor_data)));++  {+    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++    descriptor_data->reactor_ = this;+    descriptor_data->descriptor_ = descriptor;+    descriptor_data->shutdown_ = false;+    for (int i = 0; i < max_ops; ++i)+      descriptor_data->try_speculative_[i] = true;+  }++  epoll_event ev = { 0, { 0 } };+  ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;+  descriptor_data->registered_events_ = ev.events;+  ev.data.ptr = descriptor_data;+  int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);+  if (result != 0)+  {+    if (errno == EPERM)+    {+      // This file descriptor type is not supported by epoll. However, if it is+      // a regular file then operations on it will not block. We will allow+      // this descriptor to be used and fail later if an operation on it would+      // otherwise require a trip through the reactor.+      descriptor_data->registered_events_ = 0;+      return 0;+    }+    return errno;+  }++  return 0;+}++int epoll_reactor::register_internal_descriptor(+    int op_type, socket_type descriptor,+    epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op)+{+  descriptor_data = allocate_descriptor_state();++  ASIO_HANDLER_REACTOR_REGISTRATION((+        context(), static_cast<uintmax_t>(descriptor),+        reinterpret_cast<uintmax_t>(descriptor_data)));++  {+    mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++    descriptor_data->reactor_ = this;+    descriptor_data->descriptor_ = descriptor;+    descriptor_data->shutdown_ = false;+    descriptor_data->op_queue_[op_type].push(op);+    for (int i = 0; i < max_ops; ++i)+      descriptor_data->try_speculative_[i] = true;+  }++  epoll_event ev = { 0, { 0 } };+  ev.events = EPOLLIN | EPOLLERR | EPOLLHUP | EPOLLPRI | EPOLLET;+  descriptor_data->registered_events_ = ev.events;+  ev.data.ptr = descriptor_data;+  int result = epoll_ctl(epoll_fd_, EPOLL_CTL_ADD, descriptor, &ev);+  if (result != 0)+    return errno;++  return 0;+}++void epoll_reactor::move_descriptor(socket_type,+    epoll_reactor::per_descriptor_data& target_descriptor_data,+    epoll_reactor::per_descriptor_data& source_descriptor_data)+{+  target_descriptor_data = source_descriptor_data;+  source_descriptor_data = 0;+}++void epoll_reactor::start_op(int op_type, socket_type descriptor,+    epoll_reactor::per_descriptor_data& descriptor_data, reactor_op* op,+    bool is_continuation, bool allow_speculative)+{+  if (!descriptor_data)+  {+    op->ec_ = asio::error::bad_descriptor;+    post_immediate_completion(op, is_continuation);+    return;+  }++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  if (descriptor_data->shutdown_)+  {+    post_immediate_completion(op, is_continuation);+    return;+  }++  if (descriptor_data->op_queue_[op_type].empty())+  {+    if (allow_speculative+        && (op_type != read_op+          || descriptor_data->op_queue_[except_op].empty()))+    {+      if (descriptor_data->try_speculative_[op_type])+      {+        if (reactor_op::status status = op->perform())+        {+          if (status == reactor_op::done_and_exhausted)+            if (descriptor_data->registered_events_ != 0)+              descriptor_data->try_speculative_[op_type] = false;+          descriptor_lock.unlock();+          scheduler_.post_immediate_completion(op, is_continuation);+          return;+        }+      }++      if (descriptor_data->registered_events_ == 0)+      {+        op->ec_ = asio::error::operation_not_supported;+        scheduler_.post_immediate_completion(op, is_continuation);+        return;+      }++      if (op_type == write_op)+      {+        if ((descriptor_data->registered_events_ & EPOLLOUT) == 0)+        {+          epoll_event ev = { 0, { 0 } };+          ev.events = descriptor_data->registered_events_ | EPOLLOUT;+          ev.data.ptr = descriptor_data;+          if (epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev) == 0)+          {+            descriptor_data->registered_events_ |= ev.events;+          }+          else+          {+            op->ec_ = asio::error_code(errno,+                asio::error::get_system_category());+            scheduler_.post_immediate_completion(op, is_continuation);+            return;+          }+        }+      }+    }+    else if (descriptor_data->registered_events_ == 0)+    {+      op->ec_ = asio::error::operation_not_supported;+      scheduler_.post_immediate_completion(op, is_continuation);+      return;+    }+    else+    {+      if (op_type == write_op)+      {+        descriptor_data->registered_events_ |= EPOLLOUT;+      }++      epoll_event ev = { 0, { 0 } };+      ev.events = descriptor_data->registered_events_;+      ev.data.ptr = descriptor_data;+      epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, descriptor, &ev);+    }+  }++  descriptor_data->op_queue_[op_type].push(op);+  scheduler_.work_started();+}++void epoll_reactor::cancel_ops(socket_type,+    epoll_reactor::per_descriptor_data& descriptor_data)+{+  if (!descriptor_data)+    return;++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  op_queue<operation> ops;+  for (int i = 0; i < max_ops; ++i)+  {+    while (reactor_op* op = descriptor_data->op_queue_[i].front())+    {+      op->ec_ = asio::error::operation_aborted;+      descriptor_data->op_queue_[i].pop();+      ops.push(op);+    }+  }++  descriptor_lock.unlock();++  scheduler_.post_deferred_completions(ops);+}++void epoll_reactor::deregister_descriptor(socket_type descriptor,+    epoll_reactor::per_descriptor_data& descriptor_data, bool closing)+{+  if (!descriptor_data)+    return;++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  if (!descriptor_data->shutdown_)+  {+    if (closing)+    {+      // The descriptor will be automatically removed from the epoll set when+      // it is closed.+    }+    else if (descriptor_data->registered_events_ != 0)+    {+      epoll_event ev = { 0, { 0 } };+      epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);+    }++    op_queue<operation> ops;+    for (int i = 0; i < max_ops; ++i)+    {+      while (reactor_op* op = descriptor_data->op_queue_[i].front())+      {+        op->ec_ = asio::error::operation_aborted;+        descriptor_data->op_queue_[i].pop();+        ops.push(op);+      }+    }++    descriptor_data->descriptor_ = -1;+    descriptor_data->shutdown_ = true;++    descriptor_lock.unlock();++    ASIO_HANDLER_REACTOR_DEREGISTRATION((+          context(), static_cast<uintmax_t>(descriptor),+          reinterpret_cast<uintmax_t>(descriptor_data)));++    scheduler_.post_deferred_completions(ops);++    // Leave descriptor_data set so that it will be freed by the subsequent+    // call to cleanup_descriptor_data.+  }+  else+  {+    // We are shutting down, so prevent cleanup_descriptor_data from freeing+    // the descriptor_data object and let the destructor free it instead.+    descriptor_data = 0;+  }+}++void epoll_reactor::deregister_internal_descriptor(socket_type descriptor,+    epoll_reactor::per_descriptor_data& descriptor_data)+{+  if (!descriptor_data)+    return;++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  if (!descriptor_data->shutdown_)+  {+    epoll_event ev = { 0, { 0 } };+    epoll_ctl(epoll_fd_, EPOLL_CTL_DEL, descriptor, &ev);++    op_queue<operation> ops;+    for (int i = 0; i < max_ops; ++i)+      ops.push(descriptor_data->op_queue_[i]);++    descriptor_data->descriptor_ = -1;+    descriptor_data->shutdown_ = true;++    descriptor_lock.unlock();++    ASIO_HANDLER_REACTOR_DEREGISTRATION((+          context(), static_cast<uintmax_t>(descriptor),+          reinterpret_cast<uintmax_t>(descriptor_data)));++    // Leave descriptor_data set so that it will be freed by the subsequent+    // call to cleanup_descriptor_data.+  }+  else+  {+    // We are shutting down, so prevent cleanup_descriptor_data from freeing+    // the descriptor_data object and let the destructor free it instead.+    descriptor_data = 0;+  }+}++void epoll_reactor::cleanup_descriptor_data(+    per_descriptor_data& descriptor_data)+{+  if (descriptor_data)+  {+    free_descriptor_state(descriptor_data);+    descriptor_data = 0;+  }+}++void epoll_reactor::run(long usec, op_queue<operation>& ops)+{+  // This code relies on the fact that the scheduler queues the reactor task+  // behind all descriptor operations generated by this function. This means,+  // that by the time we reach this point, any previously returned descriptor+  // operations have already been dequeued. Therefore it is now safe for us to+  // reuse and return them for the scheduler to queue again.++  // Calculate timeout. Check the timer queues only if timerfd is not in use.+  int timeout;+  if (usec == 0)+    timeout = 0;+  else+  {+    timeout = (usec < 0) ? -1 : ((usec - 1) / 1000 + 1);+    if (timer_fd_ == -1)+    {+      mutex::scoped_lock lock(mutex_);+      timeout = get_timeout(timeout);+    }+  }++  // Block on the epoll descriptor.+  epoll_event events[128];+  int num_events = epoll_wait(epoll_fd_, events, 128, timeout);++#if defined(ASIO_ENABLE_HANDLER_TRACKING)+  // Trace the waiting events.+  for (int i = 0; i < num_events; ++i)+  {+    void* ptr = events[i].data.ptr;+    if (ptr == &interrupter_)+    {+      // Ignore.+    }+# if defined(ASIO_HAS_TIMERFD)+    else if (ptr == &timer_fd_)+    {+      // Ignore.+    }+# endif // defined(ASIO_HAS_TIMERFD)+    else+    {+      unsigned event_mask = 0;+      if ((events[i].events & EPOLLIN) != 0)+        event_mask |= ASIO_HANDLER_REACTOR_READ_EVENT;+      if ((events[i].events & EPOLLOUT))+        event_mask |= ASIO_HANDLER_REACTOR_WRITE_EVENT;+      if ((events[i].events & (EPOLLERR | EPOLLHUP)) != 0)+        event_mask |= ASIO_HANDLER_REACTOR_ERROR_EVENT;+      ASIO_HANDLER_REACTOR_EVENTS((context(),+            reinterpret_cast<uintmax_t>(ptr), event_mask));+    }+  }+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)++#if defined(ASIO_HAS_TIMERFD)+  bool check_timers = (timer_fd_ == -1);+#else // defined(ASIO_HAS_TIMERFD)+  bool check_timers = true;+#endif // defined(ASIO_HAS_TIMERFD)++  // Dispatch the waiting events.+  for (int i = 0; i < num_events; ++i)+  {+    void* ptr = events[i].data.ptr;+    if (ptr == &interrupter_)+    {+      // No need to reset the interrupter since we're leaving the descriptor+      // in a ready-to-read state and relying on edge-triggered notifications+      // to make it so that we only get woken up when the descriptor's epoll+      // registration is updated.++#if defined(ASIO_HAS_TIMERFD)+      if (timer_fd_ == -1)+        check_timers = true;+#else // defined(ASIO_HAS_TIMERFD)+      check_timers = true;+#endif // defined(ASIO_HAS_TIMERFD)+    }+#if defined(ASIO_HAS_TIMERFD)+    else if (ptr == &timer_fd_)+    {+      check_timers = true;+    }+#endif // defined(ASIO_HAS_TIMERFD)+    else+    {+      // The descriptor operation doesn't count as work in and of itself, so we+      // don't call work_started() here. This still allows the scheduler to+      // stop if the only remaining operations are descriptor operations.+      descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);+      if (!ops.is_enqueued(descriptor_data))+      {+        descriptor_data->set_ready_events(events[i].events);+        ops.push(descriptor_data);+      }+      else+      {+        descriptor_data->add_ready_events(events[i].events);+      }+    }+  }++  if (check_timers)+  {+    mutex::scoped_lock common_lock(mutex_);+    timer_queues_.get_ready_timers(ops);++#if defined(ASIO_HAS_TIMERFD)+    if (timer_fd_ != -1)+    {+      itimerspec new_timeout;+      itimerspec old_timeout;+      int flags = get_timeout(new_timeout);+      timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);+    }+#endif // defined(ASIO_HAS_TIMERFD)+  }+}++void epoll_reactor::interrupt()+{+  epoll_event ev = { 0, { 0 } };+  ev.events = EPOLLIN | EPOLLERR | EPOLLET;+  ev.data.ptr = &interrupter_;+  epoll_ctl(epoll_fd_, EPOLL_CTL_MOD, interrupter_.read_descriptor(), &ev);+}++int epoll_reactor::do_epoll_create()+{+#if defined(EPOLL_CLOEXEC)+  int fd = epoll_create1(EPOLL_CLOEXEC);+#else // defined(EPOLL_CLOEXEC)+  int fd = -1;+  errno = EINVAL;+#endif // defined(EPOLL_CLOEXEC)++  if (fd == -1 && (errno == EINVAL || errno == ENOSYS))+  {+    fd = epoll_create(epoll_size);+    if (fd != -1)+      ::fcntl(fd, F_SETFD, FD_CLOEXEC);+  }++  if (fd == -1)+  {+    asio::error_code ec(errno,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "epoll");+  }++  return fd;+}++int epoll_reactor::do_timerfd_create()+{+#if defined(ASIO_HAS_TIMERFD)+# if defined(TFD_CLOEXEC)+  int fd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);+# else // defined(TFD_CLOEXEC)+  int fd = -1;+  errno = EINVAL;+# endif // defined(TFD_CLOEXEC)++  if (fd == -1 && errno == EINVAL)+  {+    fd = timerfd_create(CLOCK_MONOTONIC, 0);+    if (fd != -1)+      ::fcntl(fd, F_SETFD, FD_CLOEXEC);+  }++  return fd;+#else // defined(ASIO_HAS_TIMERFD)+  return -1;+#endif // defined(ASIO_HAS_TIMERFD)+}++epoll_reactor::descriptor_state* epoll_reactor::allocate_descriptor_state()+{+  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);+  return registered_descriptors_.alloc(ASIO_CONCURRENCY_HINT_IS_LOCKING(+        REACTOR_IO, scheduler_.concurrency_hint()));+}++void epoll_reactor::free_descriptor_state(epoll_reactor::descriptor_state* s)+{+  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);+  registered_descriptors_.free(s);+}++void epoll_reactor::do_add_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.insert(&queue);+}++void epoll_reactor::do_remove_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.erase(&queue);+}++void epoll_reactor::update_timeout()+{+#if defined(ASIO_HAS_TIMERFD)+  if (timer_fd_ != -1)+  {+    itimerspec new_timeout;+    itimerspec old_timeout;+    int flags = get_timeout(new_timeout);+    timerfd_settime(timer_fd_, flags, &new_timeout, &old_timeout);+    return;+  }+#endif // defined(ASIO_HAS_TIMERFD)+  interrupt();+}++int epoll_reactor::get_timeout(int msec)+{+  // By default we will wait no longer than 5 minutes. This will ensure that+  // any changes to the system clock are detected after no longer than this.+  const int max_msec = 5 * 60 * 1000;+  return timer_queues_.wait_duration_msec(+      (msec < 0 || max_msec < msec) ? max_msec : msec);+}++#if defined(ASIO_HAS_TIMERFD)+int epoll_reactor::get_timeout(itimerspec& ts)+{+  ts.it_interval.tv_sec = 0;+  ts.it_interval.tv_nsec = 0;++  long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);+  ts.it_value.tv_sec = usec / 1000000;+  ts.it_value.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;++  return usec ? 0 : TFD_TIMER_ABSTIME;+}+#endif // defined(ASIO_HAS_TIMERFD)++struct epoll_reactor::perform_io_cleanup_on_block_exit+{+  explicit perform_io_cleanup_on_block_exit(epoll_reactor* r)+    : reactor_(r), first_op_(0)+  {+  }++  ~perform_io_cleanup_on_block_exit()+  {+    if (first_op_)+    {+      // Post the remaining completed operations for invocation.+      if (!ops_.empty())+        reactor_->scheduler_.post_deferred_completions(ops_);++      // A user-initiated operation has completed, but there's no need to+      // explicitly call work_finished() here. Instead, we'll take advantage of+      // the fact that the scheduler will call work_finished() once we return.+    }+    else+    {+      // No user-initiated operations have completed, so we need to compensate+      // for the work_finished() call that the scheduler will make once this+      // operation returns.+      reactor_->scheduler_.compensating_work_started();+    }+  }++  epoll_reactor* reactor_;+  op_queue<operation> ops_;+  operation* first_op_;+};++epoll_reactor::descriptor_state::descriptor_state(bool locking)+  : operation(&epoll_reactor::descriptor_state::do_complete),+    mutex_(locking)+{+}++operation* epoll_reactor::descriptor_state::perform_io(uint32_t events)+{+  mutex_.lock();+  perform_io_cleanup_on_block_exit io_cleanup(reactor_);+  mutex::scoped_lock descriptor_lock(mutex_, mutex::scoped_lock::adopt_lock);++  // Exception operations must be processed first to ensure that any+  // out-of-band data is read before normal data.+  static const int flag[max_ops] = { EPOLLIN, EPOLLOUT, EPOLLPRI };+  for (int j = max_ops - 1; j >= 0; --j)+  {+    if (events & (flag[j] | EPOLLERR | EPOLLHUP))+    {+      try_speculative_[j] = true;+      while (reactor_op* op = op_queue_[j].front())+      {+        if (reactor_op::status status = op->perform())+        {+          op_queue_[j].pop();+          io_cleanup.ops_.push(op);+          if (status == reactor_op::done_and_exhausted)+          {+            try_speculative_[j] = false;+            break;+          }+        }+        else+          break;+      }+    }+  }++  // The first operation will be returned for completion now. The others will+  // be posted for later by the io_cleanup object's destructor.+  io_cleanup.first_op_ = io_cleanup.ops_.front();+  io_cleanup.ops_.pop();+  return io_cleanup.first_op_;+}++void epoll_reactor::descriptor_state::do_complete(+    void* owner, operation* base,+    const asio::error_code& ec, std::size_t bytes_transferred)+{+  if (owner)+  {+    descriptor_state* descriptor_data = static_cast<descriptor_state*>(base);+    uint32_t events = static_cast<uint32_t>(bytes_transferred);+    if (operation* op = descriptor_data->perform_io(events))+    {+      op->complete(owner, ec, 0);+    }+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_EPOLL)++#endif // ASIO_DETAIL_IMPL_EPOLL_REACTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp view
@@ -0,0 +1,169 @@+//+// detail/impl/eventfd_select_interrupter.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2008 Roelof Naude (roelof.naude at gmail dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP+#define ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP++#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_EVENTFD)++#include <sys/stat.h>+#include <sys/types.h>+#include <fcntl.h>+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+# include <asm/unistd.h>+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+# include <sys/eventfd.h>+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#include "asio/detail/cstdint.hpp"+#include "asio/detail/eventfd_select_interrupter.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++eventfd_select_interrupter::eventfd_select_interrupter()+{+  open_descriptors();+}++void eventfd_select_interrupter::open_descriptors()+{+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+  write_descriptor_ = read_descriptor_ = syscall(__NR_eventfd, 0);+  if (read_descriptor_ != -1)+  {+    ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);+    ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);+  }+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+# if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)+  write_descriptor_ = read_descriptor_ =+    ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);+# else // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)+  errno = EINVAL;+  write_descriptor_ = read_descriptor_ = -1;+# endif // defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)+  if (read_descriptor_ == -1 && errno == EINVAL)+  {+    write_descriptor_ = read_descriptor_ = ::eventfd(0, 0);+    if (read_descriptor_ != -1)+    {+      ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);+      ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);+    }+  }+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8++  if (read_descriptor_ == -1)+  {+    int pipe_fds[2];+    if (pipe(pipe_fds) == 0)+    {+      read_descriptor_ = pipe_fds[0];+      ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);+      ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);+      write_descriptor_ = pipe_fds[1];+      ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);+      ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC);+    }+    else+    {+      asio::error_code ec(errno,+          asio::error::get_system_category());+      asio::detail::throw_error(ec, "eventfd_select_interrupter");+    }+  }+}++eventfd_select_interrupter::~eventfd_select_interrupter()+{+  close_descriptors();+}++void eventfd_select_interrupter::close_descriptors()+{+  if (write_descriptor_ != -1 && write_descriptor_ != read_descriptor_)+    ::close(write_descriptor_);+  if (read_descriptor_ != -1)+    ::close(read_descriptor_);+}++void eventfd_select_interrupter::recreate()+{+  close_descriptors();++  write_descriptor_ = -1;+  read_descriptor_ = -1;++  open_descriptors();+}++void eventfd_select_interrupter::interrupt()+{+  uint64_t counter(1UL);+  int result = ::write(write_descriptor_, &counter, sizeof(uint64_t));+  (void)result;+}++bool eventfd_select_interrupter::reset()+{+  if (write_descriptor_ == read_descriptor_)+  {+    for (;;)+    {+      // Only perform one read. The kernel maintains an atomic counter.+      uint64_t counter(0);+      errno = 0;+      int bytes_read = ::read(read_descriptor_, &counter, sizeof(uint64_t));+      if (bytes_read < 0 && errno == EINTR)+        continue;+      return true;+    }+  }+  else+  {+    for (;;)+    {+      // Clear all data from the pipe.+      char data[1024];+      int bytes_read = ::read(read_descriptor_, data, sizeof(data));+      if (bytes_read == sizeof(data))+        continue;+      if (bytes_read > 0)+        return true;+      if (bytes_read == 0)+        return false;+      if (errno == EINTR)+        continue;+      if (errno == EWOULDBLOCK || errno == EAGAIN)+        return true;+      return false;+    }+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_EVENTFD)++#endif // ASIO_DETAIL_IMPL_EVENTFD_SELECT_INTERRUPTER_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/handler_tracking.ipp view
@@ -0,0 +1,396 @@+//+// detail/impl/handler_tracking.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP+#define ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_CUSTOM_HANDLER_TRACKING)++// The handler tracking implementation is provided by the user-specified header.++#elif defined(ASIO_ENABLE_HANDLER_TRACKING)++#include <cstdarg>+#include <cstdio>+#include "asio/detail/handler_tracking.hpp"++#if defined(ASIO_HAS_BOOST_DATE_TIME)+# include "asio/time_traits.hpp"+#elif defined(ASIO_HAS_CHRONO)+# include "asio/detail/chrono.hpp"+# include "asio/detail/chrono_time_traits.hpp"+# include "asio/wait_traits.hpp"+#endif // defined(ASIO_HAS_BOOST_DATE_TIME)++#if defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/socket_types.hpp"+#elif !defined(ASIO_WINDOWS)+# include <unistd.h>+#endif // !defined(ASIO_WINDOWS)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct handler_tracking_timestamp+{+  uint64_t seconds;+  uint64_t microseconds;++  handler_tracking_timestamp()+  {+#if defined(ASIO_HAS_BOOST_DATE_TIME)+    boost::posix_time::ptime epoch(boost::gregorian::date(1970, 1, 1));+    boost::posix_time::time_duration now =+      boost::posix_time::microsec_clock::universal_time() - epoch;+#elif defined(ASIO_HAS_CHRONO)+    typedef chrono_time_traits<chrono::system_clock,+        asio::wait_traits<chrono::system_clock> > traits_helper;+    traits_helper::posix_time_duration now(+        chrono::system_clock::now().time_since_epoch());+#endif+    seconds = static_cast<uint64_t>(now.total_seconds());+    microseconds = static_cast<uint64_t>(now.total_microseconds() % 1000000);+  }+};++struct handler_tracking::tracking_state+{+  static_mutex mutex_;+  uint64_t next_id_;+  tss_ptr<completion>* current_completion_;+  tss_ptr<location>* current_location_;+};++handler_tracking::tracking_state* handler_tracking::get_state()+{+  static tracking_state state = { ASIO_STATIC_MUTEX_INIT, 1, 0, 0 };+  return &state;+}++void handler_tracking::init()+{+  static tracking_state* state = get_state();++  state->mutex_.init();++  static_mutex::scoped_lock lock(state->mutex_);+  if (state->current_completion_ == 0)+    state->current_completion_ = new tss_ptr<completion>;+  if (state->current_location_ == 0)+    state->current_location_ = new tss_ptr<location>;+}++handler_tracking::location::location(+    const char* file, int line, const char* func)+  : file_(file),+    line_(line),+    func_(func),+    next_(*get_state()->current_location_)+{+  if (file_)+    *get_state()->current_location_ = this;+}++handler_tracking::location::~location()+{+  if (file_)+    *get_state()->current_location_ = next_;+}++void handler_tracking::creation(execution_context&,+    handler_tracking::tracked_handler& h,+    const char* object_type, void* object,+    uintmax_t /*native_handle*/, const char* op_name)+{+  static tracking_state* state = get_state();++  static_mutex::scoped_lock lock(state->mutex_);+  h.id_ = state->next_id_++;+  lock.unlock();++  handler_tracking_timestamp timestamp;++  uint64_t current_id = 0;+  if (completion* current_completion = *state->current_completion_)+    current_id = current_completion->id_;++  for (location* current_location = *state->current_location_;+      current_location; current_location = current_location->next_)+  {+    write_line(+#if defined(ASIO_WINDOWS)+        "@asio|%I64u.%06I64u|%I64u^%I64u|%s%s%.80s%s(%.80s:%d)\n",+#else // defined(ASIO_WINDOWS)+        "@asio|%llu.%06llu|%llu^%llu|%s%s%.80s%s(%.80s:%d)\n",+#endif // defined(ASIO_WINDOWS)+        timestamp.seconds, timestamp.microseconds,+        current_id, h.id_,+        current_location == *state->current_location_ ? "in " : "called from ",+        current_location->func_ ? "'" : "",+        current_location->func_ ? current_location->func_ : "",+        current_location->func_ ? "' " : "",+        current_location->file_, current_location->line_);+  }++  write_line(+#if defined(ASIO_WINDOWS)+      "@asio|%I64u.%06I64u|%I64u*%I64u|%.20s@%p.%.50s\n",+#else // defined(ASIO_WINDOWS)+      "@asio|%llu.%06llu|%llu*%llu|%.20s@%p.%.50s\n",+#endif // defined(ASIO_WINDOWS)+      timestamp.seconds, timestamp.microseconds,+      current_id, h.id_, object_type, object, op_name);+}++handler_tracking::completion::completion(+    const handler_tracking::tracked_handler& h)+  : id_(h.id_),+    invoked_(false),+    next_(*get_state()->current_completion_)+{+  *get_state()->current_completion_ = this;+}++handler_tracking::completion::~completion()+{+  if (id_)+  {+    handler_tracking_timestamp timestamp;++    write_line(+#if defined(ASIO_WINDOWS)+        "@asio|%I64u.%06I64u|%c%I64u|\n",+#else // defined(ASIO_WINDOWS)+        "@asio|%llu.%06llu|%c%llu|\n",+#endif // defined(ASIO_WINDOWS)+        timestamp.seconds, timestamp.microseconds,+        invoked_ ? '!' : '~', id_);+  }++  *get_state()->current_completion_ = next_;+}++void handler_tracking::completion::invocation_begin()+{+  handler_tracking_timestamp timestamp;++  write_line(+#if defined(ASIO_WINDOWS)+      "@asio|%I64u.%06I64u|>%I64u|\n",+#else // defined(ASIO_WINDOWS)+      "@asio|%llu.%06llu|>%llu|\n",+#endif // defined(ASIO_WINDOWS)+      timestamp.seconds, timestamp.microseconds, id_);++  invoked_ = true;+}++void handler_tracking::completion::invocation_begin(+    const asio::error_code& ec)+{+  handler_tracking_timestamp timestamp;++  write_line(+#if defined(ASIO_WINDOWS)+      "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d\n",+#else // defined(ASIO_WINDOWS)+      "@asio|%llu.%06llu|>%llu|ec=%.20s:%d\n",+#endif // defined(ASIO_WINDOWS)+      timestamp.seconds, timestamp.microseconds,+      id_, ec.category().name(), ec.value());++  invoked_ = true;+}++void handler_tracking::completion::invocation_begin(+    const asio::error_code& ec, std::size_t bytes_transferred)+{+  handler_tracking_timestamp timestamp;++  write_line(+#if defined(ASIO_WINDOWS)+      "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,bytes_transferred=%I64u\n",+#else // defined(ASIO_WINDOWS)+      "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,bytes_transferred=%llu\n",+#endif // defined(ASIO_WINDOWS)+      timestamp.seconds, timestamp.microseconds,+      id_, ec.category().name(), ec.value(),+      static_cast<uint64_t>(bytes_transferred));++  invoked_ = true;+}++void handler_tracking::completion::invocation_begin(+    const asio::error_code& ec, int signal_number)+{+  handler_tracking_timestamp timestamp;++  write_line(+#if defined(ASIO_WINDOWS)+      "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,signal_number=%d\n",+#else // defined(ASIO_WINDOWS)+      "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,signal_number=%d\n",+#endif // defined(ASIO_WINDOWS)+      timestamp.seconds, timestamp.microseconds,+      id_, ec.category().name(), ec.value(), signal_number);++  invoked_ = true;+}++void handler_tracking::completion::invocation_begin(+    const asio::error_code& ec, const char* arg)+{+  handler_tracking_timestamp timestamp;++  write_line(+#if defined(ASIO_WINDOWS)+      "@asio|%I64u.%06I64u|>%I64u|ec=%.20s:%d,%.50s\n",+#else // defined(ASIO_WINDOWS)+      "@asio|%llu.%06llu|>%llu|ec=%.20s:%d,%.50s\n",+#endif // defined(ASIO_WINDOWS)+      timestamp.seconds, timestamp.microseconds,+      id_, ec.category().name(), ec.value(), arg);++  invoked_ = true;+}++void handler_tracking::completion::invocation_end()+{+  if (id_)+  {+    handler_tracking_timestamp timestamp;++    write_line(+#if defined(ASIO_WINDOWS)+        "@asio|%I64u.%06I64u|<%I64u|\n",+#else // defined(ASIO_WINDOWS)+        "@asio|%llu.%06llu|<%llu|\n",+#endif // defined(ASIO_WINDOWS)+        timestamp.seconds, timestamp.microseconds, id_);++    id_ = 0;+  }+}++void handler_tracking::operation(execution_context&,+    const char* object_type, void* object,+    uintmax_t /*native_handle*/, const char* op_name)+{+  static tracking_state* state = get_state();++  handler_tracking_timestamp timestamp;++  unsigned long long current_id = 0;+  if (completion* current_completion = *state->current_completion_)+    current_id = current_completion->id_;++  write_line(+#if defined(ASIO_WINDOWS)+      "@asio|%I64u.%06I64u|%I64u|%.20s@%p.%.50s\n",+#else // defined(ASIO_WINDOWS)+      "@asio|%llu.%06llu|%llu|%.20s@%p.%.50s\n",+#endif // defined(ASIO_WINDOWS)+      timestamp.seconds, timestamp.microseconds,+      current_id, object_type, object, op_name);+}++void handler_tracking::reactor_registration(execution_context& /*context*/,+    uintmax_t /*native_handle*/, uintmax_t /*registration*/)+{+}++void handler_tracking::reactor_deregistration(execution_context& /*context*/,+    uintmax_t /*native_handle*/, uintmax_t /*registration*/)+{+}++void handler_tracking::reactor_events(execution_context& /*context*/,+    uintmax_t /*native_handle*/, unsigned /*events*/)+{+}++void handler_tracking::reactor_operation(+    const tracked_handler& h, const char* op_name,+    const asio::error_code& ec)+{+  handler_tracking_timestamp timestamp;++  write_line(+#if defined(ASIO_WINDOWS)+      "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d\n",+#else // defined(ASIO_WINDOWS)+      "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d\n",+#endif // defined(ASIO_WINDOWS)+      timestamp.seconds, timestamp.microseconds,+      h.id_, op_name, ec.category().name(), ec.value());+}++void handler_tracking::reactor_operation(+    const tracked_handler& h, const char* op_name,+    const asio::error_code& ec, std::size_t bytes_transferred)+{+  handler_tracking_timestamp timestamp;++  write_line(+#if defined(ASIO_WINDOWS)+      "@asio|%I64u.%06I64u|.%I64u|%s,ec=%.20s:%d,bytes_transferred=%I64u\n",+#else // defined(ASIO_WINDOWS)+      "@asio|%llu.%06llu|.%llu|%s,ec=%.20s:%d,bytes_transferred=%llu\n",+#endif // defined(ASIO_WINDOWS)+      timestamp.seconds, timestamp.microseconds,+      h.id_, op_name, ec.category().name(), ec.value(),+      static_cast<uint64_t>(bytes_transferred));+}++void handler_tracking::write_line(const char* format, ...)+{+  using namespace std; // For sprintf (or equivalent).++  va_list args;+  va_start(args, format);++  char line[256] = "";+#if defined(ASIO_HAS_SECURE_RTL)+  int length = vsprintf_s(line, sizeof(line), format, args);+#else // defined(ASIO_HAS_SECURE_RTL)+  int length = vsprintf(line, format, args);+#endif // defined(ASIO_HAS_SECURE_RTL)++  va_end(args);++#if defined(ASIO_WINDOWS_RUNTIME)+  wchar_t wline[256] = L"";+  mbstowcs_s(0, wline, sizeof(wline) / sizeof(wchar_t), line, length);+  ::OutputDebugStringW(wline);+#elif defined(ASIO_WINDOWS)+  HANDLE stderr_handle = ::GetStdHandle(STD_ERROR_HANDLE);+  DWORD bytes_written = 0;+  ::WriteFile(stderr_handle, line, length, &bytes_written, 0);+#else // defined(ASIO_WINDOWS)+  ::write(STDERR_FILENO, line, length);+#endif // defined(ASIO_WINDOWS)+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)++#endif // ASIO_DETAIL_IMPL_HANDLER_TRACKING_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.hpp view
@@ -0,0 +1,93 @@+//+// detail/impl/kqueue_reactor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP+#define ASIO_DETAIL_IMPL_KQUEUE_REACTOR_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_KQUEUE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Time_Traits>+void kqueue_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_add_timer_queue(queue);+}++// Remove a timer queue from the reactor.+template <typename Time_Traits>+void kqueue_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_remove_timer_queue(queue);+}++template <typename Time_Traits>+void kqueue_reactor::schedule_timer(timer_queue<Time_Traits>& queue,+    const typename Time_Traits::time_type& time,+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)+{+  mutex::scoped_lock lock(mutex_);++  if (shutdown_)+  {+    scheduler_.post_immediate_completion(op, false);+    return;+  }++  bool earliest = queue.enqueue_timer(time, timer, op);+  scheduler_.work_started();+  if (earliest)+    interrupt();+}++template <typename Time_Traits>+std::size_t kqueue_reactor::cancel_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& timer,+    std::size_t max_cancelled)+{+  mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+  return n;+}++template <typename Time_Traits>+void kqueue_reactor::move_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& target,+    typename timer_queue<Time_Traits>::per_timer_data& source)+{+  mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer(target, ops);+  queue.move_timer(target, source);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_KQUEUE)++#endif // ASIO_DETAIL_IMPL_KQUEUE_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.ipp view
@@ -0,0 +1,570 @@+//+// detail/impl/kqueue_reactor.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP+#define ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP++#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_KQUEUE)++#include "asio/detail/kqueue_reactor.hpp"+#include "asio/detail/scheduler.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#if defined(__NetBSD__)+# include <sys/param.h>+#endif++#include "asio/detail/push_options.hpp"++#if defined(__NetBSD__) && __NetBSD_Version__ < 999001500+# define ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \+    EV_SET(ev, ident, filt, flags, fflags, data, \+      reinterpret_cast<intptr_t>(static_cast<void*>(udata)))+#else+# define ASIO_KQUEUE_EV_SET(ev, ident, filt, flags, fflags, data, udata) \+    EV_SET(ev, ident, filt, flags, fflags, data, udata)+#endif++namespace asio {+namespace detail {++kqueue_reactor::kqueue_reactor(asio::execution_context& ctx)+  : execution_context_service_base<kqueue_reactor>(ctx),+    scheduler_(use_service<scheduler>(ctx)),+    mutex_(ASIO_CONCURRENCY_HINT_IS_LOCKING(+          REACTOR_REGISTRATION, scheduler_.concurrency_hint())),+    kqueue_fd_(do_kqueue_create()),+    interrupter_(),+    shutdown_(false),+    registered_descriptors_mutex_(mutex_.enabled())+{+  struct kevent events[1];+  ASIO_KQUEUE_EV_SET(&events[0], interrupter_.read_descriptor(),+      EVFILT_READ, EV_ADD, 0, 0, &interrupter_);+  if (::kevent(kqueue_fd_, events, 1, 0, 0, 0) == -1)+  {+    asio::error_code error(errno,+        asio::error::get_system_category());+    asio::detail::throw_error(error);+  }+}++kqueue_reactor::~kqueue_reactor()+{+  close(kqueue_fd_);+}++void kqueue_reactor::shutdown()+{+  mutex::scoped_lock lock(mutex_);+  shutdown_ = true;+  lock.unlock();++  op_queue<operation> ops;++  while (descriptor_state* state = registered_descriptors_.first())+  {+    for (int i = 0; i < max_ops; ++i)+      ops.push(state->op_queue_[i]);+    state->shutdown_ = true;+    registered_descriptors_.free(state);+  }++  timer_queues_.get_all_timers(ops);++  scheduler_.abandon_operations(ops);+}++void kqueue_reactor::notify_fork(+    asio::execution_context::fork_event fork_ev)+{+  if (fork_ev == asio::execution_context::fork_child)+  {+    // The kqueue descriptor is automatically closed in the child.+    kqueue_fd_ = -1;+    kqueue_fd_ = do_kqueue_create();++    interrupter_.recreate();++    struct kevent events[2];+    ASIO_KQUEUE_EV_SET(&events[0], interrupter_.read_descriptor(),+        EVFILT_READ, EV_ADD, 0, 0, &interrupter_);+    if (::kevent(kqueue_fd_, events, 1, 0, 0, 0) == -1)+    {+      asio::error_code ec(errno,+          asio::error::get_system_category());+      asio::detail::throw_error(ec, "kqueue interrupter registration");+    }++    // Re-register all descriptors with kqueue.+    mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);+    for (descriptor_state* state = registered_descriptors_.first();+        state != 0; state = state->next_)+    {+      if (state->num_kevents_ > 0)+      {+        ASIO_KQUEUE_EV_SET(&events[0], state->descriptor_,+            EVFILT_READ, EV_ADD | EV_CLEAR, 0, 0, state);+        ASIO_KQUEUE_EV_SET(&events[1], state->descriptor_,+            EVFILT_WRITE, EV_ADD | EV_CLEAR, 0, 0, state);+        if (::kevent(kqueue_fd_, events, state->num_kevents_, 0, 0, 0) == -1)+        {+          asio::error_code ec(errno,+              asio::error::get_system_category());+          asio::detail::throw_error(ec, "kqueue re-registration");+        }+      }+    }+  }+}++void kqueue_reactor::init_task()+{+  scheduler_.init_task();+}++int kqueue_reactor::register_descriptor(socket_type descriptor,+    kqueue_reactor::per_descriptor_data& descriptor_data)+{+  descriptor_data = allocate_descriptor_state();++  ASIO_HANDLER_REACTOR_REGISTRATION((+        context(), static_cast<uintmax_t>(descriptor),+        reinterpret_cast<uintmax_t>(descriptor_data)));++  mutex::scoped_lock lock(descriptor_data->mutex_);++  descriptor_data->descriptor_ = descriptor;+  descriptor_data->num_kevents_ = 0;+  descriptor_data->shutdown_ = false;++  return 0;+}++int kqueue_reactor::register_internal_descriptor(+    int op_type, socket_type descriptor,+    kqueue_reactor::per_descriptor_data& descriptor_data, reactor_op* op)+{+  descriptor_data = allocate_descriptor_state();++  ASIO_HANDLER_REACTOR_REGISTRATION((+        context(), static_cast<uintmax_t>(descriptor),+        reinterpret_cast<uintmax_t>(descriptor_data)));++  mutex::scoped_lock lock(descriptor_data->mutex_);++  descriptor_data->descriptor_ = descriptor;+  descriptor_data->num_kevents_ = 1;+  descriptor_data->shutdown_ = false;+  descriptor_data->op_queue_[op_type].push(op);++  struct kevent events[1];+  ASIO_KQUEUE_EV_SET(&events[0], descriptor, EVFILT_READ,+      EV_ADD | EV_CLEAR, 0, 0, descriptor_data);+  if (::kevent(kqueue_fd_, events, 1, 0, 0, 0) == -1)+    return errno;++  return 0;+}++void kqueue_reactor::move_descriptor(socket_type,+    kqueue_reactor::per_descriptor_data& target_descriptor_data,+    kqueue_reactor::per_descriptor_data& source_descriptor_data)+{+  target_descriptor_data = source_descriptor_data;+  source_descriptor_data = 0;+}++void kqueue_reactor::start_op(int op_type, socket_type descriptor,+    kqueue_reactor::per_descriptor_data& descriptor_data, reactor_op* op,+    bool is_continuation, bool allow_speculative)+{+  if (!descriptor_data)+  {+    op->ec_ = asio::error::bad_descriptor;+    post_immediate_completion(op, is_continuation);+    return;+  }++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  if (descriptor_data->shutdown_)+  {+    post_immediate_completion(op, is_continuation);+    return;+  }++  if (descriptor_data->op_queue_[op_type].empty())+  {+    static const int num_kevents[max_ops] = { 1, 2, 1 };++    if (allow_speculative+        && (op_type != read_op+          || descriptor_data->op_queue_[except_op].empty()))+    {+      if (op->perform())+      {+        descriptor_lock.unlock();+        scheduler_.post_immediate_completion(op, is_continuation);+        return;+      }++      if (descriptor_data->num_kevents_ < num_kevents[op_type])+      {+        struct kevent events[2];+        ASIO_KQUEUE_EV_SET(&events[0], descriptor, EVFILT_READ,+            EV_ADD | EV_CLEAR, 0, 0, descriptor_data);+        ASIO_KQUEUE_EV_SET(&events[1], descriptor, EVFILT_WRITE,+            EV_ADD | EV_CLEAR, 0, 0, descriptor_data);+        if (::kevent(kqueue_fd_, events, num_kevents[op_type], 0, 0, 0) != -1)+        {+          descriptor_data->num_kevents_ = num_kevents[op_type];+        }+        else+        {+          op->ec_ = asio::error_code(errno,+              asio::error::get_system_category());+          scheduler_.post_immediate_completion(op, is_continuation);+          return;+        }+      }+    }+    else+    {+      if (descriptor_data->num_kevents_ < num_kevents[op_type])+        descriptor_data->num_kevents_ = num_kevents[op_type];++      struct kevent events[2];+      ASIO_KQUEUE_EV_SET(&events[0], descriptor, EVFILT_READ,+          EV_ADD | EV_CLEAR, 0, 0, descriptor_data);+      ASIO_KQUEUE_EV_SET(&events[1], descriptor, EVFILT_WRITE,+          EV_ADD | EV_CLEAR, 0, 0, descriptor_data);+      ::kevent(kqueue_fd_, events, descriptor_data->num_kevents_, 0, 0, 0);+    }+  }++  descriptor_data->op_queue_[op_type].push(op);+  scheduler_.work_started();+}++void kqueue_reactor::cancel_ops(socket_type,+    kqueue_reactor::per_descriptor_data& descriptor_data)+{+  if (!descriptor_data)+    return;++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  op_queue<operation> ops;+  for (int i = 0; i < max_ops; ++i)+  {+    while (reactor_op* op = descriptor_data->op_queue_[i].front())+    {+      op->ec_ = asio::error::operation_aborted;+      descriptor_data->op_queue_[i].pop();+      ops.push(op);+    }+  }++  descriptor_lock.unlock();++  scheduler_.post_deferred_completions(ops);+}++void kqueue_reactor::deregister_descriptor(socket_type descriptor,+    kqueue_reactor::per_descriptor_data& descriptor_data, bool closing)+{+  if (!descriptor_data)+    return;++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  if (!descriptor_data->shutdown_)+  {+    if (closing)+    {+      // The descriptor will be automatically removed from the kqueue when it+      // is closed.+    }+    else+    {+      struct kevent events[2];+      ASIO_KQUEUE_EV_SET(&events[0], descriptor,+          EVFILT_READ, EV_DELETE, 0, 0, 0);+      ASIO_KQUEUE_EV_SET(&events[1], descriptor,+          EVFILT_WRITE, EV_DELETE, 0, 0, 0);+      ::kevent(kqueue_fd_, events, descriptor_data->num_kevents_, 0, 0, 0);+    }++    op_queue<operation> ops;+    for (int i = 0; i < max_ops; ++i)+    {+      while (reactor_op* op = descriptor_data->op_queue_[i].front())+      {+        op->ec_ = asio::error::operation_aborted;+        descriptor_data->op_queue_[i].pop();+        ops.push(op);+      }+    }++    descriptor_data->descriptor_ = -1;+    descriptor_data->shutdown_ = true;++    descriptor_lock.unlock();++    ASIO_HANDLER_REACTOR_DEREGISTRATION((+          context(), static_cast<uintmax_t>(descriptor),+          reinterpret_cast<uintmax_t>(descriptor_data)));++    scheduler_.post_deferred_completions(ops);++    // Leave descriptor_data set so that it will be freed by the subsequent+    // call to cleanup_descriptor_data.+  }+  else+  {+    // We are shutting down, so prevent cleanup_descriptor_data from freeing+    // the descriptor_data object and let the destructor free it instead.+    descriptor_data = 0;+  }+}++void kqueue_reactor::deregister_internal_descriptor(socket_type descriptor,+    kqueue_reactor::per_descriptor_data& descriptor_data)+{+  if (!descriptor_data)+    return;++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  if (!descriptor_data->shutdown_)+  {+    struct kevent events[2];+    ASIO_KQUEUE_EV_SET(&events[0], descriptor,+        EVFILT_READ, EV_DELETE, 0, 0, 0);+    ASIO_KQUEUE_EV_SET(&events[1], descriptor,+        EVFILT_WRITE, EV_DELETE, 0, 0, 0);+    ::kevent(kqueue_fd_, events, descriptor_data->num_kevents_, 0, 0, 0);++    op_queue<operation> ops;+    for (int i = 0; i < max_ops; ++i)+      ops.push(descriptor_data->op_queue_[i]);++    descriptor_data->descriptor_ = -1;+    descriptor_data->shutdown_ = true;++    descriptor_lock.unlock();++    ASIO_HANDLER_REACTOR_DEREGISTRATION((+          context(), static_cast<uintmax_t>(descriptor),+          reinterpret_cast<uintmax_t>(descriptor_data)));++    // Leave descriptor_data set so that it will be freed by the subsequent+    // call to cleanup_descriptor_data.+  }+  else+  {+    // We are shutting down, so prevent cleanup_descriptor_data from freeing+    // the descriptor_data object and let the destructor free it instead.+    descriptor_data = 0;+  }+}++void kqueue_reactor::cleanup_descriptor_data(+    per_descriptor_data& descriptor_data)+{+  if (descriptor_data)+  {+    free_descriptor_state(descriptor_data);+    descriptor_data = 0;+  }+}++void kqueue_reactor::run(long usec, op_queue<operation>& ops)+{+  mutex::scoped_lock lock(mutex_);++  // Determine how long to block while waiting for events.+  timespec timeout_buf = { 0, 0 };+  timespec* timeout = usec ? get_timeout(usec, timeout_buf) : &timeout_buf;++  lock.unlock();++  // Block on the kqueue descriptor.+  struct kevent events[128];+  int num_events = kevent(kqueue_fd_, 0, 0, events, 128, timeout);++#if defined(ASIO_ENABLE_HANDLER_TRACKING)+  // Trace the waiting events.+  for (int i = 0; i < num_events; ++i)+  {+    void* ptr = reinterpret_cast<void*>(events[i].udata);+    if (ptr != &interrupter_)+    {+      unsigned event_mask = 0;+      switch (events[i].filter)+      {+      case EVFILT_READ:+        event_mask |= ASIO_HANDLER_REACTOR_READ_EVENT;+        break;+      case EVFILT_WRITE:+        event_mask |= ASIO_HANDLER_REACTOR_WRITE_EVENT;+        break;+      }+      if ((events[i].flags & (EV_ERROR | EV_OOBAND)) != 0)+        event_mask |= ASIO_HANDLER_REACTOR_ERROR_EVENT;+      ASIO_HANDLER_REACTOR_EVENTS((context(),+            reinterpret_cast<uintmax_t>(ptr), event_mask));+    }+  }+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)++  // Dispatch the waiting events.+  for (int i = 0; i < num_events; ++i)+  {+    void* ptr = reinterpret_cast<void*>(events[i].udata);+    if (ptr == &interrupter_)+    {+      interrupter_.reset();+    }+    else+    {+      descriptor_state* descriptor_data = static_cast<descriptor_state*>(ptr);+      mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++      if (events[i].filter == EVFILT_WRITE+          && descriptor_data->num_kevents_ == 2+          && descriptor_data->op_queue_[write_op].empty())+      {+        // Some descriptor types, like serial ports, don't seem to support+        // EV_CLEAR with EVFILT_WRITE. Since we have no pending write+        // operations we'll remove the EVFILT_WRITE registration here so that+        // we don't end up in a tight spin.+        struct kevent delete_events[1];+        ASIO_KQUEUE_EV_SET(&delete_events[0],+            descriptor_data->descriptor_, EVFILT_WRITE, EV_DELETE, 0, 0, 0);+        ::kevent(kqueue_fd_, delete_events, 1, 0, 0, 0);+        descriptor_data->num_kevents_ = 1;+      }++      // Exception operations must be processed first to ensure that any+      // out-of-band data is read before normal data.+#if defined(__NetBSD__)+      static const unsigned int filter[max_ops] =+#else+      static const int filter[max_ops] =+#endif+        { EVFILT_READ, EVFILT_WRITE, EVFILT_READ };+      for (int j = max_ops - 1; j >= 0; --j)+      {+        if (events[i].filter == filter[j])+        {+          if (j != except_op || events[i].flags & EV_OOBAND)+          {+            while (reactor_op* op = descriptor_data->op_queue_[j].front())+            {+              if (events[i].flags & EV_ERROR)+              {+                op->ec_ = asio::error_code(+                    static_cast<int>(events[i].data),+                    asio::error::get_system_category());+                descriptor_data->op_queue_[j].pop();+                ops.push(op);+              }+              if (op->perform())+              {+                descriptor_data->op_queue_[j].pop();+                ops.push(op);+              }+              else+                break;+            }+          }+        }+      }+    }+  }++  lock.lock();+  timer_queues_.get_ready_timers(ops);+}++void kqueue_reactor::interrupt()+{+  interrupter_.interrupt();+}++int kqueue_reactor::do_kqueue_create()+{+  int fd = ::kqueue();+  if (fd == -1)+  {+    asio::error_code ec(errno,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "kqueue");+  }+  return fd;+}++kqueue_reactor::descriptor_state* kqueue_reactor::allocate_descriptor_state()+{+  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);+  return registered_descriptors_.alloc(ASIO_CONCURRENCY_HINT_IS_LOCKING(+        REACTOR_IO, scheduler_.concurrency_hint()));+}++void kqueue_reactor::free_descriptor_state(kqueue_reactor::descriptor_state* s)+{+  mutex::scoped_lock descriptors_lock(registered_descriptors_mutex_);+  registered_descriptors_.free(s);+}++void kqueue_reactor::do_add_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.insert(&queue);+}++void kqueue_reactor::do_remove_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.erase(&queue);+}++timespec* kqueue_reactor::get_timeout(long usec, timespec& ts)+{+  // By default we will wait no longer than 5 minutes. This will ensure that+  // any changes to the system clock are detected after no longer than this.+  const long max_usec = 5 * 60 * 1000 * 1000;+  usec = timer_queues_.wait_duration_usec(+      (usec < 0 || max_usec < usec) ? max_usec : usec);+  ts.tv_sec = usec / 1000000;+  ts.tv_nsec = (usec % 1000000) * 1000;+  return &ts;+}++} // namespace detail+} // namespace asio++#undef ASIO_KQUEUE_EV_SET++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_KQUEUE)++#endif // ASIO_DETAIL_IMPL_KQUEUE_REACTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/null_event.ipp view
@@ -0,0 +1,74 @@+//+// detail/impl/null_event.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_NULL_EVENT_IPP+#define ASIO_DETAIL_IMPL_NULL_EVENT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)+# include <thread>+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# include "asio/detail/socket_types.hpp"+#else+# include <unistd.h>+# if defined(__hpux)+#  include <sys/time.h>+# endif+# if !defined(__hpux) || defined(__SELECT)+#  include <sys/select.h>+# endif+#endif++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++void null_event::do_wait()+{+#if defined(ASIO_WINDOWS_RUNTIME)+  std::this_thread::sleep_until((std::chrono::steady_clock::time_point::max)());+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  ::Sleep(INFINITE);+#else+  ::pause();+#endif+}++void null_event::do_wait_for_usec(long usec)+{+#if defined(ASIO_WINDOWS_RUNTIME)+  std::this_thread::sleep_for(std::chrono::microseconds(usec));+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  ::Sleep(usec / 1000);+#elif defined(__hpux) && defined(__SELECT)+  timespec ts;+  ts.tv_sec = usec / 1000000;+  ts.tv_nsec = (usec % 1000000) * 1000;+  ::pselect(0, 0, 0, 0, &ts, 0);+#else+  timeval tv;+  tv.tv_sec = usec / 1000000;+  tv.tv_usec = usec % 1000000;+  ::select(0, 0, 0, 0, &tv);+#endif+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_NULL_EVENT_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/pipe_select_interrupter.ipp view
@@ -0,0 +1,129 @@+//+// detail/impl/pipe_select_interrupter.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP+#define ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if !defined(ASIO_WINDOWS_RUNTIME)+#if !defined(ASIO_WINDOWS)+#if !defined(__CYGWIN__)+#if !defined(__SYMBIAN32__)+#if !defined(ASIO_HAS_EVENTFD)++#include <fcntl.h>+#include <sys/stat.h>+#include <sys/types.h>+#include <unistd.h>+#include "asio/detail/pipe_select_interrupter.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++pipe_select_interrupter::pipe_select_interrupter()+{+  open_descriptors();+}++void pipe_select_interrupter::open_descriptors()+{+  int pipe_fds[2];+  if (pipe(pipe_fds) == 0)+  {+    read_descriptor_ = pipe_fds[0];+    ::fcntl(read_descriptor_, F_SETFL, O_NONBLOCK);+    write_descriptor_ = pipe_fds[1];+    ::fcntl(write_descriptor_, F_SETFL, O_NONBLOCK);++#if defined(FD_CLOEXEC)+    ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);+    ::fcntl(write_descriptor_, F_SETFD, FD_CLOEXEC);+#endif // defined(FD_CLOEXEC)+  }+  else+  {+    asio::error_code ec(errno,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "pipe_select_interrupter");+  }+}++pipe_select_interrupter::~pipe_select_interrupter()+{+  close_descriptors();+}++void pipe_select_interrupter::close_descriptors()+{+  if (read_descriptor_ != -1)+    ::close(read_descriptor_);+  if (write_descriptor_ != -1)+    ::close(write_descriptor_);+}++void pipe_select_interrupter::recreate()+{+  close_descriptors();++  write_descriptor_ = -1;+  read_descriptor_ = -1;++  open_descriptors();+}++void pipe_select_interrupter::interrupt()+{+  char byte = 0;+  signed_size_type result = ::write(write_descriptor_, &byte, 1);+  (void)result;+}++bool pipe_select_interrupter::reset()+{+  for (;;)+  {+    char data[1024];+    signed_size_type bytes_read = ::read(read_descriptor_, data, sizeof(data));+    if (bytes_read == sizeof(data))+      continue;+    if (bytes_read > 0)+      return true;+    if (bytes_read == 0)+      return false;+    if (errno == EINTR)+      continue;+    if (errno == EWOULDBLOCK || errno == EAGAIN)+      return true;+    return false;+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_HAS_EVENTFD)+#endif // !defined(__SYMBIAN32__)+#endif // !defined(__CYGWIN__)+#endif // !defined(ASIO_WINDOWS)+#endif // !defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_IMPL_PIPE_SELECT_INTERRUPTER_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/posix_event.ipp view
@@ -0,0 +1,59 @@+//+// detail/impl/posix_event.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_POSIX_EVENT_IPP+#define ASIO_DETAIL_IMPL_POSIX_EVENT_IPP++#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_PTHREADS)++#include "asio/detail/posix_event.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++posix_event::posix_event()+  : state_(0)+{+#if (defined(__MACH__) && defined(__APPLE__)) \+      || (defined(__ANDROID__) && (__ANDROID_API__ < 21))+  int error = ::pthread_cond_init(&cond_, 0);+#else // (defined(__MACH__) && defined(__APPLE__))+      // || (defined(__ANDROID__) && (__ANDROID_API__ < 21))+  ::pthread_condattr_t attr;+  ::pthread_condattr_init(&attr);+  int error = ::pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);+  if (error == 0)+    error = ::pthread_cond_init(&cond_, &attr);+#endif // (defined(__MACH__) && defined(__APPLE__))+       // || (defined(__ANDROID__) && (__ANDROID_API__ < 21))++  asio::error_code ec(error,+      asio::error::get_system_category());+  asio::detail::throw_error(ec, "event");+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_IMPL_POSIX_EVENT_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/posix_mutex.ipp view
@@ -0,0 +1,46 @@+//+// detail/impl/posix_mutex.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP+#define ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP++#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_PTHREADS)++#include "asio/detail/posix_mutex.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++posix_mutex::posix_mutex()+{+  int error = ::pthread_mutex_init(&mutex_, 0);+  asio::error_code ec(error,+      asio::error::get_system_category());+  asio::detail::throw_error(ec, "mutex");+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_IMPL_POSIX_MUTEX_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/posix_thread.ipp view
@@ -0,0 +1,84 @@+//+// detail/impl/posix_thread.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_POSIX_THREAD_IPP+#define ASIO_DETAIL_IMPL_POSIX_THREAD_IPP++#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_PTHREADS)++#include "asio/detail/posix_thread.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++posix_thread::~posix_thread()+{+  if (!joined_)+    ::pthread_detach(thread_);+}++void posix_thread::join()+{+  if (!joined_)+  {+    ::pthread_join(thread_, 0);+    joined_ = true;+  }+}++std::size_t posix_thread::hardware_concurrency()+{+#if defined(_SC_NPROCESSORS_ONLN)+  long result = sysconf(_SC_NPROCESSORS_ONLN);+  if (result > 0)+    return result;+#endif // defined(_SC_NPROCESSORS_ONLN)+  return 0;+}++void posix_thread::start_thread(func_base* arg)+{+  int error = ::pthread_create(&thread_, 0,+        asio_detail_posix_thread_function, arg);+  if (error != 0)+  {+    delete arg;+    asio::error_code ec(error,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "thread");+  }+}++void* asio_detail_posix_thread_function(void* arg)+{+  posix_thread::auto_func_base_ptr func = {+      static_cast<posix_thread::func_base*>(arg) };+  func.ptr->run();+  return 0;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_IMPL_POSIX_THREAD_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/posix_tss_ptr.ipp view
@@ -0,0 +1,46 @@+//+// detail/impl/posix_tss_ptr.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP+#define ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP++#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_PTHREADS)++#include "asio/detail/posix_tss_ptr.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++void posix_tss_ptr_create(pthread_key_t& key)+{+  int error = ::pthread_key_create(&key, 0);+  asio::error_code ec(error,+      asio::error::get_system_category());+  asio::detail::throw_error(ec, "tss");+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_IMPL_POSIX_TSS_PTR_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_descriptor_service.ipp view
@@ -0,0 +1,223 @@+//+// detail/impl/reactive_descriptor_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP+#define ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)++#include "asio/error.hpp"+#include "asio/detail/reactive_descriptor_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++reactive_descriptor_service::reactive_descriptor_service(+    execution_context& context)+  : execution_context_service_base<reactive_descriptor_service>(context),+    reactor_(asio::use_service<reactor>(context))+{+  reactor_.init_task();+}++void reactive_descriptor_service::shutdown()+{+}++void reactive_descriptor_service::construct(+    reactive_descriptor_service::implementation_type& impl)+{+  impl.descriptor_ = -1;+  impl.state_ = 0;+}++void reactive_descriptor_service::move_construct(+    reactive_descriptor_service::implementation_type& impl,+    reactive_descriptor_service::implementation_type& other_impl)+  ASIO_NOEXCEPT+{+  impl.descriptor_ = other_impl.descriptor_;+  other_impl.descriptor_ = -1;++  impl.state_ = other_impl.state_;+  other_impl.state_ = 0;++  reactor_.move_descriptor(impl.descriptor_,+      impl.reactor_data_, other_impl.reactor_data_);+}++void reactive_descriptor_service::move_assign(+    reactive_descriptor_service::implementation_type& impl,+    reactive_descriptor_service& other_service,+    reactive_descriptor_service::implementation_type& other_impl)+{+  destroy(impl);++  impl.descriptor_ = other_impl.descriptor_;+  other_impl.descriptor_ = -1;++  impl.state_ = other_impl.state_;+  other_impl.state_ = 0;++  other_service.reactor_.move_descriptor(impl.descriptor_,+      impl.reactor_data_, other_impl.reactor_data_);+}++void reactive_descriptor_service::destroy(+    reactive_descriptor_service::implementation_type& impl)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((reactor_.context(),+          "descriptor", &impl, impl.descriptor_, "close"));++    reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_,+        (impl.state_ & descriptor_ops::possible_dup) == 0);++    asio::error_code ignored_ec;+    descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec);++    reactor_.cleanup_descriptor_data(impl.reactor_data_);+  }+}++asio::error_code reactive_descriptor_service::assign(+    reactive_descriptor_service::implementation_type& impl,+    const native_handle_type& native_descriptor, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  if (int err = reactor_.register_descriptor(+        native_descriptor, impl.reactor_data_))+  {+    ec = asio::error_code(err,+        asio::error::get_system_category());+    return ec;+  }++  impl.descriptor_ = native_descriptor;+  impl.state_ = descriptor_ops::possible_dup;+  ec = asio::error_code();+  return ec;+}++asio::error_code reactive_descriptor_service::close(+    reactive_descriptor_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((reactor_.context(),+          "descriptor", &impl, impl.descriptor_, "close"));++    reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_,+        (impl.state_ & descriptor_ops::possible_dup) == 0);++    descriptor_ops::close(impl.descriptor_, impl.state_, ec);++    reactor_.cleanup_descriptor_data(impl.reactor_data_);+  }+  else+  {+    ec = asio::error_code();+  }++  // The descriptor is closed by the OS even if close() returns an error.+  //+  // (Actually, POSIX says the state of the descriptor is unspecified. On+  // Linux the descriptor is apparently closed anyway; e.g. see+  //   http://lkml.org/lkml/2005/9/10/129+  // We'll just have to assume that other OSes follow the same behaviour.)+  construct(impl);++  return ec;+}++reactive_descriptor_service::native_handle_type+reactive_descriptor_service::release(+    reactive_descriptor_service::implementation_type& impl)+{+  native_handle_type descriptor = impl.descriptor_;++  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((reactor_.context(),+          "descriptor", &impl, impl.descriptor_, "release"));++    reactor_.deregister_descriptor(impl.descriptor_, impl.reactor_data_, false);+    reactor_.cleanup_descriptor_data(impl.reactor_data_);+    construct(impl);+  }++  return descriptor;+}++asio::error_code reactive_descriptor_service::cancel(+    reactive_descriptor_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return ec;+  }++  ASIO_HANDLER_OPERATION((reactor_.context(),+        "descriptor", &impl, impl.descriptor_, "cancel"));++  reactor_.cancel_ops(impl.descriptor_, impl.reactor_data_);+  ec = asio::error_code();+  return ec;+}++void reactive_descriptor_service::start_op(+    reactive_descriptor_service::implementation_type& impl,+    int op_type, reactor_op* op, bool is_continuation,+    bool is_non_blocking, bool noop)+{+  if (!noop)+  {+    if ((impl.state_ & descriptor_ops::non_blocking) ||+        descriptor_ops::set_internal_non_blocking(+          impl.descriptor_, impl.state_, true, op->ec_))+    {+      reactor_.start_op(op_type, impl.descriptor_,+          impl.reactor_data_, op, is_continuation, is_non_blocking);+      return;+    }+  }++  reactor_.post_immediate_completion(op, is_continuation);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)++#endif // ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_serial_port_service.ipp view
@@ -0,0 +1,149 @@+//+// detail/impl/reactive_serial_port_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP+#define ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP++#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)+#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++#include <cstring>+#include "asio/detail/reactive_serial_port_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++reactive_serial_port_service::reactive_serial_port_service(+    execution_context& context)+  : execution_context_service_base<reactive_serial_port_service>(context),+    descriptor_service_(context)+{+}++void reactive_serial_port_service::shutdown()+{+  descriptor_service_.shutdown();+}++asio::error_code reactive_serial_port_service::open(+    reactive_serial_port_service::implementation_type& impl,+    const std::string& device, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  descriptor_ops::state_type state = 0;+  int fd = descriptor_ops::open(device.c_str(),+      O_RDWR | O_NONBLOCK | O_NOCTTY, ec);+  if (fd < 0)+    return ec;++  int s = descriptor_ops::fcntl(fd, F_GETFL, ec);+  if (s >= 0)+    s = descriptor_ops::fcntl(fd, F_SETFL, s | O_NONBLOCK, ec);+  if (s < 0)+  {+    asio::error_code ignored_ec;+    descriptor_ops::close(fd, state, ignored_ec);+    return ec;+  }++  // Set up default serial port options.+  termios ios;+  s = ::tcgetattr(fd, &ios);+  descriptor_ops::get_last_error(ec, s < 0);+  if (s >= 0)+  {+#if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)+    ::cfmakeraw(&ios);+#else+    ios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK+        | ISTRIP | INLCR | IGNCR | ICRNL | IXON);+    ios.c_oflag &= ~OPOST;+    ios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);+    ios.c_cflag &= ~(CSIZE | PARENB);+    ios.c_cflag |= CS8;+#endif+    ios.c_iflag |= IGNPAR;+    ios.c_cflag |= CREAD | CLOCAL;+    s = ::tcsetattr(fd, TCSANOW, &ios);+    descriptor_ops::get_last_error(ec, s < 0);+  }+  if (s < 0)+  {+    asio::error_code ignored_ec;+    descriptor_ops::close(fd, state, ignored_ec);+    return ec;+  }++  // We're done. Take ownership of the serial port descriptor.+  if (descriptor_service_.assign(impl, fd, ec))+  {+    asio::error_code ignored_ec;+    descriptor_ops::close(fd, state, ignored_ec);+  }++  return ec;+}++asio::error_code reactive_serial_port_service::do_set_option(+    reactive_serial_port_service::implementation_type& impl,+    reactive_serial_port_service::store_function_type store,+    const void* option, asio::error_code& ec)+{+  termios ios;+  int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios);+  descriptor_ops::get_last_error(ec, s < 0);+  if (s < 0)+    return ec;++  if (store(option, ios, ec))+    return ec;++  s = ::tcsetattr(descriptor_service_.native_handle(impl), TCSANOW, &ios);+  descriptor_ops::get_last_error(ec, s < 0);+  return ec;+}++asio::error_code reactive_serial_port_service::do_get_option(+    const reactive_serial_port_service::implementation_type& impl,+    reactive_serial_port_service::load_function_type load,+    void* option, asio::error_code& ec) const+{+  termios ios;+  int s = ::tcgetattr(descriptor_service_.native_handle(impl), &ios);+  descriptor_ops::get_last_error(ec, s < 0);+  if (s < 0)+    return ec;++  return load(option, ios, ec);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+#endif // defined(ASIO_HAS_SERIAL_PORT)++#endif // ASIO_DETAIL_IMPL_REACTIVE_SERIAL_PORT_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_socket_service_base.ipp view
@@ -0,0 +1,300 @@+//+// detail/reactive_socket_service_base.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP+#define ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP++#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_IOCP) \+  && !defined(ASIO_WINDOWS_RUNTIME)++#include "asio/detail/reactive_socket_service_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++reactive_socket_service_base::reactive_socket_service_base(+    execution_context& context)+  : reactor_(use_service<reactor>(context))+{+  reactor_.init_task();+}++void reactive_socket_service_base::base_shutdown()+{+}++void reactive_socket_service_base::construct(+    reactive_socket_service_base::base_implementation_type& impl)+{+  impl.socket_ = invalid_socket;+  impl.state_ = 0;+}++void reactive_socket_service_base::base_move_construct(+    reactive_socket_service_base::base_implementation_type& impl,+    reactive_socket_service_base::base_implementation_type& other_impl)+  ASIO_NOEXCEPT+{+  impl.socket_ = other_impl.socket_;+  other_impl.socket_ = invalid_socket;++  impl.state_ = other_impl.state_;+  other_impl.state_ = 0;++  reactor_.move_descriptor(impl.socket_,+      impl.reactor_data_, other_impl.reactor_data_);+}++void reactive_socket_service_base::base_move_assign(+    reactive_socket_service_base::base_implementation_type& impl,+    reactive_socket_service_base& other_service,+    reactive_socket_service_base::base_implementation_type& other_impl)+{+  destroy(impl);++  impl.socket_ = other_impl.socket_;+  other_impl.socket_ = invalid_socket;++  impl.state_ = other_impl.state_;+  other_impl.state_ = 0;++  other_service.reactor_.move_descriptor(impl.socket_,+      impl.reactor_data_, other_impl.reactor_data_);+}++void reactive_socket_service_base::destroy(+    reactive_socket_service_base::base_implementation_type& impl)+{+  if (impl.socket_ != invalid_socket)+  {+    ASIO_HANDLER_OPERATION((reactor_.context(),+          "socket", &impl, impl.socket_, "close"));++    reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,+        (impl.state_ & socket_ops::possible_dup) == 0);++    asio::error_code ignored_ec;+    socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);++    reactor_.cleanup_descriptor_data(impl.reactor_data_);+  }+}++asio::error_code reactive_socket_service_base::close(+    reactive_socket_service_base::base_implementation_type& impl,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((reactor_.context(),+          "socket", &impl, impl.socket_, "close"));++    reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_,+        (impl.state_ & socket_ops::possible_dup) == 0);++    socket_ops::close(impl.socket_, impl.state_, false, ec);++    reactor_.cleanup_descriptor_data(impl.reactor_data_);+  }+  else+  {+    ec = asio::error_code();+  }++  // The descriptor is closed by the OS even if close() returns an error.+  //+  // (Actually, POSIX says the state of the descriptor is unspecified. On+  // Linux the descriptor is apparently closed anyway; e.g. see+  //   http://lkml.org/lkml/2005/9/10/129+  // We'll just have to assume that other OSes follow the same behaviour. The+  // known exception is when Windows's closesocket() function fails with+  // WSAEWOULDBLOCK, but this case is handled inside socket_ops::close().+  construct(impl);++  return ec;+}++socket_type reactive_socket_service_base::release(+    reactive_socket_service_base::base_implementation_type& impl,+    asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return invalid_socket;+  }++  ASIO_HANDLER_OPERATION((reactor_.context(),+        "socket", &impl, impl.socket_, "release"));++  reactor_.deregister_descriptor(impl.socket_, impl.reactor_data_, false);+  reactor_.cleanup_descriptor_data(impl.reactor_data_);+  socket_type sock = impl.socket_;+  construct(impl);+  ec = asio::error_code();+  return sock;+}++asio::error_code reactive_socket_service_base::cancel(+    reactive_socket_service_base::base_implementation_type& impl,+    asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return ec;+  }++  ASIO_HANDLER_OPERATION((reactor_.context(),+        "socket", &impl, impl.socket_, "cancel"));++  reactor_.cancel_ops(impl.socket_, impl.reactor_data_);+  ec = asio::error_code();+  return ec;+}++asio::error_code reactive_socket_service_base::do_open(+    reactive_socket_service_base::base_implementation_type& impl,+    int af, int type, int protocol, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  socket_holder sock(socket_ops::socket(af, type, protocol, ec));+  if (sock.get() == invalid_socket)+    return ec;++  if (int err = reactor_.register_descriptor(sock.get(), impl.reactor_data_))+  {+    ec = asio::error_code(err,+        asio::error::get_system_category());+    return ec;+  }++  impl.socket_ = sock.release();+  switch (type)+  {+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;+  default: impl.state_ = 0; break;+  }+  ec = asio::error_code();+  return ec;+}++asio::error_code reactive_socket_service_base::do_assign(+    reactive_socket_service_base::base_implementation_type& impl, int type,+    const reactive_socket_service_base::native_handle_type& native_socket,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  if (int err = reactor_.register_descriptor(+        native_socket, impl.reactor_data_))+  {+    ec = asio::error_code(err,+        asio::error::get_system_category());+    return ec;+  }++  impl.socket_ = native_socket;+  switch (type)+  {+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;+  default: impl.state_ = 0; break;+  }+  impl.state_ |= socket_ops::possible_dup;+  ec = asio::error_code();+  return ec;+}++void reactive_socket_service_base::start_op(+    reactive_socket_service_base::base_implementation_type& impl,+    int op_type, reactor_op* op, bool is_continuation,+    bool is_non_blocking, bool noop)+{+  if (!noop)+  {+    if ((impl.state_ & socket_ops::non_blocking)+        || socket_ops::set_internal_non_blocking(+          impl.socket_, impl.state_, true, op->ec_))+    {+      reactor_.start_op(op_type, impl.socket_,+          impl.reactor_data_, op, is_continuation, is_non_blocking);+      return;+    }+  }++  reactor_.post_immediate_completion(op, is_continuation);+}++void reactive_socket_service_base::start_accept_op(+    reactive_socket_service_base::base_implementation_type& impl,+    reactor_op* op, bool is_continuation, bool peer_is_open)+{+  if (!peer_is_open)+    start_op(impl, reactor::read_op, op, is_continuation, true, false);+  else+  {+    op->ec_ = asio::error::already_open;+    reactor_.post_immediate_completion(op, is_continuation);+  }+}++void reactive_socket_service_base::start_connect_op(+    reactive_socket_service_base::base_implementation_type& impl,+    reactor_op* op, bool is_continuation,+    const socket_addr_type* addr, size_t addrlen)+{+  if ((impl.state_ & socket_ops::non_blocking)+      || socket_ops::set_internal_non_blocking(+        impl.socket_, impl.state_, true, op->ec_))+  {+    if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)+    {+      if (op->ec_ == asio::error::in_progress+          || op->ec_ == asio::error::would_block)+      {+        op->ec_ = asio::error_code();+        reactor_.start_op(reactor::connect_op, impl.socket_,+            impl.reactor_data_, op, is_continuation, false);+        return;+      }+    }+  }++  reactor_.post_immediate_completion(op, is_continuation);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_HAS_IOCP)+       //   && !defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/resolver_service_base.ipp view
@@ -0,0 +1,158 @@+//+// detail/impl/resolver_service_base.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP+#define ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/resolver_service_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class resolver_service_base::work_scheduler_runner+{+public:+  work_scheduler_runner(scheduler_impl& work_scheduler)+    : work_scheduler_(work_scheduler)+  {+  }++  void operator()()+  {+    asio::error_code ec;+    work_scheduler_.run(ec);+  }++private:+  scheduler_impl& work_scheduler_;+};++resolver_service_base::resolver_service_base(execution_context& context)+  : scheduler_(asio::use_service<scheduler_impl>(context)),+    work_scheduler_(new scheduler_impl(context, -1, false)),+    work_thread_(0)+{+  work_scheduler_->work_started();+}++resolver_service_base::~resolver_service_base()+{+  base_shutdown();+}++void resolver_service_base::base_shutdown()+{+  if (work_scheduler_.get())+  {+    work_scheduler_->work_finished();+    work_scheduler_->stop();+    if (work_thread_.get())+    {+      work_thread_->join();+      work_thread_.reset();+    }+    work_scheduler_.reset();+  }+}++void resolver_service_base::base_notify_fork(+    execution_context::fork_event fork_ev)+{+  if (work_thread_.get())+  {+    if (fork_ev == execution_context::fork_prepare)+    {+      work_scheduler_->stop();+      work_thread_->join();+      work_thread_.reset();+    }+  }+  else if (fork_ev != execution_context::fork_prepare)+  {+    work_scheduler_->restart();+  }+}++void resolver_service_base::construct(+    resolver_service_base::implementation_type& impl)+{+  impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());+}++void resolver_service_base::destroy(+    resolver_service_base::implementation_type& impl)+{+  ASIO_HANDLER_OPERATION((scheduler_.context(),+        "resolver", &impl, 0, "cancel"));++  impl.reset();+}++void resolver_service_base::move_construct(implementation_type& impl,+    implementation_type& other_impl)+{+  impl = ASIO_MOVE_CAST(implementation_type)(other_impl);+}++void resolver_service_base::move_assign(implementation_type& impl,+    resolver_service_base&, implementation_type& other_impl)+{+  destroy(impl);+  impl = ASIO_MOVE_CAST(implementation_type)(other_impl);+}++void resolver_service_base::cancel(+    resolver_service_base::implementation_type& impl)+{+  ASIO_HANDLER_OPERATION((scheduler_.context(),+        "resolver", &impl, 0, "cancel"));++  impl.reset(static_cast<void*>(0), socket_ops::noop_deleter());+}++void resolver_service_base::start_resolve_op(resolve_op* op)+{+  if (ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,+        scheduler_.concurrency_hint()))+  {+    start_work_thread();+    scheduler_.work_started();+    work_scheduler_->post_immediate_completion(op, false);+  }+  else+  {+    op->ec_ = asio::error::operation_not_supported;+    scheduler_.post_immediate_completion(op, false);+  }+}++void resolver_service_base::start_work_thread()+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  if (!work_thread_.get())+  {+    work_thread_.reset(new asio::detail::thread(+          work_scheduler_runner(*work_scheduler_)));+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_RESOLVER_SERVICE_BASE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/scheduler.ipp view
@@ -0,0 +1,654 @@+//+// detail/impl/scheduler.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_SCHEDULER_IPP+#define ASIO_DETAIL_IMPL_SCHEDULER_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/detail/concurrency_hint.hpp"+#include "asio/detail/event.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/reactor.hpp"+#include "asio/detail/scheduler.hpp"+#include "asio/detail/scheduler_thread_info.hpp"+#include "asio/detail/signal_blocker.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class scheduler::thread_function+{+public:+  explicit thread_function(scheduler* s)+    : this_(s)+  {+  }++  void operator()()+  {+    asio::error_code ec;+    this_->run(ec);+  }++private:+  scheduler* this_;+};++struct scheduler::task_cleanup+{+  ~task_cleanup()+  {+    if (this_thread_->private_outstanding_work > 0)+    {+      asio::detail::increment(+          scheduler_->outstanding_work_,+          this_thread_->private_outstanding_work);+    }+    this_thread_->private_outstanding_work = 0;++    // Enqueue the completed operations and reinsert the task at the end of+    // the operation queue.+    lock_->lock();+    scheduler_->task_interrupted_ = true;+    scheduler_->op_queue_.push(this_thread_->private_op_queue);+    scheduler_->op_queue_.push(&scheduler_->task_operation_);+  }++  scheduler* scheduler_;+  mutex::scoped_lock* lock_;+  thread_info* this_thread_;+};++struct scheduler::work_cleanup+{+  ~work_cleanup()+  {+    if (this_thread_->private_outstanding_work > 1)+    {+      asio::detail::increment(+          scheduler_->outstanding_work_,+          this_thread_->private_outstanding_work - 1);+    }+    else if (this_thread_->private_outstanding_work < 1)+    {+      scheduler_->work_finished();+    }+    this_thread_->private_outstanding_work = 0;++#if defined(ASIO_HAS_THREADS)+    if (!this_thread_->private_op_queue.empty())+    {+      lock_->lock();+      scheduler_->op_queue_.push(this_thread_->private_op_queue);+    }+#endif // defined(ASIO_HAS_THREADS)+  }++  scheduler* scheduler_;+  mutex::scoped_lock* lock_;+  thread_info* this_thread_;+};++scheduler::scheduler(asio::execution_context& ctx,+    int concurrency_hint, bool own_thread)+  : asio::detail::execution_context_service_base<scheduler>(ctx),+    one_thread_(concurrency_hint == 1+        || !ASIO_CONCURRENCY_HINT_IS_LOCKING(+          SCHEDULER, concurrency_hint)+        || !ASIO_CONCURRENCY_HINT_IS_LOCKING(+          REACTOR_IO, concurrency_hint)),+    mutex_(ASIO_CONCURRENCY_HINT_IS_LOCKING(+          SCHEDULER, concurrency_hint)),+    task_(0),+    task_interrupted_(true),+    outstanding_work_(0),+    stopped_(false),+    shutdown_(false),+    concurrency_hint_(concurrency_hint),+    thread_(0)+{+  ASIO_HANDLER_TRACKING_INIT;++  if (own_thread)+  {+    ++outstanding_work_;+    asio::detail::signal_blocker sb;+    thread_ = new asio::detail::thread(thread_function(this));+  }+}++scheduler::~scheduler()+{+  if (thread_)+  {+    mutex::scoped_lock lock(mutex_);+    shutdown_ = true;+    stop_all_threads(lock);+    lock.unlock();+    thread_->join();+    delete thread_;+  }+}++void scheduler::shutdown()+{+  mutex::scoped_lock lock(mutex_);+  shutdown_ = true;+  if (thread_)+    stop_all_threads(lock);+  lock.unlock();++  // Join thread to ensure task operation is returned to queue.+  if (thread_)+  {+    thread_->join();+    delete thread_;+    thread_ = 0;+  }++  // Destroy handler objects.+  while (!op_queue_.empty())+  {+    operation* o = op_queue_.front();+    op_queue_.pop();+    if (o != &task_operation_)+      o->destroy();+  }++  // Reset to initial state.+  task_ = 0;+}++void scheduler::init_task()+{+  mutex::scoped_lock lock(mutex_);+  if (!shutdown_ && !task_)+  {+    task_ = &use_service<reactor>(this->context());+    op_queue_.push(&task_operation_);+    wake_one_thread_and_unlock(lock);+  }+}++std::size_t scheduler::run(asio::error_code& ec)+{+  ec = asio::error_code();+  if (outstanding_work_ == 0)+  {+    stop();+    return 0;+  }++  thread_info this_thread;+  this_thread.private_outstanding_work = 0;+  thread_call_stack::context ctx(this, this_thread);++  mutex::scoped_lock lock(mutex_);++  std::size_t n = 0;+  for (; do_run_one(lock, this_thread, ec); lock.lock())+    if (n != (std::numeric_limits<std::size_t>::max)())+      ++n;+  return n;+}++std::size_t scheduler::run_one(asio::error_code& ec)+{+  ec = asio::error_code();+  if (outstanding_work_ == 0)+  {+    stop();+    return 0;+  }++  thread_info this_thread;+  this_thread.private_outstanding_work = 0;+  thread_call_stack::context ctx(this, this_thread);++  mutex::scoped_lock lock(mutex_);++  return do_run_one(lock, this_thread, ec);+}++std::size_t scheduler::wait_one(long usec, asio::error_code& ec)+{+  ec = asio::error_code();+  if (outstanding_work_ == 0)+  {+    stop();+    return 0;+  }++  thread_info this_thread;+  this_thread.private_outstanding_work = 0;+  thread_call_stack::context ctx(this, this_thread);++  mutex::scoped_lock lock(mutex_);++  return do_wait_one(lock, this_thread, usec, ec);+}++std::size_t scheduler::poll(asio::error_code& ec)+{+  ec = asio::error_code();+  if (outstanding_work_ == 0)+  {+    stop();+    return 0;+  }++  thread_info this_thread;+  this_thread.private_outstanding_work = 0;+  thread_call_stack::context ctx(this, this_thread);++  mutex::scoped_lock lock(mutex_);++#if defined(ASIO_HAS_THREADS)+  // We want to support nested calls to poll() and poll_one(), so any handlers+  // that are already on a thread-private queue need to be put on to the main+  // queue now.+  if (one_thread_)+    if (thread_info* outer_info = static_cast<thread_info*>(ctx.next_by_key()))+      op_queue_.push(outer_info->private_op_queue);+#endif // defined(ASIO_HAS_THREADS)++  std::size_t n = 0;+  for (; do_poll_one(lock, this_thread, ec); lock.lock())+    if (n != (std::numeric_limits<std::size_t>::max)())+      ++n;+  return n;+}++std::size_t scheduler::poll_one(asio::error_code& ec)+{+  ec = asio::error_code();+  if (outstanding_work_ == 0)+  {+    stop();+    return 0;+  }++  thread_info this_thread;+  this_thread.private_outstanding_work = 0;+  thread_call_stack::context ctx(this, this_thread);++  mutex::scoped_lock lock(mutex_);++#if defined(ASIO_HAS_THREADS)+  // We want to support nested calls to poll() and poll_one(), so any handlers+  // that are already on a thread-private queue need to be put on to the main+  // queue now.+  if (one_thread_)+    if (thread_info* outer_info = static_cast<thread_info*>(ctx.next_by_key()))+      op_queue_.push(outer_info->private_op_queue);+#endif // defined(ASIO_HAS_THREADS)++  return do_poll_one(lock, this_thread, ec);+}++void scheduler::stop()+{+  mutex::scoped_lock lock(mutex_);+  stop_all_threads(lock);+}++bool scheduler::stopped() const+{+  mutex::scoped_lock lock(mutex_);+  return stopped_;+}++void scheduler::restart()+{+  mutex::scoped_lock lock(mutex_);+  stopped_ = false;+}++void scheduler::compensating_work_started()+{+  thread_info_base* this_thread = thread_call_stack::contains(this);+  ++static_cast<thread_info*>(this_thread)->private_outstanding_work;+}++void scheduler::capture_current_exception()+{+  if (thread_info_base* this_thread = thread_call_stack::contains(this))+    this_thread->capture_current_exception();+}++void scheduler::post_immediate_completion(+    scheduler::operation* op, bool is_continuation)+{+#if defined(ASIO_HAS_THREADS)+  if (one_thread_ || is_continuation)+  {+    if (thread_info_base* this_thread = thread_call_stack::contains(this))+    {+      ++static_cast<thread_info*>(this_thread)->private_outstanding_work;+      static_cast<thread_info*>(this_thread)->private_op_queue.push(op);+      return;+    }+  }+#else // defined(ASIO_HAS_THREADS)+  (void)is_continuation;+#endif // defined(ASIO_HAS_THREADS)++  work_started();+  mutex::scoped_lock lock(mutex_);+  op_queue_.push(op);+  wake_one_thread_and_unlock(lock);+}++void scheduler::post_immediate_completions(std::size_t n,+    op_queue<scheduler::operation>& ops, bool is_continuation)+{+#if defined(ASIO_HAS_THREADS)+  if (one_thread_ || is_continuation)+  {+    if (thread_info_base* this_thread = thread_call_stack::contains(this))+    {+      static_cast<thread_info*>(this_thread)->private_outstanding_work+        += static_cast<long>(n);+      static_cast<thread_info*>(this_thread)->private_op_queue.push(ops);+      return;+    }+  }+#else // defined(ASIO_HAS_THREADS)+  (void)is_continuation;+#endif // defined(ASIO_HAS_THREADS)++  increment(outstanding_work_, static_cast<long>(n));+  mutex::scoped_lock lock(mutex_);+  op_queue_.push(ops);+  wake_one_thread_and_unlock(lock);+}++void scheduler::post_deferred_completion(scheduler::operation* op)+{+#if defined(ASIO_HAS_THREADS)+  if (one_thread_)+  {+    if (thread_info_base* this_thread = thread_call_stack::contains(this))+    {+      static_cast<thread_info*>(this_thread)->private_op_queue.push(op);+      return;+    }+  }+#endif // defined(ASIO_HAS_THREADS)++  mutex::scoped_lock lock(mutex_);+  op_queue_.push(op);+  wake_one_thread_and_unlock(lock);+}++void scheduler::post_deferred_completions(+    op_queue<scheduler::operation>& ops)+{+  if (!ops.empty())+  {+#if defined(ASIO_HAS_THREADS)+    if (one_thread_)+    {+      if (thread_info_base* this_thread = thread_call_stack::contains(this))+      {+        static_cast<thread_info*>(this_thread)->private_op_queue.push(ops);+        return;+      }+    }+#endif // defined(ASIO_HAS_THREADS)++    mutex::scoped_lock lock(mutex_);+    op_queue_.push(ops);+    wake_one_thread_and_unlock(lock);+  }+}++void scheduler::do_dispatch(+    scheduler::operation* op)+{+  work_started();+  mutex::scoped_lock lock(mutex_);+  op_queue_.push(op);+  wake_one_thread_and_unlock(lock);+}++void scheduler::abandon_operations(+    op_queue<scheduler::operation>& ops)+{+  op_queue<scheduler::operation> ops2;+  ops2.push(ops);+}++std::size_t scheduler::do_run_one(mutex::scoped_lock& lock,+    scheduler::thread_info& this_thread,+    const asio::error_code& ec)+{+  while (!stopped_)+  {+    if (!op_queue_.empty())+    {+      // Prepare to execute first handler from queue.+      operation* o = op_queue_.front();+      op_queue_.pop();+      bool more_handlers = (!op_queue_.empty());++      if (o == &task_operation_)+      {+        task_interrupted_ = more_handlers;++        if (more_handlers && !one_thread_)+          wakeup_event_.unlock_and_signal_one(lock);+        else+          lock.unlock();++        task_cleanup on_exit = { this, &lock, &this_thread };+        (void)on_exit;++        // Run the task. May throw an exception. Only block if the operation+        // queue is empty and we're not polling, otherwise we want to return+        // as soon as possible.+        task_->run(more_handlers ? 0 : -1, this_thread.private_op_queue);+      }+      else+      {+        std::size_t task_result = o->task_result_;++        if (more_handlers && !one_thread_)+          wake_one_thread_and_unlock(lock);+        else+          lock.unlock();++        // Ensure the count of outstanding work is decremented on block exit.+        work_cleanup on_exit = { this, &lock, &this_thread };+        (void)on_exit;++        // Complete the operation. May throw an exception. Deletes the object.+        o->complete(this, ec, task_result);+        this_thread.rethrow_pending_exception();++        return 1;+      }+    }+    else+    {+      wakeup_event_.clear(lock);+      wakeup_event_.wait(lock);+    }+  }++  return 0;+}++std::size_t scheduler::do_wait_one(mutex::scoped_lock& lock,+    scheduler::thread_info& this_thread, long usec,+    const asio::error_code& ec)+{+  if (stopped_)+    return 0;++  operation* o = op_queue_.front();+  if (o == 0)+  {+    wakeup_event_.clear(lock);+    wakeup_event_.wait_for_usec(lock, usec);+    usec = 0; // Wait at most once.+    o = op_queue_.front();+  }++  if (o == &task_operation_)+  {+    op_queue_.pop();+    bool more_handlers = (!op_queue_.empty());++    task_interrupted_ = more_handlers;++    if (more_handlers && !one_thread_)+      wakeup_event_.unlock_and_signal_one(lock);+    else+      lock.unlock();++    {+      task_cleanup on_exit = { this, &lock, &this_thread };+      (void)on_exit;++      // Run the task. May throw an exception. Only block if the operation+      // queue is empty and we're not polling, otherwise we want to return+      // as soon as possible.+      task_->run(more_handlers ? 0 : usec, this_thread.private_op_queue);+    }++    o = op_queue_.front();+    if (o == &task_operation_)+    {+      if (!one_thread_)+        wakeup_event_.maybe_unlock_and_signal_one(lock);+      return 0;+    }+  }++  if (o == 0)+    return 0;++  op_queue_.pop();+  bool more_handlers = (!op_queue_.empty());++  std::size_t task_result = o->task_result_;++  if (more_handlers && !one_thread_)+    wake_one_thread_and_unlock(lock);+  else+    lock.unlock();++  // Ensure the count of outstanding work is decremented on block exit.+  work_cleanup on_exit = { this, &lock, &this_thread };+  (void)on_exit;++  // Complete the operation. May throw an exception. Deletes the object.+  o->complete(this, ec, task_result);+  this_thread.rethrow_pending_exception();++  return 1;+}++std::size_t scheduler::do_poll_one(mutex::scoped_lock& lock,+    scheduler::thread_info& this_thread,+    const asio::error_code& ec)+{+  if (stopped_)+    return 0;++  operation* o = op_queue_.front();+  if (o == &task_operation_)+  {+    op_queue_.pop();+    lock.unlock();++    {+      task_cleanup c = { this, &lock, &this_thread };+      (void)c;++      // Run the task. May throw an exception. Only block if the operation+      // queue is empty and we're not polling, otherwise we want to return+      // as soon as possible.+      task_->run(0, this_thread.private_op_queue);+    }++    o = op_queue_.front();+    if (o == &task_operation_)+    {+      wakeup_event_.maybe_unlock_and_signal_one(lock);+      return 0;+    }+  }++  if (o == 0)+    return 0;++  op_queue_.pop();+  bool more_handlers = (!op_queue_.empty());++  std::size_t task_result = o->task_result_;++  if (more_handlers && !one_thread_)+    wake_one_thread_and_unlock(lock);+  else+    lock.unlock();++  // Ensure the count of outstanding work is decremented on block exit.+  work_cleanup on_exit = { this, &lock, &this_thread };+  (void)on_exit;++  // Complete the operation. May throw an exception. Deletes the object.+  o->complete(this, ec, task_result);+  this_thread.rethrow_pending_exception();++  return 1;+}++void scheduler::stop_all_threads(+    mutex::scoped_lock& lock)+{+  stopped_ = true;+  wakeup_event_.signal_all(lock);++  if (!task_interrupted_ && task_)+  {+    task_interrupted_ = true;+    task_->interrupt();+  }+}++void scheduler::wake_one_thread_and_unlock(+    mutex::scoped_lock& lock)+{+  if (!wakeup_event_.maybe_unlock_and_signal_one(lock))+  {+    if (!task_interrupted_ && task_)+    {+      task_interrupted_ = true;+      task_->interrupt();+    }+    lock.unlock();+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_SCHEDULER_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.hpp view
@@ -0,0 +1,100 @@+//+// detail/impl/select_reactor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP+#define ASIO_DETAIL_IMPL_SELECT_REACTOR_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_IOCP) \+  || (!defined(ASIO_HAS_DEV_POLL) \+      && !defined(ASIO_HAS_EPOLL) \+      && !defined(ASIO_HAS_KQUEUE) \+      && !defined(ASIO_WINDOWS_RUNTIME))++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Time_Traits>+void select_reactor::add_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_add_timer_queue(queue);+}++// Remove a timer queue from the reactor.+template <typename Time_Traits>+void select_reactor::remove_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_remove_timer_queue(queue);+}++template <typename Time_Traits>+void select_reactor::schedule_timer(timer_queue<Time_Traits>& queue,+    const typename Time_Traits::time_type& time,+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  if (shutdown_)+  {+    scheduler_.post_immediate_completion(op, false);+    return;+  }++  bool earliest = queue.enqueue_timer(time, timer, op);+  scheduler_.work_started();+  if (earliest)+    interrupter_.interrupt();+}++template <typename Time_Traits>+std::size_t select_reactor::cancel_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& timer,+    std::size_t max_cancelled)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+  return n;+}++template <typename Time_Traits>+void select_reactor::move_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& target,+    typename timer_queue<Time_Traits>::per_timer_data& source)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer(target, ops);+  queue.move_timer(target, source);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)+       //   || (!defined(ASIO_HAS_DEV_POLL)+       //       && !defined(ASIO_HAS_EPOLL)+       //       && !defined(ASIO_HAS_KQUEUE)+       //       && !defined(ASIO_WINDOWS_RUNTIME))++#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.ipp view
@@ -0,0 +1,338 @@+//+// detail/impl/select_reactor.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP+#define ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP++#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_IOCP) \+  || (!defined(ASIO_HAS_DEV_POLL) \+      && !defined(ASIO_HAS_EPOLL) \+      && !defined(ASIO_HAS_KQUEUE) \+      && !defined(ASIO_WINDOWS_RUNTIME))++#include "asio/detail/fd_set_adapter.hpp"+#include "asio/detail/select_reactor.hpp"+#include "asio/detail/signal_blocker.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_HAS_IOCP)+class select_reactor::thread_function+{+public:+  explicit thread_function(select_reactor* r)+    : this_(r)+  {+  }++  void operator()()+  {+    this_->run_thread();+  }++private:+  select_reactor* this_;+};+#endif // defined(ASIO_HAS_IOCP)++select_reactor::select_reactor(asio::execution_context& ctx)+  : execution_context_service_base<select_reactor>(ctx),+    scheduler_(use_service<scheduler_type>(ctx)),+    mutex_(),+    interrupter_(),+#if defined(ASIO_HAS_IOCP)+    stop_thread_(false),+    thread_(0),+#endif // defined(ASIO_HAS_IOCP)+    shutdown_(false)+{+#if defined(ASIO_HAS_IOCP)+  asio::detail::signal_blocker sb;+  thread_ = new asio::detail::thread(thread_function(this));+#endif // defined(ASIO_HAS_IOCP)+}++select_reactor::~select_reactor()+{+  shutdown();+}++void select_reactor::shutdown()+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  shutdown_ = true;+#if defined(ASIO_HAS_IOCP)+  stop_thread_ = true;+  if (thread_)+    interrupter_.interrupt();+#endif // defined(ASIO_HAS_IOCP)+  lock.unlock();++#if defined(ASIO_HAS_IOCP)+  if (thread_)+  {+    thread_->join();+    delete thread_;+    thread_ = 0;+  }+#endif // defined(ASIO_HAS_IOCP)++  op_queue<operation> ops;++  for (int i = 0; i < max_ops; ++i)+    op_queue_[i].get_all_operations(ops);++  timer_queues_.get_all_timers(ops);++  scheduler_.abandon_operations(ops);+}++void select_reactor::notify_fork(+    asio::execution_context::fork_event fork_ev)+{+  if (fork_ev == asio::execution_context::fork_child)+    interrupter_.recreate();+}++void select_reactor::init_task()+{+  scheduler_.init_task();+}++int select_reactor::register_descriptor(socket_type,+    select_reactor::per_descriptor_data&)+{+  return 0;+}++int select_reactor::register_internal_descriptor(+    int op_type, socket_type descriptor,+    select_reactor::per_descriptor_data&, reactor_op* op)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  op_queue_[op_type].enqueue_operation(descriptor, op);+  interrupter_.interrupt();++  return 0;+}++void select_reactor::move_descriptor(socket_type,+    select_reactor::per_descriptor_data&,+    select_reactor::per_descriptor_data&)+{+}++void select_reactor::start_op(int op_type, socket_type descriptor,+    select_reactor::per_descriptor_data&, reactor_op* op,+    bool is_continuation, bool)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  if (shutdown_)+  {+    post_immediate_completion(op, is_continuation);+    return;+  }++  bool first = op_queue_[op_type].enqueue_operation(descriptor, op);+  scheduler_.work_started();+  if (first)+    interrupter_.interrupt();+}++void select_reactor::cancel_ops(socket_type descriptor,+    select_reactor::per_descriptor_data&)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);+}++void select_reactor::deregister_descriptor(socket_type descriptor,+    select_reactor::per_descriptor_data&, bool)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  cancel_ops_unlocked(descriptor, asio::error::operation_aborted);+}++void select_reactor::deregister_internal_descriptor(+    socket_type descriptor, select_reactor::per_descriptor_data&)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  for (int i = 0; i < max_ops; ++i)+    op_queue_[i].cancel_operations(descriptor, ops);+}++void select_reactor::cleanup_descriptor_data(+    select_reactor::per_descriptor_data&)+{+}++void select_reactor::run(long usec, op_queue<operation>& ops)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++#if defined(ASIO_HAS_IOCP)+  // Check if the thread is supposed to stop.+  if (stop_thread_)+    return;+#endif // defined(ASIO_HAS_IOCP)++  // Set up the descriptor sets.+  for (int i = 0; i < max_select_ops; ++i)+    fd_sets_[i].reset();+  fd_sets_[read_op].set(interrupter_.read_descriptor());+  socket_type max_fd = 0;+  bool have_work_to_do = !timer_queues_.all_empty();+  for (int i = 0; i < max_select_ops; ++i)+  {+    have_work_to_do = have_work_to_do || !op_queue_[i].empty();+    fd_sets_[i].set(op_queue_[i], ops);+    if (fd_sets_[i].max_descriptor() > max_fd)+      max_fd = fd_sets_[i].max_descriptor();+  }++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  // Connection operations on Windows use both except and write fd_sets.+  have_work_to_do = have_work_to_do || !op_queue_[connect_op].empty();+  fd_sets_[write_op].set(op_queue_[connect_op], ops);+  if (fd_sets_[write_op].max_descriptor() > max_fd)+    max_fd = fd_sets_[write_op].max_descriptor();+  fd_sets_[except_op].set(op_queue_[connect_op], ops);+  if (fd_sets_[except_op].max_descriptor() > max_fd)+    max_fd = fd_sets_[except_op].max_descriptor();+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++  // We can return immediately if there's no work to do and the reactor is+  // not supposed to block.+  if (!usec && !have_work_to_do)+    return;++  // Determine how long to block while waiting for events.+  timeval tv_buf = { 0, 0 };+  timeval* tv = usec ? get_timeout(usec, tv_buf) : &tv_buf;++  lock.unlock();++  // Block on the select call until descriptors become ready.+  asio::error_code ec;+  int retval = socket_ops::select(static_cast<int>(max_fd + 1),+      fd_sets_[read_op], fd_sets_[write_op], fd_sets_[except_op], tv, ec);++  // Reset the interrupter.+  if (retval > 0 && fd_sets_[read_op].is_set(interrupter_.read_descriptor()))+  {+    if (!interrupter_.reset())+    {+      lock.lock();+      interrupter_.recreate();+    }+    --retval;+  }++  lock.lock();++  // Dispatch all ready operations.+  if (retval > 0)+  {+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+    // Connection operations on Windows use both except and write fd_sets.+    fd_sets_[except_op].perform(op_queue_[connect_op], ops);+    fd_sets_[write_op].perform(op_queue_[connect_op], ops);+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++    // Exception operations must be processed first to ensure that any+    // out-of-band data is read before normal data.+    for (int i = max_select_ops - 1; i >= 0; --i)+      fd_sets_[i].perform(op_queue_[i], ops);+  }+  timer_queues_.get_ready_timers(ops);+}++void select_reactor::interrupt()+{+  interrupter_.interrupt();+}++#if defined(ASIO_HAS_IOCP)+void select_reactor::run_thread()+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  while (!stop_thread_)+  {+    lock.unlock();+    op_queue<operation> ops;+    run(true, ops);+    scheduler_.post_deferred_completions(ops);+    lock.lock();+  }+}+#endif // defined(ASIO_HAS_IOCP)++void select_reactor::do_add_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.insert(&queue);+}++void select_reactor::do_remove_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.erase(&queue);+}++timeval* select_reactor::get_timeout(long usec, timeval& tv)+{+  // By default we will wait no longer than 5 minutes. This will ensure that+  // any changes to the system clock are detected after no longer than this.+  const long max_usec = 5 * 60 * 1000 * 1000;+  usec = timer_queues_.wait_duration_usec(+      (usec < 0 || max_usec < usec) ? max_usec : usec);+  tv.tv_sec = usec / 1000000;+  tv.tv_usec = usec % 1000000;+  return &tv;+}++void select_reactor::cancel_ops_unlocked(socket_type descriptor,+    const asio::error_code& ec)+{+  bool need_interrupt = false;+  op_queue<operation> ops;+  for (int i = 0; i < max_ops; ++i)+    need_interrupt = op_queue_[i].cancel_operations(+        descriptor, ops, ec) || need_interrupt;+  scheduler_.post_deferred_completions(ops);+  if (need_interrupt)+    interrupter_.interrupt();+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)+       //   || (!defined(ASIO_HAS_DEV_POLL)+       //       && !defined(ASIO_HAS_EPOLL)+       //       && !defined(ASIO_HAS_KQUEUE))+       //       && !defined(ASIO_WINDOWS_RUNTIME))++#endif // ASIO_DETAIL_IMPL_SELECT_REACTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.hpp view
@@ -0,0 +1,94 @@+//+// detail/impl/service_registry.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP+#define ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Service>+Service& service_registry::use_service()+{+  execution_context::service::key key;+  init_key<Service>(key, 0);+  factory_type factory = &service_registry::create<Service, execution_context>;+  return *static_cast<Service*>(do_use_service(key, factory, &owner_));+}++template <typename Service>+Service& service_registry::use_service(io_context& owner)+{+  execution_context::service::key key;+  init_key<Service>(key, 0);+  factory_type factory = &service_registry::create<Service, io_context>;+  return *static_cast<Service*>(do_use_service(key, factory, &owner));+}++template <typename Service>+void service_registry::add_service(Service* new_service)+{+  execution_context::service::key key;+  init_key<Service>(key, 0);+  return do_add_service(key, new_service);+}++template <typename Service>+bool service_registry::has_service() const+{+  execution_context::service::key key;+  init_key<Service>(key, 0);+  return do_has_service(key);+}++template <typename Service>+inline void service_registry::init_key(+    execution_context::service::key& key, ...)+{+  init_key_from_id(key, Service::id);+}++#if !defined(ASIO_NO_TYPEID)+template <typename Service>+void service_registry::init_key(execution_context::service::key& key,+    typename enable_if<+      is_base_of<typename Service::key_type, Service>::value>::type*)+{+  key.type_info_ = &typeid(typeid_wrapper<Service>);+  key.id_ = 0;+}++template <typename Service>+void service_registry::init_key_from_id(execution_context::service::key& key,+    const service_id<Service>& /*id*/)+{+  key.type_info_ = &typeid(typeid_wrapper<Service>);+  key.id_ = 0;+}+#endif // !defined(ASIO_NO_TYPEID)++template <typename Service, typename Owner>+execution_context::service* service_registry::create(void* owner)+{+  return new Service(*static_cast<Owner*>(owner));+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_SERVICE_REGISTRY_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.ipp view
@@ -0,0 +1,197 @@+//+// detail/impl/service_registry.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP+#define ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <vector>+#include "asio/detail/service_registry.hpp"+#include "asio/detail/throw_exception.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++service_registry::service_registry(execution_context& owner)+  : owner_(owner),+    first_service_(0)+{+}++service_registry::~service_registry()+{+}++void service_registry::shutdown_services()+{+  execution_context::service* service = first_service_;+  while (service)+  {+    service->shutdown();+    service = service->next_;+  }+}++void service_registry::destroy_services()+{+  while (first_service_)+  {+    execution_context::service* next_service = first_service_->next_;+    destroy(first_service_);+    first_service_ = next_service;+  }+}++void service_registry::notify_fork(execution_context::fork_event fork_ev)+{+  // Make a copy of all of the services while holding the lock. We don't want+  // to hold the lock while calling into each service, as it may try to call+  // back into this class.+  std::vector<execution_context::service*> services;+  {+    asio::detail::mutex::scoped_lock lock(mutex_);+    execution_context::service* service = first_service_;+    while (service)+    {+      services.push_back(service);+      service = service->next_;+    }+  }++  // If processing the fork_prepare event, we want to go in reverse order of+  // service registration, which happens to be the existing order of the+  // services in the vector. For the other events we want to go in the other+  // direction.+  std::size_t num_services = services.size();+  if (fork_ev == execution_context::fork_prepare)+    for (std::size_t i = 0; i < num_services; ++i)+      services[i]->notify_fork(fork_ev);+  else+    for (std::size_t i = num_services; i > 0; --i)+      services[i - 1]->notify_fork(fork_ev);+}++void service_registry::init_key_from_id(execution_context::service::key& key,+    const execution_context::id& id)+{+  key.type_info_ = 0;+  key.id_ = &id;+}++bool service_registry::keys_match(+    const execution_context::service::key& key1,+    const execution_context::service::key& key2)+{+  if (key1.id_ && key2.id_)+    if (key1.id_ == key2.id_)+      return true;+  if (key1.type_info_ && key2.type_info_)+    if (*key1.type_info_ == *key2.type_info_)+      return true;+  return false;+}++void service_registry::destroy(execution_context::service* service)+{+  delete service;+}++execution_context::service* service_registry::do_use_service(+    const execution_context::service::key& key,+    factory_type factory, void* owner)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  // First see if there is an existing service object with the given key.+  execution_context::service* service = first_service_;+  while (service)+  {+    if (keys_match(service->key_, key))+      return service;+    service = service->next_;+  }++  // Create a new service object. The service registry's mutex is not locked+  // at this time to allow for nested calls into this function from the new+  // service's constructor.+  lock.unlock();+  auto_service_ptr new_service = { factory(owner) };+  new_service.ptr_->key_ = key;+  lock.lock();++  // Check that nobody else created another service object of the same type+  // while the lock was released.+  service = first_service_;+  while (service)+  {+    if (keys_match(service->key_, key))+      return service;+    service = service->next_;+  }++  // Service was successfully initialised, pass ownership to registry.+  new_service.ptr_->next_ = first_service_;+  first_service_ = new_service.ptr_;+  new_service.ptr_ = 0;+  return first_service_;+}++void service_registry::do_add_service(+    const execution_context::service::key& key,+    execution_context::service* new_service)+{+  if (&owner_ != &new_service->context())+    asio::detail::throw_exception(invalid_service_owner());++  asio::detail::mutex::scoped_lock lock(mutex_);++  // Check if there is an existing service object with the given key.+  execution_context::service* service = first_service_;+  while (service)+  {+    if (keys_match(service->key_, key))+      asio::detail::throw_exception(service_already_exists());+    service = service->next_;+  }++  // Take ownership of the service object.+  new_service->key_ = key;+  new_service->next_ = first_service_;+  first_service_ = new_service;+}++bool service_registry::do_has_service(+    const execution_context::service::key& key) const+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  execution_context::service* service = first_service_;+  while (service)+  {+    if (keys_match(service->key_, key))+      return true;+    service = service->next_;+  }++  return false;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_SERVICE_REGISTRY_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/signal_set_service.ipp view
@@ -0,0 +1,668 @@+//+// detail/impl/signal_set_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP+#define ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <cstring>+#include <stdexcept>+#include "asio/detail/reactor.hpp"+#include "asio/detail/signal_blocker.hpp"+#include "asio/detail/signal_set_service.hpp"+#include "asio/detail/static_mutex.hpp"+#include "asio/detail/throw_exception.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct signal_state+{+  // Mutex used for protecting global state.+  static_mutex mutex_;++  // The read end of the pipe used for signal notifications.+  int read_descriptor_;++  // The write end of the pipe used for signal notifications.+  int write_descriptor_;++  // Whether the signal state has been prepared for a fork.+  bool fork_prepared_;++  // The head of a linked list of all signal_set_service instances.+  class signal_set_service* service_list_;++  // A count of the number of objects that are registered for each signal.+  std::size_t registration_count_[max_signal_number];+};++signal_state* get_signal_state()+{+  static signal_state state = {+    ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, { 0 } };+  return &state;+}++void asio_signal_handler(int signal_number)+{+#if defined(ASIO_WINDOWS) \+  || defined(ASIO_WINDOWS_RUNTIME) \+  || defined(__CYGWIN__)+  signal_set_service::deliver_signal(signal_number);+#else // defined(ASIO_WINDOWS)+      //   || defined(ASIO_WINDOWS_RUNTIME)+      //   || defined(__CYGWIN__)+  int saved_errno = errno;+  signal_state* state = get_signal_state();+  signed_size_type result = ::write(state->write_descriptor_,+      &signal_number, sizeof(signal_number));+  (void)result;+  errno = saved_errno;+#endif // defined(ASIO_WINDOWS)+       //   || defined(ASIO_WINDOWS_RUNTIME)+       //   || defined(__CYGWIN__)++#if defined(ASIO_HAS_SIGNAL) && !defined(ASIO_HAS_SIGACTION)+  ::signal(signal_number, asio_signal_handler);+#endif // defined(ASIO_HAS_SIGNAL) && !defined(ASIO_HAS_SIGACTION)+}++#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+class signal_set_service::pipe_read_op : public reactor_op+{+public:+  pipe_read_op()+    : reactor_op(asio::error_code(),+        &pipe_read_op::do_perform, pipe_read_op::do_complete)+  {+  }++  static status do_perform(reactor_op*)+  {+    signal_state* state = get_signal_state();++    int fd = state->read_descriptor_;+    int signal_number = 0;+    while (::read(fd, &signal_number, sizeof(int)) == sizeof(int))+      if (signal_number >= 0 && signal_number < max_signal_number)+        signal_set_service::deliver_signal(signal_number);++    return not_done;+  }++  static void do_complete(void* /*owner*/, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    pipe_read_op* o(static_cast<pipe_read_op*>(base));+    delete o;+  }+};+#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)++signal_set_service::signal_set_service(execution_context& context)+  : execution_context_service_base<signal_set_service>(context),+    scheduler_(asio::use_service<scheduler_impl>(context)),+#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+    reactor_(asio::use_service<reactor>(context)),+#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)+    next_(0),+    prev_(0)+{+  get_signal_state()->mutex_.init();++#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+  reactor_.init_task();+#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)++  for (int i = 0; i < max_signal_number; ++i)+    registrations_[i] = 0;++  add_service(this);+}++signal_set_service::~signal_set_service()+{+  remove_service(this);+}++void signal_set_service::shutdown()+{+  remove_service(this);++  op_queue<operation> ops;++  for (int i = 0; i < max_signal_number; ++i)+  {+    registration* reg = registrations_[i];+    while (reg)+    {+      ops.push(*reg->queue_);+      reg = reg->next_in_table_;+    }+  }++  scheduler_.abandon_operations(ops);+}++void signal_set_service::notify_fork(execution_context::fork_event fork_ev)+{+#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+  signal_state* state = get_signal_state();+  static_mutex::scoped_lock lock(state->mutex_);++  switch (fork_ev)+  {+  case execution_context::fork_prepare:+    {+      int read_descriptor = state->read_descriptor_;+      state->fork_prepared_ = true;+      lock.unlock();+      reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_);+      reactor_.cleanup_descriptor_data(reactor_data_);+    }+    break;+  case execution_context::fork_parent:+    if (state->fork_prepared_)+    {+      int read_descriptor = state->read_descriptor_;+      state->fork_prepared_ = false;+      lock.unlock();+      reactor_.register_internal_descriptor(reactor::read_op,+          read_descriptor, reactor_data_, new pipe_read_op);+    }+    break;+  case execution_context::fork_child:+    if (state->fork_prepared_)+    {+      asio::detail::signal_blocker blocker;+      close_descriptors();+      open_descriptors();+      int read_descriptor = state->read_descriptor_;+      state->fork_prepared_ = false;+      lock.unlock();+      reactor_.register_internal_descriptor(reactor::read_op,+          read_descriptor, reactor_data_, new pipe_read_op);+    }+    break;+  default:+    break;+  }+#else // !defined(ASIO_WINDOWS)+      //   && !defined(ASIO_WINDOWS_RUNTIME)+      //   && !defined(__CYGWIN__)+  (void)fork_ev;+#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)+}++void signal_set_service::construct(+    signal_set_service::implementation_type& impl)+{+  impl.signals_ = 0;+}++void signal_set_service::destroy(+    signal_set_service::implementation_type& impl)+{+  asio::error_code ignored_ec;+  clear(impl, ignored_ec);+  cancel(impl, ignored_ec);+}++asio::error_code signal_set_service::add(+    signal_set_service::implementation_type& impl,+    int signal_number, asio::error_code& ec)+{+  // Check that the signal number is valid.+  if (signal_number < 0 || signal_number >= max_signal_number)+  {+    ec = asio::error::invalid_argument;+    return ec;+  }++  signal_state* state = get_signal_state();+  static_mutex::scoped_lock lock(state->mutex_);++  // Find the appropriate place to insert the registration.+  registration** insertion_point = &impl.signals_;+  registration* next = impl.signals_;+  while (next && next->signal_number_ < signal_number)+  {+    insertion_point = &next->next_in_set_;+    next = next->next_in_set_;+  }++  // Only do something if the signal is not already registered.+  if (next == 0 || next->signal_number_ != signal_number)+  {+    registration* new_registration = new registration;++#if defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION)+    // Register for the signal if we're the first.+    if (state->registration_count_[signal_number] == 0)+    {+# if defined(ASIO_HAS_SIGACTION)+      using namespace std; // For memset.+      struct sigaction sa;+      memset(&sa, 0, sizeof(sa));+      sa.sa_handler = asio_signal_handler;+      sigfillset(&sa.sa_mask);+      if (::sigaction(signal_number, &sa, 0) == -1)+# else // defined(ASIO_HAS_SIGACTION)+      if (::signal(signal_number, asio_signal_handler) == SIG_ERR)+# endif // defined(ASIO_HAS_SIGACTION)+      {+# if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+        ec = asio::error::invalid_argument;+# else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+        ec = asio::error_code(errno,+            asio::error::get_system_category());+# endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+        delete new_registration;+        return ec;+      }+    }+#endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION)++    // Record the new registration in the set.+    new_registration->signal_number_ = signal_number;+    new_registration->queue_ = &impl.queue_;+    new_registration->next_in_set_ = next;+    *insertion_point = new_registration;++    // Insert registration into the registration table.+    new_registration->next_in_table_ = registrations_[signal_number];+    if (registrations_[signal_number])+      registrations_[signal_number]->prev_in_table_ = new_registration;+    registrations_[signal_number] = new_registration;++    ++state->registration_count_[signal_number];+  }++  ec = asio::error_code();+  return ec;+}++asio::error_code signal_set_service::remove(+    signal_set_service::implementation_type& impl,+    int signal_number, asio::error_code& ec)+{+  // Check that the signal number is valid.+  if (signal_number < 0 || signal_number >= max_signal_number)+  {+    ec = asio::error::invalid_argument;+    return ec;+  }++  signal_state* state = get_signal_state();+  static_mutex::scoped_lock lock(state->mutex_);++  // Find the signal number in the list of registrations.+  registration** deletion_point = &impl.signals_;+  registration* reg = impl.signals_;+  while (reg && reg->signal_number_ < signal_number)+  {+    deletion_point = &reg->next_in_set_;+    reg = reg->next_in_set_;+  }++  if (reg != 0 && reg->signal_number_ == signal_number)+  {+#if defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION)+    // Set signal handler back to the default if we're the last.+    if (state->registration_count_[signal_number] == 1)+    {+# if defined(ASIO_HAS_SIGACTION)+      using namespace std; // For memset.+      struct sigaction sa;+      memset(&sa, 0, sizeof(sa));+      sa.sa_handler = SIG_DFL;+      if (::sigaction(signal_number, &sa, 0) == -1)+# else // defined(ASIO_HAS_SIGACTION)+      if (::signal(signal_number, SIG_DFL) == SIG_ERR)+# endif // defined(ASIO_HAS_SIGACTION)+      {+# if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+        ec = asio::error::invalid_argument;+# else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+        ec = asio::error_code(errno,+            asio::error::get_system_category());+# endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+        return ec;+      }+    }+#endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION)++    // Remove the registration from the set.+    *deletion_point = reg->next_in_set_;++    // Remove the registration from the registration table.+    if (registrations_[signal_number] == reg)+      registrations_[signal_number] = reg->next_in_table_;+    if (reg->prev_in_table_)+      reg->prev_in_table_->next_in_table_ = reg->next_in_table_;+    if (reg->next_in_table_)+      reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;++    --state->registration_count_[signal_number];++    delete reg;+  }++  ec = asio::error_code();+  return ec;+}++asio::error_code signal_set_service::clear(+    signal_set_service::implementation_type& impl,+    asio::error_code& ec)+{+  signal_state* state = get_signal_state();+  static_mutex::scoped_lock lock(state->mutex_);++  while (registration* reg = impl.signals_)+  {+#if defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION)+    // Set signal handler back to the default if we're the last.+    if (state->registration_count_[reg->signal_number_] == 1)+    {+# if defined(ASIO_HAS_SIGACTION)+      using namespace std; // For memset.+      struct sigaction sa;+      memset(&sa, 0, sizeof(sa));+      sa.sa_handler = SIG_DFL;+      if (::sigaction(reg->signal_number_, &sa, 0) == -1)+# else // defined(ASIO_HAS_SIGACTION)+      if (::signal(reg->signal_number_, SIG_DFL) == SIG_ERR)+# endif // defined(ASIO_HAS_SIGACTION)+      {+# if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+        ec = asio::error::invalid_argument;+# else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+        ec = asio::error_code(errno,+            asio::error::get_system_category());+# endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+        return ec;+      }+    }+#endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION)++    // Remove the registration from the registration table.+    if (registrations_[reg->signal_number_] == reg)+      registrations_[reg->signal_number_] = reg->next_in_table_;+    if (reg->prev_in_table_)+      reg->prev_in_table_->next_in_table_ = reg->next_in_table_;+    if (reg->next_in_table_)+      reg->next_in_table_->prev_in_table_ = reg->prev_in_table_;++    --state->registration_count_[reg->signal_number_];++    impl.signals_ = reg->next_in_set_;+    delete reg;+  }++  ec = asio::error_code();+  return ec;+}++asio::error_code signal_set_service::cancel(+    signal_set_service::implementation_type& impl,+    asio::error_code& ec)+{+  ASIO_HANDLER_OPERATION((scheduler_.context(),+        "signal_set", &impl, 0, "cancel"));++  op_queue<operation> ops;+  {+    signal_state* state = get_signal_state();+    static_mutex::scoped_lock lock(state->mutex_);++    while (signal_op* op = impl.queue_.front())+    {+      op->ec_ = asio::error::operation_aborted;+      impl.queue_.pop();+      ops.push(op);+    }+  }++  scheduler_.post_deferred_completions(ops);++  ec = asio::error_code();+  return ec;+}++void signal_set_service::deliver_signal(int signal_number)+{+  signal_state* state = get_signal_state();+  static_mutex::scoped_lock lock(state->mutex_);++  signal_set_service* service = state->service_list_;+  while (service)+  {+    op_queue<operation> ops;++    registration* reg = service->registrations_[signal_number];+    while (reg)+    {+      if (reg->queue_->empty())+      {+        ++reg->undelivered_;+      }+      else+      {+        while (signal_op* op = reg->queue_->front())+        {+          op->signal_number_ = signal_number;+          reg->queue_->pop();+          ops.push(op);+        }+      }++      reg = reg->next_in_table_;+    }++    service->scheduler_.post_deferred_completions(ops);++    service = service->next_;+  }+}++void signal_set_service::add_service(signal_set_service* service)+{+  signal_state* state = get_signal_state();+  static_mutex::scoped_lock lock(state->mutex_);++#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+  // If this is the first service to be created, open a new pipe.+  if (state->service_list_ == 0)+    open_descriptors();+#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++  // If a scheduler_ object is thread-unsafe then it must be the only+  // scheduler used to create signal_set objects.+  if (state->service_list_ != 0)+  {+    if (!ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,+          service->scheduler_.concurrency_hint())+        || !ASIO_CONCURRENCY_HINT_IS_LOCKING(SCHEDULER,+          state->service_list_->scheduler_.concurrency_hint()))+    {+      std::logic_error ex(+          "Thread-unsafe execution context objects require "+          "exclusive access to signal handling.");+      asio::detail::throw_exception(ex);+    }+  }++  // Insert service into linked list of all services.+  service->next_ = state->service_list_;+  service->prev_ = 0;+  if (state->service_list_)+    state->service_list_->prev_ = service;+  state->service_list_ = service;++#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+  // Register for pipe readiness notifications.+  int read_descriptor = state->read_descriptor_;+  lock.unlock();+  service->reactor_.register_internal_descriptor(reactor::read_op,+      read_descriptor, service->reactor_data_, new pipe_read_op);+#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)+}++void signal_set_service::remove_service(signal_set_service* service)+{+  signal_state* state = get_signal_state();+  static_mutex::scoped_lock lock(state->mutex_);++  if (service->next_ || service->prev_ || state->service_list_ == service)+  {+#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+    // Disable the pipe readiness notifications.+    int read_descriptor = state->read_descriptor_;+    lock.unlock();+    service->reactor_.deregister_internal_descriptor(+        read_descriptor, service->reactor_data_);+    service->reactor_.cleanup_descriptor_data(service->reactor_data_);+    lock.lock();+#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)++    // Remove service from linked list of all services.+    if (state->service_list_ == service)+      state->service_list_ = service->next_;+    if (service->prev_)+      service->prev_->next_ = service->next_;+    if (service->next_)+      service->next_->prev_= service->prev_;+    service->next_ = 0;+    service->prev_ = 0;++#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+    // If this is the last service to be removed, close the pipe.+    if (state->service_list_ == 0)+      close_descriptors();+#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+  }+}++void signal_set_service::open_descriptors()+{+#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+  signal_state* state = get_signal_state();++  int pipe_fds[2];+  if (::pipe(pipe_fds) == 0)+  {+    state->read_descriptor_ = pipe_fds[0];+    ::fcntl(state->read_descriptor_, F_SETFL, O_NONBLOCK);++    state->write_descriptor_ = pipe_fds[1];+    ::fcntl(state->write_descriptor_, F_SETFL, O_NONBLOCK);++#if defined(FD_CLOEXEC)+    ::fcntl(state->read_descriptor_, F_SETFD, FD_CLOEXEC);+    ::fcntl(state->write_descriptor_, F_SETFD, FD_CLOEXEC);+#endif // defined(FD_CLOEXEC)+  }+  else+  {+    asio::error_code ec(errno,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "signal_set_service pipe");+  }+#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)+}++void signal_set_service::close_descriptors()+{+#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+  signal_state* state = get_signal_state();++  if (state->read_descriptor_ != -1)+    ::close(state->read_descriptor_);+  state->read_descriptor_ = -1;++  if (state->write_descriptor_ != -1)+    ::close(state->write_descriptor_);+  state->write_descriptor_ = -1;+#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)+}++void signal_set_service::start_wait_op(+    signal_set_service::implementation_type& impl, signal_op* op)+{+  scheduler_.work_started();++  signal_state* state = get_signal_state();+  static_mutex::scoped_lock lock(state->mutex_);++  registration* reg = impl.signals_;+  while (reg)+  {+    if (reg->undelivered_ > 0)+    {+      --reg->undelivered_;+      op->signal_number_ = reg->signal_number_;+      scheduler_.post_deferred_completion(op);+      return;+    }++    reg = reg->next_in_set_;+  }++  impl.queue_.push(op);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_SIGNAL_SET_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/socket_ops.ipp view
@@ -0,0 +1,3962 @@+//+// detail/impl/socket_ops.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SOCKET_OPS_IPP+#define ASIO_DETAIL_SOCKET_OPS_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <cctype>+#include <cstdio>+#include <cstdlib>+#include <cstring>+#include <cerrno>+#include <new>+#include "asio/detail/assert.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)+# include <codecvt>+# include <locale>+# include <string>+#endif // defined(ASIO_WINDOWS_RUNTIME)++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) \+  || defined(__MACH__) && defined(__APPLE__)+# if defined(ASIO_HAS_PTHREADS)+#  include <pthread.h>+# endif // defined(ASIO_HAS_PTHREADS)+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+       // || defined(__MACH__) && defined(__APPLE__)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {+namespace socket_ops {++#if !defined(ASIO_WINDOWS_RUNTIME)++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+struct msghdr { int msg_namelen; };+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++#if defined(__hpux)+// HP-UX doesn't declare these functions extern "C", so they are declared again+// here to avoid linker errors about undefined symbols.+extern "C" char* if_indextoname(unsigned int, char*);+extern "C" unsigned int if_nametoindex(const char*);+#endif // defined(__hpux)++#endif // !defined(ASIO_WINDOWS_RUNTIME)++inline void clear_last_error()+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  WSASetLastError(0);+#else+  errno = 0;+#endif+}++#if !defined(ASIO_WINDOWS_RUNTIME)++inline void get_last_error(+    asio::error_code& ec, bool is_error_condition)+{+  if (!is_error_condition)+  {+    ec.assign(0, ec.category());+  }+  else+  {+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+    ec = asio::error_code(WSAGetLastError(),+        asio::error::get_system_category());+#else+    ec = asio::error_code(errno,+        asio::error::get_system_category());+#endif+  }+}++template <typename SockLenType>+inline socket_type call_accept(SockLenType msghdr::*,+    socket_type s, socket_addr_type* addr, std::size_t* addrlen)+{+  SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;+  socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);+  if (addrlen)+    *addrlen = (std::size_t)tmp_addrlen;+  return result;+}++socket_type accept(socket_type s, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return invalid_socket;+  }++  socket_type new_s = call_accept(&msghdr::msg_namelen, s, addr, addrlen);+  get_last_error(ec, new_s == invalid_socket);+  if (new_s == invalid_socket)+    return new_s;++#if defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)+  int optval = 1;+  int result = ::setsockopt(new_s, SOL_SOCKET,+      SO_NOSIGPIPE, &optval, sizeof(optval));+  get_last_error(ec, result != 0);+  if (result != 0)+  {+    ::close(new_s);+    return invalid_socket;+  }+#endif++  ec.assign(0, ec.category());+  return new_s;+}++socket_type sync_accept(socket_type s, state_type state,+    socket_addr_type* addr, std::size_t* addrlen, asio::error_code& ec)+{+  // Accept a socket.+  for (;;)+  {+    // Try to complete the operation without blocking.+    socket_type new_socket = socket_ops::accept(s, addr, addrlen, ec);++    // Check if operation succeeded.+    if (new_socket != invalid_socket)+      return new_socket;++    // Operation failed.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+    {+      if (state & user_set_non_blocking)+        return invalid_socket;+      // Fall through to retry operation.+    }+    else if (ec == asio::error::connection_aborted)+    {+      if (state & enable_connection_aborted)+        return invalid_socket;+      // Fall through to retry operation.+    }+#if defined(EPROTO)+    else if (ec.value() == EPROTO)+    {+      if (state & enable_connection_aborted)+        return invalid_socket;+      // Fall through to retry operation.+    }+#endif // defined(EPROTO)+    else+      return invalid_socket;++    // Wait for socket to become ready.+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)+      return invalid_socket;+  }+}++#if defined(ASIO_HAS_IOCP)++void complete_iocp_accept(socket_type s,+    void* output_buffer, DWORD address_length,+    socket_addr_type* addr, std::size_t* addrlen,+    socket_type new_socket, asio::error_code& ec)+{+  // Map non-portable errors to their portable counterparts.+  if (ec.value() == ERROR_NETNAME_DELETED)+    ec = asio::error::connection_aborted;++  if (!ec)+  {+    // Get the address of the peer.+    if (addr && addrlen)+    {+      LPSOCKADDR local_addr = 0;+      int local_addr_length = 0;+      LPSOCKADDR remote_addr = 0;+      int remote_addr_length = 0;+      GetAcceptExSockaddrs(output_buffer, 0, address_length,+          address_length, &local_addr, &local_addr_length,+          &remote_addr, &remote_addr_length);+      if (static_cast<std::size_t>(remote_addr_length) > *addrlen)+      {+        ec = asio::error::invalid_argument;+      }+      else+      {+        using namespace std; // For memcpy.+        memcpy(addr, remote_addr, remote_addr_length);+        *addrlen = static_cast<std::size_t>(remote_addr_length);+      }+    }++    // Need to set the SO_UPDATE_ACCEPT_CONTEXT option so that getsockname+    // and getpeername will work on the accepted socket.+    SOCKET update_ctx_param = s;+    socket_ops::state_type state = 0;+    socket_ops::setsockopt(new_socket, state,+          SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,+          &update_ctx_param, sizeof(SOCKET), ec);+  }+}++#else // defined(ASIO_HAS_IOCP)++bool non_blocking_accept(socket_type s,+    state_type state, socket_addr_type* addr, std::size_t* addrlen,+    asio::error_code& ec, socket_type& new_socket)+{+  for (;;)+  {+    // Accept the waiting connection.+    new_socket = socket_ops::accept(s, addr, addrlen, ec);++    // Check if operation succeeded.+    if (new_socket != invalid_socket)+      return true;++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Operation failed.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+    {+      // Fall through to retry operation.+    }+    else if (ec == asio::error::connection_aborted)+    {+      if (state & enable_connection_aborted)+        return true;+      // Fall through to retry operation.+    }+#if defined(EPROTO)+    else if (ec.value() == EPROTO)+    {+      if (state & enable_connection_aborted)+        return true;+      // Fall through to retry operation.+    }+#endif // defined(EPROTO)+    else+      return true;++    return false;+  }+}++#endif // defined(ASIO_HAS_IOCP)++template <typename SockLenType>+inline int call_bind(SockLenType msghdr::*,+    socket_type s, const socket_addr_type* addr, std::size_t addrlen)+{+  return ::bind(s, addr, (SockLenType)addrlen);+}++int bind(socket_type s, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++  int result = call_bind(&msghdr::msg_namelen, s, addr, addrlen);+  get_last_error(ec, result != 0);+  return result;+}++int close(socket_type s, state_type& state,+    bool destruction, asio::error_code& ec)+{+  int result = 0;+  if (s != invalid_socket)+  {+    // We don't want the destructor to block, so set the socket to linger in+    // the background. If the user doesn't like this behaviour then they need+    // to explicitly close the socket.+    if (destruction && (state & user_set_linger))+    {+      ::linger opt;+      opt.l_onoff = 0;+      opt.l_linger = 0;+      asio::error_code ignored_ec;+      socket_ops::setsockopt(s, state, SOL_SOCKET,+          SO_LINGER, &opt, sizeof(opt), ignored_ec);+    }++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+    result = ::closesocket(s);+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+    result = ::close(s);+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+    get_last_error(ec, result != 0);++    if (result != 0+        && (ec == asio::error::would_block+          || ec == asio::error::try_again))+    {+      // According to UNIX Network Programming Vol. 1, it is possible for+      // close() to fail with EWOULDBLOCK under certain circumstances. What+      // isn't clear is the state of the descriptor after this error. The one+      // current OS where this behaviour is seen, Windows, says that the socket+      // remains open. Therefore we'll put the descriptor back into blocking+      // mode and have another attempt at closing it.+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+      ioctl_arg_type arg = 0;+      ::ioctlsocket(s, FIONBIO, &arg);+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# if defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+      int flags = ::fcntl(s, F_GETFL, 0);+      if (flags >= 0)+        ::fcntl(s, F_SETFL, flags & ~O_NONBLOCK);+# else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+      ioctl_arg_type arg = 0;+      ::ioctl(s, FIONBIO, &arg);+# endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+      state &= ~non_blocking;++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+      result = ::closesocket(s);+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+      result = ::close(s);+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+      get_last_error(ec, result != 0);+    }+  }++  return result;+}++bool set_user_non_blocking(socket_type s,+    state_type& state, bool value, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return false;+  }++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  ioctl_arg_type arg = (value ? 1 : 0);+  int result = ::ioctlsocket(s, FIONBIO, &arg);+  get_last_error(ec, result < 0);+#elif defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+  int result = ::fcntl(s, F_GETFL, 0);+  get_last_error(ec, result < 0);+  if (result >= 0)+  {+    int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));+    result = ::fcntl(s, F_SETFL, flag);+    get_last_error(ec, result < 0);+  }+#else+  ioctl_arg_type arg = (value ? 1 : 0);+  int result = ::ioctl(s, FIONBIO, &arg);+  get_last_error(ec, result < 0);+#endif++  if (result >= 0)+  {+    if (value)+      state |= user_set_non_blocking;+    else+    {+      // Clearing the user-set non-blocking mode always overrides any+      // internally-set non-blocking flag. Any subsequent asynchronous+      // operations will need to re-enable non-blocking I/O.+      state &= ~(user_set_non_blocking | internal_non_blocking);+    }+    return true;+  }++  return false;+}++bool set_internal_non_blocking(socket_type s,+    state_type& state, bool value, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return false;+  }++  if (!value && (state & user_set_non_blocking))+  {+    // It does not make sense to clear the internal non-blocking flag if the+    // user still wants non-blocking behaviour. Return an error and let the+    // caller figure out whether to update the user-set non-blocking flag.+    ec = asio::error::invalid_argument;+    return false;+  }++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  ioctl_arg_type arg = (value ? 1 : 0);+  int result = ::ioctlsocket(s, FIONBIO, &arg);+  get_last_error(ec, result < 0);+#elif defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)+  int result = ::fcntl(s, F_GETFL, 0);+  get_last_error(ec, result < 0);+  if (result >= 0)+  {+    int flag = (value ? (result | O_NONBLOCK) : (result & ~O_NONBLOCK));+    result = ::fcntl(s, F_SETFL, flag);+    get_last_error(ec, result < 0);+  }+#else+  ioctl_arg_type arg = (value ? 1 : 0);+  int result = ::ioctl(s, FIONBIO, &arg);+  get_last_error(ec, result < 0);+#endif++  if (result >= 0)+  {+    if (value)+      state |= internal_non_blocking;+    else+      state &= ~internal_non_blocking;+    return true;+  }++  return false;+}++int shutdown(socket_type s, int what, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++  int result = ::shutdown(s, what);+  get_last_error(ec, result != 0);+  return result;+}++template <typename SockLenType>+inline int call_connect(SockLenType msghdr::*,+    socket_type s, const socket_addr_type* addr, std::size_t addrlen)+{+  return ::connect(s, addr, (SockLenType)addrlen);+}++int connect(socket_type s, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++  int result = call_connect(&msghdr::msg_namelen, s, addr, addrlen);+  get_last_error(ec, result != 0);+#if defined(__linux__)+  if (result != 0 && ec == asio::error::try_again)+    ec = asio::error::no_buffer_space;+#endif // defined(__linux__)+  return result;+}++void sync_connect(socket_type s, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec)+{+  // Perform the connect operation.+  socket_ops::connect(s, addr, addrlen, ec);+  if (ec != asio::error::in_progress+      && ec != asio::error::would_block)+  {+    // The connect operation finished immediately.+    return;+  }++  // Wait for socket to become ready.+  if (socket_ops::poll_connect(s, -1, ec) < 0)+    return;++  // Get the error code from the connect operation.+  int connect_error = 0;+  size_t connect_error_len = sizeof(connect_error);+  if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR,+        &connect_error, &connect_error_len, ec) == socket_error_retval)+    return;++  // Return the result of the connect operation.+  ec = asio::error_code(connect_error,+      asio::error::get_system_category());+}++#if defined(ASIO_HAS_IOCP)++void complete_iocp_connect(socket_type s, asio::error_code& ec)+{+  // Map non-portable errors to their portable counterparts.+  switch (ec.value())+  {+  case ERROR_CONNECTION_REFUSED:+    ec = asio::error::connection_refused;+    break;+  case ERROR_NETWORK_UNREACHABLE:+    ec = asio::error::network_unreachable;+    break;+  case ERROR_HOST_UNREACHABLE:+    ec = asio::error::host_unreachable;+    break;+  case ERROR_SEM_TIMEOUT:+    ec = asio::error::timed_out;+    break;+  default:+    break;+  }++  if (!ec)+  {+    // Need to set the SO_UPDATE_CONNECT_CONTEXT option so that getsockname+    // and getpeername will work on the connected socket.+    socket_ops::state_type state = 0;+    const int so_update_connect_context = 0x7010;+    socket_ops::setsockopt(s, state, SOL_SOCKET,+        so_update_connect_context, 0, 0, ec);+  }+}++#endif // defined(ASIO_HAS_IOCP)++bool non_blocking_connect(socket_type s, asio::error_code& ec)+{+  // Check if the connect operation has finished. This is required since we may+  // get spurious readiness notifications from the reactor.+#if defined(ASIO_WINDOWS) \+  || defined(__CYGWIN__) \+  || defined(__SYMBIAN32__)+  fd_set write_fds;+  FD_ZERO(&write_fds);+  FD_SET(s, &write_fds);+  fd_set except_fds;+  FD_ZERO(&except_fds);+  FD_SET(s, &except_fds);+  timeval zero_timeout;+  zero_timeout.tv_sec = 0;+  zero_timeout.tv_usec = 0;+  int ready = ::select(s + 1, 0, &write_fds, &except_fds, &zero_timeout);+#else // defined(ASIO_WINDOWS)+      // || defined(__CYGWIN__)+      // || defined(__SYMBIAN32__)+  pollfd fds;+  fds.fd = s;+  fds.events = POLLOUT;+  fds.revents = 0;+  int ready = ::poll(&fds, 1, 0);+#endif // defined(ASIO_WINDOWS)+       // || defined(__CYGWIN__)+       // || defined(__SYMBIAN32__)+  if (ready == 0)+  {+    // The asynchronous connect operation is still in progress.+    return false;+  }++  // Get the error code from the connect operation.+  int connect_error = 0;+  size_t connect_error_len = sizeof(connect_error);+  if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_ERROR,+        &connect_error, &connect_error_len, ec) == 0)+  {+    if (connect_error)+    {+      ec = asio::error_code(connect_error,+          asio::error::get_system_category());+    }+    else+      ec.assign(0, ec.category());+  }++  return true;+}++int socketpair(int af, int type, int protocol,+    socket_type sv[2], asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  (void)(af);+  (void)(type);+  (void)(protocol);+  (void)(sv);+  ec = asio::error::operation_not_supported;+  return socket_error_retval;+#else+  int result = ::socketpair(af, type, protocol, sv);+  get_last_error(ec, result != 0);+  return result;+#endif+}++bool sockatmark(socket_type s, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return false;+  }++#if defined(SIOCATMARK)+  ioctl_arg_type value = 0;+# if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  int result = ::ioctlsocket(s, SIOCATMARK, &value);+# else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  int result = ::ioctl(s, SIOCATMARK, &value);+# endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  get_last_error(ec, result < 0);+# if defined(ENOTTY)+  if (ec.value() == ENOTTY)+    ec = asio::error::not_socket;+# endif // defined(ENOTTY)+#else // defined(SIOCATMARK)+  int value = ::sockatmark(s);+  get_last_error(ec, result < 0);+#endif // defined(SIOCATMARK)++  return ec ? false : value != 0;+}++size_t available(socket_type s, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  ioctl_arg_type value = 0;+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  int result = ::ioctlsocket(s, FIONREAD, &value);+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  int result = ::ioctl(s, FIONREAD, &value);+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  get_last_error(ec, result < 0);+#if defined(ENOTTY)+  if (ec.value() == ENOTTY)+    ec = asio::error::not_socket;+#endif // defined(ENOTTY)++  return ec ? static_cast<size_t>(0) : static_cast<size_t>(value);+}++int listen(socket_type s, int backlog, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++  int result = ::listen(s, backlog);+  get_last_error(ec, result != 0);+  return result;+}++inline void init_buf_iov_base(void*& base, void* addr)+{+  base = addr;+}++template <typename T>+inline void init_buf_iov_base(T& base, void* addr)+{+  base = static_cast<T>(addr);+}++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+typedef WSABUF buf;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+typedef iovec buf;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++void init_buf(buf& b, void* data, size_t size)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  b.buf = static_cast<char*>(data);+  b.len = static_cast<u_long>(size);+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  init_buf_iov_base(b.iov_base, data);+  b.iov_len = size;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++void init_buf(buf& b, const void* data, size_t size)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  b.buf = static_cast<char*>(const_cast<void*>(data));+  b.len = static_cast<u_long>(size);+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  init_buf_iov_base(b.iov_base, const_cast<void*>(data));+  b.iov_len = size;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)+{+  name = addr;+}++inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)+{+  name = const_cast<socket_addr_type*>(addr);+}++template <typename T>+inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)+{+  name = reinterpret_cast<T>(addr);+}++template <typename T>+inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)+{+  name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));+}++signed_size_type recv(socket_type s, buf* bufs, size_t count,+    int flags, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  // Receive some data.+  DWORD recv_buf_count = static_cast<DWORD>(count);+  DWORD bytes_transferred = 0;+  DWORD recv_flags = flags;+  int result = ::WSARecv(s, bufs, recv_buf_count,+      &bytes_transferred, &recv_flags, 0, 0);+  get_last_error(ec, true);+  if (ec.value() == ERROR_NETNAME_DELETED)+    ec = asio::error::connection_reset;+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+    ec = asio::error::connection_refused;+  else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)+    result = 0;+  if (result != 0)+    return socket_error_retval;+  ec.assign(0, ec.category());+  return bytes_transferred;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  msghdr msg = msghdr();+  msg.msg_iov = bufs;+  msg.msg_iovlen = static_cast<int>(count);+  signed_size_type result = ::recvmsg(s, &msg, flags);+  get_last_error(ec, result < 0);+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++signed_size_type recv1(socket_type s, void* data, size_t size,+    int flags, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  // Receive some data.+  WSABUF buf;+  buf.buf = const_cast<char*>(static_cast<const char*>(data));+  buf.len = static_cast<ULONG>(size);+  DWORD bytes_transferred = 0;+  DWORD recv_flags = flags;+  int result = ::WSARecv(s, &buf, 1,+      &bytes_transferred, &recv_flags, 0, 0);+  get_last_error(ec, true);+  if (ec.value() == ERROR_NETNAME_DELETED)+    ec = asio::error::connection_reset;+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+    ec = asio::error::connection_refused;+  else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)+    result = 0;+  if (result != 0)+    return socket_error_retval;+  ec.assign(0, ec.category());+  return bytes_transferred;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  signed_size_type result = ::recv(s, static_cast<char*>(data), size, flags);+  get_last_error(ec, result < 0);+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++size_t sync_recv(socket_type s, state_type state, buf* bufs,+    size_t count, int flags, bool all_empty, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // A request to read 0 bytes on a stream is a no-op.+  if (all_empty && (state & stream_oriented))+  {+    ec.assign(0, ec.category());+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec);++    // Check for EOF.+    if ((state & stream_oriented) && bytes == 0)+    {+      ec = asio::error::eof;+      return 0;+    }++    // Check if operation succeeded.+    if (bytes >= 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for socket to become ready.+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)+      return 0;+  }+}++size_t sync_recv1(socket_type s, state_type state, void* data,+    size_t size, int flags, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // A request to read 0 bytes on a stream is a no-op.+  if (size == 0 && (state & stream_oriented))+  {+    ec.assign(0, ec.category());+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = socket_ops::recv1(s, data, size, flags, ec);++    // Check for EOF.+    if ((state & stream_oriented) && bytes == 0)+    {+      ec = asio::error::eof;+      return 0;+    }++    // Check if operation succeeded.+    if (bytes >= 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for socket to become ready.+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)+      return 0;+  }+}++#if defined(ASIO_HAS_IOCP)++void complete_iocp_recv(state_type state,+    const weak_cancel_token_type& cancel_token, bool all_empty,+    asio::error_code& ec, size_t bytes_transferred)+{+  // Map non-portable errors to their portable counterparts.+  if (ec.value() == ERROR_NETNAME_DELETED)+  {+    if (cancel_token.expired())+      ec = asio::error::operation_aborted;+    else+      ec = asio::error::connection_reset;+  }+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+  {+    ec = asio::error::connection_refused;+  }+  else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)+  {+    ec.assign(0, ec.category());+  }++  // Check for connection closed.+  else if (!ec && bytes_transferred == 0+      && (state & stream_oriented) != 0+      && !all_empty)+  {+    ec = asio::error::eof;+  }+}++#else // defined(ASIO_HAS_IOCP)++bool non_blocking_recv(socket_type s,+    buf* bufs, size_t count, int flags, bool is_stream,+    asio::error_code& ec, size_t& bytes_transferred)+{+  for (;;)+  {+    // Read some data.+    signed_size_type bytes = socket_ops::recv(s, bufs, count, flags, ec);++    // Check for end of stream.+    if (is_stream && bytes == 0)+    {+      ec = asio::error::eof;+      return true;+    }++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++bool non_blocking_recv1(socket_type s,+    void* data, size_t size, int flags, bool is_stream,+    asio::error_code& ec, size_t& bytes_transferred)+{+  for (;;)+  {+    // Read some data.+    signed_size_type bytes = socket_ops::recv1(s, data, size, flags, ec);++    // Check for end of stream.+    if (is_stream && bytes == 0)+    {+      ec = asio::error::eof;+      return true;+    }++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++#endif // defined(ASIO_HAS_IOCP)++signed_size_type recvfrom(socket_type s, buf* bufs, size_t count,+    int flags, socket_addr_type* addr, std::size_t* addrlen,+    asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  // Receive some data.+  DWORD recv_buf_count = static_cast<DWORD>(count);+  DWORD bytes_transferred = 0;+  DWORD recv_flags = flags;+  int tmp_addrlen = (int)*addrlen;+  int result = ::WSARecvFrom(s, bufs, recv_buf_count,+        &bytes_transferred, &recv_flags, addr, &tmp_addrlen, 0, 0);+  get_last_error(ec, true);+  *addrlen = (std::size_t)tmp_addrlen;+  if (ec.value() == ERROR_NETNAME_DELETED)+    ec = asio::error::connection_reset;+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+    ec = asio::error::connection_refused;+  else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)+    result = 0;+  if (result != 0)+    return socket_error_retval;+  ec.assign(0, ec.category());+  return bytes_transferred;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  msghdr msg = msghdr();+  init_msghdr_msg_name(msg.msg_name, addr);+  msg.msg_namelen = static_cast<int>(*addrlen);+  msg.msg_iov = bufs;+  msg.msg_iovlen = static_cast<int>(count);+  signed_size_type result = ::recvmsg(s, &msg, flags);+  get_last_error(ec, result < 0);+  *addrlen = msg.msg_namelen;+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++template <typename SockLenType>+inline signed_size_type call_recvfrom(SockLenType msghdr::*,+    socket_type s, void* data, size_t size, int flags,+    socket_addr_type* addr, std::size_t* addrlen)+{+  SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;+  signed_size_type result = ::recvfrom(s, static_cast<char*>(data),+      size, flags, addr, addrlen ? &tmp_addrlen : 0);+  if (addrlen)+    *addrlen = (std::size_t)tmp_addrlen;+  return result;+}++signed_size_type recvfrom1(socket_type s, void* data, size_t size,+    int flags, socket_addr_type* addr, std::size_t* addrlen,+    asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  // Receive some data.+  WSABUF buf;+  buf.buf = static_cast<char*>(data);+  buf.len = static_cast<ULONG>(size);+  DWORD bytes_transferred = 0;+  DWORD recv_flags = flags;+  int tmp_addrlen = (int)*addrlen;+  int result = ::WSARecvFrom(s, &buf, 1, &bytes_transferred,+      &recv_flags, addr, &tmp_addrlen, 0, 0);+  get_last_error(ec, true);+  *addrlen = (std::size_t)tmp_addrlen;+  if (ec.value() == ERROR_NETNAME_DELETED)+    ec = asio::error::connection_reset;+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+    ec = asio::error::connection_refused;+  else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)+    result = 0;+  if (result != 0)+    return socket_error_retval;+  ec.assign(0, ec.category());+  return bytes_transferred;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  signed_size_type result = call_recvfrom(&msghdr::msg_namelen,+      s, data, size, flags, addr, addrlen);+  get_last_error(ec, result < 0);+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++size_t sync_recvfrom(socket_type s, state_type state, buf* bufs,+    size_t count, int flags, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = socket_ops::recvfrom(+        s, bufs, count, flags, addr, addrlen, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for socket to become ready.+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)+      return 0;+  }+}++size_t sync_recvfrom1(socket_type s, state_type state, void* data,+    size_t size, int flags, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = socket_ops::recvfrom1(+        s, data, size, flags, addr, addrlen, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for socket to become ready.+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)+      return 0;+  }+}++#if defined(ASIO_HAS_IOCP)++void complete_iocp_recvfrom(+    const weak_cancel_token_type& cancel_token,+    asio::error_code& ec)+{+  // Map non-portable errors to their portable counterparts.+  if (ec.value() == ERROR_NETNAME_DELETED)+  {+    if (cancel_token.expired())+      ec = asio::error::operation_aborted;+    else+      ec = asio::error::connection_reset;+  }+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+  {+    ec = asio::error::connection_refused;+  }+  else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)+  {+    ec.assign(0, ec.category());+  }+}++#else // defined(ASIO_HAS_IOCP)++bool non_blocking_recvfrom(socket_type s,+    buf* bufs, size_t count, int flags,+    socket_addr_type* addr, std::size_t* addrlen,+    asio::error_code& ec, size_t& bytes_transferred)+{+  for (;;)+  {+    // Read some data.+    signed_size_type bytes = socket_ops::recvfrom(+        s, bufs, count, flags, addr, addrlen, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++bool non_blocking_recvfrom1(socket_type s,+    void* data, size_t size, int flags,+    socket_addr_type* addr, std::size_t* addrlen,+    asio::error_code& ec, size_t& bytes_transferred)+{+  for (;;)+  {+    // Read some data.+    signed_size_type bytes = socket_ops::recvfrom1(+        s, data, size, flags, addr, addrlen, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++#endif // defined(ASIO_HAS_IOCP)++signed_size_type recvmsg(socket_type s, buf* bufs, size_t count,+    int in_flags, int& out_flags, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  out_flags = 0;+  return socket_ops::recv(s, bufs, count, in_flags, ec);+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  msghdr msg = msghdr();+  msg.msg_iov = bufs;+  msg.msg_iovlen = static_cast<int>(count);+  signed_size_type result = ::recvmsg(s, &msg, in_flags);+  get_last_error(ec, result < 0);+  if (result >= 0)+    out_flags = msg.msg_flags;+  else+    out_flags = 0;+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++size_t sync_recvmsg(socket_type s, state_type state,+    buf* bufs, size_t count, int in_flags, int& out_flags,+    asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = socket_ops::recvmsg(+        s, bufs, count, in_flags, out_flags, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for socket to become ready.+    if (socket_ops::poll_read(s, 0, -1, ec) < 0)+      return 0;+  }+}++#if defined(ASIO_HAS_IOCP)++void complete_iocp_recvmsg(+    const weak_cancel_token_type& cancel_token,+    asio::error_code& ec)+{+  // Map non-portable errors to their portable counterparts.+  if (ec.value() == ERROR_NETNAME_DELETED)+  {+    if (cancel_token.expired())+      ec = asio::error::operation_aborted;+    else+      ec = asio::error::connection_reset;+  }+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+  {+    ec = asio::error::connection_refused;+  }+  else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)+  {+    ec.assign(0, ec.category());+  }+}++#else // defined(ASIO_HAS_IOCP)++bool non_blocking_recvmsg(socket_type s,+    buf* bufs, size_t count, int in_flags, int& out_flags,+    asio::error_code& ec, size_t& bytes_transferred)+{+  for (;;)+  {+    // Read some data.+    signed_size_type bytes = socket_ops::recvmsg(+        s, bufs, count, in_flags, out_flags, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++#endif // defined(ASIO_HAS_IOCP)++signed_size_type send(socket_type s, const buf* bufs, size_t count,+    int flags, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  // Send the data.+  DWORD send_buf_count = static_cast<DWORD>(count);+  DWORD bytes_transferred = 0;+  DWORD send_flags = flags;+  int result = ::WSASend(s, const_cast<buf*>(bufs),+        send_buf_count, &bytes_transferred, send_flags, 0, 0);+  get_last_error(ec, true);+  if (ec.value() == ERROR_NETNAME_DELETED)+    ec = asio::error::connection_reset;+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+    ec = asio::error::connection_refused;+  if (result != 0)+    return socket_error_retval;+  ec.assign(0, ec.category());+  return bytes_transferred;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  msghdr msg = msghdr();+  msg.msg_iov = const_cast<buf*>(bufs);+  msg.msg_iovlen = static_cast<int>(count);+#if defined(__linux__)+  flags |= MSG_NOSIGNAL;+#endif // defined(__linux__)+  signed_size_type result = ::sendmsg(s, &msg, flags);+  get_last_error(ec, result < 0);+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++signed_size_type send1(socket_type s, const void* data, size_t size,+    int flags, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  // Send the data.+  WSABUF buf;+  buf.buf = const_cast<char*>(static_cast<const char*>(data));+  buf.len = static_cast<ULONG>(size);+  DWORD bytes_transferred = 0;+  DWORD send_flags = flags;+  int result = ::WSASend(s, &buf, 1,+        &bytes_transferred, send_flags, 0, 0);+  get_last_error(ec, true);+  if (ec.value() == ERROR_NETNAME_DELETED)+    ec = asio::error::connection_reset;+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+    ec = asio::error::connection_refused;+  if (result != 0)+    return socket_error_retval;+  ec.assign(0, ec.category());+  return bytes_transferred;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+#if defined(__linux__)+  flags |= MSG_NOSIGNAL;+#endif // defined(__linux__)+  signed_size_type result = ::send(s,+      static_cast<const char*>(data), size, flags);+  get_last_error(ec, result < 0);+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++size_t sync_send(socket_type s, state_type state, const buf* bufs,+    size_t count, int flags, bool all_empty, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // A request to write 0 bytes to a stream is a no-op.+  if (all_empty && (state & stream_oriented))+  {+    ec.assign(0, ec.category());+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for socket to become ready.+    if (socket_ops::poll_write(s, 0, -1, ec) < 0)+      return 0;+  }+}++size_t sync_send1(socket_type s, state_type state, const void* data,+    size_t size, int flags, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // A request to write 0 bytes to a stream is a no-op.+  if (size == 0 && (state & stream_oriented))+  {+    ec.assign(0, ec.category());+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = socket_ops::send1(s, data, size, flags, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for socket to become ready.+    if (socket_ops::poll_write(s, 0, -1, ec) < 0)+      return 0;+  }+}++#if defined(ASIO_HAS_IOCP)++void complete_iocp_send(+    const weak_cancel_token_type& cancel_token,+    asio::error_code& ec)+{+  // Map non-portable errors to their portable counterparts.+  if (ec.value() == ERROR_NETNAME_DELETED)+  {+    if (cancel_token.expired())+      ec = asio::error::operation_aborted;+    else+      ec = asio::error::connection_reset;+  }+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+  {+    ec = asio::error::connection_refused;+  }+}++#else // defined(ASIO_HAS_IOCP)++bool non_blocking_send(socket_type s,+    const buf* bufs, size_t count, int flags,+    asio::error_code& ec, size_t& bytes_transferred)+{+  for (;;)+  {+    // Write some data.+    signed_size_type bytes = socket_ops::send(s, bufs, count, flags, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++bool non_blocking_send1(socket_type s,+    const void* data, size_t size, int flags,+    asio::error_code& ec, size_t& bytes_transferred)+{+  for (;;)+  {+    // Write some data.+    signed_size_type bytes = socket_ops::send1(s, data, size, flags, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++#endif // defined(ASIO_HAS_IOCP)++signed_size_type sendto(socket_type s, const buf* bufs, size_t count,+    int flags, const socket_addr_type* addr, std::size_t addrlen,+    asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  // Send the data.+  DWORD send_buf_count = static_cast<DWORD>(count);+  DWORD bytes_transferred = 0;+  int result = ::WSASendTo(s, const_cast<buf*>(bufs),+        send_buf_count, &bytes_transferred, flags, addr,+        static_cast<int>(addrlen), 0, 0);+  get_last_error(ec, true);+  if (ec.value() == ERROR_NETNAME_DELETED)+    ec = asio::error::connection_reset;+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+    ec = asio::error::connection_refused;+  if (result != 0)+    return socket_error_retval;+  ec.assign(0, ec.category());+  return bytes_transferred;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  msghdr msg = msghdr();+  init_msghdr_msg_name(msg.msg_name, addr);+  msg.msg_namelen = static_cast<int>(addrlen);+  msg.msg_iov = const_cast<buf*>(bufs);+  msg.msg_iovlen = static_cast<int>(count);+#if defined(__linux__)+  flags |= MSG_NOSIGNAL;+#endif // defined(__linux__)+  signed_size_type result = ::sendmsg(s, &msg, flags);+  get_last_error(ec, result < 0);+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++template <typename SockLenType>+inline signed_size_type call_sendto(SockLenType msghdr::*,+    socket_type s, const void* data, size_t size, int flags,+    const socket_addr_type* addr, std::size_t addrlen)+{+  return ::sendto(s, static_cast<char*>(const_cast<void*>(data)),+      size, flags, addr, (SockLenType)addrlen);+}++signed_size_type sendto1(socket_type s, const void* data, size_t size,+    int flags, const socket_addr_type* addr, std::size_t addrlen,+    asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  // Send the data.+  WSABUF buf;+  buf.buf = const_cast<char*>(static_cast<const char*>(data));+  buf.len = static_cast<ULONG>(size);+  DWORD bytes_transferred = 0;+  int result = ::WSASendTo(s, &buf, 1, &bytes_transferred,+      flags, addr, static_cast<int>(addrlen), 0, 0);+  get_last_error(ec, true);+  if (ec.value() == ERROR_NETNAME_DELETED)+    ec = asio::error::connection_reset;+  else if (ec.value() == ERROR_PORT_UNREACHABLE)+    ec = asio::error::connection_refused;+  if (result != 0)+    return socket_error_retval;+  ec.assign(0, ec.category());+  return bytes_transferred;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+#if defined(__linux__)+  flags |= MSG_NOSIGNAL;+#endif // defined(__linux__)+  signed_size_type result = call_sendto(&msghdr::msg_namelen,+      s, data, size, flags, addr, addrlen);+  get_last_error(ec, result < 0);+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++size_t sync_sendto(socket_type s, state_type state, const buf* bufs,+    size_t count, int flags, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // Write some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = socket_ops::sendto(+        s, bufs, count, flags, addr, addrlen, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for socket to become ready.+    if (socket_ops::poll_write(s, 0, -1, ec) < 0)+      return 0;+  }+}++size_t sync_sendto1(socket_type s, state_type state, const void* data,+    size_t size, int flags, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // Write some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = socket_ops::sendto1(+        s, data, size, flags, addr, addrlen, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+      return bytes;++    // Operation failed.+    if ((state & user_set_non_blocking)+        || (ec != asio::error::would_block+          && ec != asio::error::try_again))+      return 0;++    // Wait for socket to become ready.+    if (socket_ops::poll_write(s, 0, -1, ec) < 0)+      return 0;+  }+}++#if !defined(ASIO_HAS_IOCP)++bool non_blocking_sendto(socket_type s,+    const buf* bufs, size_t count, int flags,+    const socket_addr_type* addr, std::size_t addrlen,+    asio::error_code& ec, size_t& bytes_transferred)+{+  for (;;)+  {+    // Write some data.+    signed_size_type bytes = socket_ops::sendto(+        s, bufs, count, flags, addr, addrlen, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++bool non_blocking_sendto1(socket_type s,+    const void* data, size_t size, int flags,+    const socket_addr_type* addr, std::size_t addrlen,+    asio::error_code& ec, size_t& bytes_transferred)+{+  for (;;)+  {+    // Write some data.+    signed_size_type bytes = socket_ops::sendto1(+        s, data, size, flags, addr, addrlen, ec);++    // Check if operation succeeded.+    if (bytes >= 0)+    {+      bytes_transferred = bytes;+      return true;+    }++    // Retry operation if interrupted by signal.+    if (ec == asio::error::interrupted)+      continue;++    // Check if we need to run the operation again.+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return false;++    // Operation failed.+    bytes_transferred = 0;+    return true;+  }+}++#endif // !defined(ASIO_HAS_IOCP)++socket_type socket(int af, int type, int protocol,+    asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  socket_type s = ::WSASocketW(af, type, protocol, 0, 0, WSA_FLAG_OVERLAPPED);+  get_last_error(ec, s == invalid_socket);+  if (s == invalid_socket)+    return s;++  if (af == ASIO_OS_DEF(AF_INET6))+  {+    // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to+    // false. This will only succeed on Windows Vista and later versions of+    // Windows, where a dual-stack IPv4/v6 implementation is available.+    DWORD optval = 0;+    ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY,+        reinterpret_cast<const char*>(&optval), sizeof(optval));+  }++  return s;+#elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)+  socket_type s = ::socket(af, type, protocol);+  get_last_error(ec, s < 0);++  int optval = 1;+  int result = ::setsockopt(s, SOL_SOCKET,+      SO_NOSIGPIPE, &optval, sizeof(optval));+  get_last_error(ec, result != 0);+  if (result != 0)+  {+    ::close(s);+    return invalid_socket;+  }++  return s;+#else+  int s = ::socket(af, type, protocol);+  get_last_error(ec, s < 0);+  return s;+#endif+}++template <typename SockLenType>+inline int call_setsockopt(SockLenType msghdr::*,+    socket_type s, int level, int optname,+    const void* optval, std::size_t optlen)+{+  return ::setsockopt(s, level, optname,+      (const char*)optval, (SockLenType)optlen);+}++int setsockopt(socket_type s, state_type& state, int level, int optname,+    const void* optval, std::size_t optlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++  if (level == custom_socket_option_level && optname == always_fail_option)+  {+    ec = asio::error::invalid_argument;+    return socket_error_retval;+  }++  if (level == custom_socket_option_level+      && optname == enable_connection_aborted_option)+  {+    if (optlen != sizeof(int))+    {+      ec = asio::error::invalid_argument;+      return socket_error_retval;+    }++    if (*static_cast<const int*>(optval))+      state |= enable_connection_aborted;+    else+      state &= ~enable_connection_aborted;+    ec.assign(0, ec.category());+    return 0;+  }++  if (level == SOL_SOCKET && optname == SO_LINGER)+    state |= user_set_linger;++#if defined(__BORLANDC__)+  // Mysteriously, using the getsockopt and setsockopt functions directly with+  // Borland C++ results in incorrect values being set and read. The bug can be+  // worked around by using function addresses resolved with GetProcAddress.+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))+  {+    typedef int (WSAAPI *sso_t)(SOCKET, int, int, const char*, int);+    if (sso_t sso = (sso_t)::GetProcAddress(winsock_module, "setsockopt"))+    {+      int result = sso(s, level, optname,+            reinterpret_cast<const char*>(optval),+            static_cast<int>(optlen));+      get_last_error(ec, result != 0);+      return result;+    }+  }+  ec = asio::error::fault;+  return socket_error_retval;+#else // defined(__BORLANDC__)+  int result = call_setsockopt(&msghdr::msg_namelen,+        s, level, optname, optval, optlen);+  get_last_error(ec, result != 0);+  if (result == 0)+  {+#if defined(__MACH__) && defined(__APPLE__) \+  || defined(__NetBSD__) || defined(__FreeBSD__) \+  || defined(__OpenBSD__) || defined(__QNX__)+    // To implement portable behaviour for SO_REUSEADDR with UDP sockets we+    // need to also set SO_REUSEPORT on BSD-based platforms.+    if ((state & datagram_oriented)+        && level == SOL_SOCKET && optname == SO_REUSEADDR)+    {+      call_setsockopt(&msghdr::msg_namelen, s,+          SOL_SOCKET, SO_REUSEPORT, optval, optlen);+    }+#endif+  }++  return result;+#endif // defined(__BORLANDC__)+}++template <typename SockLenType>+inline int call_getsockopt(SockLenType msghdr::*,+    socket_type s, int level, int optname,+    void* optval, std::size_t* optlen)+{+  SockLenType tmp_optlen = (SockLenType)*optlen;+  int result = ::getsockopt(s, level, optname, (char*)optval, &tmp_optlen);+  *optlen = (std::size_t)tmp_optlen;+  return result;+}++int getsockopt(socket_type s, state_type state, int level, int optname,+    void* optval, size_t* optlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++  if (level == custom_socket_option_level && optname == always_fail_option)+  {+    ec = asio::error::invalid_argument;+    return socket_error_retval;+  }++  if (level == custom_socket_option_level+      && optname == enable_connection_aborted_option)+  {+    if (*optlen != sizeof(int))+    {+      ec = asio::error::invalid_argument;+      return socket_error_retval;+    }++    *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0;+    ec.assign(0, ec.category());+    return 0;+  }++#if defined(__BORLANDC__)+  // Mysteriously, using the getsockopt and setsockopt functions directly with+  // Borland C++ results in incorrect values being set and read. The bug can be+  // worked around by using function addresses resolved with GetProcAddress.+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))+  {+    typedef int (WSAAPI *gso_t)(SOCKET, int, int, char*, int*);+    if (gso_t gso = (gso_t)::GetProcAddress(winsock_module, "getsockopt"))+    {+      int tmp_optlen = static_cast<int>(*optlen);+      int result = gso(s, level, optname,+            reinterpret_cast<char*>(optval), &tmp_optlen);+      get_last_error(ec, result != 0);+      *optlen = static_cast<size_t>(tmp_optlen);+      if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY+          && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))+      {+        // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are+        // only supported on Windows Vista and later. To simplify program logic+        // we will fake success of getting this option and specify that the+        // value is non-zero (i.e. true). This corresponds to the behavior of+        // IPv6 sockets on Windows platforms pre-Vista.+        *static_cast<DWORD*>(optval) = 1;+        ec.assign(0, ec.category());+      }+      return result;+    }+  }+  ec = asio::error::fault;+  return socket_error_retval;+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  int result = call_getsockopt(&msghdr::msg_namelen,+        s, level, optname, optval, optlen);+  get_last_error(ec, result != 0);+  if (result != 0 && level == IPPROTO_IPV6 && optname == IPV6_V6ONLY+      && ec.value() == WSAENOPROTOOPT && *optlen == sizeof(DWORD))+  {+    // Dual-stack IPv4/v6 sockets, and the IPV6_V6ONLY socket option, are only+    // supported on Windows Vista and later. To simplify program logic we will+    // fake success of getting this option and specify that the value is+    // non-zero (i.e. true). This corresponds to the behavior of IPv6 sockets+    // on Windows platforms pre-Vista.+    *static_cast<DWORD*>(optval) = 1;+    ec.assign(0, ec.category());+  }+  return result;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  int result = call_getsockopt(&msghdr::msg_namelen,+        s, level, optname, optval, optlen);+  get_last_error(ec, result != 0);+#if defined(__linux__)+  if (result == 0 && level == SOL_SOCKET && *optlen == sizeof(int)+      && (optname == SO_SNDBUF || optname == SO_RCVBUF))+  {+    // On Linux, setting SO_SNDBUF or SO_RCVBUF to N actually causes the kernel+    // to set the buffer size to N*2. Linux puts additional stuff into the+    // buffers so that only about half is actually available to the application.+    // The retrieved value is divided by 2 here to make it appear as though the+    // correct value has been set.+    *static_cast<int*>(optval) /= 2;+  }+#endif // defined(__linux__)+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++template <typename SockLenType>+inline int call_getpeername(SockLenType msghdr::*,+    socket_type s, socket_addr_type* addr, std::size_t* addrlen)+{+  SockLenType tmp_addrlen = (SockLenType)*addrlen;+  int result = ::getpeername(s, addr, &tmp_addrlen);+  *addrlen = (std::size_t)tmp_addrlen;+  return result;+}++int getpeername(socket_type s, socket_addr_type* addr,+    std::size_t* addrlen, bool cached, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++#if defined(ASIO_WINDOWS) && !defined(ASIO_WINDOWS_APP) \+  || defined(__CYGWIN__)+  if (cached)+  {+    // Check if socket is still connected.+    DWORD connect_time = 0;+    size_t connect_time_len = sizeof(connect_time);+    if (socket_ops::getsockopt(s, 0, SOL_SOCKET, SO_CONNECT_TIME,+          &connect_time, &connect_time_len, ec) == socket_error_retval)+    {+      return socket_error_retval;+    }+    if (connect_time == 0xFFFFFFFF)+    {+      ec = asio::error::not_connected;+      return socket_error_retval;+    }++    // The cached value is still valid.+    ec.assign(0, ec.category());+    return 0;+  }+#else // defined(ASIO_WINDOWS) && !defined(ASIO_WINDOWS_APP)+      // || defined(__CYGWIN__)+  (void)cached;+#endif // defined(ASIO_WINDOWS) && !defined(ASIO_WINDOWS_APP)+       // || defined(__CYGWIN__)++  int result = call_getpeername(&msghdr::msg_namelen, s, addr, addrlen);+  get_last_error(ec, result != 0);+  return result;+}++template <typename SockLenType>+inline int call_getsockname(SockLenType msghdr::*,+    socket_type s, socket_addr_type* addr, std::size_t* addrlen)+{+  SockLenType tmp_addrlen = (SockLenType)*addrlen;+  int result = ::getsockname(s, addr, &tmp_addrlen);+  *addrlen = (std::size_t)tmp_addrlen;+  return result;+}++int getsockname(socket_type s, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++  int result = call_getsockname(&msghdr::msg_namelen, s, addr, addrlen);+  get_last_error(ec, result != 0);+  return result;+}++int ioctl(socket_type s, state_type& state, int cmd,+    ioctl_arg_type* arg, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  int result = ::ioctlsocket(s, cmd, arg);+#elif defined(__MACH__) && defined(__APPLE__) \+  || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__OpenBSD__)+  int result = ::ioctl(s, static_cast<unsigned int>(cmd), arg);+#else+  int result = ::ioctl(s, cmd, arg);+#endif+  get_last_error(ec, result < 0);+  if (result >= 0)+  {+    // When updating the non-blocking mode we always perform the ioctl syscall,+    // even if the flags would otherwise indicate that the socket is already in+    // the correct state. This ensures that the underlying socket is put into+    // the state that has been requested by the user. If the ioctl syscall was+    // successful then we need to update the flags to match.+    if (cmd == static_cast<int>(FIONBIO))+    {+      if (*arg)+      {+        state |= user_set_non_blocking;+      }+      else+      {+        // Clearing the non-blocking mode always overrides any internally-set+        // non-blocking flag. Any subsequent asynchronous operations will need+        // to re-enable non-blocking I/O.+        state &= ~(user_set_non_blocking | internal_non_blocking);+      }+    }+  }++  return result;+}++int select(int nfds, fd_set* readfds, fd_set* writefds,+    fd_set* exceptfds, timeval* timeout, asio::error_code& ec)+{+#if defined(__EMSCRIPTEN__)+  exceptfds = 0;+#endif // defined(__EMSCRIPTEN__)+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  if (!readfds && !writefds && !exceptfds && timeout)+  {+    DWORD milliseconds = timeout->tv_sec * 1000 + timeout->tv_usec / 1000;+    if (milliseconds == 0)+      milliseconds = 1; // Force context switch.+    ::Sleep(milliseconds);+    ec.assign(0, ec.category());+    return 0;+  }++  // The select() call allows timeout values measured in microseconds, but the+  // system clock (as wrapped by boost::posix_time::microsec_clock) typically+  // has a resolution of 10 milliseconds. This can lead to a spinning select+  // reactor, meaning increased CPU usage, when waiting for the earliest+  // scheduled timeout if it's less than 10 milliseconds away. To avoid a tight+  // spin we'll use a minimum timeout of 1 millisecond.+  if (timeout && timeout->tv_sec == 0+      && timeout->tv_usec > 0 && timeout->tv_usec < 1000)+    timeout->tv_usec = 1000;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++#if defined(__hpux) && defined(__SELECT)+  timespec ts;+  ts.tv_sec = timeout ? timeout->tv_sec : 0;+  ts.tv_nsec = timeout ? timeout->tv_usec * 1000 : 0;+  int result = ::pselect(nfds, readfds,+        writefds, exceptfds, timeout ? &ts : 0, 0);+#else+  int result = ::select(nfds, readfds, writefds, exceptfds, timeout);+#endif+  get_last_error(ec, result < 0);+  return result;+}++int poll_read(socket_type s, state_type state,+    int msec, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++#if defined(ASIO_WINDOWS) \+  || defined(__CYGWIN__) \+  || defined(__SYMBIAN32__)+  fd_set fds;+  FD_ZERO(&fds);+  FD_SET(s, &fds);+  timeval timeout_obj;+  timeval* timeout;+  if (state & user_set_non_blocking)+  {+    timeout_obj.tv_sec = 0;+    timeout_obj.tv_usec = 0;+    timeout = &timeout_obj;+  }+  else if (msec >= 0)+  {+    timeout_obj.tv_sec = msec / 1000;+    timeout_obj.tv_usec = (msec % 1000) * 1000;+    timeout = &timeout_obj;+  }+  else+    timeout = 0;+  int result = ::select(s + 1, &fds, 0, 0, timeout);+  get_last_error(ec, result < 0);+#else // defined(ASIO_WINDOWS)+      // || defined(__CYGWIN__)+      // || defined(__SYMBIAN32__)+  pollfd fds;+  fds.fd = s;+  fds.events = POLLIN;+  fds.revents = 0;+  int timeout = (state & user_set_non_blocking) ? 0 : msec;+  int result = ::poll(&fds, 1, timeout);+  get_last_error(ec, result < 0);+#endif // defined(ASIO_WINDOWS)+       // || defined(__CYGWIN__)+       // || defined(__SYMBIAN32__)+  if (result == 0)+    if (state & user_set_non_blocking)+      ec = asio::error::would_block;+  return result;+}++int poll_write(socket_type s, state_type state,+    int msec, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++#if defined(ASIO_WINDOWS) \+  || defined(__CYGWIN__) \+  || defined(__SYMBIAN32__)+  fd_set fds;+  FD_ZERO(&fds);+  FD_SET(s, &fds);+  timeval timeout_obj;+  timeval* timeout;+  if (state & user_set_non_blocking)+  {+    timeout_obj.tv_sec = 0;+    timeout_obj.tv_usec = 0;+    timeout = &timeout_obj;+  }+  else if (msec >= 0)+  {+    timeout_obj.tv_sec = msec / 1000;+    timeout_obj.tv_usec = (msec % 1000) * 1000;+    timeout = &timeout_obj;+  }+  else+    timeout = 0;+  int result = ::select(s + 1, 0, &fds, 0, timeout);+  get_last_error(ec, result < 0);+#else // defined(ASIO_WINDOWS)+      // || defined(__CYGWIN__)+      // || defined(__SYMBIAN32__)+  pollfd fds;+  fds.fd = s;+  fds.events = POLLOUT;+  fds.revents = 0;+  int timeout = (state & user_set_non_blocking) ? 0 : msec;+  int result = ::poll(&fds, 1, timeout);+  get_last_error(ec, result < 0);+#endif // defined(ASIO_WINDOWS)+       // || defined(__CYGWIN__)+       // || defined(__SYMBIAN32__)+  if (result == 0)+    if (state & user_set_non_blocking)+      ec = asio::error::would_block;+  return result;+}++int poll_error(socket_type s, state_type state,+    int msec, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++#if defined(ASIO_WINDOWS) \+  || defined(__CYGWIN__) \+  || defined(__SYMBIAN32__)+  fd_set fds;+  FD_ZERO(&fds);+  FD_SET(s, &fds);+  timeval timeout_obj;+  timeval* timeout;+  if (state & user_set_non_blocking)+  {+    timeout_obj.tv_sec = 0;+    timeout_obj.tv_usec = 0;+    timeout = &timeout_obj;+  }+  else if (msec >= 0)+  {+    timeout_obj.tv_sec = msec / 1000;+    timeout_obj.tv_usec = (msec % 1000) * 1000;+    timeout = &timeout_obj;+  }+  else+    timeout = 0;+  int result = ::select(s + 1, 0, 0, &fds, timeout);+  get_last_error(ec, result < 0);+#else // defined(ASIO_WINDOWS)+      // || defined(__CYGWIN__)+      // || defined(__SYMBIAN32__)+  pollfd fds;+  fds.fd = s;+  fds.events = POLLPRI | POLLERR | POLLHUP;+  fds.revents = 0;+  int timeout = (state & user_set_non_blocking) ? 0 : msec;+  int result = ::poll(&fds, 1, timeout);+  get_last_error(ec, result < 0);+#endif // defined(ASIO_WINDOWS)+       // || defined(__CYGWIN__)+       // || defined(__SYMBIAN32__)+  if (result == 0)+    if (state & user_set_non_blocking)+      ec = asio::error::would_block;+  return result;+}++int poll_connect(socket_type s, int msec, asio::error_code& ec)+{+  if (s == invalid_socket)+  {+    ec = asio::error::bad_descriptor;+    return socket_error_retval;+  }++#if defined(ASIO_WINDOWS) \+  || defined(__CYGWIN__) \+  || defined(__SYMBIAN32__)+  fd_set write_fds;+  FD_ZERO(&write_fds);+  FD_SET(s, &write_fds);+  fd_set except_fds;+  FD_ZERO(&except_fds);+  FD_SET(s, &except_fds);+  timeval timeout_obj;+  timeval* timeout;+  if (msec >= 0)+  {+    timeout_obj.tv_sec = msec / 1000;+    timeout_obj.tv_usec = (msec % 1000) * 1000;+    timeout = &timeout_obj;+  }+  else+    timeout = 0;+  int result = ::select(s + 1, 0, &write_fds, &except_fds, timeout);+  get_last_error(ec, result < 0);+  return result;+#else // defined(ASIO_WINDOWS)+      // || defined(__CYGWIN__)+      // || defined(__SYMBIAN32__)+  pollfd fds;+  fds.fd = s;+  fds.events = POLLOUT;+  fds.revents = 0;+  int result = ::poll(&fds, 1, msec);+  get_last_error(ec, result < 0);+  return result;+#endif // defined(ASIO_WINDOWS)+       // || defined(__CYGWIN__)+       // || defined(__SYMBIAN32__)+}++#endif // !defined(ASIO_WINDOWS_RUNTIME)++const char* inet_ntop(int af, const void* src, char* dest, size_t length,+    unsigned long scope_id, asio::error_code& ec)+{+  clear_last_error();+#if defined(ASIO_WINDOWS_RUNTIME)+  using namespace std; // For sprintf.+  const unsigned char* bytes = static_cast<const unsigned char*>(src);+  if (af == ASIO_OS_DEF(AF_INET))+  {+    sprintf_s(dest, length, "%u.%u.%u.%u",+        bytes[0], bytes[1], bytes[2], bytes[3]);+    return dest;+  }+  else if (af == ASIO_OS_DEF(AF_INET6))+  {+    size_t n = 0, b = 0, z = 0;+    while (n < length && b < 16)+    {+      if (bytes[b] == 0 && bytes[b + 1] == 0 && z == 0)+      {+        do b += 2; while (b < 16 && bytes[b] == 0 && bytes[b + 1] == 0);+        n += sprintf_s(dest + n, length - n, ":%s", b < 16 ? "" : ":"), ++z;+      }+      else+      {+        n += sprintf_s(dest + n, length - n, "%s%x", b ? ":" : "",+            (static_cast<u_long_type>(bytes[b]) << 8) | bytes[b + 1]);+        b += 2;+      }+    }+    if (scope_id)+      n += sprintf_s(dest + n, length - n, "%%%lu", scope_id);+    return dest;+  }+  else+  {+    ec = asio::error::address_family_not_supported;+    return 0;+  }+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  using namespace std; // For memcpy.++  if (af != ASIO_OS_DEF(AF_INET) && af != ASIO_OS_DEF(AF_INET6))+  {+    ec = asio::error::address_family_not_supported;+    return 0;+  }++  union+  {+    socket_addr_type base;+    sockaddr_storage_type storage;+    sockaddr_in4_type v4;+    sockaddr_in6_type v6;+  } address;+  DWORD address_length;+  if (af == ASIO_OS_DEF(AF_INET))+  {+    address_length = sizeof(sockaddr_in4_type);+    address.v4.sin_family = ASIO_OS_DEF(AF_INET);+    address.v4.sin_port = 0;+    memcpy(&address.v4.sin_addr, src, sizeof(in4_addr_type));+  }+  else // AF_INET6+  {+    address_length = sizeof(sockaddr_in6_type);+    address.v6.sin6_family = ASIO_OS_DEF(AF_INET6);+    address.v6.sin6_port = 0;+    address.v6.sin6_flowinfo = 0;+    address.v6.sin6_scope_id = scope_id;+    memcpy(&address.v6.sin6_addr, src, sizeof(in6_addr_type));+  }++  DWORD string_length = static_cast<DWORD>(length);+#if defined(BOOST_NO_ANSI_APIS) || (defined(_MSC_VER) && (_MSC_VER >= 1800))+  LPWSTR string_buffer = (LPWSTR)_alloca(length * sizeof(WCHAR));+  int result = ::WSAAddressToStringW(&address.base,+        address_length, 0, string_buffer, &string_length);+  get_last_error(ec, true);+  ::WideCharToMultiByte(CP_ACP, 0, string_buffer, -1,+      dest, static_cast<int>(length), 0, 0);+#else+  int result = ::WSAAddressToStringA(&address.base,+      address_length, 0, dest, &string_length);+  get_last_error(ec, true);+#endif++  // Windows may set error code on success.+  if (result != socket_error_retval)+    ec.assign(0, ec.category());++  // Windows may not set an error code on failure.+  else if (result == socket_error_retval && !ec)+    ec = asio::error::invalid_argument;++  return result == socket_error_retval ? 0 : dest;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  const char* result = ::inet_ntop(af, src, dest, static_cast<int>(length));+  get_last_error(ec, true);+  if (result == 0 && !ec)+    ec = asio::error::invalid_argument;+  if (result != 0 && af == ASIO_OS_DEF(AF_INET6) && scope_id != 0)+  {+    using namespace std; // For strcat and sprintf.+    char if_name[(IF_NAMESIZE > 21 ? IF_NAMESIZE : 21) + 1] = "%";+    const in6_addr_type* ipv6_address = static_cast<const in6_addr_type*>(src);+    bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe)+        && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80));+    bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff)+        && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02));+    if ((!is_link_local && !is_multicast_link_local)+        || if_indextoname(static_cast<unsigned>(scope_id), if_name + 1) == 0)+      sprintf(if_name + 1, "%lu", scope_id);+    strcat(dest, if_name);+  }+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++int inet_pton(int af, const char* src, void* dest,+    unsigned long* scope_id, asio::error_code& ec)+{+  clear_last_error();+#if defined(ASIO_WINDOWS_RUNTIME)+  using namespace std; // For sscanf.+  unsigned char* bytes = static_cast<unsigned char*>(dest);+  if (af == ASIO_OS_DEF(AF_INET))+  {+    unsigned int b0, b1, b2, b3;+    if (sscanf_s(src, "%u.%u.%u.%u", &b0, &b1, &b2, &b3) != 4)+    {+      ec = asio::error::invalid_argument;+      return -1;+    }+    if (b0 > 255 || b1 > 255 || b2 > 255 || b3 > 255)+    {+      ec = asio::error::invalid_argument;+      return -1;+    }+    bytes[0] = static_cast<unsigned char>(b0);+    bytes[1] = static_cast<unsigned char>(b1);+    bytes[2] = static_cast<unsigned char>(b2);+    bytes[3] = static_cast<unsigned char>(b3);+    ec.assign(), ec.category());+    return 1;+  }+  else if (af == ASIO_OS_DEF(AF_INET6))+  {+    unsigned char* bytes = static_cast<unsigned char*>(dest);+    std::memset(bytes, 0, 16);+    unsigned char back_bytes[16] = { 0 };+    int num_front_bytes = 0, num_back_bytes = 0;+    const char* p = src;++    enum { fword, fcolon, bword, scope, done } state = fword;+    unsigned long current_word = 0;+    while (state != done)+    {+      if (current_word > 0xFFFF)+      {+        ec = asio::error::invalid_argument;+        return -1;+      }++      switch (state)+      {+      case fword:+        if (*p >= '0' && *p <= '9')+          current_word = current_word * 16 + *p++ - '0';+        else if (*p >= 'a' && *p <= 'f')+          current_word = current_word * 16 + *p++ - 'a' + 10;+        else if (*p >= 'A' && *p <= 'F')+          current_word = current_word * 16 + *p++ - 'A' + 10;+        else+        {+          if (num_front_bytes == 16)+          {+            ec = asio::error::invalid_argument;+            return -1;+          }++          bytes[num_front_bytes++] = (current_word >> 8) & 0xFF;+          bytes[num_front_bytes++] = current_word & 0xFF;+          current_word = 0;++          if (*p == ':')+            state = fcolon, ++p;+          else if (*p == '%')+            state = scope, ++p;+          else if (*p == 0)+            state = done;+          else+          {+            ec = asio::error::invalid_argument;+            return -1;+          }+        }+        break;++      case fcolon:+        if (*p == ':')+          state = bword, ++p;+        else+          state = fword;+        break;++      case bword:+        if (*p >= '0' && *p <= '9')+          current_word = current_word * 16 + *p++ - '0';+        else if (*p >= 'a' && *p <= 'f')+          current_word = current_word * 16 + *p++ - 'a' + 10;+        else if (*p >= 'A' && *p <= 'F')+          current_word = current_word * 16 + *p++ - 'A' + 10;+        else+        {+          if (num_front_bytes + num_back_bytes == 16)+          {+            ec = asio::error::invalid_argument;+            return -1;+          }++          back_bytes[num_back_bytes++] = (current_word >> 8) & 0xFF;+          back_bytes[num_back_bytes++] = current_word & 0xFF;+          current_word = 0;++          if (*p == ':')+            state = bword, ++p;+          else if (*p == '%')+            state = scope, ++p;+          else if (*p == 0)+            state = done;+          else+          {+            ec = asio::error::invalid_argument;+            return -1;+          }+        }+        break;++      case scope:+        if (*p >= '0' && *p <= '9')+          current_word = current_word * 10 + *p++ - '0';+        else if (*p == 0)+          *scope_id = current_word, state = done;+        else+        {+          ec = asio::error::invalid_argument;+          return -1;+        }+        break;++      default:+        break;+      }+    }++    for (int i = 0; i < num_back_bytes; ++i)+      bytes[16 - num_back_bytes + i] = back_bytes[i];++    ec.assign(0, ec.category());+    return 1;+  }+  else+  {+    ec = asio::error::address_family_not_supported;+    return -1;+  }+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  using namespace std; // For memcpy and strcmp.++  if (af != ASIO_OS_DEF(AF_INET) && af != ASIO_OS_DEF(AF_INET6))+  {+    ec = asio::error::address_family_not_supported;+    return -1;+  }++  union+  {+    socket_addr_type base;+    sockaddr_storage_type storage;+    sockaddr_in4_type v4;+    sockaddr_in6_type v6;+  } address;+  int address_length = sizeof(sockaddr_storage_type);+#if defined(BOOST_NO_ANSI_APIS) || (defined(_MSC_VER) && (_MSC_VER >= 1800))+  int num_wide_chars = static_cast<int>(strlen(src)) + 1;+  LPWSTR wide_buffer = (LPWSTR)_alloca(num_wide_chars * sizeof(WCHAR));+  ::MultiByteToWideChar(CP_ACP, 0, src, -1, wide_buffer, num_wide_chars);+  int result = ::WSAStringToAddressW(wide_buffer,+      af, 0, &address.base, &address_length);+  get_last_error(ec, true);+#else+  int result = ::WSAStringToAddressA(const_cast<char*>(src),+      af, 0, &address.base, &address_length);+  get_last_error(ec, true);+#endif++  if (af == ASIO_OS_DEF(AF_INET))+  {+    if (result != socket_error_retval)+    {+      memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));+      ec.assign(0, ec.category());+    }+    else if (strcmp(src, "255.255.255.255") == 0)+    {+      static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;+      ec.assign(0, ec.category());+    }+  }+  else // AF_INET6+  {+    if (result != socket_error_retval)+    {+      memcpy(dest, &address.v6.sin6_addr, sizeof(in6_addr_type));+      if (scope_id)+        *scope_id = address.v6.sin6_scope_id;+      ec.assign(0, ec.category());+    }+  }++  // Windows may not set an error code on failure.+  if (result == socket_error_retval && !ec)+    ec = asio::error::invalid_argument;++  if (result != socket_error_retval)+    ec.assign(0, ec.category());++  return result == socket_error_retval ? -1 : 1;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  using namespace std; // For strchr, memcpy and atoi.++  // On some platforms, inet_pton fails if an address string contains a scope+  // id. Detect and remove the scope id before passing the string to inet_pton.+  const bool is_v6 = (af == ASIO_OS_DEF(AF_INET6));+  const char* if_name = is_v6 ? strchr(src, '%') : 0;+  char src_buf[max_addr_v6_str_len + 1];+  const char* src_ptr = src;+  if (if_name != 0)+  {+    if (if_name - src > max_addr_v6_str_len)+    {+      ec = asio::error::invalid_argument;+      return 0;+    }+    memcpy(src_buf, src, if_name - src);+    src_buf[if_name - src] = 0;+    src_ptr = src_buf;+  }++  int result = ::inet_pton(af, src_ptr, dest);+  get_last_error(ec, true);+  if (result <= 0 && !ec)+    ec = asio::error::invalid_argument;+  if (result > 0 && is_v6 && scope_id)+  {+    using namespace std; // For strchr and atoi.+    *scope_id = 0;+    if (if_name != 0)+    {+      in6_addr_type* ipv6_address = static_cast<in6_addr_type*>(dest);+      bool is_link_local = ((ipv6_address->s6_addr[0] == 0xfe)+          && ((ipv6_address->s6_addr[1] & 0xc0) == 0x80));+      bool is_multicast_link_local = ((ipv6_address->s6_addr[0] == 0xff)+          && ((ipv6_address->s6_addr[1] & 0x0f) == 0x02));+      if (is_link_local || is_multicast_link_local)+        *scope_id = if_nametoindex(if_name + 1);+      if (*scope_id == 0)+        *scope_id = atoi(if_name + 1);+    }+  }+  return result;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+}++int gethostname(char* name, int namelen, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS_RUNTIME)+  try+  {+    using namespace Windows::Foundation::Collections;+    using namespace Windows::Networking;+    using namespace Windows::Networking::Connectivity;+    IVectorView<HostName^>^ hostnames = NetworkInformation::GetHostNames();+    for (unsigned i = 0; i < hostnames->Size; ++i)+    {+      HostName^ hostname = hostnames->GetAt(i);+      if (hostname->Type == HostNameType::DomainName)+      {+        std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;+        std::string raw_name = converter.to_bytes(hostname->RawName->Data());+        if (namelen > 0 && raw_name.size() < static_cast<std::size_t>(namelen))+        {+          strcpy_s(name, namelen, raw_name.c_str());+          return 0;+        }+      }+    }+    return -1;+  }+  catch (Platform::Exception^ e)+  {+    ec = asio::error_code(e->HResult,+        asio::system_category());+    return -1;+  }+#else // defined(ASIO_WINDOWS_RUNTIME)+  int result = ::gethostname(name, namelen);+  get_last_error(ec, result != 0);+  return result;+#endif // defined(ASIO_WINDOWS_RUNTIME)+}++#if !defined(ASIO_WINDOWS_RUNTIME)++#if !defined(ASIO_HAS_GETADDRINFO)++// The following functions are only needed for emulation of getaddrinfo and+// getnameinfo.++inline asio::error_code translate_netdb_error(int error)+{+  switch (error)+  {+  case 0:+    return asio::error_code();+  case HOST_NOT_FOUND:+    return asio::error::host_not_found;+  case TRY_AGAIN:+    return asio::error::host_not_found_try_again;+  case NO_RECOVERY:+    return asio::error::no_recovery;+  case NO_DATA:+    return asio::error::no_data;+  default:+    ASIO_ASSERT(false);+    return asio::error::invalid_argument;+  }+}++inline hostent* gethostbyaddr(const char* addr, int length, int af,+    hostent* result, char* buffer, int buflength, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  (void)(buffer);+  (void)(buflength);+  hostent* retval = ::gethostbyaddr(addr, length, af);+  get_last_error(ec, !retval);+  if (!retval)+    return 0;+  *result = *retval;+  return retval;+#elif defined(__sun) || defined(__QNX__)+  int error = 0;+  hostent* retval = ::gethostbyaddr_r(addr, length,+      af, result, buffer, buflength, &error);+  get_last_error(ec, !retval);+  if (error)+    ec = translate_netdb_error(error);+  return retval;+#elif defined(__MACH__) && defined(__APPLE__)+  (void)(buffer);+  (void)(buflength);+  int error = 0;+  hostent* retval = ::getipnodebyaddr(addr, length, af, &error);+  get_last_error(ec, !retval);+  if (error)+    ec = translate_netdb_error(error);+  if (!retval)+    return 0;+  *result = *retval;+  return retval;+#else+  hostent* retval = 0;+  int error = 0;+  clear_last_error();+  ::gethostbyaddr_r(addr, length, af, result,+      buffer, buflength, &retval, &error);+  get_last_error(ec, true);+  if (error)+    ec = translate_netdb_error(error);+  return retval;+#endif+}++inline hostent* gethostbyname(const char* name, int af, struct hostent* result,+    char* buffer, int buflength, int ai_flags, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  (void)(buffer);+  (void)(buflength);+  (void)(ai_flags);+  if (af != ASIO_OS_DEF(AF_INET))+  {+    ec = asio::error::address_family_not_supported;+    return 0;+  }+  hostent* retval = ::gethostbyname(name);+  get_last_error(ec, !retval);+  if (!retval)+    return 0;+  *result = *retval;+  return result;+#elif defined(__sun) || defined(__QNX__)+  (void)(ai_flags);+  if (af != ASIO_OS_DEF(AF_INET))+  {+    ec = asio::error::address_family_not_supported;+    return 0;+  }+  int error = 0;+  hostent* retval = ::gethostbyname_r(name, result, buffer, buflength, &error);+  get_last_error(ec, !retval);+  if (error)+    ec = translate_netdb_error(error);+  return retval;+#elif defined(__MACH__) && defined(__APPLE__)+  (void)(buffer);+  (void)(buflength);+  int error = 0;+  hostent* retval = ::getipnodebyname(name, af, ai_flags, &error);+  get_last_error(ec, !retval);+  if (error)+    ec = translate_netdb_error(error);+  if (!retval)+    return 0;+  *result = *retval;+  return retval;+#else+  (void)(ai_flags);+  if (af != ASIO_OS_DEF(AF_INET))+  {+    ec = asio::error::address_family_not_supported;+    return 0;+  }+  hostent* retval = 0;+  int error = 0;+  clear_last_error();+  ::gethostbyname_r(name, result, buffer, buflength, &retval, &error);+  get_last_error(ec, true);+  if (error)+    ec = translate_netdb_error(error);+  return retval;+#endif+}++inline void freehostent(hostent* h)+{+#if defined(__MACH__) && defined(__APPLE__)+  if (h)+    ::freehostent(h);+#else+  (void)(h);+#endif+}++// Emulation of getaddrinfo based on implementation in:+// Stevens, W. R., UNIX Network Programming Vol. 1, 2nd Ed., Prentice-Hall 1998.++struct gai_search+{+  const char* host;+  int family;+};++inline int gai_nsearch(const char* host,+    const addrinfo_type* hints, gai_search (&search)[2])+{+  int search_count = 0;+  if (host == 0 || host[0] == '\0')+  {+    if (hints->ai_flags & AI_PASSIVE)+    {+      // No host and AI_PASSIVE implies wildcard bind.+      switch (hints->ai_family)+      {+      case ASIO_OS_DEF(AF_INET):+        search[search_count].host = "0.0.0.0";+        search[search_count].family = ASIO_OS_DEF(AF_INET);+        ++search_count;+        break;+      case ASIO_OS_DEF(AF_INET6):+        search[search_count].host = "0::0";+        search[search_count].family = ASIO_OS_DEF(AF_INET6);+        ++search_count;+        break;+      case ASIO_OS_DEF(AF_UNSPEC):+        search[search_count].host = "0::0";+        search[search_count].family = ASIO_OS_DEF(AF_INET6);+        ++search_count;+        search[search_count].host = "0.0.0.0";+        search[search_count].family = ASIO_OS_DEF(AF_INET);+        ++search_count;+        break;+      default:+        break;+      }+    }+    else+    {+      // No host and not AI_PASSIVE means connect to local host.+      switch (hints->ai_family)+      {+      case ASIO_OS_DEF(AF_INET):+        search[search_count].host = "localhost";+        search[search_count].family = ASIO_OS_DEF(AF_INET);+        ++search_count;+        break;+      case ASIO_OS_DEF(AF_INET6):+        search[search_count].host = "localhost";+        search[search_count].family = ASIO_OS_DEF(AF_INET6);+        ++search_count;+        break;+      case ASIO_OS_DEF(AF_UNSPEC):+        search[search_count].host = "localhost";+        search[search_count].family = ASIO_OS_DEF(AF_INET6);+        ++search_count;+        search[search_count].host = "localhost";+        search[search_count].family = ASIO_OS_DEF(AF_INET);+        ++search_count;+        break;+      default:+        break;+      }+    }+  }+  else+  {+    // Host is specified.+    switch (hints->ai_family)+    {+    case ASIO_OS_DEF(AF_INET):+      search[search_count].host = host;+      search[search_count].family = ASIO_OS_DEF(AF_INET);+      ++search_count;+      break;+    case ASIO_OS_DEF(AF_INET6):+      search[search_count].host = host;+      search[search_count].family = ASIO_OS_DEF(AF_INET6);+      ++search_count;+      break;+    case ASIO_OS_DEF(AF_UNSPEC):+      search[search_count].host = host;+      search[search_count].family = ASIO_OS_DEF(AF_INET6);+      ++search_count;+      search[search_count].host = host;+      search[search_count].family = ASIO_OS_DEF(AF_INET);+      ++search_count;+      break;+    default:+      break;+    }+  }+  return search_count;+}++template <typename T>+inline T* gai_alloc(std::size_t size = sizeof(T))+{+  using namespace std;+  T* p = static_cast<T*>(::operator new(size, std::nothrow));+  if (p)+    memset(p, 0, size);+  return p;+}++inline void gai_free(void* p)+{+  ::operator delete(p);+}++inline void gai_strcpy(char* target, const char* source, std::size_t max_size)+{+  using namespace std;+#if defined(ASIO_HAS_SECURE_RTL)+  strcpy_s(target, max_size, source);+#else // defined(ASIO_HAS_SECURE_RTL)+  *target = 0;+  if (max_size > 0)+    strncat(target, source, max_size - 1);+#endif // defined(ASIO_HAS_SECURE_RTL)+}++enum { gai_clone_flag = 1 << 30 };++inline int gai_aistruct(addrinfo_type*** next, const addrinfo_type* hints,+    const void* addr, int family)+{+  using namespace std;++  addrinfo_type* ai = gai_alloc<addrinfo_type>();+  if (ai == 0)+    return EAI_MEMORY;++  ai->ai_next = 0;+  **next = ai;+  *next = &ai->ai_next;++  ai->ai_canonname = 0;+  ai->ai_socktype = hints->ai_socktype;+  if (ai->ai_socktype == 0)+    ai->ai_flags |= gai_clone_flag;+  ai->ai_protocol = hints->ai_protocol;+  ai->ai_family = family;++  switch (ai->ai_family)+  {+  case ASIO_OS_DEF(AF_INET):+    {+      sockaddr_in4_type* sinptr = gai_alloc<sockaddr_in4_type>();+      if (sinptr == 0)+        return EAI_MEMORY;+      sinptr->sin_family = ASIO_OS_DEF(AF_INET);+      memcpy(&sinptr->sin_addr, addr, sizeof(in4_addr_type));+      ai->ai_addr = reinterpret_cast<sockaddr*>(sinptr);+      ai->ai_addrlen = sizeof(sockaddr_in4_type);+      break;+    }+  case ASIO_OS_DEF(AF_INET6):+    {+      sockaddr_in6_type* sin6ptr = gai_alloc<sockaddr_in6_type>();+      if (sin6ptr == 0)+        return EAI_MEMORY;+      sin6ptr->sin6_family = ASIO_OS_DEF(AF_INET6);+      memcpy(&sin6ptr->sin6_addr, addr, sizeof(in6_addr_type));+      ai->ai_addr = reinterpret_cast<sockaddr*>(sin6ptr);+      ai->ai_addrlen = sizeof(sockaddr_in6_type);+      break;+    }+  default:+    break;+  }++  return 0;+}++inline addrinfo_type* gai_clone(addrinfo_type* ai)+{+  using namespace std;++  addrinfo_type* new_ai = gai_alloc<addrinfo_type>();+  if (new_ai == 0)+    return new_ai;++  new_ai->ai_next = ai->ai_next;+  ai->ai_next = new_ai;++  new_ai->ai_flags = 0;+  new_ai->ai_family = ai->ai_family;+  new_ai->ai_socktype = ai->ai_socktype;+  new_ai->ai_protocol = ai->ai_protocol;+  new_ai->ai_canonname = 0;+  new_ai->ai_addrlen = ai->ai_addrlen;+  new_ai->ai_addr = gai_alloc<sockaddr>(ai->ai_addrlen);+  memcpy(new_ai->ai_addr, ai->ai_addr, ai->ai_addrlen);++  return new_ai;+}++inline int gai_port(addrinfo_type* aihead, int port, int socktype)+{+  int num_found = 0;++  for (addrinfo_type* ai = aihead; ai; ai = ai->ai_next)+  {+    if (ai->ai_flags & gai_clone_flag)+    {+      if (ai->ai_socktype != 0)+      {+        ai = gai_clone(ai);+        if (ai == 0)+          return -1;+        // ai now points to newly cloned entry.+      }+    }+    else if (ai->ai_socktype != socktype)+    {+      // Ignore if mismatch on socket type.+      continue;+    }++    ai->ai_socktype = socktype;++    switch (ai->ai_family)+    {+    case ASIO_OS_DEF(AF_INET):+      {+        sockaddr_in4_type* sinptr =+          reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);+        sinptr->sin_port = port;+        ++num_found;+        break;+      }+    case ASIO_OS_DEF(AF_INET6):+      {+        sockaddr_in6_type* sin6ptr =+          reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);+        sin6ptr->sin6_port = port;+        ++num_found;+        break;+      }+    default:+      break;+    }+  }++  return num_found;+}++inline int gai_serv(addrinfo_type* aihead,+    const addrinfo_type* hints, const char* serv)+{+  using namespace std;++  int num_found = 0;++  if (+#if defined(AI_NUMERICSERV)+      (hints->ai_flags & AI_NUMERICSERV) ||+#endif+      isdigit(static_cast<unsigned char>(serv[0])))+  {+    int port = htons(atoi(serv));+    if (hints->ai_socktype)+    {+      // Caller specifies socket type.+      int rc = gai_port(aihead, port, hints->ai_socktype);+      if (rc < 0)+        return EAI_MEMORY;+      num_found += rc;+    }+    else+    {+      // Caller does not specify socket type.+      int rc = gai_port(aihead, port, SOCK_STREAM);+      if (rc < 0)+        return EAI_MEMORY;+      num_found += rc;+      rc = gai_port(aihead, port, SOCK_DGRAM);+      if (rc < 0)+        return EAI_MEMORY;+      num_found += rc;+    }+  }+  else+  {+    // Try service name with TCP first, then UDP.+    if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_STREAM)+    {+      servent* sptr = getservbyname(serv, "tcp");+      if (sptr != 0)+      {+        int rc = gai_port(aihead, sptr->s_port, SOCK_STREAM);+        if (rc < 0)+          return EAI_MEMORY;+        num_found += rc;+      }+    }+    if (hints->ai_socktype == 0 || hints->ai_socktype == SOCK_DGRAM)+    {+      servent* sptr = getservbyname(serv, "udp");+      if (sptr != 0)+      {+        int rc = gai_port(aihead, sptr->s_port, SOCK_DGRAM);+        if (rc < 0)+          return EAI_MEMORY;+        num_found += rc;+      }+    }+  }++  if (num_found == 0)+  {+    if (hints->ai_socktype == 0)+    {+      // All calls to getservbyname() failed.+      return EAI_NONAME;+    }+    else+    {+      // Service not supported for socket type.+      return EAI_SERVICE;+    }+  }++  return 0;+}++inline int gai_echeck(const char* host, const char* service,+    int flags, int family, int socktype, int protocol)+{+  (void)(flags);+  (void)(protocol);++  // Host or service must be specified.+  if (host == 0 || host[0] == '\0')+    if (service == 0 || service[0] == '\0')+      return EAI_NONAME;++  // Check combination of family and socket type.+  switch (family)+  {+  case ASIO_OS_DEF(AF_UNSPEC):+    break;+  case ASIO_OS_DEF(AF_INET):+  case ASIO_OS_DEF(AF_INET6):+    if (service != 0 && service[0] != '\0')+      if (socktype != 0 && socktype != SOCK_STREAM && socktype != SOCK_DGRAM)+        return EAI_SOCKTYPE;+    break;+  default:+    return EAI_FAMILY;+  }++  return 0;+}++inline void freeaddrinfo_emulation(addrinfo_type* aihead)+{+  addrinfo_type* ai = aihead;+  while (ai)+  {+    gai_free(ai->ai_addr);+    gai_free(ai->ai_canonname);+    addrinfo_type* ainext = ai->ai_next;+    gai_free(ai);+    ai = ainext;+  }+}++inline int getaddrinfo_emulation(const char* host, const char* service,+    const addrinfo_type* hintsp, addrinfo_type** result)+{+  // Set up linked list of addrinfo structures.+  addrinfo_type* aihead = 0;+  addrinfo_type** ainext = &aihead;+  char* canon = 0;++  // Supply default hints if not specified by caller.+  addrinfo_type hints = addrinfo_type();+  hints.ai_family = ASIO_OS_DEF(AF_UNSPEC);+  if (hintsp)+    hints = *hintsp;++  // If the resolution is not specifically for AF_INET6, remove the AI_V4MAPPED+  // and AI_ALL flags.+#if defined(AI_V4MAPPED)+  if (hints.ai_family != ASIO_OS_DEF(AF_INET6))+    hints.ai_flags &= ~AI_V4MAPPED;+#endif+#if defined(AI_ALL)+  if (hints.ai_family != ASIO_OS_DEF(AF_INET6))+    hints.ai_flags &= ~AI_ALL;+#endif++  // Basic error checking.+  int rc = gai_echeck(host, service, hints.ai_flags, hints.ai_family,+      hints.ai_socktype, hints.ai_protocol);+  if (rc != 0)+  {+    freeaddrinfo_emulation(aihead);+    return rc;+  }++  gai_search search[2];+  int search_count = gai_nsearch(host, &hints, search);+  for (gai_search* sptr = search; sptr < search + search_count; ++sptr)+  {+    // Check for IPv4 dotted decimal string.+    in4_addr_type inaddr;+    asio::error_code ec;+    if (socket_ops::inet_pton(ASIO_OS_DEF(AF_INET),+          sptr->host, &inaddr, 0, ec) == 1)+    {+      if (hints.ai_family != ASIO_OS_DEF(AF_UNSPEC)+          && hints.ai_family != ASIO_OS_DEF(AF_INET))+      {+        freeaddrinfo_emulation(aihead);+        gai_free(canon);+        return EAI_FAMILY;+      }+      if (sptr->family == ASIO_OS_DEF(AF_INET))+      {+        rc = gai_aistruct(&ainext, &hints, &inaddr, ASIO_OS_DEF(AF_INET));+        if (rc != 0)+        {+          freeaddrinfo_emulation(aihead);+          gai_free(canon);+          return rc;+        }+      }+      continue;+    }++    // Check for IPv6 hex string.+    in6_addr_type in6addr;+    if (socket_ops::inet_pton(ASIO_OS_DEF(AF_INET6),+          sptr->host, &in6addr, 0, ec) == 1)+    {+      if (hints.ai_family != ASIO_OS_DEF(AF_UNSPEC)+          && hints.ai_family != ASIO_OS_DEF(AF_INET6))+      {+        freeaddrinfo_emulation(aihead);+        gai_free(canon);+        return EAI_FAMILY;+      }+      if (sptr->family == ASIO_OS_DEF(AF_INET6))+      {+        rc = gai_aistruct(&ainext, &hints, &in6addr,+            ASIO_OS_DEF(AF_INET6));+        if (rc != 0)+        {+          freeaddrinfo_emulation(aihead);+          gai_free(canon);+          return rc;+        }+      }+      continue;+    }++    // Look up hostname.+    hostent hent;+    char hbuf[8192] = "";+    hostent* hptr = socket_ops::gethostbyname(sptr->host,+        sptr->family, &hent, hbuf, sizeof(hbuf), hints.ai_flags, ec);+    if (hptr == 0)+    {+      if (search_count == 2)+      {+        // Failure is OK if there are multiple searches.+        continue;+      }+      freeaddrinfo_emulation(aihead);+      gai_free(canon);+      if (ec == asio::error::host_not_found)+        return EAI_NONAME;+      if (ec == asio::error::host_not_found_try_again)+        return EAI_AGAIN;+      if (ec == asio::error::no_recovery)+        return EAI_FAIL;+      if (ec == asio::error::no_data)+        return EAI_NONAME;+      return EAI_NONAME;+    }++    // Check for address family mismatch if one was specified.+    if (hints.ai_family != ASIO_OS_DEF(AF_UNSPEC)+        && hints.ai_family != hptr->h_addrtype)+    {+      freeaddrinfo_emulation(aihead);+      gai_free(canon);+      socket_ops::freehostent(hptr);+      return EAI_FAMILY;+    }++    // Save canonical name first time.+    if (host != 0 && host[0] != '\0' && hptr->h_name && hptr->h_name[0]+        && (hints.ai_flags & AI_CANONNAME) && canon == 0)+    {+      std::size_t canon_len = strlen(hptr->h_name) + 1;+      canon = gai_alloc<char>(canon_len);+      if (canon == 0)+      {+        freeaddrinfo_emulation(aihead);+        socket_ops::freehostent(hptr);+        return EAI_MEMORY;+      }+      gai_strcpy(canon, hptr->h_name, canon_len);+    }++    // Create an addrinfo structure for each returned address.+    for (char** ap = hptr->h_addr_list; *ap; ++ap)+    {+      rc = gai_aistruct(&ainext, &hints, *ap, hptr->h_addrtype);+      if (rc != 0)+      {+        freeaddrinfo_emulation(aihead);+        gai_free(canon);+        socket_ops::freehostent(hptr);+        return EAI_FAMILY;+      }+    }++    socket_ops::freehostent(hptr);+  }++  // Check if we found anything.+  if (aihead == 0)+  {+    gai_free(canon);+    return EAI_NONAME;+  }++  // Return canonical name in first entry.+  if (host != 0 && host[0] != '\0' && (hints.ai_flags & AI_CANONNAME))+  {+    if (canon)+    {+      aihead->ai_canonname = canon;+      canon = 0;+    }+    else+    {+      std::size_t canonname_len = strlen(search[0].host) + 1;+      aihead->ai_canonname = gai_alloc<char>(canonname_len);+      if (aihead->ai_canonname == 0)+      {+        freeaddrinfo_emulation(aihead);+        return EAI_MEMORY;+      }+      gai_strcpy(aihead->ai_canonname, search[0].host, canonname_len);+    }+  }+  gai_free(canon);++  // Process the service name.+  if (service != 0 && service[0] != '\0')+  {+    rc = gai_serv(aihead, &hints, service);+    if (rc != 0)+    {+      freeaddrinfo_emulation(aihead);+      return rc;+    }+  }++  // Return result to caller.+  *result = aihead;+  return 0;+}++inline asio::error_code getnameinfo_emulation(+    const socket_addr_type* sa, std::size_t salen, char* host,+    std::size_t hostlen, char* serv, std::size_t servlen, int flags,+    asio::error_code& ec)+{+  using namespace std;++  const char* addr;+  size_t addr_len;+  unsigned short port;+  switch (sa->sa_family)+  {+  case ASIO_OS_DEF(AF_INET):+    if (salen != sizeof(sockaddr_in4_type))+    {+      return ec = asio::error::invalid_argument;+    }+    addr = reinterpret_cast<const char*>(+        &reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_addr);+    addr_len = sizeof(in4_addr_type);+    port = reinterpret_cast<const sockaddr_in4_type*>(sa)->sin_port;+    break;+  case ASIO_OS_DEF(AF_INET6):+    if (salen != sizeof(sockaddr_in6_type))+    {+      return ec = asio::error::invalid_argument;+    }+    addr = reinterpret_cast<const char*>(+        &reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_addr);+    addr_len = sizeof(in6_addr_type);+    port = reinterpret_cast<const sockaddr_in6_type*>(sa)->sin6_port;+    break;+  default:+    return ec = asio::error::address_family_not_supported;+  }++  if (host && hostlen > 0)+  {+    if (flags & NI_NUMERICHOST)+    {+      if (socket_ops::inet_ntop(sa->sa_family, addr, host, hostlen, 0, ec) == 0)+      {+        return ec;+      }+    }+    else+    {+      hostent hent;+      char hbuf[8192] = "";+      hostent* hptr = socket_ops::gethostbyaddr(addr,+          static_cast<int>(addr_len), sa->sa_family,+          &hent, hbuf, sizeof(hbuf), ec);+      if (hptr && hptr->h_name && hptr->h_name[0] != '\0')+      {+        if (flags & NI_NOFQDN)+        {+          char* dot = strchr(hptr->h_name, '.');+          if (dot)+          {+            *dot = 0;+          }+        }+        gai_strcpy(host, hptr->h_name, hostlen);+        socket_ops::freehostent(hptr);+      }+      else+      {+        socket_ops::freehostent(hptr);+        if (flags & NI_NAMEREQD)+        {+          return ec = asio::error::host_not_found;+        }+        if (socket_ops::inet_ntop(sa->sa_family,+              addr, host, hostlen, 0, ec) == 0)+        {+          return ec;+        }+      }+    }+  }++  if (serv && servlen > 0)+  {+    if (flags & NI_NUMERICSERV)+    {+      if (servlen < 6)+      {+        return ec = asio::error::no_buffer_space;+      }+#if defined(ASIO_HAS_SECURE_RTL)+      sprintf_s(serv, servlen, "%u", ntohs(port));+#else // defined(ASIO_HAS_SECURE_RTL)+      sprintf(serv, "%u", ntohs(port));+#endif // defined(ASIO_HAS_SECURE_RTL)+    }+    else+    {+#if defined(ASIO_HAS_PTHREADS)+      static ::pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;+      ::pthread_mutex_lock(&mutex);+#endif // defined(ASIO_HAS_PTHREADS)+      servent* sptr = ::getservbyport(port, (flags & NI_DGRAM) ? "udp" : 0);+      if (sptr && sptr->s_name && sptr->s_name[0] != '\0')+      {+        gai_strcpy(serv, sptr->s_name, servlen);+      }+      else+      {+        if (servlen < 6)+        {+          return ec = asio::error::no_buffer_space;+        }+#if defined(ASIO_HAS_SECURE_RTL)+        sprintf_s(serv, servlen, "%u", ntohs(port));+#else // defined(ASIO_HAS_SECURE_RTL)+        sprintf(serv, "%u", ntohs(port));+#endif // defined(ASIO_HAS_SECURE_RTL)+      }+#if defined(ASIO_HAS_PTHREADS)+      ::pthread_mutex_unlock(&mutex);+#endif // defined(ASIO_HAS_PTHREADS)+    }+  }++  ec.assign(0, ec.category());+  return ec;+}++#endif // !defined(ASIO_HAS_GETADDRINFO)++inline asio::error_code translate_addrinfo_error(int error)+{+  switch (error)+  {+  case 0:+    return asio::error_code();+  case EAI_AGAIN:+    return asio::error::host_not_found_try_again;+  case EAI_BADFLAGS:+    return asio::error::invalid_argument;+  case EAI_FAIL:+    return asio::error::no_recovery;+  case EAI_FAMILY:+    return asio::error::address_family_not_supported;+  case EAI_MEMORY:+    return asio::error::no_memory;+  case EAI_NONAME:+#if defined(EAI_ADDRFAMILY)+  case EAI_ADDRFAMILY:+#endif+#if defined(EAI_NODATA) && (EAI_NODATA != EAI_NONAME)+  case EAI_NODATA:+#endif+    return asio::error::host_not_found;+  case EAI_SERVICE:+    return asio::error::service_not_found;+  case EAI_SOCKTYPE:+    return asio::error::socket_type_not_supported;+  default: // Possibly the non-portable EAI_SYSTEM.+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+    return asio::error_code(+        WSAGetLastError(), asio::error::get_system_category());+#else+    return asio::error_code(+        errno, asio::error::get_system_category());+#endif+  }+}++asio::error_code getaddrinfo(const char* host,+    const char* service, const addrinfo_type& hints,+    addrinfo_type** result, asio::error_code& ec)+{+  host = (host && *host) ? host : 0;+  service = (service && *service) ? service : 0;+  clear_last_error();+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# if defined(ASIO_HAS_GETADDRINFO)+  // Building for Windows XP, Windows Server 2003, or later.+  int error = ::getaddrinfo(host, service, &hints, result);+  return ec = translate_addrinfo_error(error);+# else+  // Building for Windows 2000 or earlier.+  typedef int (WSAAPI *gai_t)(const char*,+      const char*, const addrinfo_type*, addrinfo_type**);+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))+  {+    if (gai_t gai = (gai_t)::GetProcAddress(winsock_module, "getaddrinfo"))+    {+      int error = gai(host, service, &hints, result);+      return ec = translate_addrinfo_error(error);+    }+  }+  int error = getaddrinfo_emulation(host, service, &hints, result);+  return ec = translate_addrinfo_error(error);+# endif+#elif !defined(ASIO_HAS_GETADDRINFO)+  int error = getaddrinfo_emulation(host, service, &hints, result);+  return ec = translate_addrinfo_error(error);+#else+  int error = ::getaddrinfo(host, service, &hints, result);+#if defined(__MACH__) && defined(__APPLE__)+  using namespace std; // For isdigit and atoi.+  if (error == 0 && service && isdigit(static_cast<unsigned char>(service[0])))+  {+    u_short_type port = host_to_network_short(atoi(service));+    for (addrinfo_type* ai = *result; ai; ai = ai->ai_next)+    {+      switch (ai->ai_family)+      {+      case ASIO_OS_DEF(AF_INET):+        {+          sockaddr_in4_type* sinptr =+            reinterpret_cast<sockaddr_in4_type*>(ai->ai_addr);+          if (sinptr->sin_port == 0)+            sinptr->sin_port = port;+          break;+        }+      case ASIO_OS_DEF(AF_INET6):+        {+          sockaddr_in6_type* sin6ptr =+            reinterpret_cast<sockaddr_in6_type*>(ai->ai_addr);+          if (sin6ptr->sin6_port == 0)+            sin6ptr->sin6_port = port;+          break;+        }+      default:+        break;+      }+    }+  }+#endif+  return ec = translate_addrinfo_error(error);+#endif+}++asio::error_code background_getaddrinfo(+    const weak_cancel_token_type& cancel_token, const char* host,+    const char* service, const addrinfo_type& hints,+    addrinfo_type** result, asio::error_code& ec)+{+  if (cancel_token.expired())+    ec = asio::error::operation_aborted;+  else+    socket_ops::getaddrinfo(host, service, hints, result, ec);+  return ec;+}++void freeaddrinfo(addrinfo_type* ai)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# if defined(ASIO_HAS_GETADDRINFO)+  // Building for Windows XP, Windows Server 2003, or later.+  ::freeaddrinfo(ai);+# else+  // Building for Windows 2000 or earlier.+  typedef int (WSAAPI *fai_t)(addrinfo_type*);+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))+  {+    if (fai_t fai = (fai_t)::GetProcAddress(winsock_module, "freeaddrinfo"))+    {+      fai(ai);+      return;+    }+  }+  freeaddrinfo_emulation(ai);+# endif+#elif !defined(ASIO_HAS_GETADDRINFO)+  freeaddrinfo_emulation(ai);+#else+  ::freeaddrinfo(ai);+#endif+}++asio::error_code getnameinfo(const socket_addr_type* addr,+    std::size_t addrlen, char* host, std::size_t hostlen,+    char* serv, std::size_t servlen, int flags, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# if defined(ASIO_HAS_GETADDRINFO)+  // Building for Windows XP, Windows Server 2003, or later.+  clear_last_error();+  int error = ::getnameinfo(addr, static_cast<socklen_t>(addrlen),+      host, static_cast<DWORD>(hostlen),+      serv, static_cast<DWORD>(servlen), flags);+  return ec = translate_addrinfo_error(error);+# else+  // Building for Windows 2000 or earlier.+  typedef int (WSAAPI *gni_t)(const socket_addr_type*,+      int, char*, DWORD, char*, DWORD, int);+  if (HMODULE winsock_module = ::GetModuleHandleA("ws2_32"))+  {+    if (gni_t gni = (gni_t)::GetProcAddress(winsock_module, "getnameinfo"))+    {+      clear_last_error();+      int error = gni(addr, static_cast<int>(addrlen),+          host, static_cast<DWORD>(hostlen),+          serv, static_cast<DWORD>(servlen), flags);+      return ec = translate_addrinfo_error(error);+    }+  }+  clear_last_error();+  return getnameinfo_emulation(addr, addrlen,+      host, hostlen, serv, servlen, flags, ec);+# endif+#elif !defined(ASIO_HAS_GETADDRINFO)+  using namespace std; // For memcpy.+  sockaddr_storage_type tmp_addr;+  memcpy(&tmp_addr, addr, addrlen);+  addr = reinterpret_cast<socket_addr_type*>(&tmp_addr);+  clear_last_error();+  return getnameinfo_emulation(addr, addrlen,+      host, hostlen, serv, servlen, flags, ec);+#else+  clear_last_error();+  int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);+  return ec = translate_addrinfo_error(error);+#endif+}++asio::error_code sync_getnameinfo(+    const socket_addr_type* addr, std::size_t addrlen,+    char* host, std::size_t hostlen, char* serv,+    std::size_t servlen, int sock_type, asio::error_code& ec)+{+  // First try resolving with the service name. If that fails try resolving+  // but allow the service to be returned as a number.+  int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0;+  socket_ops::getnameinfo(addr, addrlen, host,+      hostlen, serv, servlen, flags, ec);+  if (ec)+  {+    socket_ops::getnameinfo(addr, addrlen, host, hostlen,+        serv, servlen, flags | NI_NUMERICSERV, ec);+  }++  return ec;+}++asio::error_code background_getnameinfo(+    const weak_cancel_token_type& cancel_token,+    const socket_addr_type* addr, std::size_t addrlen,+    char* host, std::size_t hostlen, char* serv,+    std::size_t servlen, int sock_type, asio::error_code& ec)+{+  if (cancel_token.expired())+  {+    ec = asio::error::operation_aborted;+  }+  else+  {+    // First try resolving with the service name. If that fails try resolving+    // but allow the service to be returned as a number.+    int flags = (sock_type == SOCK_DGRAM) ? NI_DGRAM : 0;+    socket_ops::getnameinfo(addr, addrlen, host,+        hostlen, serv, servlen, flags, ec);+    if (ec)+    {+      socket_ops::getnameinfo(addr, addrlen, host, hostlen,+          serv, servlen, flags | NI_NUMERICSERV, ec);+    }+  }++  return ec;+}++#endif // !defined(ASIO_WINDOWS_RUNTIME)++u_long_type network_to_host_long(u_long_type value)+{+#if defined(ASIO_WINDOWS_RUNTIME)+  unsigned char* value_p = reinterpret_cast<unsigned char*>(&value);+  u_long_type result = (static_cast<u_long_type>(value_p[0]) << 24)+    | (static_cast<u_long_type>(value_p[1]) << 16)+    | (static_cast<u_long_type>(value_p[2]) << 8)+    | static_cast<u_long_type>(value_p[3]);+  return result;+#else // defined(ASIO_WINDOWS_RUNTIME)+  return ntohl(value);+#endif // defined(ASIO_WINDOWS_RUNTIME)+}++u_long_type host_to_network_long(u_long_type value)+{+#if defined(ASIO_WINDOWS_RUNTIME)+  u_long_type result;+  unsigned char* result_p = reinterpret_cast<unsigned char*>(&result);+  result_p[0] = static_cast<unsigned char>((value >> 24) & 0xFF);+  result_p[1] = static_cast<unsigned char>((value >> 16) & 0xFF);+  result_p[2] = static_cast<unsigned char>((value >> 8) & 0xFF);+  result_p[3] = static_cast<unsigned char>(value & 0xFF);+  return result;+#else // defined(ASIO_WINDOWS_RUNTIME)+  return htonl(value);+#endif // defined(ASIO_WINDOWS_RUNTIME)+}++u_short_type network_to_host_short(u_short_type value)+{+#if defined(ASIO_WINDOWS_RUNTIME)+  unsigned char* value_p = reinterpret_cast<unsigned char*>(&value);+  u_short_type result = (static_cast<u_short_type>(value_p[0]) << 8)+    | static_cast<u_short_type>(value_p[1]);+  return result;+#else // defined(ASIO_WINDOWS_RUNTIME)+  return ntohs(value);+#endif // defined(ASIO_WINDOWS_RUNTIME)+}++u_short_type host_to_network_short(u_short_type value)+{+#if defined(ASIO_WINDOWS_RUNTIME)+  u_short_type result;+  unsigned char* result_p = reinterpret_cast<unsigned char*>(&result);+  result_p[0] = static_cast<unsigned char>((value >> 8) & 0xFF);+  result_p[1] = static_cast<unsigned char>(value & 0xFF);+  return result;+#else // defined(ASIO_WINDOWS_RUNTIME)+  return htons(value);+#endif // defined(ASIO_WINDOWS_RUNTIME)+}++} // namespace socket_ops+} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SOCKET_OPS_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/socket_select_interrupter.ipp view
@@ -0,0 +1,185 @@+//+// detail/impl/socket_select_interrupter.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP+#define ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if !defined(ASIO_WINDOWS_RUNTIME)++#if defined(ASIO_WINDOWS) \+  || defined(__CYGWIN__) \+  || defined(__SYMBIAN32__)++#include <cstdlib>+#include "asio/detail/socket_holder.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_select_interrupter.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++socket_select_interrupter::socket_select_interrupter()+{+  open_descriptors();+}++void socket_select_interrupter::open_descriptors()+{+  asio::error_code ec;+  socket_holder acceptor(socket_ops::socket(+        AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));+  if (acceptor.get() == invalid_socket)+    asio::detail::throw_error(ec, "socket_select_interrupter");++  int opt = 1;+  socket_ops::state_type acceptor_state = 0;+  socket_ops::setsockopt(acceptor.get(), acceptor_state,+      SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt), ec);++  using namespace std; // For memset.+  sockaddr_in4_type addr;+  std::size_t addr_len = sizeof(addr);+  memset(&addr, 0, sizeof(addr));+  addr.sin_family = AF_INET;+  addr.sin_addr.s_addr = socket_ops::host_to_network_long(INADDR_LOOPBACK);+  addr.sin_port = 0;+  if (socket_ops::bind(acceptor.get(), (const socket_addr_type*)&addr,+        addr_len, ec) == socket_error_retval)+    asio::detail::throw_error(ec, "socket_select_interrupter");++  if (socket_ops::getsockname(acceptor.get(), (socket_addr_type*)&addr,+        &addr_len, ec) == socket_error_retval)+    asio::detail::throw_error(ec, "socket_select_interrupter");++  // Some broken firewalls on Windows will intermittently cause getsockname to+  // return 0.0.0.0 when the socket is actually bound to 127.0.0.1. We+  // explicitly specify the target address here to work around this problem.+  if (addr.sin_addr.s_addr == socket_ops::host_to_network_long(INADDR_ANY))+    addr.sin_addr.s_addr = socket_ops::host_to_network_long(INADDR_LOOPBACK);++  if (socket_ops::listen(acceptor.get(),+        SOMAXCONN, ec) == socket_error_retval)+    asio::detail::throw_error(ec, "socket_select_interrupter");++  socket_holder client(socket_ops::socket(+        AF_INET, SOCK_STREAM, IPPROTO_TCP, ec));+  if (client.get() == invalid_socket)+    asio::detail::throw_error(ec, "socket_select_interrupter");++  if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,+        addr_len, ec) == socket_error_retval)+    asio::detail::throw_error(ec, "socket_select_interrupter");++  socket_holder server(socket_ops::accept(acceptor.get(), 0, 0, ec));+  if (server.get() == invalid_socket)+    asio::detail::throw_error(ec, "socket_select_interrupter");+  +  ioctl_arg_type non_blocking = 1;+  socket_ops::state_type client_state = 0;+  if (socket_ops::ioctl(client.get(), client_state,+        FIONBIO, &non_blocking, ec))+    asio::detail::throw_error(ec, "socket_select_interrupter");++  opt = 1;+  socket_ops::setsockopt(client.get(), client_state,+      IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);++  non_blocking = 1;+  socket_ops::state_type server_state = 0;+  if (socket_ops::ioctl(server.get(), server_state,+        FIONBIO, &non_blocking, ec))+    asio::detail::throw_error(ec, "socket_select_interrupter");++  opt = 1;+  socket_ops::setsockopt(server.get(), server_state,+      IPPROTO_TCP, TCP_NODELAY, &opt, sizeof(opt), ec);++  read_descriptor_ = server.release();+  write_descriptor_ = client.release();+}++socket_select_interrupter::~socket_select_interrupter()+{+  close_descriptors();+}++void socket_select_interrupter::close_descriptors()+{+  asio::error_code ec;+  socket_ops::state_type state = socket_ops::internal_non_blocking;+  if (read_descriptor_ != invalid_socket)+    socket_ops::close(read_descriptor_, state, true, ec);+  if (write_descriptor_ != invalid_socket)+    socket_ops::close(write_descriptor_, state, true, ec);+}++void socket_select_interrupter::recreate()+{+  close_descriptors();++  write_descriptor_ = invalid_socket;+  read_descriptor_ = invalid_socket;++  open_descriptors();+}++void socket_select_interrupter::interrupt()+{+  char byte = 0;+  socket_ops::buf b;+  socket_ops::init_buf(b, &byte, 1);+  asio::error_code ec;+  socket_ops::send(write_descriptor_, &b, 1, 0, ec);+}++bool socket_select_interrupter::reset()+{+  char data[1024];+  socket_ops::buf b;+  socket_ops::init_buf(b, data, sizeof(data));+  asio::error_code ec;+  for (;;)+  {+    int bytes_read = socket_ops::recv(read_descriptor_, &b, 1, 0, ec);+    if (bytes_read == sizeof(data))+      continue;+    if (bytes_read > 0)+      return true;+    if (bytes_read == 0)+      return false;+    if (ec == asio::error::would_block+        || ec == asio::error::try_again)+      return true;+    return false;+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS)+       // || defined(__CYGWIN__)+       // || defined(__SYMBIAN32__)++#endif // !defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_IMPL_SOCKET_SELECT_INTERRUPTER_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.hpp view
@@ -0,0 +1,385 @@+//+// detail/impl/strand_executor_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_HPP+#define ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/call_stack.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/executor_work_guard.hpp"+#include "asio/defer.hpp"+#include "asio/dispatch.hpp"+#include "asio/post.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename F, typename Allocator>+class strand_executor_service::allocator_binder+{+public:+  typedef Allocator allocator_type;++  allocator_binder(ASIO_MOVE_ARG(F) f, const Allocator& a)+    : f_(ASIO_MOVE_CAST(F)(f)),+      allocator_(a)+  {+  }++  allocator_binder(const allocator_binder& other)+    : f_(other.f_),+      allocator_(other.allocator_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  allocator_binder(allocator_binder&& other)+    : f_(ASIO_MOVE_CAST(F)(other.f_)),+      allocator_(ASIO_MOVE_CAST(allocator_type)(other.allocator_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  allocator_type get_allocator() const ASIO_NOEXCEPT+  {+    return allocator_;+  }++  void operator()()+  {+    f_();+  }++private:+  F f_;+  allocator_type allocator_;+};++template <typename Executor>+class strand_executor_service::invoker<Executor,+    typename enable_if<+      execution::is_executor<Executor>::value+    >::type>+{+public:+  invoker(const implementation_type& impl, Executor& ex)+    : impl_(impl),+      executor_(asio::prefer(ex, execution::outstanding_work.tracked))+  {+  }++  invoker(const invoker& other)+    : impl_(other.impl_),+      executor_(other.executor_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  invoker(invoker&& other)+    : impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_)),+      executor_(ASIO_MOVE_CAST(executor_type)(other.executor_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  struct on_invoker_exit+  {+    invoker* this_;++    ~on_invoker_exit()+    {+      this_->impl_->mutex_->lock();+      this_->impl_->ready_queue_.push(this_->impl_->waiting_queue_);+      bool more_handlers = this_->impl_->locked_ =+        !this_->impl_->ready_queue_.empty();+      this_->impl_->mutex_->unlock();++      if (more_handlers)+      {+        recycling_allocator<void> allocator;+        execution::execute(+            asio::prefer(+              asio::require(this_->executor_,+                execution::blocking.never),+            execution::allocator(allocator)),+            ASIO_MOVE_CAST(invoker)(*this_));+      }+    }+  };++  void operator()()+  {+    // Indicate that this strand is executing on the current thread.+    call_stack<strand_impl>::context ctx(impl_.get());++    // Ensure the next handler, if any, is scheduled on block exit.+    on_invoker_exit on_exit = { this };+    (void)on_exit;++    // Run all ready handlers. No lock is required since the ready queue is+    // accessed only within the strand.+    asio::error_code ec;+    while (scheduler_operation* o = impl_->ready_queue_.front())+    {+      impl_->ready_queue_.pop();+      o->complete(impl_.get(), ec, 0);+    }+  }++private:+  typedef typename decay<+      typename prefer_result<+        Executor,+        execution::outstanding_work_t::tracked_t+      >::type+    >::type executor_type;++  implementation_type impl_;+  executor_type executor_;+};++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Executor>+class strand_executor_service::invoker<Executor,+    typename enable_if<+      !execution::is_executor<Executor>::value+    >::type>+{+public:+  invoker(const implementation_type& impl, Executor& ex)+    : impl_(impl),+      work_(ex)+  {+  }++  invoker(const invoker& other)+    : impl_(other.impl_),+      work_(other.work_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  invoker(invoker&& other)+    : impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_)),+      work_(ASIO_MOVE_CAST(executor_work_guard<Executor>)(other.work_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  struct on_invoker_exit+  {+    invoker* this_;++    ~on_invoker_exit()+    {+      this_->impl_->mutex_->lock();+      this_->impl_->ready_queue_.push(this_->impl_->waiting_queue_);+      bool more_handlers = this_->impl_->locked_ =+        !this_->impl_->ready_queue_.empty();+      this_->impl_->mutex_->unlock();++      if (more_handlers)+      {+        Executor ex(this_->work_.get_executor());+        recycling_allocator<void> allocator;+        ex.post(ASIO_MOVE_CAST(invoker)(*this_), allocator);+      }+    }+  };++  void operator()()+  {+    // Indicate that this strand is executing on the current thread.+    call_stack<strand_impl>::context ctx(impl_.get());++    // Ensure the next handler, if any, is scheduled on block exit.+    on_invoker_exit on_exit = { this };+    (void)on_exit;++    // Run all ready handlers. No lock is required since the ready queue is+    // accessed only within the strand.+    asio::error_code ec;+    while (scheduler_operation* o = impl_->ready_queue_.front())+    {+      impl_->ready_queue_.pop();+      o->complete(impl_.get(), ec, 0);+    }+  }++private:+  implementation_type impl_;+  executor_work_guard<Executor> work_;+};++#endif // !defined(ASIO_NO_TS_EXECUTORS)++template <typename Executor, typename Function>+inline void strand_executor_service::execute(const implementation_type& impl,+    Executor& ex, ASIO_MOVE_ARG(Function) function,+    typename enable_if<+      can_query<Executor, execution::allocator_t<void> >::value+    >::type*)+{+  return strand_executor_service::do_execute(impl, ex,+      ASIO_MOVE_CAST(Function)(function),+      asio::query(ex, execution::allocator));+}++template <typename Executor, typename Function>+inline void strand_executor_service::execute(const implementation_type& impl,+    Executor& ex, ASIO_MOVE_ARG(Function) function,+    typename enable_if<+      !can_query<Executor, execution::allocator_t<void> >::value+    >::type*)+{+  return strand_executor_service::do_execute(impl, ex,+      ASIO_MOVE_CAST(Function)(function),+      std::allocator<void>());+}++template <typename Executor, typename Function, typename Allocator>+void strand_executor_service::do_execute(const implementation_type& impl,+    Executor& ex, ASIO_MOVE_ARG(Function) function, const Allocator& a)+{+  typedef typename decay<Function>::type function_type;++  // If the executor is not never-blocking, and we are already in the strand,+  // then the function can run immediately.+  if (asio::query(ex, execution::blocking) != execution::blocking.never+      && call_stack<strand_impl>::contains(impl.get()))+  {+    // Make a local, non-const copy of the function.+    function_type tmp(ASIO_MOVE_CAST(Function)(function));++    fenced_block b(fenced_block::full);+    asio_handler_invoke_helpers::invoke(tmp, tmp);+    return;+  }++  // Allocate and construct an operation to wrap the function.+  typedef executor_op<function_type, Allocator> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(function), a);++  ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,+        "strand_executor", impl.get(), 0, "execute"));++  // Add the function to the strand and schedule the strand if required.+  bool first = enqueue(impl, p.p);+  p.v = p.p = 0;+  if (first)+  {+    execution::execute(ex, invoker<Executor>(impl, ex));+  }+}++template <typename Executor, typename Function, typename Allocator>+void strand_executor_service::dispatch(const implementation_type& impl,+    Executor& ex, ASIO_MOVE_ARG(Function) function, const Allocator& a)+{+  typedef typename decay<Function>::type function_type;++  // If we are already in the strand then the function can run immediately.+  if (call_stack<strand_impl>::contains(impl.get()))+  {+    // Make a local, non-const copy of the function.+    function_type tmp(ASIO_MOVE_CAST(Function)(function));++    fenced_block b(fenced_block::full);+    asio_handler_invoke_helpers::invoke(tmp, tmp);+    return;+  }++  // Allocate and construct an operation to wrap the function.+  typedef executor_op<function_type, Allocator> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(function), a);++  ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,+        "strand_executor", impl.get(), 0, "dispatch"));++  // Add the function to the strand and schedule the strand if required.+  bool first = enqueue(impl, p.p);+  p.v = p.p = 0;+  if (first)+  {+    asio::dispatch(ex,+        allocator_binder<invoker<Executor>, Allocator>(+          invoker<Executor>(impl, ex), a));+  }+}++// Request invocation of the given function and return immediately.+template <typename Executor, typename Function, typename Allocator>+void strand_executor_service::post(const implementation_type& impl,+    Executor& ex, ASIO_MOVE_ARG(Function) function, const Allocator& a)+{+  typedef typename decay<Function>::type function_type;++  // Allocate and construct an operation to wrap the function.+  typedef executor_op<function_type, Allocator> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(function), a);++  ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,+        "strand_executor", impl.get(), 0, "post"));++  // Add the function to the strand and schedule the strand if required.+  bool first = enqueue(impl, p.p);+  p.v = p.p = 0;+  if (first)+  {+    asio::post(ex,+        allocator_binder<invoker<Executor>, Allocator>(+          invoker<Executor>(impl, ex), a));+  }+}++// Request invocation of the given function and return immediately.+template <typename Executor, typename Function, typename Allocator>+void strand_executor_service::defer(const implementation_type& impl,+    Executor& ex, ASIO_MOVE_ARG(Function) function, const Allocator& a)+{+  typedef typename decay<Function>::type function_type;++  // Allocate and construct an operation to wrap the function.+  typedef executor_op<function_type, Allocator> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(function), a);++  ASIO_HANDLER_CREATION((impl->service_->context(), *p.p,+        "strand_executor", impl.get(), 0, "defer"));++  // Add the function to the strand and schedule the strand if required.+  bool first = enqueue(impl, p.p);+  p.v = p.p = 0;+  if (first)+  {+    asio::defer(ex,+        allocator_binder<invoker<Executor>, Allocator>(+          invoker<Executor>(impl, ex), a));+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.ipp view
@@ -0,0 +1,134 @@+//+// detail/impl/strand_executor_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_IPP+#define ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/strand_executor_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++strand_executor_service::strand_executor_service(execution_context& ctx)+  : execution_context_service_base<strand_executor_service>(ctx),+    mutex_(),+    salt_(0),+    impl_list_(0)+{+}++void strand_executor_service::shutdown()+{+  op_queue<scheduler_operation> ops;++  asio::detail::mutex::scoped_lock lock(mutex_);++  strand_impl* impl = impl_list_;+  while (impl)+  {+    impl->mutex_->lock();+    impl->shutdown_ = true;+    ops.push(impl->waiting_queue_);+    ops.push(impl->ready_queue_);+    impl->mutex_->unlock();+    impl = impl->next_;+  }+}++strand_executor_service::implementation_type+strand_executor_service::create_implementation()+{+  implementation_type new_impl(new strand_impl);+  new_impl->locked_ = false;+  new_impl->shutdown_ = false;++  asio::detail::mutex::scoped_lock lock(mutex_);++  // Select a mutex from the pool of shared mutexes.+  std::size_t salt = salt_++;+  std::size_t mutex_index = reinterpret_cast<std::size_t>(new_impl.get());+  mutex_index += (reinterpret_cast<std::size_t>(new_impl.get()) >> 3);+  mutex_index ^= salt + 0x9e3779b9 + (mutex_index << 6) + (mutex_index >> 2);+  mutex_index = mutex_index % num_mutexes;+  if (!mutexes_[mutex_index].get())+    mutexes_[mutex_index].reset(new mutex);+  new_impl->mutex_ = mutexes_[mutex_index].get();++  // Insert implementation into linked list of all implementations.+  new_impl->next_ = impl_list_;+  new_impl->prev_ = 0;+  if (impl_list_)+    impl_list_->prev_ = new_impl.get();+  impl_list_ = new_impl.get();+  new_impl->service_ = this;++  return new_impl;+}++strand_executor_service::strand_impl::~strand_impl()+{+  asio::detail::mutex::scoped_lock lock(service_->mutex_);++  // Remove implementation from linked list of all implementations.+  if (service_->impl_list_ == this)+    service_->impl_list_ = next_;+  if (prev_)+    prev_->next_ = next_;+  if (next_)+    next_->prev_= prev_;+}++bool strand_executor_service::enqueue(const implementation_type& impl,+    scheduler_operation* op)+{+  impl->mutex_->lock();+  if (impl->shutdown_)+  {+    impl->mutex_->unlock();+    op->destroy();+    return false;+  }+  else if (impl->locked_)+  {+    // Some other function already holds the strand lock. Enqueue for later.+    impl->waiting_queue_.push(op);+    impl->mutex_->unlock();+    return false;+  }+  else+  {+    // The function is acquiring the strand lock and so is responsible for+    // scheduling the strand.+    impl->locked_ = true;+    impl->mutex_->unlock();+    impl->ready_queue_.push(op);+    return true;+  }+}++bool strand_executor_service::running_in_this_thread(+    const implementation_type& impl)+{+  return !!call_stack<strand_impl>::contains(impl.get());+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_STRAND_EXECUTOR_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.hpp view
@@ -0,0 +1,117 @@+//+// detail/impl/strand_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP+#define ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/call_stack.hpp"+#include "asio/detail/completion_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++inline strand_service::strand_impl::strand_impl()+  : operation(&strand_service::do_complete),+    locked_(false)+{+}++struct strand_service::on_dispatch_exit+{+  io_context_impl* io_context_impl_;+  strand_impl* impl_;++  ~on_dispatch_exit()+  {+    impl_->mutex_.lock();+    impl_->ready_queue_.push(impl_->waiting_queue_);+    bool more_handlers = impl_->locked_ = !impl_->ready_queue_.empty();+    impl_->mutex_.unlock();++    if (more_handlers)+      io_context_impl_->post_immediate_completion(impl_, false);+  }+};++template <typename Handler>+void strand_service::dispatch(strand_service::implementation_type& impl,+    Handler& handler)+{+  // If we are already in the strand then the handler can run immediately.+  if (call_stack<strand_impl>::contains(impl))+  {+    fenced_block b(fenced_block::full);+    asio_handler_invoke_helpers::invoke(handler, handler);+    return;+  }++  // Allocate and construct an operation to wrap the handler.+  typedef completion_handler<Handler, io_context::executor_type> op;+  typename op::ptr p = { asio::detail::addressof(handler),+    op::ptr::allocate(handler), 0 };+  p.p = new (p.v) op(handler, io_context_.get_executor());++  ASIO_HANDLER_CREATION((this->context(),+        *p.p, "strand", impl, 0, "dispatch"));++  bool dispatch_immediately = do_dispatch(impl, p.p);+  operation* o = p.p;+  p.v = p.p = 0;++  if (dispatch_immediately)+  {+    // Indicate that this strand is executing on the current thread.+    call_stack<strand_impl>::context ctx(impl);++    // Ensure the next handler, if any, is scheduled on block exit.+    on_dispatch_exit on_exit = { &io_context_impl_, impl };+    (void)on_exit;++    op::do_complete(&io_context_impl_, o, asio::error_code(), 0);+  }+}++// Request the io_context to invoke the given handler and return immediately.+template <typename Handler>+void strand_service::post(strand_service::implementation_type& impl,+    Handler& handler)+{+  bool is_continuation =+    asio_handler_cont_helpers::is_continuation(handler);++  // Allocate and construct an operation to wrap the handler.+  typedef completion_handler<Handler, io_context::executor_type> op;+  typename op::ptr p = { asio::detail::addressof(handler),+    op::ptr::allocate(handler), 0 };+  p.p = new (p.v) op(handler, io_context_.get_executor());++  ASIO_HANDLER_CREATION((this->context(),+        *p.p, "strand", impl, 0, "post"));++  do_post(impl, p.p, is_continuation);+  p.v = p.p = 0;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_STRAND_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.ipp view
@@ -0,0 +1,178 @@+//+// detail/impl/strand_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP+#define ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/call_stack.hpp"+#include "asio/detail/strand_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct strand_service::on_do_complete_exit+{+  io_context_impl* owner_;+  strand_impl* impl_;++  ~on_do_complete_exit()+  {+    impl_->mutex_.lock();+    impl_->ready_queue_.push(impl_->waiting_queue_);+    bool more_handlers = impl_->locked_ = !impl_->ready_queue_.empty();+    impl_->mutex_.unlock();++    if (more_handlers)+      owner_->post_immediate_completion(impl_, true);+  }+};++strand_service::strand_service(asio::io_context& io_context)+  : asio::detail::service_base<strand_service>(io_context),+    io_context_(io_context),+    io_context_impl_(asio::use_service<io_context_impl>(io_context)),+    mutex_(),+    salt_(0)+{+}++void strand_service::shutdown()+{+  op_queue<operation> ops;++  asio::detail::mutex::scoped_lock lock(mutex_);++  for (std::size_t i = 0; i < num_implementations; ++i)+  {+    if (strand_impl* impl = implementations_[i].get())+    {+      ops.push(impl->waiting_queue_);+      ops.push(impl->ready_queue_);+    }+  }+}++void strand_service::construct(strand_service::implementation_type& impl)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  std::size_t salt = salt_++;+#if defined(ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)+  std::size_t index = salt;+#else // defined(ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)+  std::size_t index = reinterpret_cast<std::size_t>(&impl);+  index += (reinterpret_cast<std::size_t>(&impl) >> 3);+  index ^= salt + 0x9e3779b9 + (index << 6) + (index >> 2);+#endif // defined(ASIO_ENABLE_SEQUENTIAL_STRAND_ALLOCATION)+  index = index % num_implementations;++  if (!implementations_[index].get())+    implementations_[index].reset(new strand_impl);+  impl = implementations_[index].get();+}++bool strand_service::running_in_this_thread(+    const implementation_type& impl) const+{+  return call_stack<strand_impl>::contains(impl) != 0;+}++bool strand_service::do_dispatch(implementation_type& impl, operation* op)+{+  // If we are running inside the io_context, and no other handler already+  // holds the strand lock, then the handler can run immediately.+  bool can_dispatch = io_context_impl_.can_dispatch();+  impl->mutex_.lock();+  if (can_dispatch && !impl->locked_)+  {+    // Immediate invocation is allowed.+    impl->locked_ = true;+    impl->mutex_.unlock();+    return true;+  }++  if (impl->locked_)+  {+    // Some other handler already holds the strand lock. Enqueue for later.+    impl->waiting_queue_.push(op);+    impl->mutex_.unlock();+  }+  else+  {+    // The handler is acquiring the strand lock and so is responsible for+    // scheduling the strand.+    impl->locked_ = true;+    impl->mutex_.unlock();+    impl->ready_queue_.push(op);+    io_context_impl_.post_immediate_completion(impl, false);+  }++  return false;+}++void strand_service::do_post(implementation_type& impl,+    operation* op, bool is_continuation)+{+  impl->mutex_.lock();+  if (impl->locked_)+  {+    // Some other handler already holds the strand lock. Enqueue for later.+    impl->waiting_queue_.push(op);+    impl->mutex_.unlock();+  }+  else+  {+    // The handler is acquiring the strand lock and so is responsible for+    // scheduling the strand.+    impl->locked_ = true;+    impl->mutex_.unlock();+    impl->ready_queue_.push(op);+    io_context_impl_.post_immediate_completion(impl, is_continuation);+  }+}++void strand_service::do_complete(void* owner, operation* base,+    const asio::error_code& ec, std::size_t /*bytes_transferred*/)+{+  if (owner)+  {+    strand_impl* impl = static_cast<strand_impl*>(base);++    // Indicate that this strand is executing on the current thread.+    call_stack<strand_impl>::context ctx(impl);++    // Ensure the next handler, if any, is scheduled on block exit.+    on_do_complete_exit on_exit;+    on_exit.owner_ = static_cast<io_context_impl*>(owner);+    on_exit.impl_ = impl;++    // Run all ready handlers. No lock is required since the ready queue is+    // accessed only within the strand.+    while (operation* o = impl->ready_queue_.front())+    {+      impl->ready_queue_.pop();+      o->complete(owner, ec, 0);+    }+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_STRAND_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/throw_error.ipp view
@@ -0,0 +1,60 @@+//+// detail/impl/throw_error.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_THROW_ERROR_IPP+#define ASIO_DETAIL_IMPL_THROW_ERROR_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/system_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++void do_throw_error(const asio::error_code& err)+{+  asio::system_error e(err);+  asio::detail::throw_exception(e);+}++void do_throw_error(const asio::error_code& err, const char* location)+{+  // boostify: non-boost code starts here+#if defined(ASIO_MSVC) && defined(ASIO_HAS_STD_SYSTEM_ERROR)+  // Microsoft's implementation of std::system_error is non-conformant in that+  // it ignores the error code's message when a "what" string is supplied. We'll+  // work around this by explicitly formatting the "what" string.+  std::string what_msg = location;+  what_msg += ": ";+  what_msg += err.message();+  asio::system_error e(err, what_msg);+  asio::detail::throw_exception(e);+#else // defined(ASIO_MSVC) && defined(ASIO_HAS_STD_SYSTEM_ERROR)+  // boostify: non-boost code ends here+  asio::system_error e(err, location);+  asio::detail::throw_exception(e);+  // boostify: non-boost code starts here+#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_STD_SYSTEM_ERROR)+  // boostify: non-boost code ends here+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_THROW_ERROR_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_ptime.ipp view
@@ -0,0 +1,91 @@+//+// detail/impl/timer_queue_ptime.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_TIMER_QUEUE_PTIME_IPP+#define ASIO_DETAIL_IMPL_TIMER_QUEUE_PTIME_IPP++#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)++#include "asio/detail/timer_queue_ptime.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++timer_queue<time_traits<boost::posix_time::ptime> >::timer_queue()+{+}++timer_queue<time_traits<boost::posix_time::ptime> >::~timer_queue()+{+}++bool timer_queue<time_traits<boost::posix_time::ptime> >::enqueue_timer(+    const time_type& time, per_timer_data& timer, wait_op* op)+{+  return impl_.enqueue_timer(time, timer, op);+}++bool timer_queue<time_traits<boost::posix_time::ptime> >::empty() const+{+  return impl_.empty();+}++long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_msec(+    long max_duration) const+{+  return impl_.wait_duration_msec(max_duration);+}++long timer_queue<time_traits<boost::posix_time::ptime> >::wait_duration_usec(+    long max_duration) const+{+  return impl_.wait_duration_usec(max_duration);+}++void timer_queue<time_traits<boost::posix_time::ptime> >::get_ready_timers(+    op_queue<operation>& ops)+{+  impl_.get_ready_timers(ops);+}++void timer_queue<time_traits<boost::posix_time::ptime> >::get_all_timers(+    op_queue<operation>& ops)+{+  impl_.get_all_timers(ops);+}++std::size_t timer_queue<time_traits<boost::posix_time::ptime> >::cancel_timer(+    per_timer_data& timer, op_queue<operation>& ops, std::size_t max_cancelled)+{+  return impl_.cancel_timer(timer, ops, max_cancelled);+}++void timer_queue<time_traits<boost::posix_time::ptime> >::move_timer(+    per_timer_data& target, per_timer_data& source)+{+  impl_.move_timer(target, source);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_BOOST_DATE_TIME)++#endif // ASIO_DETAIL_IMPL_TIMER_QUEUE_PTIME_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_set.ipp view
@@ -0,0 +1,101 @@+//+// detail/impl/timer_queue_set.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP+#define ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/timer_queue_set.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++timer_queue_set::timer_queue_set()+  : first_(0)+{+}++void timer_queue_set::insert(timer_queue_base* q)+{+  q->next_ = first_;+  first_ = q;+}++void timer_queue_set::erase(timer_queue_base* q)+{+  if (first_)+  {+    if (q == first_)+    {+      first_ = q->next_;+      q->next_ = 0;+      return;+    }++    for (timer_queue_base* p = first_; p->next_; p = p->next_)+    {+      if (p->next_ == q)+      {+        p->next_ = q->next_;+        q->next_ = 0;+        return;+      }+    }+  }+}++bool timer_queue_set::all_empty() const+{+  for (timer_queue_base* p = first_; p; p = p->next_)+    if (!p->empty())+      return false;+  return true;+}++long timer_queue_set::wait_duration_msec(long max_duration) const+{+  long min_duration = max_duration;+  for (timer_queue_base* p = first_; p; p = p->next_)+    min_duration = p->wait_duration_msec(min_duration);+  return min_duration;+}++long timer_queue_set::wait_duration_usec(long max_duration) const+{+  long min_duration = max_duration;+  for (timer_queue_base* p = first_; p; p = p->next_)+    min_duration = p->wait_duration_usec(min_duration);+  return min_duration;+}++void timer_queue_set::get_ready_timers(op_queue<operation>& ops)+{+  for (timer_queue_base* p = first_; p; p = p->next_)+    p->get_ready_timers(ops);+}++void timer_queue_set::get_all_timers(op_queue<operation>& ops)+{+  for (timer_queue_base* p = first_; p; p = p->next_)+    p->get_all_timers(ops);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_TIMER_QUEUE_SET_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_event.ipp view
@@ -0,0 +1,76 @@+//+// detail/win_event.ipp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_EVENT_IPP+#define ASIO_DETAIL_IMPL_WIN_EVENT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS)++#include "asio/detail/throw_error.hpp"+#include "asio/detail/win_event.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++win_event::win_event()+  : state_(0)+{+#if defined(ASIO_WINDOWS_APP)+  events_[0] = ::CreateEventExW(0, 0,+      CREATE_EVENT_MANUAL_RESET, EVENT_ALL_ACCESS);+#else // defined(ASIO_WINDOWS_APP)+  events_[0] = ::CreateEventW(0, true, false, 0);+#endif // defined(ASIO_WINDOWS_APP)+  if (!events_[0])+  {+    DWORD last_error = ::GetLastError();+    asio::error_code ec(last_error,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "event");+  }++#if defined(ASIO_WINDOWS_APP)+  events_[1] = ::CreateEventExW(0, 0, 0, EVENT_ALL_ACCESS);+#else // defined(ASIO_WINDOWS_APP)+  events_[1] = ::CreateEventW(0, false, false, 0);+#endif // defined(ASIO_WINDOWS_APP)+  if (!events_[1])+  {+    DWORD last_error = ::GetLastError();+    ::CloseHandle(events_[0]);+    asio::error_code ec(last_error,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "event");+  }+}++win_event::~win_event()+{+  ::CloseHandle(events_[0]);+  ::CloseHandle(events_[1]);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS)++#endif // ASIO_DETAIL_IMPL_WIN_EVENT_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_handle_service.ipp view
@@ -0,0 +1,525 @@+//+// detail/impl/win_iocp_handle_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP+#define ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP++#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_IOCP)++#include "asio/detail/win_iocp_handle_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class win_iocp_handle_service::overlapped_wrapper+  : public OVERLAPPED+{+public:+  explicit overlapped_wrapper(asio::error_code& ec)+  {+    Internal = 0;+    InternalHigh = 0;+    Offset = 0;+    OffsetHigh = 0;++    // Create a non-signalled manual-reset event, for GetOverlappedResult.+    hEvent = ::CreateEventW(0, TRUE, FALSE, 0);+    if (hEvent)+    {+      // As documented in GetQueuedCompletionStatus, setting the low order+      // bit of this event prevents our synchronous writes from being treated+      // as completion port events.+      DWORD_PTR tmp = reinterpret_cast<DWORD_PTR>(hEvent);+      hEvent = reinterpret_cast<HANDLE>(tmp | 1);+    }+    else+    {+      DWORD last_error = ::GetLastError();+      ec = asio::error_code(last_error,+          asio::error::get_system_category());+    }+  }++  ~overlapped_wrapper()+  {+    if (hEvent)+    {+      ::CloseHandle(hEvent);+    }+  }+};++win_iocp_handle_service::win_iocp_handle_service(execution_context& context)+  : execution_context_service_base<win_iocp_handle_service>(context),+    iocp_service_(asio::use_service<win_iocp_io_context>(context)),+    mutex_(),+    impl_list_(0)+{+}++void win_iocp_handle_service::shutdown()+{+  // Close all implementations, causing all operations to complete.+  asio::detail::mutex::scoped_lock lock(mutex_);+  implementation_type* impl = impl_list_;+  while (impl)+  {+    close_for_destruction(*impl);+    impl = impl->next_;+  }+}++void win_iocp_handle_service::construct(+    win_iocp_handle_service::implementation_type& impl)+{+  impl.handle_ = INVALID_HANDLE_VALUE;+  impl.safe_cancellation_thread_id_ = 0;++  // Insert implementation into linked list of all implementations.+  asio::detail::mutex::scoped_lock lock(mutex_);+  impl.next_ = impl_list_;+  impl.prev_ = 0;+  if (impl_list_)+    impl_list_->prev_ = &impl;+  impl_list_ = &impl;+}++void win_iocp_handle_service::move_construct(+    win_iocp_handle_service::implementation_type& impl,+    win_iocp_handle_service::implementation_type& other_impl)+{+  impl.handle_ = other_impl.handle_;+  other_impl.handle_ = INVALID_HANDLE_VALUE;++  impl.safe_cancellation_thread_id_ = other_impl.safe_cancellation_thread_id_;+  other_impl.safe_cancellation_thread_id_ = 0;++  // Insert implementation into linked list of all implementations.+  asio::detail::mutex::scoped_lock lock(mutex_);+  impl.next_ = impl_list_;+  impl.prev_ = 0;+  if (impl_list_)+    impl_list_->prev_ = &impl;+  impl_list_ = &impl;+}++void win_iocp_handle_service::move_assign(+    win_iocp_handle_service::implementation_type& impl,+    win_iocp_handle_service& other_service,+    win_iocp_handle_service::implementation_type& other_impl)+{+  close_for_destruction(impl);++  if (this != &other_service)+  {+    // Remove implementation from linked list of all implementations.+    asio::detail::mutex::scoped_lock lock(mutex_);+    if (impl_list_ == &impl)+      impl_list_ = impl.next_;+    if (impl.prev_)+      impl.prev_->next_ = impl.next_;+    if (impl.next_)+      impl.next_->prev_= impl.prev_;+    impl.next_ = 0;+    impl.prev_ = 0;+  }++  impl.handle_ = other_impl.handle_;+  other_impl.handle_ = INVALID_HANDLE_VALUE;++  impl.safe_cancellation_thread_id_ = other_impl.safe_cancellation_thread_id_;+  other_impl.safe_cancellation_thread_id_ = 0;++  if (this != &other_service)+  {+    // Insert implementation into linked list of all implementations.+    asio::detail::mutex::scoped_lock lock(other_service.mutex_);+    impl.next_ = other_service.impl_list_;+    impl.prev_ = 0;+    if (other_service.impl_list_)+      other_service.impl_list_->prev_ = &impl;+    other_service.impl_list_ = &impl;+  }+}++void win_iocp_handle_service::destroy(+    win_iocp_handle_service::implementation_type& impl)+{+  close_for_destruction(impl);+  +  // Remove implementation from linked list of all implementations.+  asio::detail::mutex::scoped_lock lock(mutex_);+  if (impl_list_ == &impl)+    impl_list_ = impl.next_;+  if (impl.prev_)+    impl.prev_->next_ = impl.next_;+  if (impl.next_)+    impl.next_->prev_= impl.prev_;+  impl.next_ = 0;+  impl.prev_ = 0;+}++asio::error_code win_iocp_handle_service::assign(+    win_iocp_handle_service::implementation_type& impl,+    const native_handle_type& handle, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  if (iocp_service_.register_handle(handle, ec))+    return ec;++  impl.handle_ = handle;+  ec = asio::error_code();+  return ec;+}++asio::error_code win_iocp_handle_service::close(+    win_iocp_handle_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((iocp_service_.context(), "handle",+          &impl, reinterpret_cast<uintmax_t>(impl.handle_), "close"));++    if (!::CloseHandle(impl.handle_))+    {+      DWORD last_error = ::GetLastError();+      ec = asio::error_code(last_error,+          asio::error::get_system_category());+    }+    else+    {+      ec = asio::error_code();+    }++    impl.handle_ = INVALID_HANDLE_VALUE;+    impl.safe_cancellation_thread_id_ = 0;+  }+  else+  {+    ec = asio::error_code();+  }++  return ec;+}++asio::error_code win_iocp_handle_service::cancel(+    win_iocp_handle_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return ec;+  }++  ASIO_HANDLER_OPERATION((iocp_service_.context(), "handle",+        &impl, reinterpret_cast<uintmax_t>(impl.handle_), "cancel"));++  if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(+        ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))+  {+    // The version of Windows supports cancellation from any thread.+    typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);+    cancel_io_ex_t cancel_io_ex = reinterpret_cast<cancel_io_ex_t>(+        reinterpret_cast<void*>(cancel_io_ex_ptr));+    if (!cancel_io_ex(impl.handle_, 0))+    {+      DWORD last_error = ::GetLastError();+      if (last_error == ERROR_NOT_FOUND)+      {+        // ERROR_NOT_FOUND means that there were no operations to be+        // cancelled. We swallow this error to match the behaviour on other+        // platforms.+        ec = asio::error_code();+      }+      else+      {+        ec = asio::error_code(last_error,+            asio::error::get_system_category());+      }+    }+    else+    {+      ec = asio::error_code();+    }+  }+  else if (impl.safe_cancellation_thread_id_ == 0)+  {+    // No operations have been started, so there's nothing to cancel.+    ec = asio::error_code();+  }+  else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())+  {+    // Asynchronous operations have been started from the current thread only,+    // so it is safe to try to cancel them using CancelIo.+    if (!::CancelIo(impl.handle_))+    {+      DWORD last_error = ::GetLastError();+      ec = asio::error_code(last_error,+          asio::error::get_system_category());+    }+    else+    {+      ec = asio::error_code();+    }+  }+  else+  {+    // Asynchronous operations have been started from more than one thread,+    // so cancellation is not safe.+    ec = asio::error::operation_not_supported;+  }++  return ec;+}++size_t win_iocp_handle_service::do_write(+    win_iocp_handle_service::implementation_type& impl, uint64_t offset,+    const asio::const_buffer& buffer, asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  // A request to write 0 bytes on a handle is a no-op.+  if (buffer.size() == 0)+  {+    ec = asio::error_code();+    return 0;+  }++  overlapped_wrapper overlapped(ec);+  if (ec)+  {+    return 0;+  }++  // Write the data. +  overlapped.Offset = offset & 0xFFFFFFFF;+  overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;+  BOOL ok = ::WriteFile(impl.handle_, buffer.data(),+      static_cast<DWORD>(buffer.size()), 0, &overlapped);+  if (!ok) +  {+    DWORD last_error = ::GetLastError();+    if (last_error != ERROR_IO_PENDING)+    {+      ec = asio::error_code(last_error,+          asio::error::get_system_category());+      return 0;+    }+  }++  // Wait for the operation to complete.+  DWORD bytes_transferred = 0;+  ok = ::GetOverlappedResult(impl.handle_,+      &overlapped, &bytes_transferred, TRUE);+  if (!ok)+  {+    DWORD last_error = ::GetLastError();+    ec = asio::error_code(last_error,+        asio::error::get_system_category());+    return 0;+  }++  ec = asio::error_code();+  return bytes_transferred;+}++void win_iocp_handle_service::start_write_op(+    win_iocp_handle_service::implementation_type& impl, uint64_t offset,+    const asio::const_buffer& buffer, operation* op)+{+  update_cancellation_thread_id(impl);+  iocp_service_.work_started();++  if (!is_open(impl))+  {+    iocp_service_.on_completion(op, asio::error::bad_descriptor);+  }+  else if (buffer.size() == 0)+  {+    // A request to write 0 bytes on a handle is a no-op.+    iocp_service_.on_completion(op);+  }+  else+  {+    DWORD bytes_transferred = 0;+    op->Offset = offset & 0xFFFFFFFF;+    op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;+    BOOL ok = ::WriteFile(impl.handle_, buffer.data(),+        static_cast<DWORD>(buffer.size()),+        &bytes_transferred, op);+    DWORD last_error = ::GetLastError();+    if (!ok && last_error != ERROR_IO_PENDING+        && last_error != ERROR_MORE_DATA)+    {+      iocp_service_.on_completion(op, last_error, bytes_transferred);+    }+    else+    {+      iocp_service_.on_pending(op);+    }+  }+}++size_t win_iocp_handle_service::do_read(+    win_iocp_handle_service::implementation_type& impl, uint64_t offset,+    const asio::mutable_buffer& buffer, asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }+  +  // A request to read 0 bytes on a stream handle is a no-op.+  if (buffer.size() == 0)+  {+    ec = asio::error_code();+    return 0;+  }++  overlapped_wrapper overlapped(ec);+  if (ec)+  {+    return 0;+  }++  // Read some data.+  overlapped.Offset = offset & 0xFFFFFFFF;+  overlapped.OffsetHigh = (offset >> 32) & 0xFFFFFFFF;+  BOOL ok = ::ReadFile(impl.handle_, buffer.data(),+      static_cast<DWORD>(buffer.size()), 0, &overlapped);+  if (!ok) +  {+    DWORD last_error = ::GetLastError();+    if (last_error != ERROR_IO_PENDING && last_error != ERROR_MORE_DATA)+    {+      if (last_error == ERROR_HANDLE_EOF)+      {+        ec = asio::error::eof;+      }+      else+      {+        ec = asio::error_code(last_error,+            asio::error::get_system_category());+      }+      return 0;+    }+  }++  // Wait for the operation to complete.+  DWORD bytes_transferred = 0;+  ok = ::GetOverlappedResult(impl.handle_,+      &overlapped, &bytes_transferred, TRUE);+  if (!ok)+  {+    DWORD last_error = ::GetLastError();+    if (last_error == ERROR_HANDLE_EOF)+    {+      ec = asio::error::eof;+    }+    else+    {+      ec = asio::error_code(last_error,+          asio::error::get_system_category());+    }+    return (last_error == ERROR_MORE_DATA) ? bytes_transferred : 0;+  }++  ec = asio::error_code();+  return bytes_transferred;+}++void win_iocp_handle_service::start_read_op(+    win_iocp_handle_service::implementation_type& impl, uint64_t offset,+    const asio::mutable_buffer& buffer, operation* op)+{+  update_cancellation_thread_id(impl);+  iocp_service_.work_started();++  if (!is_open(impl))+  {+    iocp_service_.on_completion(op, asio::error::bad_descriptor);+  }+  else if (buffer.size() == 0)+  {+    // A request to read 0 bytes on a handle is a no-op.+    iocp_service_.on_completion(op);+  }+  else+  {+    DWORD bytes_transferred = 0;+    op->Offset = offset & 0xFFFFFFFF;+    op->OffsetHigh = (offset >> 32) & 0xFFFFFFFF;+    BOOL ok = ::ReadFile(impl.handle_, buffer.data(),+        static_cast<DWORD>(buffer.size()),+        &bytes_transferred, op);+    DWORD last_error = ::GetLastError();+    if (!ok && last_error != ERROR_IO_PENDING+        && last_error != ERROR_MORE_DATA)+    {+      iocp_service_.on_completion(op, last_error, bytes_transferred);+    }+    else+    {+      iocp_service_.on_pending(op);+    }+  }+}++void win_iocp_handle_service::update_cancellation_thread_id(+    win_iocp_handle_service::implementation_type& impl)+{+  if (impl.safe_cancellation_thread_id_ == 0)+    impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();+  else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())+    impl.safe_cancellation_thread_id_ = ~DWORD(0);+}++void win_iocp_handle_service::close_for_destruction(implementation_type& impl)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((iocp_service_.context(), "handle",+          &impl, reinterpret_cast<uintmax_t>(impl.handle_), "close"));++    ::CloseHandle(impl.handle_);+    impl.handle_ = INVALID_HANDLE_VALUE;+    impl.safe_cancellation_thread_id_ = 0;+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_IMPL_WIN_IOCP_HANDLE_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.hpp view
@@ -0,0 +1,103 @@+//+// detail/impl/win_iocp_io_context.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_HPP+#define ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_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_IOCP)++#include "asio/detail/completion_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Time_Traits>+void win_iocp_io_context::add_timer_queue(+    timer_queue<Time_Traits>& queue)+{+  do_add_timer_queue(queue);+}++template <typename Time_Traits>+void win_iocp_io_context::remove_timer_queue(+    timer_queue<Time_Traits>& queue)+{+  do_remove_timer_queue(queue);+}++template <typename Time_Traits>+void win_iocp_io_context::schedule_timer(timer_queue<Time_Traits>& queue,+    const typename Time_Traits::time_type& time,+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)+{+  // If the service has been shut down we silently discard the timer.+  if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)+  {+    post_immediate_completion(op, false);+    return;+  }++  mutex::scoped_lock lock(dispatch_mutex_);++  bool earliest = queue.enqueue_timer(time, timer, op);+  work_started();+  if (earliest)+    update_timeout();+}++template <typename Time_Traits>+std::size_t win_iocp_io_context::cancel_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& timer,+    std::size_t max_cancelled)+{+  // If the service has been shut down we silently ignore the cancellation.+  if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)+    return 0;++  mutex::scoped_lock lock(dispatch_mutex_);+  op_queue<win_iocp_operation> ops;+  std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);+  post_deferred_completions(ops);+  return n;+}++template <typename Time_Traits>+void win_iocp_io_context::move_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& to,+    typename timer_queue<Time_Traits>::per_timer_data& from)+{+  asio::detail::mutex::scoped_lock lock(dispatch_mutex_);+  op_queue<operation> ops;+  queue.cancel_timer(to, ops);+  queue.move_timer(to, from);+  lock.unlock();+  post_deferred_completions(ops);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.ipp view
@@ -0,0 +1,603 @@+//+// detail/impl/win_iocp_io_context.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_IPP+#define ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_IPP++#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_IOCP)++#include "asio/error.hpp"+#include "asio/detail/cstdint.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/thread.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/win_iocp_io_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct win_iocp_io_context::thread_function+{+  explicit thread_function(win_iocp_io_context* s)+    : this_(s)+  {+  }++  void operator()()+  {+    asio::error_code ec;+    this_->run(ec);+  }++  win_iocp_io_context* this_;+};++struct win_iocp_io_context::work_finished_on_block_exit+{+  ~work_finished_on_block_exit()+  {+    io_context_->work_finished();+  }++  win_iocp_io_context* io_context_;+};++struct win_iocp_io_context::timer_thread_function+{+  void operator()()+  {+    while (::InterlockedExchangeAdd(&io_context_->shutdown_, 0) == 0)+    {+      if (::WaitForSingleObject(io_context_->waitable_timer_.handle,+            INFINITE) == WAIT_OBJECT_0)+      {+        ::InterlockedExchange(&io_context_->dispatch_required_, 1);+        ::PostQueuedCompletionStatus(io_context_->iocp_.handle,+            0, wake_for_dispatch, 0);+      }+    }+  }++  win_iocp_io_context* io_context_;+};++win_iocp_io_context::win_iocp_io_context(+    asio::execution_context& ctx, int concurrency_hint, bool own_thread)+  : execution_context_service_base<win_iocp_io_context>(ctx),+    iocp_(),+    outstanding_work_(0),+    stopped_(0),+    stop_event_posted_(0),+    shutdown_(0),+    gqcs_timeout_(get_gqcs_timeout()),+    dispatch_required_(0),+    concurrency_hint_(concurrency_hint)+{+  ASIO_HANDLER_TRACKING_INIT;++  iocp_.handle = ::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0,+      static_cast<DWORD>(concurrency_hint >= 0 ? concurrency_hint : DWORD(~0)));+  if (!iocp_.handle)+  {+    DWORD last_error = ::GetLastError();+    asio::error_code ec(last_error,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "iocp");+  }++  if (own_thread)+  {+    ::InterlockedIncrement(&outstanding_work_);+    thread_.reset(new asio::detail::thread(thread_function(this)));+  }+}++win_iocp_io_context::~win_iocp_io_context()+{+  if (thread_.get())+  {+    stop();+    thread_->join();+    thread_.reset();+  }+}++void win_iocp_io_context::shutdown()+{+  ::InterlockedExchange(&shutdown_, 1);++  if (timer_thread_.get())+  {+    LARGE_INTEGER timeout;+    timeout.QuadPart = 1;+    ::SetWaitableTimer(waitable_timer_.handle, &timeout, 1, 0, 0, FALSE);+  }++  if (thread_.get())+  {+    stop();+    thread_->join();+    thread_.reset();+    ::InterlockedDecrement(&outstanding_work_);+  }++  while (::InterlockedExchangeAdd(&outstanding_work_, 0) > 0)+  {+    op_queue<win_iocp_operation> ops;+    timer_queues_.get_all_timers(ops);+    ops.push(completed_ops_);+    if (!ops.empty())+    {+      while (win_iocp_operation* op = ops.front())+      {+        ops.pop();+        ::InterlockedDecrement(&outstanding_work_);+        op->destroy();+      }+    }+    else+    {+      DWORD bytes_transferred = 0;+      dword_ptr_t completion_key = 0;+      LPOVERLAPPED overlapped = 0;+      ::GetQueuedCompletionStatus(iocp_.handle, &bytes_transferred,+          &completion_key, &overlapped, gqcs_timeout_);+      if (overlapped)+      {+        ::InterlockedDecrement(&outstanding_work_);+        static_cast<win_iocp_operation*>(overlapped)->destroy();+      }+    }+  }++  if (timer_thread_.get())+    timer_thread_->join();+}++asio::error_code win_iocp_io_context::register_handle(+    HANDLE handle, asio::error_code& ec)+{+  if (::CreateIoCompletionPort(handle, iocp_.handle, 0, 0) == 0)+  {+    DWORD last_error = ::GetLastError();+    ec = asio::error_code(last_error,+        asio::error::get_system_category());+  }+  else+  {+    ec = asio::error_code();+  }+  return ec;+}++size_t win_iocp_io_context::run(asio::error_code& ec)+{+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)+  {+    stop();+    ec = asio::error_code();+    return 0;+  }++  win_iocp_thread_info this_thread;+  thread_call_stack::context ctx(this, this_thread);++  size_t n = 0;+  while (do_one(INFINITE, this_thread, ec))+    if (n != (std::numeric_limits<size_t>::max)())+      ++n;+  return n;+}++size_t win_iocp_io_context::run_one(asio::error_code& ec)+{+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)+  {+    stop();+    ec = asio::error_code();+    return 0;+  }++  win_iocp_thread_info this_thread;+  thread_call_stack::context ctx(this, this_thread);++  return do_one(INFINITE, this_thread, ec);+}++size_t win_iocp_io_context::wait_one(long usec, asio::error_code& ec)+{+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)+  {+    stop();+    ec = asio::error_code();+    return 0;+  }++  win_iocp_thread_info this_thread;+  thread_call_stack::context ctx(this, this_thread);++  return do_one(usec < 0 ? INFINITE : ((usec - 1) / 1000 + 1), this_thread, ec);+}++size_t win_iocp_io_context::poll(asio::error_code& ec)+{+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)+  {+    stop();+    ec = asio::error_code();+    return 0;+  }++  win_iocp_thread_info this_thread;+  thread_call_stack::context ctx(this, this_thread);++  size_t n = 0;+  while (do_one(0, this_thread, ec))+    if (n != (std::numeric_limits<size_t>::max)())+      ++n;+  return n;+}++size_t win_iocp_io_context::poll_one(asio::error_code& ec)+{+  if (::InterlockedExchangeAdd(&outstanding_work_, 0) == 0)+  {+    stop();+    ec = asio::error_code();+    return 0;+  }++  win_iocp_thread_info this_thread;+  thread_call_stack::context ctx(this, this_thread);++  return do_one(0, this_thread, ec);+}++void win_iocp_io_context::stop()+{+  if (::InterlockedExchange(&stopped_, 1) == 0)+  {+    if (::InterlockedExchange(&stop_event_posted_, 1) == 0)+    {+      if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))+      {+        DWORD last_error = ::GetLastError();+        asio::error_code ec(last_error,+            asio::error::get_system_category());+        asio::detail::throw_error(ec, "pqcs");+      }+    }+  }+}++void win_iocp_io_context::capture_current_exception()+{+  if (thread_info_base* this_thread = thread_call_stack::contains(this))+    this_thread->capture_current_exception();+}++void win_iocp_io_context::post_deferred_completion(win_iocp_operation* op)+{+  // Flag the operation as ready.+  op->ready_ = 1;++  // Enqueue the operation on the I/O completion port.+  if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op))+  {+    // Out of resources. Put on completed queue instead.+    mutex::scoped_lock lock(dispatch_mutex_);+    completed_ops_.push(op);+    ::InterlockedExchange(&dispatch_required_, 1);+  }+}++void win_iocp_io_context::post_deferred_completions(+    op_queue<win_iocp_operation>& ops)+{+  while (win_iocp_operation* op = ops.front())+  {+    ops.pop();++    // Flag the operation as ready.+    op->ready_ = 1;++    // Enqueue the operation on the I/O completion port.+    if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, op))+    {+      // Out of resources. Put on completed queue instead.+      mutex::scoped_lock lock(dispatch_mutex_);+      completed_ops_.push(op);+      completed_ops_.push(ops);+      ::InterlockedExchange(&dispatch_required_, 1);+    }+  }+}++void win_iocp_io_context::abandon_operations(+    op_queue<win_iocp_operation>& ops)+{+  while (win_iocp_operation* op = ops.front())+  {+    ops.pop();+    ::InterlockedDecrement(&outstanding_work_);+    op->destroy();+  }+}++void win_iocp_io_context::on_pending(win_iocp_operation* op)+{+  if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)+  {+    // Enqueue the operation on the I/O completion port.+    if (!::PostQueuedCompletionStatus(iocp_.handle,+          0, overlapped_contains_result, op))+    {+      // Out of resources. Put on completed queue instead.+      mutex::scoped_lock lock(dispatch_mutex_);+      completed_ops_.push(op);+      ::InterlockedExchange(&dispatch_required_, 1);+    }+  }+}++void win_iocp_io_context::on_completion(win_iocp_operation* op,+    DWORD last_error, DWORD bytes_transferred)+{+  // Flag that the operation is ready for invocation.+  op->ready_ = 1;++  // Store results in the OVERLAPPED structure.+  op->Internal = reinterpret_cast<ulong_ptr_t>(+      &asio::error::get_system_category());+  op->Offset = last_error;+  op->OffsetHigh = bytes_transferred;++  // Enqueue the operation on the I/O completion port.+  if (!::PostQueuedCompletionStatus(iocp_.handle,+        0, overlapped_contains_result, op))+  {+    // Out of resources. Put on completed queue instead.+    mutex::scoped_lock lock(dispatch_mutex_);+    completed_ops_.push(op);+    ::InterlockedExchange(&dispatch_required_, 1);+  }+}++void win_iocp_io_context::on_completion(win_iocp_operation* op,+    const asio::error_code& ec, DWORD bytes_transferred)+{+  // Flag that the operation is ready for invocation.+  op->ready_ = 1;++  // Store results in the OVERLAPPED structure.+  op->Internal = reinterpret_cast<ulong_ptr_t>(&ec.category());+  op->Offset = ec.value();+  op->OffsetHigh = bytes_transferred;++  // Enqueue the operation on the I/O completion port.+  if (!::PostQueuedCompletionStatus(iocp_.handle,+        0, overlapped_contains_result, op))+  {+    // Out of resources. Put on completed queue instead.+    mutex::scoped_lock lock(dispatch_mutex_);+    completed_ops_.push(op);+    ::InterlockedExchange(&dispatch_required_, 1);+  }+}++size_t win_iocp_io_context::do_one(DWORD msec,+    win_iocp_thread_info& this_thread, asio::error_code& ec)+{+  for (;;)+  {+    // Try to acquire responsibility for dispatching timers and completed ops.+    if (::InterlockedCompareExchange(&dispatch_required_, 0, 1) == 1)+    {+      mutex::scoped_lock lock(dispatch_mutex_);++      // Dispatch pending timers and operations.+      op_queue<win_iocp_operation> ops;+      ops.push(completed_ops_);+      timer_queues_.get_ready_timers(ops);+      post_deferred_completions(ops);+      update_timeout();+    }++    // Get the next operation from the queue.+    DWORD bytes_transferred = 0;+    dword_ptr_t completion_key = 0;+    LPOVERLAPPED overlapped = 0;+    ::SetLastError(0);+    BOOL ok = ::GetQueuedCompletionStatus(iocp_.handle,+        &bytes_transferred, &completion_key, &overlapped,+        msec < gqcs_timeout_ ? msec : gqcs_timeout_);+    DWORD last_error = ::GetLastError();++    if (overlapped)+    {+      win_iocp_operation* op = static_cast<win_iocp_operation*>(overlapped);+      asio::error_code result_ec(last_error,+          asio::error::get_system_category());++      // We may have been passed the last_error and bytes_transferred in the+      // OVERLAPPED structure itself.+      if (completion_key == overlapped_contains_result)+      {+        result_ec = asio::error_code(static_cast<int>(op->Offset),+            *reinterpret_cast<asio::error_category*>(op->Internal));+        bytes_transferred = op->OffsetHigh;+      }++      // Otherwise ensure any result has been saved into the OVERLAPPED+      // structure.+      else+      {+        op->Internal = reinterpret_cast<ulong_ptr_t>(&result_ec.category());+        op->Offset = result_ec.value();+        op->OffsetHigh = bytes_transferred;+      }++      // Dispatch the operation only if ready. The operation may not be ready+      // if the initiating function (e.g. a call to WSARecv) has not yet+      // returned. This is because the initiating function still wants access+      // to the operation's OVERLAPPED structure.+      if (::InterlockedCompareExchange(&op->ready_, 1, 0) == 1)+      {+        // Ensure the count of outstanding work is decremented on block exit.+        work_finished_on_block_exit on_exit = { this };+        (void)on_exit;++        op->complete(this, result_ec, bytes_transferred);+        this_thread.rethrow_pending_exception();+        ec = asio::error_code();+        return 1;+      }+    }+    else if (!ok)+    {+      if (last_error != WAIT_TIMEOUT)+      {+        ec = asio::error_code(last_error,+            asio::error::get_system_category());+        return 0;+      }++      // If we're waiting indefinitely we need to keep going until we get a+      // real handler.+      if (msec == INFINITE)+        continue;++      ec = asio::error_code();+      return 0;+    }+    else if (completion_key == wake_for_dispatch)+    {+      // We have been woken up to try to acquire responsibility for dispatching+      // timers and completed operations.+    }+    else+    {+      // Indicate that there is no longer an in-flight stop event.+      ::InterlockedExchange(&stop_event_posted_, 0);++      // The stopped_ flag is always checked to ensure that any leftover+      // stop events from a previous run invocation are ignored.+      if (::InterlockedExchangeAdd(&stopped_, 0) != 0)+      {+        // Wake up next thread that is blocked on GetQueuedCompletionStatus.+        if (::InterlockedExchange(&stop_event_posted_, 1) == 0)+        {+          if (!::PostQueuedCompletionStatus(iocp_.handle, 0, 0, 0))+          {+            last_error = ::GetLastError();+            ec = asio::error_code(last_error,+                asio::error::get_system_category());+            return 0;+          }+        }++        ec = asio::error_code();+        return 0;+      }+    }+  }+}++DWORD win_iocp_io_context::get_gqcs_timeout()+{+  OSVERSIONINFOEX osvi;+  ZeroMemory(&osvi, sizeof(osvi));+  osvi.dwOSVersionInfoSize = sizeof(osvi);+  osvi.dwMajorVersion = 6ul;++  const uint64_t condition_mask = ::VerSetConditionMask(+      0, VER_MAJORVERSION, VER_GREATER_EQUAL);++  if (!!::VerifyVersionInfo(&osvi, VER_MAJORVERSION, condition_mask))+    return INFINITE;++  return default_gqcs_timeout;+}++void win_iocp_io_context::do_add_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(dispatch_mutex_);++  timer_queues_.insert(&queue);++  if (!waitable_timer_.handle)+  {+    waitable_timer_.handle = ::CreateWaitableTimer(0, FALSE, 0);+    if (waitable_timer_.handle == 0)+    {+      DWORD last_error = ::GetLastError();+      asio::error_code ec(last_error,+          asio::error::get_system_category());+      asio::detail::throw_error(ec, "timer");+    }++    LARGE_INTEGER timeout;+    timeout.QuadPart = -max_timeout_usec;+    timeout.QuadPart *= 10;+    ::SetWaitableTimer(waitable_timer_.handle,+        &timeout, max_timeout_msec, 0, 0, FALSE);+  }++  if (!timer_thread_.get())+  {+    timer_thread_function thread_function = { this };+    timer_thread_.reset(new thread(thread_function, 65536));+  }+}++void win_iocp_io_context::do_remove_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(dispatch_mutex_);++  timer_queues_.erase(&queue);+}++void win_iocp_io_context::update_timeout()+{+  if (timer_thread_.get())+  {+    // There's no point updating the waitable timer if the new timeout period+    // exceeds the maximum timeout. In that case, we might as well wait for the+    // existing period of the timer to expire.+    long timeout_usec = timer_queues_.wait_duration_usec(max_timeout_usec);+    if (timeout_usec < max_timeout_usec)+    {+      LARGE_INTEGER timeout;+      timeout.QuadPart = -timeout_usec;+      timeout.QuadPart *= 10;+      ::SetWaitableTimer(waitable_timer_.handle,+          &timeout, max_timeout_msec, 0, 0, FALSE);+    }+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_IMPL_WIN_IOCP_IO_CONTEXT_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp view
@@ -0,0 +1,192 @@+//+// detail/impl/win_iocp_serial_port_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP+#define ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP++#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_IOCP) && defined(ASIO_HAS_SERIAL_PORT)++#include <cstring>+#include "asio/detail/win_iocp_serial_port_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++win_iocp_serial_port_service::win_iocp_serial_port_service(+    execution_context& context)+  : execution_context_service_base<win_iocp_serial_port_service>(context),+    handle_service_(context)+{+}++void win_iocp_serial_port_service::shutdown()+{+}++asio::error_code win_iocp_serial_port_service::open(+    win_iocp_serial_port_service::implementation_type& impl,+    const std::string& device, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  // For convenience, add a leading \\.\ sequence if not already present.+  std::string name = (device[0] == '\\') ? device : "\\\\.\\" + device;++  // Open a handle to the serial port.+  ::HANDLE handle = ::CreateFileA(name.c_str(),+      GENERIC_READ | GENERIC_WRITE, 0, 0,+      OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);+  if (handle == INVALID_HANDLE_VALUE)+  {+    DWORD last_error = ::GetLastError();+    ec = asio::error_code(last_error,+        asio::error::get_system_category());+    return ec;+  }++  // Determine the initial serial port parameters.+  using namespace std; // For memset.+  ::DCB dcb;+  memset(&dcb, 0, sizeof(DCB));+  dcb.DCBlength = sizeof(DCB);+  if (!::GetCommState(handle, &dcb))+  {+    DWORD last_error = ::GetLastError();+    ::CloseHandle(handle);+    ec = asio::error_code(last_error,+        asio::error::get_system_category());+    return ec;+  }++  // Set some default serial port parameters. This implementation does not+  // support changing all of these, so they might as well be in a known state.+  dcb.fBinary = TRUE; // Win32 only supports binary mode.+  dcb.fNull = FALSE; // Do not ignore NULL characters.+  dcb.fAbortOnError = FALSE; // Ignore serial framing errors.+  dcb.BaudRate = CBR_9600; // 9600 baud by default+  dcb.ByteSize = 8; // 8 bit bytes+  dcb.fOutxCtsFlow = FALSE; // No flow control+  dcb.fOutxDsrFlow = FALSE;+  dcb.fDtrControl = DTR_CONTROL_DISABLE;+  dcb.fDsrSensitivity = FALSE;+  dcb.fOutX = FALSE;+  dcb.fInX = FALSE;+  dcb.fRtsControl = RTS_CONTROL_DISABLE;+  dcb.fParity = FALSE; // No parity+  dcb.Parity = NOPARITY;+  dcb.StopBits = ONESTOPBIT; // One stop bit+  if (!::SetCommState(handle, &dcb))+  {+    DWORD last_error = ::GetLastError();+    ::CloseHandle(handle);+    ec = asio::error_code(last_error,+        asio::error::get_system_category());+    return ec;+  }++  // Set up timeouts so that the serial port will behave similarly to a+  // network socket. Reads wait for at least one byte, then return with+  // whatever they have. Writes return once everything is out the door.+  ::COMMTIMEOUTS timeouts;+  timeouts.ReadIntervalTimeout = 1;+  timeouts.ReadTotalTimeoutMultiplier = 0;+  timeouts.ReadTotalTimeoutConstant = 0;+  timeouts.WriteTotalTimeoutMultiplier = 0;+  timeouts.WriteTotalTimeoutConstant = 0;+  if (!::SetCommTimeouts(handle, &timeouts))+  {+    DWORD last_error = ::GetLastError();+    ::CloseHandle(handle);+    ec = asio::error_code(last_error,+        asio::error::get_system_category());+    return ec;+  }++  // We're done. Take ownership of the serial port handle.+  if (handle_service_.assign(impl, handle, ec))+    ::CloseHandle(handle);+  return ec;+}++asio::error_code win_iocp_serial_port_service::do_set_option(+    win_iocp_serial_port_service::implementation_type& impl,+    win_iocp_serial_port_service::store_function_type store,+    const void* option, asio::error_code& ec)+{+  using namespace std; // For memcpy.++  ::DCB dcb;+  memset(&dcb, 0, sizeof(DCB));+  dcb.DCBlength = sizeof(DCB);+  if (!::GetCommState(handle_service_.native_handle(impl), &dcb))+  {+    DWORD last_error = ::GetLastError();+    ec = asio::error_code(last_error,+        asio::error::get_system_category());+    return ec;+  }++  if (store(option, dcb, ec))+    return ec;++  if (!::SetCommState(handle_service_.native_handle(impl), &dcb))+  {+    DWORD last_error = ::GetLastError();+    ec = asio::error_code(last_error,+        asio::error::get_system_category());+    return ec;+  }++  ec = asio::error_code();+  return ec;+}++asio::error_code win_iocp_serial_port_service::do_get_option(+    const win_iocp_serial_port_service::implementation_type& impl,+    win_iocp_serial_port_service::load_function_type load,+    void* option, asio::error_code& ec) const+{+  using namespace std; // For memset.++  ::DCB dcb;+  memset(&dcb, 0, sizeof(DCB));+  dcb.DCBlength = sizeof(DCB);+  if (!::GetCommState(handle_service_.native_handle(impl), &dcb))+  {+    DWORD last_error = ::GetLastError();+    ec = asio::error_code(last_error,+        asio::error::get_system_category());+    return ec;+  }++  return load(option, dcb, ec);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)++#endif // ASIO_DETAIL_IMPL_WIN_IOCP_SERIAL_PORT_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp view
@@ -0,0 +1,801 @@+//+// detail/impl/win_iocp_socket_service_base.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP+#define ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP++#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_IOCP)++#include "asio/detail/win_iocp_socket_service_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++win_iocp_socket_service_base::win_iocp_socket_service_base(+    execution_context& context)+  : context_(context),+    iocp_service_(use_service<win_iocp_io_context>(context)),+    reactor_(0),+    connect_ex_(0),+    nt_set_info_(0),+    mutex_(),+    impl_list_(0)+{+}++void win_iocp_socket_service_base::base_shutdown()+{+  // Close all implementations, causing all operations to complete.+  asio::detail::mutex::scoped_lock lock(mutex_);+  base_implementation_type* impl = impl_list_;+  while (impl)+  {+    close_for_destruction(*impl);+    impl = impl->next_;+  }+}++void win_iocp_socket_service_base::construct(+    win_iocp_socket_service_base::base_implementation_type& impl)+{+  impl.socket_ = invalid_socket;+  impl.state_ = 0;+  impl.cancel_token_.reset();+#if defined(ASIO_ENABLE_CANCELIO)+  impl.safe_cancellation_thread_id_ = 0;+#endif // defined(ASIO_ENABLE_CANCELIO)++  // Insert implementation into linked list of all implementations.+  asio::detail::mutex::scoped_lock lock(mutex_);+  impl.next_ = impl_list_;+  impl.prev_ = 0;+  if (impl_list_)+    impl_list_->prev_ = &impl;+  impl_list_ = &impl;+}++void win_iocp_socket_service_base::base_move_construct(+    win_iocp_socket_service_base::base_implementation_type& impl,+    win_iocp_socket_service_base::base_implementation_type& other_impl)+  ASIO_NOEXCEPT+{+  impl.socket_ = other_impl.socket_;+  other_impl.socket_ = invalid_socket;++  impl.state_ = other_impl.state_;+  other_impl.state_ = 0;++  impl.cancel_token_ = other_impl.cancel_token_;+  other_impl.cancel_token_.reset();++#if defined(ASIO_ENABLE_CANCELIO)+  impl.safe_cancellation_thread_id_ = other_impl.safe_cancellation_thread_id_;+  other_impl.safe_cancellation_thread_id_ = 0;+#endif // defined(ASIO_ENABLE_CANCELIO)++  // Insert implementation into linked list of all implementations.+  asio::detail::mutex::scoped_lock lock(mutex_);+  impl.next_ = impl_list_;+  impl.prev_ = 0;+  if (impl_list_)+    impl_list_->prev_ = &impl;+  impl_list_ = &impl;+}++void win_iocp_socket_service_base::base_move_assign(+    win_iocp_socket_service_base::base_implementation_type& impl,+    win_iocp_socket_service_base& other_service,+    win_iocp_socket_service_base::base_implementation_type& other_impl)+{+  close_for_destruction(impl);++  if (this != &other_service)+  {+    // Remove implementation from linked list of all implementations.+    asio::detail::mutex::scoped_lock lock(mutex_);+    if (impl_list_ == &impl)+      impl_list_ = impl.next_;+    if (impl.prev_)+      impl.prev_->next_ = impl.next_;+    if (impl.next_)+      impl.next_->prev_= impl.prev_;+    impl.next_ = 0;+    impl.prev_ = 0;+  }++  impl.socket_ = other_impl.socket_;+  other_impl.socket_ = invalid_socket;++  impl.state_ = other_impl.state_;+  other_impl.state_ = 0;++  impl.cancel_token_ = other_impl.cancel_token_;+  other_impl.cancel_token_.reset();++#if defined(ASIO_ENABLE_CANCELIO)+  impl.safe_cancellation_thread_id_ = other_impl.safe_cancellation_thread_id_;+  other_impl.safe_cancellation_thread_id_ = 0;+#endif // defined(ASIO_ENABLE_CANCELIO)++  if (this != &other_service)+  {+    // Insert implementation into linked list of all implementations.+    asio::detail::mutex::scoped_lock lock(other_service.mutex_);+    impl.next_ = other_service.impl_list_;+    impl.prev_ = 0;+    if (other_service.impl_list_)+      other_service.impl_list_->prev_ = &impl;+    other_service.impl_list_ = &impl;+  }+}++void win_iocp_socket_service_base::destroy(+    win_iocp_socket_service_base::base_implementation_type& impl)+{+  close_for_destruction(impl);++  // Remove implementation from linked list of all implementations.+  asio::detail::mutex::scoped_lock lock(mutex_);+  if (impl_list_ == &impl)+    impl_list_ = impl.next_;+  if (impl.prev_)+    impl.prev_->next_ = impl.next_;+  if (impl.next_)+    impl.next_->prev_= impl.prev_;+  impl.next_ = 0;+  impl.prev_ = 0;+}++asio::error_code win_iocp_socket_service_base::close(+    win_iocp_socket_service_base::base_implementation_type& impl,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((iocp_service_.context(),+          "socket", &impl, impl.socket_, "close"));++    // Check if the reactor was created, in which case we need to close the+    // socket on the reactor as well to cancel any operations that might be+    // running there.+    select_reactor* r = static_cast<select_reactor*>(+          interlocked_compare_exchange_pointer(+            reinterpret_cast<void**>(&reactor_), 0, 0));+    if (r)+      r->deregister_descriptor(impl.socket_, impl.reactor_data_, true);++    socket_ops::close(impl.socket_, impl.state_, false, ec);++    if (r)+      r->cleanup_descriptor_data(impl.reactor_data_);+  }+  else+  {+    ec = asio::error_code();+  }++  impl.socket_ = invalid_socket;+  impl.state_ = 0;+  impl.cancel_token_.reset();+#if defined(ASIO_ENABLE_CANCELIO)+  impl.safe_cancellation_thread_id_ = 0;+#endif // defined(ASIO_ENABLE_CANCELIO)++  return ec;+}++socket_type win_iocp_socket_service_base::release(+    win_iocp_socket_service_base::base_implementation_type& impl,+    asio::error_code& ec)+{+  if (!is_open(impl))+    return invalid_socket;++  cancel(impl, ec);+  if (ec)+    return invalid_socket;++  nt_set_info_fn fn = get_nt_set_info();+  if (fn == 0)+  {+    ec = asio::error::operation_not_supported;+    return invalid_socket;+  }++  HANDLE sock_as_handle = reinterpret_cast<HANDLE>(impl.socket_);+  ULONG_PTR iosb[2] = { 0, 0 };+  void* info[2] = { 0, 0 };+  if (fn(sock_as_handle, iosb, &info, sizeof(info),+        61 /* FileReplaceCompletionInformation */))+  {+    ec = asio::error::operation_not_supported;+    return invalid_socket;+  }++  socket_type tmp = impl.socket_;+  impl.socket_ = invalid_socket;+  return tmp;+}++asio::error_code win_iocp_socket_service_base::cancel(+    win_iocp_socket_service_base::base_implementation_type& impl,+    asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return ec;+  }++  ASIO_HANDLER_OPERATION((iocp_service_.context(),+        "socket", &impl, impl.socket_, "cancel"));++  if (FARPROC cancel_io_ex_ptr = ::GetProcAddress(+        ::GetModuleHandleA("KERNEL32"), "CancelIoEx"))+  {+    // The version of Windows supports cancellation from any thread.+    typedef BOOL (WINAPI* cancel_io_ex_t)(HANDLE, LPOVERLAPPED);+    cancel_io_ex_t cancel_io_ex = reinterpret_cast<cancel_io_ex_t>(+        reinterpret_cast<void*>(cancel_io_ex_ptr));+    socket_type sock = impl.socket_;+    HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);+    if (!cancel_io_ex(sock_as_handle, 0))+    {+      DWORD last_error = ::GetLastError();+      if (last_error == ERROR_NOT_FOUND)+      {+        // ERROR_NOT_FOUND means that there were no operations to be+        // cancelled. We swallow this error to match the behaviour on other+        // platforms.+        ec = asio::error_code();+      }+      else+      {+        ec = asio::error_code(last_error,+            asio::error::get_system_category());+      }+    }+    else+    {+      ec = asio::error_code();+    }+  }+#if defined(ASIO_ENABLE_CANCELIO)+  else if (impl.safe_cancellation_thread_id_ == 0)+  {+    // No operations have been started, so there's nothing to cancel.+    ec = asio::error_code();+  }+  else if (impl.safe_cancellation_thread_id_ == ::GetCurrentThreadId())+  {+    // Asynchronous operations have been started from the current thread only,+    // so it is safe to try to cancel them using CancelIo.+    socket_type sock = impl.socket_;+    HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock);+    if (!::CancelIo(sock_as_handle))+    {+      DWORD last_error = ::GetLastError();+      ec = asio::error_code(last_error,+          asio::error::get_system_category());+    }+    else+    {+      ec = asio::error_code();+    }+  }+  else+  {+    // Asynchronous operations have been started from more than one thread,+    // so cancellation is not safe.+    ec = asio::error::operation_not_supported;+  }+#else // defined(ASIO_ENABLE_CANCELIO)+  else+  {+    // Cancellation is not supported as CancelIo may not be used.+    ec = asio::error::operation_not_supported;+  }+#endif // defined(ASIO_ENABLE_CANCELIO)++  // Cancel any operations started via the reactor.+  if (!ec)+  {+    select_reactor* r = static_cast<select_reactor*>(+          interlocked_compare_exchange_pointer(+            reinterpret_cast<void**>(&reactor_), 0, 0));+    if (r)+      r->cancel_ops(impl.socket_, impl.reactor_data_);+  }++  return ec;+}++asio::error_code win_iocp_socket_service_base::do_open(+    win_iocp_socket_service_base::base_implementation_type& impl,+    int family, int type, int protocol, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  socket_holder sock(socket_ops::socket(family, type, protocol, ec));+  if (sock.get() == invalid_socket)+    return ec;++  HANDLE sock_as_handle = reinterpret_cast<HANDLE>(sock.get());+  if (iocp_service_.register_handle(sock_as_handle, ec))+    return ec;++  impl.socket_ = sock.release();+  switch (type)+  {+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;+  default: impl.state_ = 0; break;+  }+  impl.cancel_token_.reset(static_cast<void*>(0), socket_ops::noop_deleter());+  ec = asio::error_code();+  return ec;+}++asio::error_code win_iocp_socket_service_base::do_assign(+    win_iocp_socket_service_base::base_implementation_type& impl,+    int type, socket_type native_socket, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  HANDLE sock_as_handle = reinterpret_cast<HANDLE>(native_socket);+  if (iocp_service_.register_handle(sock_as_handle, ec))+    return ec;++  impl.socket_ = native_socket;+  switch (type)+  {+  case SOCK_STREAM: impl.state_ = socket_ops::stream_oriented; break;+  case SOCK_DGRAM: impl.state_ = socket_ops::datagram_oriented; break;+  default: impl.state_ = 0; break;+  }+  impl.cancel_token_.reset(static_cast<void*>(0), socket_ops::noop_deleter());+  ec = asio::error_code();+  return ec;+}++void win_iocp_socket_service_base::start_send_op(+    win_iocp_socket_service_base::base_implementation_type& impl,+    WSABUF* buffers, std::size_t buffer_count,+    socket_base::message_flags flags, bool noop, operation* op)+{+  update_cancellation_thread_id(impl);+  iocp_service_.work_started();++  if (noop)+    iocp_service_.on_completion(op);+  else if (!is_open(impl))+    iocp_service_.on_completion(op, asio::error::bad_descriptor);+  else+  {+    DWORD bytes_transferred = 0;+    int result = ::WSASend(impl.socket_, buffers,+        static_cast<DWORD>(buffer_count), &bytes_transferred, flags, op, 0);+    DWORD last_error = ::WSAGetLastError();+    if (last_error == ERROR_PORT_UNREACHABLE)+      last_error = WSAECONNREFUSED;+    if (result != 0 && last_error != WSA_IO_PENDING)+      iocp_service_.on_completion(op, last_error, bytes_transferred);+    else+      iocp_service_.on_pending(op);+  }+}++void win_iocp_socket_service_base::start_send_to_op(+    win_iocp_socket_service_base::base_implementation_type& impl,+    WSABUF* buffers, std::size_t buffer_count,+    const socket_addr_type* addr, int addrlen,+    socket_base::message_flags flags, operation* op)+{+  update_cancellation_thread_id(impl);+  iocp_service_.work_started();++  if (!is_open(impl))+    iocp_service_.on_completion(op, asio::error::bad_descriptor);+  else+  {+    DWORD bytes_transferred = 0;+    int result = ::WSASendTo(impl.socket_, buffers,+        static_cast<DWORD>(buffer_count),+        &bytes_transferred, flags, addr, addrlen, op, 0);+    DWORD last_error = ::WSAGetLastError();+    if (last_error == ERROR_PORT_UNREACHABLE)+      last_error = WSAECONNREFUSED;+    if (result != 0 && last_error != WSA_IO_PENDING)+      iocp_service_.on_completion(op, last_error, bytes_transferred);+    else+      iocp_service_.on_pending(op);+  }+}++void win_iocp_socket_service_base::start_receive_op(+    win_iocp_socket_service_base::base_implementation_type& impl,+    WSABUF* buffers, std::size_t buffer_count,+    socket_base::message_flags flags, bool noop, operation* op)+{+  update_cancellation_thread_id(impl);+  iocp_service_.work_started();++  if (noop)+    iocp_service_.on_completion(op);+  else if (!is_open(impl))+    iocp_service_.on_completion(op, asio::error::bad_descriptor);+  else+  {+    DWORD bytes_transferred = 0;+    DWORD recv_flags = flags;+    int result = ::WSARecv(impl.socket_, buffers,+        static_cast<DWORD>(buffer_count),+        &bytes_transferred, &recv_flags, op, 0);+    DWORD last_error = ::WSAGetLastError();+    if (last_error == ERROR_NETNAME_DELETED)+      last_error = WSAECONNRESET;+    else if (last_error == ERROR_PORT_UNREACHABLE)+      last_error = WSAECONNREFUSED;+    if (result != 0 && last_error != WSA_IO_PENDING)+      iocp_service_.on_completion(op, last_error, bytes_transferred);+    else+      iocp_service_.on_pending(op);+  }+}++void win_iocp_socket_service_base::start_null_buffers_receive_op(+    win_iocp_socket_service_base::base_implementation_type& impl,+    socket_base::message_flags flags, reactor_op* op)+{+  if ((impl.state_ & socket_ops::stream_oriented) != 0)+  {+    // For stream sockets on Windows, we may issue a 0-byte overlapped+    // WSARecv to wait until there is data available on the socket.+    ::WSABUF buf = { 0, 0 };+    start_receive_op(impl, &buf, 1, flags, false, op);+  }+  else+  {+    start_reactor_op(impl,+        (flags & socket_base::message_out_of_band)+          ? select_reactor::except_op : select_reactor::read_op,+        op);+  }+}++void win_iocp_socket_service_base::start_receive_from_op(+    win_iocp_socket_service_base::base_implementation_type& impl,+    WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,+    socket_base::message_flags flags, int* addrlen, operation* op)+{+  update_cancellation_thread_id(impl);+  iocp_service_.work_started();++  if (!is_open(impl))+    iocp_service_.on_completion(op, asio::error::bad_descriptor);+  else+  {+    DWORD bytes_transferred = 0;+    DWORD recv_flags = flags;+    int result = ::WSARecvFrom(impl.socket_, buffers,+        static_cast<DWORD>(buffer_count),+        &bytes_transferred, &recv_flags, addr, addrlen, op, 0);+    DWORD last_error = ::WSAGetLastError();+    if (last_error == ERROR_PORT_UNREACHABLE)+      last_error = WSAECONNREFUSED;+    if (result != 0 && last_error != WSA_IO_PENDING)+      iocp_service_.on_completion(op, last_error, bytes_transferred);+    else+      iocp_service_.on_pending(op);+  }+}++void win_iocp_socket_service_base::start_accept_op(+    win_iocp_socket_service_base::base_implementation_type& impl,+    bool peer_is_open, socket_holder& new_socket, int family, int type,+    int protocol, void* output_buffer, DWORD address_length, operation* op)+{+  update_cancellation_thread_id(impl);+  iocp_service_.work_started();++  if (!is_open(impl))+    iocp_service_.on_completion(op, asio::error::bad_descriptor);+  else if (peer_is_open)+    iocp_service_.on_completion(op, asio::error::already_open);+  else+  {+    asio::error_code ec;+    new_socket.reset(socket_ops::socket(family, type, protocol, ec));+    if (new_socket.get() == invalid_socket)+      iocp_service_.on_completion(op, ec);+    else+    {+      DWORD bytes_read = 0;+      BOOL result = ::AcceptEx(impl.socket_, new_socket.get(), output_buffer,+          0, address_length, address_length, &bytes_read, op);+      DWORD last_error = ::WSAGetLastError();+      if (!result && last_error != WSA_IO_PENDING)+        iocp_service_.on_completion(op, last_error);+      else+        iocp_service_.on_pending(op);+    }+  }+}++void win_iocp_socket_service_base::restart_accept_op(+    socket_type s, socket_holder& new_socket, int family, int type,+    int protocol, void* output_buffer, DWORD address_length, operation* op)+{+  new_socket.reset();+  iocp_service_.work_started();++  asio::error_code ec;+  new_socket.reset(socket_ops::socket(family, type, protocol, ec));+  if (new_socket.get() == invalid_socket)+    iocp_service_.on_completion(op, ec);+  else+  {+    DWORD bytes_read = 0;+    BOOL result = ::AcceptEx(s, new_socket.get(), output_buffer,+        0, address_length, address_length, &bytes_read, op);+    DWORD last_error = ::WSAGetLastError();+    if (!result && last_error != WSA_IO_PENDING)+      iocp_service_.on_completion(op, last_error);+    else+      iocp_service_.on_pending(op);+  }+}++void win_iocp_socket_service_base::start_reactor_op(+    win_iocp_socket_service_base::base_implementation_type& impl,+    int op_type, reactor_op* op)+{+  select_reactor& r = get_reactor();+  update_cancellation_thread_id(impl);++  if (is_open(impl))+  {+    r.start_op(op_type, impl.socket_, impl.reactor_data_, op, false, false);+    return;+  }+  else+    op->ec_ = asio::error::bad_descriptor;++  iocp_service_.post_immediate_completion(op, false);+}++void win_iocp_socket_service_base::start_connect_op(+    win_iocp_socket_service_base::base_implementation_type& impl,+    int family, int type, const socket_addr_type* addr,+    std::size_t addrlen, win_iocp_socket_connect_op_base* op)+{+  // If ConnectEx is available, use that.+  if (family == ASIO_OS_DEF(AF_INET)+      || family == ASIO_OS_DEF(AF_INET6))+  {+    if (connect_ex_fn connect_ex = get_connect_ex(impl, type))+    {+      union address_union+      {+        socket_addr_type base;+        sockaddr_in4_type v4;+        sockaddr_in6_type v6;+      } a;++      using namespace std; // For memset.+      memset(&a, 0, sizeof(a));+      a.base.sa_family = family;++      socket_ops::bind(impl.socket_, &a.base,+          family == ASIO_OS_DEF(AF_INET)+          ? sizeof(a.v4) : sizeof(a.v6), op->ec_);+      if (op->ec_ && op->ec_ != asio::error::invalid_argument)+      {+        iocp_service_.post_immediate_completion(op, false);+        return;+      }++      op->connect_ex_ = true;+      update_cancellation_thread_id(impl);+      iocp_service_.work_started();++      BOOL result = connect_ex(impl.socket_,+          addr, static_cast<int>(addrlen), 0, 0, 0, op);+      DWORD last_error = ::WSAGetLastError();+      if (!result && last_error != WSA_IO_PENDING)+        iocp_service_.on_completion(op, last_error);+      else+        iocp_service_.on_pending(op);+      return;+    }+  }++  // Otherwise, fall back to a reactor-based implementation.+  select_reactor& r = get_reactor();+  update_cancellation_thread_id(impl);++  if ((impl.state_ & socket_ops::non_blocking) != 0+      || socket_ops::set_internal_non_blocking(+        impl.socket_, impl.state_, true, op->ec_))+  {+    if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)+    {+      if (op->ec_ == asio::error::in_progress+          || op->ec_ == asio::error::would_block)+      {+        op->ec_ = asio::error_code();+        r.start_op(select_reactor::connect_op, impl.socket_,+            impl.reactor_data_, op, false, false);+        return;+      }+    }+  }++  r.post_immediate_completion(op, false);+}++void win_iocp_socket_service_base::close_for_destruction(+    win_iocp_socket_service_base::base_implementation_type& impl)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((iocp_service_.context(),+          "socket", &impl, impl.socket_, "close"));++    // Check if the reactor was created, in which case we need to close the+    // socket on the reactor as well to cancel any operations that might be+    // running there.+    select_reactor* r = static_cast<select_reactor*>(+          interlocked_compare_exchange_pointer(+            reinterpret_cast<void**>(&reactor_), 0, 0));+    if (r)+      r->deregister_descriptor(impl.socket_, impl.reactor_data_, true);++    asio::error_code ignored_ec;+    socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);++    if (r)+      r->cleanup_descriptor_data(impl.reactor_data_);+  }++  impl.socket_ = invalid_socket;+  impl.state_ = 0;+  impl.cancel_token_.reset();+#if defined(ASIO_ENABLE_CANCELIO)+  impl.safe_cancellation_thread_id_ = 0;+#endif // defined(ASIO_ENABLE_CANCELIO)+}++void win_iocp_socket_service_base::update_cancellation_thread_id(+    win_iocp_socket_service_base::base_implementation_type& impl)+{+#if defined(ASIO_ENABLE_CANCELIO)+  if (impl.safe_cancellation_thread_id_ == 0)+    impl.safe_cancellation_thread_id_ = ::GetCurrentThreadId();+  else if (impl.safe_cancellation_thread_id_ != ::GetCurrentThreadId())+    impl.safe_cancellation_thread_id_ = ~DWORD(0);+#else // defined(ASIO_ENABLE_CANCELIO)+  (void)impl;+#endif // defined(ASIO_ENABLE_CANCELIO)+}++select_reactor& win_iocp_socket_service_base::get_reactor()+{+  select_reactor* r = static_cast<select_reactor*>(+        interlocked_compare_exchange_pointer(+          reinterpret_cast<void**>(&reactor_), 0, 0));+  if (!r)+  {+    r = &(use_service<select_reactor>(context_));+    interlocked_exchange_pointer(reinterpret_cast<void**>(&reactor_), r);+  }+  return *r;+}++win_iocp_socket_service_base::connect_ex_fn+win_iocp_socket_service_base::get_connect_ex(+    win_iocp_socket_service_base::base_implementation_type& impl, int type)+{+#if defined(ASIO_DISABLE_CONNECTEX)+  (void)impl;+  (void)type;+  return 0;+#else // defined(ASIO_DISABLE_CONNECTEX)+  if (type != ASIO_OS_DEF(SOCK_STREAM)+      && type != ASIO_OS_DEF(SOCK_SEQPACKET))+    return 0;++  void* ptr = interlocked_compare_exchange_pointer(&connect_ex_, 0, 0);+  if (!ptr)+  {+    GUID guid = { 0x25a207b9, 0xddf3, 0x4660,+      { 0x8e, 0xe9, 0x76, 0xe5, 0x8c, 0x74, 0x06, 0x3e } };++    DWORD bytes = 0;+    if (::WSAIoctl(impl.socket_, SIO_GET_EXTENSION_FUNCTION_POINTER,+          &guid, sizeof(guid), &ptr, sizeof(ptr), &bytes, 0, 0) != 0)+    {+      // Set connect_ex_ to a special value to indicate that ConnectEx is+      // unavailable. That way we won't bother trying to look it up again.+      ptr = this;+    }++    interlocked_exchange_pointer(&connect_ex_, ptr);+  }++  return reinterpret_cast<connect_ex_fn>(ptr == this ? 0 : ptr);+#endif // defined(ASIO_DISABLE_CONNECTEX)+}++win_iocp_socket_service_base::nt_set_info_fn+win_iocp_socket_service_base::get_nt_set_info()+{+  void* ptr = interlocked_compare_exchange_pointer(&nt_set_info_, 0, 0);+  if (!ptr)+  {+    if (HMODULE h = ::GetModuleHandleA("NTDLL.DLL"))+      ptr = reinterpret_cast<void*>(GetProcAddress(h, "NtSetInformationFile"));++    // On failure, set nt_set_info_ to a special value to indicate that the+    // NtSetInformationFile function is unavailable. That way we won't bother+    // trying to look it up again.+    interlocked_exchange_pointer(&nt_set_info_, ptr ? ptr : this);+  }++  return reinterpret_cast<nt_set_info_fn>(ptr == this ? 0 : ptr);+}++void* win_iocp_socket_service_base::interlocked_compare_exchange_pointer(+    void** dest, void* exch, void* cmp)+{+#if defined(_M_IX86)+  return reinterpret_cast<void*>(InterlockedCompareExchange(+        reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(exch),+        reinterpret_cast<LONG>(cmp)));+#else+  return InterlockedCompareExchangePointer(dest, exch, cmp);+#endif+}++void* win_iocp_socket_service_base::interlocked_exchange_pointer(+    void** dest, void* val)+{+#if defined(_M_IX86)+  return reinterpret_cast<void*>(InterlockedExchange(+        reinterpret_cast<PLONG>(dest), reinterpret_cast<LONG>(val)));+#else+  return InterlockedExchangePointer(dest, val);+#endif+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_IMPL_WIN_IOCP_SOCKET_SERVICE_BASE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_mutex.ipp view
@@ -0,0 +1,84 @@+//+// detail/impl/win_mutex.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_MUTEX_IPP+#define ASIO_DETAIL_IMPL_WIN_MUTEX_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS)++#include "asio/detail/throw_error.hpp"+#include "asio/detail/win_mutex.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++win_mutex::win_mutex()+{+  int error = do_init();+  asio::error_code ec(error,+      asio::error::get_system_category());+  asio::detail::throw_error(ec, "mutex");+}++int win_mutex::do_init()+{+#if defined(__MINGW32__)+  // Not sure if MinGW supports structured exception handling, so for now+  // we'll just call the Windows API and hope.+# if defined(UNDER_CE)+  ::InitializeCriticalSection(&crit_section_);+# elif defined(ASIO_WINDOWS_APP)+  if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0))+    return ::GetLastError();+# else+  if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))+    return ::GetLastError();+# endif+  return 0;+#else+  __try+  {+# if defined(UNDER_CE)+    ::InitializeCriticalSection(&crit_section_);+# elif defined(ASIO_WINDOWS_APP)+    if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0))+      return ::GetLastError();+# else+    if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))+      return ::GetLastError();+# endif+  }+  __except(GetExceptionCode() == STATUS_NO_MEMORY+      ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)+  {+    return ERROR_OUTOFMEMORY;+  }++  return 0;+#endif+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS)++#endif // ASIO_DETAIL_IMPL_WIN_MUTEX_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_object_handle_service.ipp view
@@ -0,0 +1,448 @@+//+// detail/impl/win_object_handle_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2011 Boris Schaeling (boris@highscore.de)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_OBJECT_HANDLE_SERVICE_IPP+#define ASIO_DETAIL_IMPL_WIN_OBJECT_HANDLE_SERVICE_IPP++#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_WINDOWS_OBJECT_HANDLE)++#include "asio/detail/win_object_handle_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++win_object_handle_service::win_object_handle_service(execution_context& context)+  : execution_context_service_base<win_object_handle_service>(context),+    scheduler_(asio::use_service<scheduler_impl>(context)),+    mutex_(),+    impl_list_(0),+    shutdown_(false)+{+}++void win_object_handle_service::shutdown()+{+  mutex::scoped_lock lock(mutex_);++  // Setting this flag to true prevents new objects from being registered, and+  // new asynchronous wait operations from being started. We only need to worry+  // about cleaning up the operations that are currently in progress.+  shutdown_ = true;++  op_queue<operation> ops;+  for (implementation_type* impl = impl_list_; impl; impl = impl->next_)+    ops.push(impl->op_queue_);++  lock.unlock();++  scheduler_.abandon_operations(ops);+}++void win_object_handle_service::construct(+    win_object_handle_service::implementation_type& impl)+{+  impl.handle_ = INVALID_HANDLE_VALUE;+  impl.wait_handle_ = INVALID_HANDLE_VALUE;+  impl.owner_ = this;++  // Insert implementation into linked list of all implementations.+  mutex::scoped_lock lock(mutex_);+  if (!shutdown_)+  {+    impl.next_ = impl_list_;+    impl.prev_ = 0;+    if (impl_list_)+      impl_list_->prev_ = &impl;+    impl_list_ = &impl;+  }+}++void win_object_handle_service::move_construct(+    win_object_handle_service::implementation_type& impl,+    win_object_handle_service::implementation_type& other_impl)+{+  mutex::scoped_lock lock(mutex_);++  // Insert implementation into linked list of all implementations.+  if (!shutdown_)+  {+    impl.next_ = impl_list_;+    impl.prev_ = 0;+    if (impl_list_)+      impl_list_->prev_ = &impl;+    impl_list_ = &impl;+  }++  impl.handle_ = other_impl.handle_;+  other_impl.handle_ = INVALID_HANDLE_VALUE;+  impl.wait_handle_ = other_impl.wait_handle_;+  other_impl.wait_handle_ = INVALID_HANDLE_VALUE;+  impl.op_queue_.push(other_impl.op_queue_);+  impl.owner_ = this;++  // We must not hold the lock while calling UnregisterWaitEx. This is because+  // the registered callback function might be invoked while we are waiting for+  // UnregisterWaitEx to complete.+  lock.unlock();++  if (impl.wait_handle_ != INVALID_HANDLE_VALUE)+    ::UnregisterWaitEx(impl.wait_handle_, INVALID_HANDLE_VALUE);++  if (!impl.op_queue_.empty())+    register_wait_callback(impl, lock);+}++void win_object_handle_service::move_assign(+    win_object_handle_service::implementation_type& impl,+    win_object_handle_service& other_service,+    win_object_handle_service::implementation_type& other_impl)+{+  asio::error_code ignored_ec;+  close(impl, ignored_ec);++  mutex::scoped_lock lock(mutex_);++  if (this != &other_service)+  {+    // Remove implementation from linked list of all implementations.+    if (impl_list_ == &impl)+      impl_list_ = impl.next_;+    if (impl.prev_)+      impl.prev_->next_ = impl.next_;+    if (impl.next_)+      impl.next_->prev_= impl.prev_;+    impl.next_ = 0;+    impl.prev_ = 0;+  }++  impl.handle_ = other_impl.handle_;+  other_impl.handle_ = INVALID_HANDLE_VALUE;+  impl.wait_handle_ = other_impl.wait_handle_;+  other_impl.wait_handle_ = INVALID_HANDLE_VALUE;+  impl.op_queue_.push(other_impl.op_queue_);+  impl.owner_ = this;++  if (this != &other_service)+  {+    // Insert implementation into linked list of all implementations.+    impl.next_ = other_service.impl_list_;+    impl.prev_ = 0;+    if (other_service.impl_list_)+      other_service.impl_list_->prev_ = &impl;+    other_service.impl_list_ = &impl;+  }++  // We must not hold the lock while calling UnregisterWaitEx. This is because+  // the registered callback function might be invoked while we are waiting for+  // UnregisterWaitEx to complete.+  lock.unlock();++  if (impl.wait_handle_ != INVALID_HANDLE_VALUE)+    ::UnregisterWaitEx(impl.wait_handle_, INVALID_HANDLE_VALUE);++  if (!impl.op_queue_.empty())+    register_wait_callback(impl, lock);+}++void win_object_handle_service::destroy(+    win_object_handle_service::implementation_type& impl)+{+  mutex::scoped_lock lock(mutex_);++  // Remove implementation from linked list of all implementations.+  if (impl_list_ == &impl)+    impl_list_ = impl.next_;+  if (impl.prev_)+    impl.prev_->next_ = impl.next_;+  if (impl.next_)+    impl.next_->prev_= impl.prev_;+  impl.next_ = 0;+  impl.prev_ = 0;++  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((scheduler_.context(), "object_handle",+          &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "close"));++    HANDLE wait_handle = impl.wait_handle_;+    impl.wait_handle_ = INVALID_HANDLE_VALUE;++    op_queue<operation> ops;+    while (wait_op* op = impl.op_queue_.front())+    {+      op->ec_ = asio::error::operation_aborted;+      impl.op_queue_.pop();+      ops.push(op);+    }++    // We must not hold the lock while calling UnregisterWaitEx. This is+    // because the registered callback function might be invoked while we are+    // waiting for UnregisterWaitEx to complete.+    lock.unlock();++    if (wait_handle != INVALID_HANDLE_VALUE)+      ::UnregisterWaitEx(wait_handle, INVALID_HANDLE_VALUE);++    ::CloseHandle(impl.handle_);+    impl.handle_ = INVALID_HANDLE_VALUE;++    scheduler_.post_deferred_completions(ops);+  }+}++asio::error_code win_object_handle_service::assign(+    win_object_handle_service::implementation_type& impl,+    const native_handle_type& handle, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  impl.handle_ = handle;+  ec = asio::error_code();+  return ec;+}++asio::error_code win_object_handle_service::close(+    win_object_handle_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((scheduler_.context(), "object_handle",+          &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "close"));++    mutex::scoped_lock lock(mutex_);++    HANDLE wait_handle = impl.wait_handle_;+    impl.wait_handle_ = INVALID_HANDLE_VALUE;++    op_queue<operation> completed_ops;+    while (wait_op* op = impl.op_queue_.front())+    {+      impl.op_queue_.pop();+      op->ec_ = asio::error::operation_aborted;+      completed_ops.push(op);+    }++    // We must not hold the lock while calling UnregisterWaitEx. This is+    // because the registered callback function might be invoked while we are+    // waiting for UnregisterWaitEx to complete.+    lock.unlock();++    if (wait_handle != INVALID_HANDLE_VALUE)+      ::UnregisterWaitEx(wait_handle, INVALID_HANDLE_VALUE);++    if (::CloseHandle(impl.handle_))+    {+      impl.handle_ = INVALID_HANDLE_VALUE;+      ec = asio::error_code();+    }+    else+    {+      DWORD last_error = ::GetLastError();+      ec = asio::error_code(last_error,+          asio::error::get_system_category());+    }++    scheduler_.post_deferred_completions(completed_ops);+  }+  else+  {+    ec = asio::error_code();+  }++  return ec;+}++asio::error_code win_object_handle_service::cancel(+    win_object_handle_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((scheduler_.context(), "object_handle",+          &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "cancel"));++    mutex::scoped_lock lock(mutex_);++    HANDLE wait_handle = impl.wait_handle_;+    impl.wait_handle_ = INVALID_HANDLE_VALUE;++    op_queue<operation> completed_ops;+    while (wait_op* op = impl.op_queue_.front())+    {+      op->ec_ = asio::error::operation_aborted;+      impl.op_queue_.pop();+      completed_ops.push(op);+    }++    // We must not hold the lock while calling UnregisterWaitEx. This is+    // because the registered callback function might be invoked while we are+    // waiting for UnregisterWaitEx to complete.+    lock.unlock();++    if (wait_handle != INVALID_HANDLE_VALUE)+      ::UnregisterWaitEx(wait_handle, INVALID_HANDLE_VALUE);++    ec = asio::error_code();++    scheduler_.post_deferred_completions(completed_ops);+  }+  else+  {+    ec = asio::error::bad_descriptor;+  }++  return ec;+}++void win_object_handle_service::wait(+    win_object_handle_service::implementation_type& impl,+    asio::error_code& ec)+{+  switch (::WaitForSingleObject(impl.handle_, INFINITE))+  {+  case WAIT_FAILED:+    {+      DWORD last_error = ::GetLastError();+      ec = asio::error_code(last_error,+          asio::error::get_system_category());+      break;+    }+  case WAIT_OBJECT_0:+  case WAIT_ABANDONED:+  default:+    ec = asio::error_code();+    break;+  }+}++void win_object_handle_service::start_wait_op(+    win_object_handle_service::implementation_type& impl, wait_op* op)+{+  scheduler_.work_started();++  if (is_open(impl))+  {+    mutex::scoped_lock lock(mutex_);++    if (!shutdown_)+    {+      impl.op_queue_.push(op);++      // Only the first operation to be queued gets to register a wait callback.+      // Subsequent operations have to wait for the first to finish.+      if (impl.op_queue_.front() == op)+        register_wait_callback(impl, lock);+    }+    else+    {+      lock.unlock();+      scheduler_.post_deferred_completion(op);+    }+  }+  else+  {+    op->ec_ = asio::error::bad_descriptor;+    scheduler_.post_deferred_completion(op);+  }+}++void win_object_handle_service::register_wait_callback(+    win_object_handle_service::implementation_type& impl,+    mutex::scoped_lock& lock)+{+  lock.lock();++  if (!RegisterWaitForSingleObject(&impl.wait_handle_,+        impl.handle_, &win_object_handle_service::wait_callback,+        &impl, INFINITE, WT_EXECUTEONLYONCE))+  {+    DWORD last_error = ::GetLastError();+    asio::error_code ec(last_error,+        asio::error::get_system_category());++    op_queue<operation> completed_ops;+    while (wait_op* op = impl.op_queue_.front())+    {+      op->ec_ = ec;+      impl.op_queue_.pop();+      completed_ops.push(op);+    }++    lock.unlock();+    scheduler_.post_deferred_completions(completed_ops);+  }+}++void win_object_handle_service::wait_callback(PVOID param, BOOLEAN)+{+  implementation_type* impl = static_cast<implementation_type*>(param);+  mutex::scoped_lock lock(impl->owner_->mutex_);++  if (impl->wait_handle_ != INVALID_HANDLE_VALUE)+  {+    ::UnregisterWaitEx(impl->wait_handle_, NULL);+    impl->wait_handle_ = INVALID_HANDLE_VALUE;+  }++  if (wait_op* op = impl->op_queue_.front())+  {+    op_queue<operation> completed_ops;++    op->ec_ = asio::error_code();+    impl->op_queue_.pop();+    completed_ops.push(op);++    if (!impl->op_queue_.empty())+    {+      if (!RegisterWaitForSingleObject(&impl->wait_handle_,+            impl->handle_, &win_object_handle_service::wait_callback,+            param, INFINITE, WT_EXECUTEONLYONCE))+      {+        DWORD last_error = ::GetLastError();+        asio::error_code ec(last_error,+            asio::error::get_system_category());++        while ((op = impl->op_queue_.front()) != 0)+        {+          op->ec_ = ec;+          impl->op_queue_.pop();+          completed_ops.push(op);+        }+      }+    }++    scheduler_impl& sched = impl->owner_->scheduler_;+    lock.unlock();+    sched.post_deferred_completions(completed_ops);+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE)++#endif // ASIO_DETAIL_IMPL_WIN_OBJECT_HANDLE_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_static_mutex.ipp view
@@ -0,0 +1,136 @@+//+// detail/impl/win_static_mutex.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP+#define ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS)++#include <cstdio>+#include "asio/detail/throw_error.hpp"+#include "asio/detail/win_static_mutex.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++void win_static_mutex::init()+{+  int error = do_init();+  asio::error_code ec(error,+      asio::error::get_system_category());+  asio::detail::throw_error(ec, "static_mutex");+}++int win_static_mutex::do_init()+{+  using namespace std; // For sprintf.+  wchar_t mutex_name[128];+#if defined(ASIO_HAS_SECURE_RTL)+  swprintf_s(+#else // defined(ASIO_HAS_SECURE_RTL)+  _snwprintf(+#endif // defined(ASIO_HAS_SECURE_RTL)+      mutex_name, 128, L"asio-58CCDC44-6264-4842-90C2-F3C545CB8AA7-%u-%p",+      static_cast<unsigned int>(::GetCurrentProcessId()), this);++#if defined(ASIO_WINDOWS_APP)+  HANDLE mutex = ::CreateMutexExW(0, mutex_name, CREATE_MUTEX_INITIAL_OWNER, 0);+#else // defined(ASIO_WINDOWS_APP)+  HANDLE mutex = ::CreateMutexW(0, TRUE, mutex_name);+#endif // defined(ASIO_WINDOWS_APP)+  DWORD last_error = ::GetLastError();+  if (mutex == 0)+    return ::GetLastError();++  if (last_error == ERROR_ALREADY_EXISTS)+  {+#if defined(ASIO_WINDOWS_APP)+    ::WaitForSingleObjectEx(mutex, INFINITE, false);+#else // defined(ASIO_WINDOWS_APP)+    ::WaitForSingleObject(mutex, INFINITE);+#endif // defined(ASIO_WINDOWS_APP)+  }++  if (initialised_)+  {+    ::ReleaseMutex(mutex);+    ::CloseHandle(mutex);+    return 0;+  }++#if defined(__MINGW32__)+  // Not sure if MinGW supports structured exception handling, so for now+  // we'll just call the Windows API and hope.+# if defined(UNDER_CE)+  ::InitializeCriticalSection(&crit_section_);+# else+  if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))+  {+    last_error = ::GetLastError();+    ::ReleaseMutex(mutex);+    ::CloseHandle(mutex);+    return last_error;+  }+# endif+#else+  __try+  {+# if defined(UNDER_CE)+    ::InitializeCriticalSection(&crit_section_);+# elif defined(ASIO_WINDOWS_APP)+    if (!::InitializeCriticalSectionEx(&crit_section_, 0, 0))+    {+      last_error = ::GetLastError();+      ::ReleaseMutex(mutex);+      ::CloseHandle(mutex);+      return last_error;+    }+# else+    if (!::InitializeCriticalSectionAndSpinCount(&crit_section_, 0x80000000))+    {+      last_error = ::GetLastError();+      ::ReleaseMutex(mutex);+      ::CloseHandle(mutex);+      return last_error;+    }+# endif+  }+  __except(GetExceptionCode() == STATUS_NO_MEMORY+      ? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)+  {+    ::ReleaseMutex(mutex);+    ::CloseHandle(mutex);+    return ERROR_OUTOFMEMORY;+  }+#endif++  initialised_ = true;+  ::ReleaseMutex(mutex);+  ::CloseHandle(mutex);+  return 0;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS)++#endif // ASIO_DETAIL_IMPL_WIN_STATIC_MUTEX_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_thread.ipp view
@@ -0,0 +1,150 @@+//+// detail/impl/win_thread.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_THREAD_IPP+#define ASIO_DETAIL_IMPL_WIN_THREAD_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_APP) \+  && !defined(UNDER_CE)++#include <process.h>+#include "asio/detail/throw_error.hpp"+#include "asio/detail/win_thread.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++win_thread::~win_thread()+{+  ::CloseHandle(thread_);++  // The exit_event_ handle is deliberately allowed to leak here since it+  // is an error for the owner of an internal thread not to join() it.+}++void win_thread::join()+{+  HANDLE handles[2] = { exit_event_, thread_ };+  ::WaitForMultipleObjects(2, handles, FALSE, INFINITE);+  ::CloseHandle(exit_event_);+  if (terminate_threads())+  {+    ::TerminateThread(thread_, 0);+  }+  else+  {+    ::QueueUserAPC(apc_function, thread_, 0);+    ::WaitForSingleObject(thread_, INFINITE);+  }+}++std::size_t win_thread::hardware_concurrency()+{+  SYSTEM_INFO system_info;+  ::GetSystemInfo(&system_info);+  return system_info.dwNumberOfProcessors;+}++void win_thread::start_thread(func_base* arg, unsigned int stack_size)+{+  ::HANDLE entry_event = 0;+  arg->entry_event_ = entry_event = ::CreateEventW(0, true, false, 0);+  if (!entry_event)+  {+    DWORD last_error = ::GetLastError();+    delete arg;+    asio::error_code ec(last_error,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "thread.entry_event");+  }++  arg->exit_event_ = exit_event_ = ::CreateEventW(0, true, false, 0);+  if (!exit_event_)+  {+    DWORD last_error = ::GetLastError();+    delete arg;+    asio::error_code ec(last_error,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "thread.exit_event");+  }++  unsigned int thread_id = 0;+  thread_ = reinterpret_cast<HANDLE>(::_beginthreadex(0,+        stack_size, win_thread_function, arg, 0, &thread_id));+  if (!thread_)+  {+    DWORD last_error = ::GetLastError();+    delete arg;+    if (entry_event)+      ::CloseHandle(entry_event);+    if (exit_event_)+      ::CloseHandle(exit_event_);+    asio::error_code ec(last_error,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "thread");+  }++  if (entry_event)+  {+    ::WaitForSingleObject(entry_event, INFINITE);+    ::CloseHandle(entry_event);+  }+}++unsigned int __stdcall win_thread_function(void* arg)+{+  win_thread::auto_func_base_ptr func = {+      static_cast<win_thread::func_base*>(arg) };++  ::SetEvent(func.ptr->entry_event_);++  func.ptr->run();++  // Signal that the thread has finished its work, but rather than returning go+  // to sleep to put the thread into a well known state. If the thread is being+  // joined during global object destruction then it may be killed using+  // TerminateThread (to avoid a deadlock in DllMain). Otherwise, the SleepEx+  // call will be interrupted using QueueUserAPC and the thread will shut down+  // cleanly.+  HANDLE exit_event = func.ptr->exit_event_;+  delete func.ptr;+  func.ptr = 0;+  ::SetEvent(exit_event);+  ::SleepEx(INFINITE, TRUE);++  return 0;+}++#if defined(WINVER) && (WINVER < 0x0500)+void __stdcall apc_function(ULONG) {}+#else+void __stdcall apc_function(ULONG_PTR) {}+#endif++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS)+       // && !defined(ASIO_WINDOWS_APP)+       // && !defined(UNDER_CE)++#endif // ASIO_DETAIL_IMPL_WIN_THREAD_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_tss_ptr.ipp view
@@ -0,0 +1,57 @@+//+// detail/impl/win_tss_ptr.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP+#define ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS)++#include "asio/detail/throw_error.hpp"+#include "asio/detail/win_tss_ptr.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++DWORD win_tss_ptr_create()+{+#if defined(UNDER_CE)+  const DWORD out_of_indexes = 0xFFFFFFFF;+#else+  const DWORD out_of_indexes = TLS_OUT_OF_INDEXES;+#endif++  DWORD tss_key = ::TlsAlloc();+  if (tss_key == out_of_indexes)+  {+    DWORD last_error = ::GetLastError();+    asio::error_code ec(last_error,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "tss");+  }+  return tss_key;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS)++#endif // ASIO_DETAIL_IMPL_WIN_TSS_PTR_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp view
@@ -0,0 +1,626 @@+//+// detail/impl/winrt_ssocket_service_base.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WINRT_SSOCKET_SERVICE_BASE_IPP+#define ASIO_DETAIL_IMPL_WINRT_SSOCKET_SERVICE_BASE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)++#include <cstring>+#include "asio/detail/winrt_ssocket_service_base.hpp"+#include "asio/detail/winrt_async_op.hpp"+#include "asio/detail/winrt_utils.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++winrt_ssocket_service_base::winrt_ssocket_service_base(+    execution_context& context)+  : scheduler_(use_service<scheduler_impl>(context)),+    async_manager_(use_service<winrt_async_manager>(context)),+    mutex_(),+    impl_list_(0)+{+}++void winrt_ssocket_service_base::base_shutdown()+{+  // Close all implementations, causing all operations to complete.+  asio::detail::mutex::scoped_lock lock(mutex_);+  base_implementation_type* impl = impl_list_;+  while (impl)+  {+    asio::error_code ignored_ec;+    close(*impl, ignored_ec);+    impl = impl->next_;+  }+}++void winrt_ssocket_service_base::construct(+    winrt_ssocket_service_base::base_implementation_type& impl)+{+  // Insert implementation into linked list of all implementations.+  asio::detail::mutex::scoped_lock lock(mutex_);+  impl.next_ = impl_list_;+  impl.prev_ = 0;+  if (impl_list_)+    impl_list_->prev_ = &impl;+  impl_list_ = &impl;+}++void winrt_ssocket_service_base::base_move_construct(+    winrt_ssocket_service_base::base_implementation_type& impl,+    winrt_ssocket_service_base::base_implementation_type& other_impl)+  ASIO_NOEXCEPT+{+  impl.socket_ = other_impl.socket_;+  other_impl.socket_ = nullptr;++  // Insert implementation into linked list of all implementations.+  asio::detail::mutex::scoped_lock lock(mutex_);+  impl.next_ = impl_list_;+  impl.prev_ = 0;+  if (impl_list_)+    impl_list_->prev_ = &impl;+  impl_list_ = &impl;+}++void winrt_ssocket_service_base::base_move_assign(+    winrt_ssocket_service_base::base_implementation_type& impl,+    winrt_ssocket_service_base& other_service,+    winrt_ssocket_service_base::base_implementation_type& other_impl)+{+  asio::error_code ignored_ec;+  close(impl, ignored_ec);++  if (this != &other_service)+  {+    // Remove implementation from linked list of all implementations.+    asio::detail::mutex::scoped_lock lock(mutex_);+    if (impl_list_ == &impl)+      impl_list_ = impl.next_;+    if (impl.prev_)+      impl.prev_->next_ = impl.next_;+    if (impl.next_)+      impl.next_->prev_= impl.prev_;+    impl.next_ = 0;+    impl.prev_ = 0;+  }++  impl.socket_ = other_impl.socket_;+  other_impl.socket_ = nullptr;++  if (this != &other_service)+  {+    // Insert implementation into linked list of all implementations.+    asio::detail::mutex::scoped_lock lock(other_service.mutex_);+    impl.next_ = other_service.impl_list_;+    impl.prev_ = 0;+    if (other_service.impl_list_)+      other_service.impl_list_->prev_ = &impl;+    other_service.impl_list_ = &impl;+  }+}++void winrt_ssocket_service_base::destroy(+    winrt_ssocket_service_base::base_implementation_type& impl)+{+  asio::error_code ignored_ec;+  close(impl, ignored_ec);++  // Remove implementation from linked list of all implementations.+  asio::detail::mutex::scoped_lock lock(mutex_);+  if (impl_list_ == &impl)+    impl_list_ = impl.next_;+  if (impl.prev_)+    impl.prev_->next_ = impl.next_;+  if (impl.next_)+    impl.next_->prev_= impl.prev_;+  impl.next_ = 0;+  impl.prev_ = 0;+}++asio::error_code winrt_ssocket_service_base::close(+    winrt_ssocket_service_base::base_implementation_type& impl,+    asio::error_code& ec)+{+  delete impl.socket_;+  impl.socket_ = nullptr;+  ec = asio::error_code();+  return ec;+}++winrt_ssocket_service_base::native_handle_type+winrt_ssocket_service_base::release(+    winrt_ssocket_service_base::base_implementation_type& impl,+    asio::error_code& ec)+{+  if (!is_open(impl))+    return nullptr;++  cancel(impl, ec);+  if (ec)+    return nullptr;++  native_handle_type tmp = impl.socket_;+  impl.socket_ = nullptr;+  return tmp;+}++std::size_t winrt_ssocket_service_base::do_get_endpoint(+    const base_implementation_type& impl, bool local,+    void* addr, std::size_t addr_len, asio::error_code& ec) const+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return addr_len;+  }++  try+  {+    std::string addr_string = winrt_utils::string(local+        ? impl.socket_->Information->LocalAddress->CanonicalName+        : impl.socket_->Information->RemoteAddress->CanonicalName);+    unsigned short port = winrt_utils::integer(local+        ? impl.socket_->Information->LocalPort+        : impl.socket_->Information->RemotePort);+    unsigned long scope = 0;++    switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family)+    {+    case ASIO_OS_DEF(AF_INET):+      if (addr_len < sizeof(sockaddr_in4_type))+      {+        ec = asio::error::invalid_argument;+        return addr_len;+      }+      else+      {+        socket_ops::inet_pton(ASIO_OS_DEF(AF_INET), addr_string.c_str(),+            &reinterpret_cast<sockaddr_in4_type*>(addr)->sin_addr, &scope, ec);+        reinterpret_cast<sockaddr_in4_type*>(addr)->sin_port+          = socket_ops::host_to_network_short(port);+        ec = asio::error_code();+        return sizeof(sockaddr_in4_type);+      }+    case ASIO_OS_DEF(AF_INET6):+      if (addr_len < sizeof(sockaddr_in6_type))+      {+        ec = asio::error::invalid_argument;+        return addr_len;+      }+      else+      {+        socket_ops::inet_pton(ASIO_OS_DEF(AF_INET6), addr_string.c_str(),+            &reinterpret_cast<sockaddr_in6_type*>(addr)->sin6_addr, &scope, ec);+        reinterpret_cast<sockaddr_in6_type*>(addr)->sin6_port+          = socket_ops::host_to_network_short(port);+        ec = asio::error_code();+        return sizeof(sockaddr_in6_type);+      }+    default:+      ec = asio::error::address_family_not_supported;+      return addr_len;+    }+  }+  catch (Platform::Exception^ e)+  {+    ec = asio::error_code(e->HResult,+        asio::system_category());+    return addr_len;+  }+}++asio::error_code winrt_ssocket_service_base::do_set_option(+    winrt_ssocket_service_base::base_implementation_type& impl,+    int level, int optname, const void* optval,+    std::size_t optlen, asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return ec;+  }++  try+  {+    if (level == ASIO_OS_DEF(SOL_SOCKET)+        && optname == ASIO_OS_DEF(SO_KEEPALIVE))+    {+      if (optlen == sizeof(int))+      {+        int value = 0;+        std::memcpy(&value, optval, optlen);+        impl.socket_->Control->KeepAlive = !!value;+        ec = asio::error_code();+      }+      else+      {+        ec = asio::error::invalid_argument;+      }+    }+    else if (level == ASIO_OS_DEF(IPPROTO_TCP)+        && optname == ASIO_OS_DEF(TCP_NODELAY))+    {+      if (optlen == sizeof(int))+      {+        int value = 0;+        std::memcpy(&value, optval, optlen);+        impl.socket_->Control->NoDelay = !!value;+        ec = asio::error_code();+      }+      else+      {+        ec = asio::error::invalid_argument;+      }+    }+    else+    {+      ec = asio::error::invalid_argument;+    }+  }+  catch (Platform::Exception^ e)+  {+    ec = asio::error_code(e->HResult,+        asio::system_category());+  }++  return ec;+}++void winrt_ssocket_service_base::do_get_option(+    const winrt_ssocket_service_base::base_implementation_type& impl,+    int level, int optname, void* optval,+    std::size_t* optlen, asio::error_code& ec) const+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return;+  }++  try+  {+    if (level == ASIO_OS_DEF(SOL_SOCKET)+        && optname == ASIO_OS_DEF(SO_KEEPALIVE))+    {+      if (*optlen >= sizeof(int))+      {+        int value = impl.socket_->Control->KeepAlive ? 1 : 0;+        std::memcpy(optval, &value, sizeof(int));+        *optlen = sizeof(int);+        ec = asio::error_code();+      }+      else+      {+        ec = asio::error::invalid_argument;+      }+    }+    else if (level == ASIO_OS_DEF(IPPROTO_TCP)+        && optname == ASIO_OS_DEF(TCP_NODELAY))+    {+      if (*optlen >= sizeof(int))+      {+        int value = impl.socket_->Control->NoDelay ? 1 : 0;+        std::memcpy(optval, &value, sizeof(int));+        *optlen = sizeof(int);+        ec = asio::error_code();+      }+      else+      {+        ec = asio::error::invalid_argument;+      }+    }+    else+    {+      ec = asio::error::invalid_argument;+    }+  }+  catch (Platform::Exception^ e)+  {+    ec = asio::error_code(e->HResult,+        asio::system_category());+  }+}++asio::error_code winrt_ssocket_service_base::do_connect(+    winrt_ssocket_service_base::base_implementation_type& impl,+    const void* addr, asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return ec;+  }++  char addr_string[max_addr_v6_str_len];+  unsigned short port;+  switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family)+  {+  case ASIO_OS_DEF(AF_INET):+    socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET),+        &reinterpret_cast<const sockaddr_in4_type*>(addr)->sin_addr,+        addr_string, sizeof(addr_string), 0, ec);+    port = socket_ops::network_to_host_short(+        reinterpret_cast<const sockaddr_in4_type*>(addr)->sin_port);+    break;+  case ASIO_OS_DEF(AF_INET6):+    socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET6),+        &reinterpret_cast<const sockaddr_in6_type*>(addr)->sin6_addr,+        addr_string, sizeof(addr_string), 0, ec);+    port = socket_ops::network_to_host_short(+        reinterpret_cast<const sockaddr_in6_type*>(addr)->sin6_port);+    break;+  default:+    ec = asio::error::address_family_not_supported;+    return ec;+  }++  if (!ec) try+  {+    async_manager_.sync(impl.socket_->ConnectAsync(+          ref new Windows::Networking::HostName(+            winrt_utils::string(addr_string)),+          winrt_utils::string(port)), ec);+  }+  catch (Platform::Exception^ e)+  {+    ec = asio::error_code(e->HResult,+        asio::system_category());+  }++  return ec;+}++void winrt_ssocket_service_base::start_connect_op(+    winrt_ssocket_service_base::base_implementation_type& impl,+    const void* addr, winrt_async_op<void>* op, bool is_continuation)+{+  if (!is_open(impl))+  {+    op->ec_ = asio::error::bad_descriptor;+    scheduler_.post_immediate_completion(op, is_continuation);+    return;+  }++  char addr_string[max_addr_v6_str_len];+  unsigned short port = 0;+  switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family)+  {+  case ASIO_OS_DEF(AF_INET):+    socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET),+        &reinterpret_cast<const sockaddr_in4_type*>(addr)->sin_addr,+        addr_string, sizeof(addr_string), 0, op->ec_);+    port = socket_ops::network_to_host_short(+        reinterpret_cast<const sockaddr_in4_type*>(addr)->sin_port);+    break;+  case ASIO_OS_DEF(AF_INET6):+    socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET6),+        &reinterpret_cast<const sockaddr_in6_type*>(addr)->sin6_addr,+        addr_string, sizeof(addr_string), 0, op->ec_);+    port = socket_ops::network_to_host_short(+        reinterpret_cast<const sockaddr_in6_type*>(addr)->sin6_port);+    break;+  default:+    op->ec_ = asio::error::address_family_not_supported;+    break;+  }++  if (op->ec_)+  {+    scheduler_.post_immediate_completion(op, is_continuation);+    return;+  }++  try+  {+    async_manager_.async(impl.socket_->ConnectAsync(+          ref new Windows::Networking::HostName(+            winrt_utils::string(addr_string)),+          winrt_utils::string(port)), op);+  }+  catch (Platform::Exception^ e)+  {+    op->ec_ = asio::error_code(+        e->HResult, asio::system_category());+    scheduler_.post_immediate_completion(op, is_continuation);+  }+}++std::size_t winrt_ssocket_service_base::do_send(+    winrt_ssocket_service_base::base_implementation_type& impl,+    const asio::const_buffer& data,+    socket_base::message_flags flags, asio::error_code& ec)+{+  if (flags)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  try+  {+    buffer_sequence_adapter<asio::const_buffer,+      asio::const_buffer> bufs(asio::buffer(data));++    if (bufs.all_empty())+    {+      ec = asio::error_code();+      return 0;+    }++    return async_manager_.sync(+        impl.socket_->OutputStream->WriteAsync(bufs.buffers()[0]), ec);+  }+  catch (Platform::Exception^ e)+  {+    ec = asio::error_code(e->HResult,+        asio::system_category());+    return 0;+  }+}++void winrt_ssocket_service_base::start_send_op(+      winrt_ssocket_service_base::base_implementation_type& impl,+      const asio::const_buffer& data, socket_base::message_flags flags,+      winrt_async_op<unsigned int>* op, bool is_continuation)+{+  if (flags)+  {+    op->ec_ = asio::error::operation_not_supported;+    scheduler_.post_immediate_completion(op, is_continuation);+    return;+  }++  if (!is_open(impl))+  {+    op->ec_ = asio::error::bad_descriptor;+    scheduler_.post_immediate_completion(op, is_continuation);+    return;+  }++  try+  {+    buffer_sequence_adapter<asio::const_buffer,+        asio::const_buffer> bufs(asio::buffer(data));++    if (bufs.all_empty())+    {+      scheduler_.post_immediate_completion(op, is_continuation);+      return;+    }++    async_manager_.async(+        impl.socket_->OutputStream->WriteAsync(bufs.buffers()[0]), op);+  }+  catch (Platform::Exception^ e)+  {+    op->ec_ = asio::error_code(e->HResult,+        asio::system_category());+    scheduler_.post_immediate_completion(op, is_continuation);+  }+}++std::size_t winrt_ssocket_service_base::do_receive(+    winrt_ssocket_service_base::base_implementation_type& impl,+    const asio::mutable_buffer& data,+    socket_base::message_flags flags, asio::error_code& ec)+{+  if (flags)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    return 0;+  }++  try+  {+    buffer_sequence_adapter<asio::mutable_buffer,+        asio::mutable_buffer> bufs(asio::buffer(data));++    if (bufs.all_empty())+    {+      ec = asio::error_code();+      return 0;+    }++    async_manager_.sync(+        impl.socket_->InputStream->ReadAsync(+          bufs.buffers()[0], bufs.buffers()[0]->Capacity,+          Windows::Storage::Streams::InputStreamOptions::Partial), ec);++    std::size_t bytes_transferred = bufs.buffers()[0]->Length;+    if (bytes_transferred == 0 && !ec)+    {+      ec = asio::error::eof;+    }++    return bytes_transferred;+  }+  catch (Platform::Exception^ e)+  {+    ec = asio::error_code(e->HResult,+        asio::system_category());+    return 0;+  }+}++void winrt_ssocket_service_base::start_receive_op(+      winrt_ssocket_service_base::base_implementation_type& impl,+      const asio::mutable_buffer& data, socket_base::message_flags flags,+      winrt_async_op<Windows::Storage::Streams::IBuffer^>* op,+      bool is_continuation)+{+  if (flags)+  {+    op->ec_ = asio::error::operation_not_supported;+    scheduler_.post_immediate_completion(op, is_continuation);+    return;+  }++  if (!is_open(impl))+  {+    op->ec_ = asio::error::bad_descriptor;+    scheduler_.post_immediate_completion(op, is_continuation);+    return;+  }++  try+  {+    buffer_sequence_adapter<asio::mutable_buffer,+        asio::mutable_buffer> bufs(asio::buffer(data));++    if (bufs.all_empty())+    {+      scheduler_.post_immediate_completion(op, is_continuation);+      return;+    }++    async_manager_.async(+        impl.socket_->InputStream->ReadAsync(+          bufs.buffers()[0], bufs.buffers()[0]->Capacity,+          Windows::Storage::Streams::InputStreamOptions::Partial), op);+  }+  catch (Platform::Exception^ e)+  {+    op->ec_ = asio::error_code(e->HResult,+        asio::system_category());+    scheduler_.post_immediate_completion(op, is_continuation);+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_IMPL_WINRT_SSOCKET_SERVICE_BASE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp view
@@ -0,0 +1,92 @@+//+// detail/impl/winrt_timer_scheduler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_HPP+#define ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_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_WINDOWS_RUNTIME)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Time_Traits>+void winrt_timer_scheduler::add_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_add_timer_queue(queue);+}++// Remove a timer queue from the reactor.+template <typename Time_Traits>+void winrt_timer_scheduler::remove_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_remove_timer_queue(queue);+}++template <typename Time_Traits>+void winrt_timer_scheduler::schedule_timer(timer_queue<Time_Traits>& queue,+    const typename Time_Traits::time_type& time,+    typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op)+{+  asio::detail::mutex::scoped_lock lock(mutex_);++  if (shutdown_)+  {+    scheduler_.post_immediate_completion(op, false);+    return;+  }++  bool earliest = queue.enqueue_timer(time, timer, op);+  scheduler_.work_started();+  if (earliest)+    event_.signal(lock);+}++template <typename Time_Traits>+std::size_t winrt_timer_scheduler::cancel_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& timer,+    std::size_t max_cancelled)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+  return n;+}++template <typename Time_Traits>+void winrt_timer_scheduler::move_timer(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data& to,+    typename timer_queue<Time_Traits>::per_timer_data& from)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer(to, ops);+  queue.move_timer(to, from);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp view
@@ -0,0 +1,121 @@+//+// detail/impl/winrt_timer_scheduler.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_IPP+#define ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/winrt_timer_scheduler.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++winrt_timer_scheduler::winrt_timer_scheduler(execution_context& context)+  : execution_context_service_base<winrt_timer_scheduler>(context),+    scheduler_(use_service<scheduler_impl>(context)),+    mutex_(),+    event_(),+    timer_queues_(),+    thread_(0),+    stop_thread_(false),+    shutdown_(false)+{+  thread_ = new asio::detail::thread(+      bind_handler(&winrt_timer_scheduler::call_run_thread, this));+}++winrt_timer_scheduler::~winrt_timer_scheduler()+{+  shutdown();+}++void winrt_timer_scheduler::shutdown()+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  shutdown_ = true;+  stop_thread_ = true;+  event_.signal(lock);+  lock.unlock();++  if (thread_)+  {+    thread_->join();+    delete thread_;+    thread_ = 0;+  }++  op_queue<operation> ops;+  timer_queues_.get_all_timers(ops);+  scheduler_.abandon_operations(ops);+}++void winrt_timer_scheduler::notify_fork(execution_context::fork_event)+{+}++void winrt_timer_scheduler::init_task()+{+}++void winrt_timer_scheduler::run_thread()+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  while (!stop_thread_)+  {+    const long max_wait_duration = 5 * 60 * 1000000;+    long wait_duration = timer_queues_.wait_duration_usec(max_wait_duration);+    event_.wait_for_usec(lock, wait_duration);+    event_.clear(lock);+    op_queue<operation> ops;+    timer_queues_.get_ready_timers(ops);+    if (!ops.empty())+    {+      lock.unlock();+      scheduler_.post_deferred_completions(ops);+      lock.lock();+    }+  }+}++void winrt_timer_scheduler::call_run_thread(winrt_timer_scheduler* scheduler)+{+  scheduler->run_thread();+}++void winrt_timer_scheduler::do_add_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.insert(&queue);+}++void winrt_timer_scheduler::do_remove_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.erase(&queue);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_IMPL_WINRT_TIMER_SCHEDULER_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/winsock_init.ipp view
@@ -0,0 +1,82 @@+//+// detail/impl/winsock_init.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IMPL_WINSOCK_INIT_IPP+#define ASIO_DETAIL_IMPL_WINSOCK_INIT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)++#include "asio/detail/socket_types.hpp"+#include "asio/detail/winsock_init.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++void winsock_init_base::startup(data& d,+    unsigned char major, unsigned char minor)+{+  if (::InterlockedIncrement(&d.init_count_) == 1)+  {+    WSADATA wsa_data;+    long result = ::WSAStartup(MAKEWORD(major, minor), &wsa_data);+    ::InterlockedExchange(&d.result_, result);+  }+}++void winsock_init_base::manual_startup(data& d)+{+  if (::InterlockedIncrement(&d.init_count_) == 1)+  {+    ::InterlockedExchange(&d.result_, 0);+  }+}++void winsock_init_base::cleanup(data& d)+{+  if (::InterlockedDecrement(&d.init_count_) == 0)+  {+    ::WSACleanup();+  }+}++void winsock_init_base::manual_cleanup(data& d)+{+  ::InterlockedDecrement(&d.init_count_);+}++void winsock_init_base::throw_on_error(data& d)+{+  long result = ::InterlockedExchangeAdd(&d.result_, 0);+  if (result != 0)+  {+    asio::error_code ec(result,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "winsock");+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++#endif // ASIO_DETAIL_IMPL_WINSOCK_INIT_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_control.hpp view
@@ -0,0 +1,84 @@+//+// detail/io_control.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_CONTROL_HPP+#define ASIO_DETAIL_IO_CONTROL_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/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {+namespace io_control {++// I/O control command for getting number of bytes available.+class bytes_readable+{+public:+  // Default constructor.+  bytes_readable()+    : value_(0)+  {+  }++  // Construct with a specific command value.+  bytes_readable(std::size_t value)+    : value_(static_cast<detail::ioctl_arg_type>(value))+  {+  }++  // Get the name of the IO control command.+  int name() const+  {+    return static_cast<int>(ASIO_OS_DEF(FIONREAD));+  }++  // Set the value of the I/O control command.+  void set(std::size_t value)+  {+    value_ = static_cast<detail::ioctl_arg_type>(value);+  }++  // Get the current value of the I/O control command.+  std::size_t get() const+  {+    return static_cast<std::size_t>(value_);+  }++  // Get the address of the command data.+  detail::ioctl_arg_type* data()+  {+    return &value_;+  }++  // Get the address of the command data.+  const detail::ioctl_arg_type* data() const+  {+    return &value_;+  }++private:+  detail::ioctl_arg_type value_;+};++} // namespace io_control+} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IO_CONTROL_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_object_impl.hpp view
@@ -0,0 +1,175 @@+//+// io_object_impl.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IO_OBJECT_IMPL_HPP+#define ASIO_DETAIL_IO_OBJECT_IMPL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include <new>+#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/context.hpp"+#include "asio/io_context.hpp"+#include "asio/query.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename IoObjectService,+    typename Executor = io_context::executor_type>+class io_object_impl+{+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;++  // The type of the executor associated with the object.+  typedef Executor executor_type;++  // Construct an I/O object using an executor.+  explicit io_object_impl(const executor_type& ex)+    : service_(&asio::use_service<IoObjectService>(+          io_object_impl::get_context(ex))),+      executor_(ex)+  {+    service_->construct(implementation_);+  }++  // Construct an I/O object using an execution context.+  template <typename ExecutionContext>+  explicit io_object_impl(ExecutionContext& context,+      typename enable_if<is_convertible<+        ExecutionContext&, execution_context&>::value>::type* = 0)+    : service_(&asio::use_service<IoObjectService>(context)),+      executor_(context.get_executor())+  {+    service_->construct(implementation_);+  }++#if defined(ASIO_HAS_MOVE)+  // Move-construct an I/O object.+  io_object_impl(io_object_impl&& other)+    : service_(&other.get_service()),+      executor_(other.get_executor())+  {+    service_->move_construct(implementation_, other.implementation_);+  }++  // Perform a converting move-construction of an I/O object.+  template <typename IoObjectService1, typename Executor1>+  io_object_impl(io_object_impl<IoObjectService1, Executor1>&& other)+    : service_(&asio::use_service<IoObjectService>(+            io_object_impl::get_context(other.get_executor()))),+      executor_(other.get_executor())+  {+    service_->converting_move_construct(implementation_,+        other.get_service(), other.get_implementation());+  }+#endif // defined(ASIO_HAS_MOVE)++  // Destructor.+  ~io_object_impl()+  {+    service_->destroy(implementation_);+  }++#if defined(ASIO_HAS_MOVE)+  // Move-assign an I/O object.+  io_object_impl& operator=(io_object_impl&& other)+  {+    if (this != &other)+    {+      service_->move_assign(implementation_,+          *other.service_, other.implementation_);+      executor_.~executor_type();+      new (&executor_) executor_type(+          std::move(other.executor_));+      service_ = other.service_;+    }+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  // Get the executor associated with the object.+  const executor_type& get_executor() ASIO_NOEXCEPT+  {+    return executor_;+  }++  // 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:+  // 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();+  }++  // Disallow copying and copy assignment.+  io_object_impl(const io_object_impl&);+  io_object_impl& operator=(const io_object_impl&);++  // The service associated with the I/O object.+  service_type* service_;++  // The underlying implementation of the I/O object.+  implementation_type implementation_;++  // The associated executor.+  executor_type executor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IO_OBJECT_IMPL_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/is_buffer_sequence.hpp view
@@ -0,0 +1,312 @@+//+// detail/is_buffer_sequence.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IS_BUFFER_SEQUENCE_HPP+#define ASIO_DETAIL_IS_BUFFER_SEQUENCE_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/push_options.hpp"++namespace asio {++class mutable_buffer;+class const_buffer;++namespace detail {++struct buffer_sequence_memfns_base+{+  void begin();+  void end();+  void size();+  void max_size();+  void capacity();+  void data();+  void prepare();+  void commit();+  void consume();+  void grow();+  void shrink();+};++template <typename T>+struct buffer_sequence_memfns_derived+  : T, buffer_sequence_memfns_base+{+};++template <typename T, T>+struct buffer_sequence_memfns_check+{+};++#if defined(ASIO_HAS_DECLTYPE)++template <typename>+char buffer_sequence_begin_helper(...);++template <typename T>+char (&buffer_sequence_begin_helper(T* t,+    typename enable_if<!is_same<+      decltype(asio::buffer_sequence_begin(*t)),+        void>::value>::type*))[2];++#else // defined(ASIO_HAS_DECLTYPE)++template <typename>+char (&buffer_sequence_begin_helper(...))[2];++template <typename T>+char buffer_sequence_begin_helper(T* t,+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::begin>*);++#endif // defined(ASIO_HAS_DECLTYPE)++#if defined(ASIO_HAS_DECLTYPE)++template <typename>+char buffer_sequence_end_helper(...);++template <typename T>+char (&buffer_sequence_end_helper(T* t,+    typename enable_if<!is_same<+      decltype(asio::buffer_sequence_end(*t)),+        void>::value>::type*))[2];++#else // defined(ASIO_HAS_DECLTYPE)++template <typename>+char (&buffer_sequence_end_helper(...))[2];++template <typename T>+char buffer_sequence_end_helper(T* t,+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::end>*);++#endif // defined(ASIO_HAS_DECLTYPE)++template <typename>+char (&size_memfn_helper(...))[2];++template <typename T>+char size_memfn_helper(+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::size>*);++template <typename>+char (&max_size_memfn_helper(...))[2];++template <typename T>+char max_size_memfn_helper(+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::max_size>*);++template <typename>+char (&capacity_memfn_helper(...))[2];++template <typename T>+char capacity_memfn_helper(+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::capacity>*);++template <typename>+char (&data_memfn_helper(...))[2];++template <typename T>+char data_memfn_helper(+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::data>*);++template <typename>+char (&prepare_memfn_helper(...))[2];++template <typename T>+char prepare_memfn_helper(+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::prepare>*);++template <typename>+char (&commit_memfn_helper(...))[2];++template <typename T>+char commit_memfn_helper(+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::commit>*);++template <typename>+char (&consume_memfn_helper(...))[2];++template <typename T>+char consume_memfn_helper(+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::consume>*);++template <typename>+char (&grow_memfn_helper(...))[2];++template <typename T>+char grow_memfn_helper(+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::grow>*);++template <typename>+char (&shrink_memfn_helper(...))[2];++template <typename T>+char shrink_memfn_helper(+    buffer_sequence_memfns_check<+      void (buffer_sequence_memfns_base::*)(),+      &buffer_sequence_memfns_derived<T>::shrink>*);++template <typename, typename>+char (&buffer_sequence_element_type_helper(...))[2];++#if defined(ASIO_HAS_DECLTYPE)++template <typename T, typename Buffer>+char buffer_sequence_element_type_helper(T* t,+    typename enable_if<is_convertible<+      decltype(*asio::buffer_sequence_begin(*t)),+        Buffer>::value>::type*);++#else // defined(ASIO_HAS_DECLTYPE)++template <typename T, typename Buffer>+char buffer_sequence_element_type_helper(+    typename T::const_iterator*,+    typename enable_if<is_convertible<+      typename T::value_type, Buffer>::value>::type*);++#endif // defined(ASIO_HAS_DECLTYPE)++template <typename>+char (&const_buffers_type_typedef_helper(...))[2];++template <typename T>+char const_buffers_type_typedef_helper(+    typename T::const_buffers_type*);++template <typename>+char (&mutable_buffers_type_typedef_helper(...))[2];++template <typename T>+char mutable_buffers_type_typedef_helper(+    typename T::mutable_buffers_type*);++template <typename T, typename Buffer>+struct is_buffer_sequence_class+  : integral_constant<bool,+      sizeof(buffer_sequence_begin_helper<T>(0, 0)) != 1 &&+      sizeof(buffer_sequence_end_helper<T>(0, 0)) != 1 &&+      sizeof(buffer_sequence_element_type_helper<T, Buffer>(0, 0)) == 1>+{+};++template <typename T, typename Buffer>+struct is_buffer_sequence+  : conditional<is_class<T>::value,+      is_buffer_sequence_class<T, Buffer>,+      false_type>::type+{+};++template <>+struct is_buffer_sequence<mutable_buffer, mutable_buffer>+  : true_type+{+};++template <>+struct is_buffer_sequence<mutable_buffer, const_buffer>+  : true_type+{+};++template <>+struct is_buffer_sequence<const_buffer, const_buffer>+  : true_type+{+};++template <>+struct is_buffer_sequence<const_buffer, mutable_buffer>+  : false_type+{+};++template <typename T>+struct is_dynamic_buffer_class_v1+  : integral_constant<bool,+      sizeof(size_memfn_helper<T>(0)) != 1 &&+      sizeof(max_size_memfn_helper<T>(0)) != 1 &&+      sizeof(capacity_memfn_helper<T>(0)) != 1 &&+      sizeof(data_memfn_helper<T>(0)) != 1 &&+      sizeof(consume_memfn_helper<T>(0)) != 1 &&+      sizeof(prepare_memfn_helper<T>(0)) != 1 &&+      sizeof(commit_memfn_helper<T>(0)) != 1 &&+      sizeof(const_buffers_type_typedef_helper<T>(0)) == 1 &&+      sizeof(mutable_buffers_type_typedef_helper<T>(0)) == 1>+{+};++template <typename T>+struct is_dynamic_buffer_v1+  : conditional<is_class<T>::value,+      is_dynamic_buffer_class_v1<T>,+      false_type>::type+{+};++template <typename T>+struct is_dynamic_buffer_class_v2+  : integral_constant<bool,+      sizeof(size_memfn_helper<T>(0)) != 1 &&+      sizeof(max_size_memfn_helper<T>(0)) != 1 &&+      sizeof(capacity_memfn_helper<T>(0)) != 1 &&+      sizeof(data_memfn_helper<T>(0)) != 1 &&+      sizeof(consume_memfn_helper<T>(0)) != 1 &&+      sizeof(grow_memfn_helper<T>(0)) != 1 &&+      sizeof(shrink_memfn_helper<T>(0)) != 1 &&+      sizeof(const_buffers_type_typedef_helper<T>(0)) == 1 &&+      sizeof(mutable_buffers_type_typedef_helper<T>(0)) == 1>+{+};++template <typename T>+struct is_dynamic_buffer_v2+  : conditional<is_class<T>::value,+      is_dynamic_buffer_class_v2<T>,+      false_type>::type+{+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IS_BUFFER_SEQUENCE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/is_executor.hpp view
@@ -0,0 +1,126 @@+//+// detail/is_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_IS_EXECUTOR_HPP+#define ASIO_DETAIL_IS_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/push_options.hpp"++namespace asio {+namespace detail {++struct executor_memfns_base+{+  void context();+  void on_work_started();+  void on_work_finished();+  void dispatch();+  void post();+  void defer();+};++template <typename T>+struct executor_memfns_derived+  : T, executor_memfns_base+{+};++template <typename T, T>+struct executor_memfns_check+{+};++template <typename>+char (&context_memfn_helper(...))[2];++template <typename T>+char context_memfn_helper(+    executor_memfns_check<+      void (executor_memfns_base::*)(),+      &executor_memfns_derived<T>::context>*);++template <typename>+char (&on_work_started_memfn_helper(...))[2];++template <typename T>+char on_work_started_memfn_helper(+    executor_memfns_check<+      void (executor_memfns_base::*)(),+      &executor_memfns_derived<T>::on_work_started>*);++template <typename>+char (&on_work_finished_memfn_helper(...))[2];++template <typename T>+char on_work_finished_memfn_helper(+    executor_memfns_check<+      void (executor_memfns_base::*)(),+      &executor_memfns_derived<T>::on_work_finished>*);++template <typename>+char (&dispatch_memfn_helper(...))[2];++template <typename T>+char dispatch_memfn_helper(+    executor_memfns_check<+      void (executor_memfns_base::*)(),+      &executor_memfns_derived<T>::dispatch>*);++template <typename>+char (&post_memfn_helper(...))[2];++template <typename T>+char post_memfn_helper(+    executor_memfns_check<+      void (executor_memfns_base::*)(),+      &executor_memfns_derived<T>::post>*);++template <typename>+char (&defer_memfn_helper(...))[2];++template <typename T>+char defer_memfn_helper(+    executor_memfns_check<+      void (executor_memfns_base::*)(),+      &executor_memfns_derived<T>::defer>*);++template <typename T>+struct is_executor_class+  : integral_constant<bool,+      sizeof(context_memfn_helper<T>(0)) != 1 &&+      sizeof(on_work_started_memfn_helper<T>(0)) != 1 &&+      sizeof(on_work_finished_memfn_helper<T>(0)) != 1 &&+      sizeof(dispatch_memfn_helper<T>(0)) != 1 &&+      sizeof(post_memfn_helper<T>(0)) != 1 &&+      sizeof(defer_memfn_helper<T>(0)) != 1>+{+};++template <typename T>+struct is_executor+  : conditional<is_class<T>::value,+      is_executor_class<T>,+      false_type>::type+{+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IS_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/keyword_tss_ptr.hpp view
@@ -0,0 +1,70 @@+//+// detail/keyword_tss_ptr.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_KEYWORD_TSS_PTR_HPP+#define ASIO_DETAIL_KEYWORD_TSS_PTR_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_THREAD_KEYWORD_EXTENSION)++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename T>+class keyword_tss_ptr+  : private noncopyable+{+public:+  // Constructor.+  keyword_tss_ptr()+  {+  }++  // Destructor.+  ~keyword_tss_ptr()+  {+  }++  // Get the value.+  operator T*() const+  {+    return value_;+  }++  // Set the value.+  void operator=(T* value)+  {+    value_ = value;+  }++private:+  static ASIO_THREAD_KEYWORD T* value_;+};++template <typename T>+ASIO_THREAD_KEYWORD T* keyword_tss_ptr<T>::value_;++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_THREAD_KEYWORD_EXTENSION)++#endif // ASIO_DETAIL_KEYWORD_TSS_PTR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/kqueue_reactor.hpp view
@@ -0,0 +1,242 @@+//+// detail/kqueue_reactor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2005 Stefan Arentz (stefan at soze dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_KQUEUE_REACTOR_HPP+#define ASIO_DETAIL_KQUEUE_REACTOR_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_KQUEUE)++#include <cstddef>+#include <sys/types.h>+#include <sys/event.h>+#include <sys/time.h>+#include "asio/detail/limits.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/object_pool.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/select_interrupter.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/timer_queue_base.hpp"+#include "asio/detail/timer_queue_set.hpp"+#include "asio/detail/wait_op.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"++// Older versions of Mac OS X may not define EV_OOBAND.+#if !defined(EV_OOBAND)+# define EV_OOBAND EV_FLAG1+#endif // !defined(EV_OOBAND)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class scheduler;++class kqueue_reactor+  : public execution_context_service_base<kqueue_reactor>+{+private:+  // The mutex type used by this reactor.+  typedef conditionally_enabled_mutex mutex;++public:+  enum op_types { read_op = 0, write_op = 1,+    connect_op = 1, except_op = 2, max_ops = 3 };++  // Per-descriptor queues.+  struct descriptor_state+  {+    descriptor_state(bool locking) : mutex_(locking) {}++    friend class kqueue_reactor;+    friend class object_pool_access;++    descriptor_state* next_;+    descriptor_state* prev_;++    mutex mutex_;+    int descriptor_;+    int num_kevents_; // 1 == read only, 2 == read and write+    op_queue<reactor_op> op_queue_[max_ops];+    bool shutdown_;+  };++  // Per-descriptor data.+  typedef descriptor_state* per_descriptor_data;++  // Constructor.+  ASIO_DECL kqueue_reactor(asio::execution_context& ctx);++  // Destructor.+  ASIO_DECL ~kqueue_reactor();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Recreate internal descriptors following a fork.+  ASIO_DECL void notify_fork(+      asio::execution_context::fork_event fork_ev);++  // Initialise the task.+  ASIO_DECL void init_task();++  // Register a socket with the reactor. Returns 0 on success, system error+  // code on failure.+  ASIO_DECL int register_descriptor(socket_type descriptor,+      per_descriptor_data& descriptor_data);++  // Register a descriptor with an associated single operation. Returns 0 on+  // success, system error code on failure.+  ASIO_DECL int register_internal_descriptor(+      int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op);++  // Move descriptor registration from one descriptor_data object to another.+  ASIO_DECL void move_descriptor(socket_type descriptor,+      per_descriptor_data& target_descriptor_data,+      per_descriptor_data& source_descriptor_data);++  // Post a reactor operation for immediate completion.+  void post_immediate_completion(reactor_op* op, bool is_continuation)+  {+    scheduler_.post_immediate_completion(op, is_continuation);+  }++  // Start a new operation. The reactor operation will be performed when the+  // given descriptor is flagged as ready, or an error has occurred.+  ASIO_DECL void start_op(int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op,+      bool is_continuation, bool allow_speculative);++  // Cancel all operations associated with the given descriptor. The+  // handlers associated with the descriptor will be invoked with the+  // operation_aborted error.+  ASIO_DECL void cancel_ops(socket_type descriptor,+      per_descriptor_data& descriptor_data);++  // Cancel any operations that are running against the descriptor and remove+  // its registration from the reactor. The reactor resources associated with+  // the descriptor must be released by calling cleanup_descriptor_data.+  ASIO_DECL void deregister_descriptor(socket_type descriptor,+      per_descriptor_data& descriptor_data, bool closing);++  // Remove the descriptor's registration from the reactor. The reactor+  // resources associated with the descriptor must be released by calling+  // cleanup_descriptor_data.+  ASIO_DECL void deregister_internal_descriptor(+      socket_type descriptor, per_descriptor_data& descriptor_data);++  // Perform any post-deregistration cleanup tasks associated with the+  // descriptor data.+  ASIO_DECL void cleanup_descriptor_data(+      per_descriptor_data& descriptor_data);++  // Add a new timer queue to the reactor.+  template <typename Time_Traits>+  void add_timer_queue(timer_queue<Time_Traits>& queue);++  // Remove a timer queue from the reactor.+  template <typename Time_Traits>+  void remove_timer_queue(timer_queue<Time_Traits>& queue);++  // Schedule a new operation in the given timer queue to expire at the+  // specified absolute time.+  template <typename Time_Traits>+  void schedule_timer(timer_queue<Time_Traits>& queue,+      const typename Time_Traits::time_type& time,+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);++  // Cancel the timer operations associated with the given token. Returns the+  // number of operations that have been posted or dispatched.+  template <typename Time_Traits>+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& timer,+      std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++  // Move the timer operations associated with the given timer.+  template <typename Time_Traits>+  void move_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& target,+      typename timer_queue<Time_Traits>::per_timer_data& source);++  // Run the kqueue loop.+  ASIO_DECL void run(long usec, op_queue<operation>& ops);++  // Interrupt the kqueue loop.+  ASIO_DECL void interrupt();++private:+  // Create the kqueue file descriptor. Throws an exception if the descriptor+  // cannot be created.+  ASIO_DECL static int do_kqueue_create();++  // Allocate a new descriptor state object.+  ASIO_DECL descriptor_state* allocate_descriptor_state();++  // Free an existing descriptor state object.+  ASIO_DECL void free_descriptor_state(descriptor_state* s);++  // Helper function to add a new timer queue.+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);++  // Helper function to remove a timer queue.+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);++  // Get the timeout value for the kevent call.+  ASIO_DECL timespec* get_timeout(long usec, timespec& ts);++  // The scheduler used to post completions.+  scheduler& scheduler_;++  // Mutex to protect access to internal data.+  mutex mutex_;++  // The kqueue file descriptor.+  int kqueue_fd_;++  // The interrupter is used to break a blocking kevent call.+  select_interrupter interrupter_;++  // The timer queues.+  timer_queue_set timer_queues_;++  // Whether the service has been shut down.+  bool shutdown_;++  // Mutex to protect access to the registered descriptors.+  mutex registered_descriptors_mutex_;++  // Keep track of all registered descriptors.+  object_pool<descriptor_state> registered_descriptors_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/kqueue_reactor.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/kqueue_reactor.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_KQUEUE)++#endif // ASIO_DETAIL_KQUEUE_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/limits.hpp view
@@ -0,0 +1,26 @@+//+// detail/limits.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2011 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_LIMITS_HPP+#define ASIO_DETAIL_LIMITS_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_LIMITS)+# include <boost/limits.hpp>+#else // defined(ASIO_HAS_BOOST_LIMITS)+# include <limits>+#endif // defined(ASIO_HAS_BOOST_LIMITS)++#endif // ASIO_DETAIL_LIMITS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/local_free_on_block_exit.hpp view
@@ -0,0 +1,59 @@+//+// detail/local_free_on_block_exit.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP+#define ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_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_WINDOWS) || defined(__CYGWIN__)+#if !defined(ASIO_WINDOWS_APP)++#include "asio/detail/noncopyable.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class local_free_on_block_exit+  : private noncopyable+{+public:+  // Constructor blocks all signals for the calling thread.+  explicit local_free_on_block_exit(void* p)+    : p_(p)+  {+  }++  // Destructor restores the previous signal mask.+  ~local_free_on_block_exit()+  {+    ::LocalFree(p_);+  }++private:+  void* p_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS_APP)+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++#endif // ASIO_DETAIL_LOCAL_FREE_ON_BLOCK_EXIT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/macos_fenced_block.hpp view
@@ -0,0 +1,62 @@+//+// detail/macos_fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP+#define ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(__MACH__) && defined(__APPLE__)++#include <libkern/OSAtomic.h>+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class macos_fenced_block+  : private noncopyable+{+public:+  enum half_t { half };+  enum full_t { full };++  // Constructor for a half fenced block.+  explicit macos_fenced_block(half_t)+  {+  }++  // Constructor for a full fenced block.+  explicit macos_fenced_block(full_t)+  {+    OSMemoryBarrier();+  }++  // Destructor.+  ~macos_fenced_block()+  {+    OSMemoryBarrier();+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(__MACH__) && defined(__APPLE__)++#endif // ASIO_DETAIL_MACOS_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/memory.hpp view
@@ -0,0 +1,73 @@+//+// detail/memory.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_MEMORY_HPP+#define ASIO_DETAIL_MEMORY_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <memory>++#if !defined(ASIO_HAS_STD_SHARED_PTR)+# include <boost/make_shared.hpp>+# include <boost/shared_ptr.hpp>+# include <boost/weak_ptr.hpp>+#endif // !defined(ASIO_HAS_STD_SHARED_PTR)++#if !defined(ASIO_HAS_STD_ADDRESSOF)+# include <boost/utility/addressof.hpp>+#endif // !defined(ASIO_HAS_STD_ADDRESSOF)++namespace asio {+namespace detail {++#if defined(ASIO_HAS_STD_SHARED_PTR)+using std::make_shared;+using std::shared_ptr;+using std::weak_ptr;+#else // defined(ASIO_HAS_STD_SHARED_PTR)+using boost::make_shared;+using boost::shared_ptr;+using boost::weak_ptr;+#endif // defined(ASIO_HAS_STD_SHARED_PTR)++#if defined(ASIO_HAS_STD_ADDRESSOF)+using std::addressof;+#else // defined(ASIO_HAS_STD_ADDRESSOF)+using boost::addressof;+#endif // defined(ASIO_HAS_STD_ADDRESSOF)++} // namespace detail++#if defined(ASIO_HAS_CXX11_ALLOCATORS)+using std::allocator_arg_t;+# define ASIO_USES_ALLOCATOR(t) \+  namespace std { \+    template <typename Allocator> \+    struct uses_allocator<t, Allocator> : true_type {}; \+  } \+  /**/+# define ASIO_REBIND_ALLOC(alloc, t) \+  typename std::allocator_traits<alloc>::template rebind_alloc<t>+  /**/+#else // defined(ASIO_HAS_CXX11_ALLOCATORS)+struct allocator_arg_t {};+# define ASIO_USES_ALLOCATOR(t)+# define ASIO_REBIND_ALLOC(alloc, t) \+  typename alloc::template rebind<t>::other+  /**/+#endif // defined(ASIO_HAS_CXX11_ALLOCATORS)++} // namespace asio++#endif // ASIO_DETAIL_MEMORY_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/mutex.hpp view
@@ -0,0 +1,48 @@+//+// detail/mutex.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_MUTEX_HPP+#define ASIO_DETAIL_MUTEX_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_THREADS)+# include "asio/detail/null_mutex.hpp"+#elif defined(ASIO_WINDOWS)+# include "asio/detail/win_mutex.hpp"+#elif defined(ASIO_HAS_PTHREADS)+# include "asio/detail/posix_mutex.hpp"+#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)+# include "asio/detail/std_mutex.hpp"+#else+# error Only Windows, POSIX and std::mutex are supported!+#endif++namespace asio {+namespace detail {++#if !defined(ASIO_HAS_THREADS)+typedef null_mutex mutex;+#elif defined(ASIO_WINDOWS)+typedef win_mutex mutex;+#elif defined(ASIO_HAS_PTHREADS)+typedef posix_mutex mutex;+#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)+typedef std_mutex mutex;+#endif++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/non_const_lvalue.hpp view
@@ -0,0 +1,54 @@+//+// detail/non_const_lvalue.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NON_CONST_LVALUE_HPP+#define ASIO_DETAIL_NON_CONST_LVALUE_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/push_options.hpp"++namespace asio {+namespace detail {++template <typename T>+struct non_const_lvalue+{+#if defined(ASIO_HAS_MOVE)+  explicit non_const_lvalue(T& t)+    : value(static_cast<typename conditional<+        is_same<T, typename decay<T>::type>::value,+          typename decay<T>::type&, T&&>::type>(t))+  {+  }++  typename conditional<is_same<T, typename decay<T>::type>::value,+      typename decay<T>::type&, typename decay<T>::type>::type value;+#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  explicit non_const_lvalue(const typename decay<T>::type& t)+    : value(t)+  {+  }++  typename decay<T>::type value;+#endif // defined(ASIO_HAS_MOVE)+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_NON_CONST_LVALUE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/noncopyable.hpp view
@@ -0,0 +1,43 @@+//+// detail/noncopyable.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NONCOPYABLE_HPP+#define ASIO_DETAIL_NONCOPYABLE_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 {+namespace detail {++class noncopyable+{+protected:+  noncopyable() {}+  ~noncopyable() {}+private:+  noncopyable(const noncopyable&);+  const noncopyable& operator=(const noncopyable&);+};++} // namespace detail++using asio::detail::noncopyable;++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_NONCOPYABLE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_event.hpp view
@@ -0,0 +1,106 @@+//+// detail/null_event.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_EVENT_HPP+#define ASIO_DETAIL_NULL_EVENT_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/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class null_event+  : private noncopyable+{+public:+  // Constructor.+  null_event()+  {+  }++  // Destructor.+  ~null_event()+  {+  }++  // Signal the event. (Retained for backward compatibility.)+  template <typename Lock>+  void signal(Lock&)+  {+  }++  // Signal all waiters.+  template <typename Lock>+  void signal_all(Lock&)+  {+  }++  // Unlock the mutex and signal one waiter.+  template <typename Lock>+  void unlock_and_signal_one(Lock&)+  {+  }++  // Unlock the mutex and signal one waiter who may destroy us.+  template <typename Lock>+  void unlock_and_signal_one_for_destruction(Lock&)+  {+  }++  // If there's a waiter, unlock the mutex and signal it.+  template <typename Lock>+  bool maybe_unlock_and_signal_one(Lock&)+  {+    return false;+  }++  // Reset the event.+  template <typename Lock>+  void clear(Lock&)+  {+  }++  // Wait for the event to become signalled.+  template <typename Lock>+  void wait(Lock&)+  {+    do_wait();+  }++  // Timed wait for the event to become signalled.+  template <typename Lock>+  bool wait_for_usec(Lock&, long usec)+  {+    do_wait_for_usec(usec);+    return true;+  }++private:+  ASIO_DECL static void do_wait();+  ASIO_DECL static void do_wait_for_usec(long usec);+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/null_event.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_NULL_EVENT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_fenced_block.hpp view
@@ -0,0 +1,47 @@+//+// detail/null_fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_FENCED_BLOCK_HPP+#define ASIO_DETAIL_NULL_FENCED_BLOCK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class null_fenced_block+  : private noncopyable+{+public:+  enum half_or_full_t { half, full };++  // Constructor.+  explicit null_fenced_block(half_or_full_t)+  {+  }++  // Destructor.+  ~null_fenced_block()+  {+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_NULL_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_global.hpp view
@@ -0,0 +1,59 @@+//+// detail/null_global.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_GLOBAL_HPP+#define ASIO_DETAIL_NULL_GLOBAL_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 {+namespace detail {++template <typename T>+struct null_global_impl+{+  null_global_impl()+    : ptr_(0)+  {+  }++  // Destructor automatically cleans up the global.+  ~null_global_impl()+  {+    delete ptr_;+  }++  static null_global_impl instance_;+  T* ptr_;+};++template <typename T>+null_global_impl<T> null_global_impl<T>::instance_;++template <typename T>+T& null_global()+{+  if (null_global_impl<T>::instance_.ptr_ == 0)+    null_global_impl<T>::instance_.ptr_ = new T;+  return *null_global_impl<T>::instance_.ptr_;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_NULL_GLOBAL_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_mutex.hpp view
@@ -0,0 +1,64 @@+//+// detail/null_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_MUTEX_HPP+#define ASIO_DETAIL_NULL_MUTEX_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_THREADS)++#include "asio/detail/noncopyable.hpp"+#include "asio/detail/scoped_lock.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class null_mutex+  : private noncopyable+{+public:+  typedef asio::detail::scoped_lock<null_mutex> scoped_lock;++  // Constructor.+  null_mutex()+  {+  }++  // Destructor.+  ~null_mutex()+  {+  }++  // Lock the mutex.+  void lock()+  {+  }++  // Unlock the mutex.+  void unlock()+  {+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_HAS_THREADS)++#endif // ASIO_DETAIL_NULL_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_reactor.hpp view
@@ -0,0 +1,68 @@+//+// detail/null_reactor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_REACTOR_HPP+#define ASIO_DETAIL_NULL_REACTOR_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_IOCP) || defined(ASIO_WINDOWS_RUNTIME)++#include "asio/detail/scheduler_operation.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class null_reactor+  : public execution_context_service_base<null_reactor>+{+public:+  // Constructor.+  null_reactor(asio::execution_context& ctx)+    : execution_context_service_base<null_reactor>(ctx)+  {+  }++  // Destructor.+  ~null_reactor()+  {+  }++  // Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+  }++  // No-op because should never be called.+  void run(long /*usec*/, op_queue<scheduler_operation>& /*ops*/)+  {+  }++  // No-op.+  void interrupt()+  {+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_NULL_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_signal_blocker.hpp view
@@ -0,0 +1,69 @@+//+// detail/null_signal_blocker.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP+#define ASIO_DETAIL_NULL_SIGNAL_BLOCKER_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_THREADS) \+  || defined(ASIO_WINDOWS) \+  || defined(ASIO_WINDOWS_RUNTIME) \+  || defined(__CYGWIN__) \+  || defined(__SYMBIAN32__)++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class null_signal_blocker+  : private noncopyable+{+public:+  // Constructor blocks all signals for the calling thread.+  null_signal_blocker()+  {+  }++  // Destructor restores the previous signal mask.+  ~null_signal_blocker()+  {+  }++  // Block all signals for the calling thread.+  void block()+  {+  }++  // Restore the previous signal mask.+  void unblock()+  {+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_HAS_THREADS)+       // || defined(ASIO_WINDOWS)+       // || defined(ASIO_WINDOWS_RUNTIME)+       // || defined(__CYGWIN__)+       // || defined(__SYMBIAN32__)++#endif // ASIO_DETAIL_NULL_SIGNAL_BLOCKER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_socket_service.hpp view
@@ -0,0 +1,519 @@+//+// detail/null_socket_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_SOCKET_SERVICE_HPP+#define ASIO_DETAIL_NULL_SOCKET_SERVICE_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_WINDOWS_RUNTIME)++#include "asio/buffer.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/post.hpp"+#include "asio/socket_base.hpp"+#include "asio/detail/bind_handler.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol>+class null_socket_service :+  public execution_context_service_base<null_socket_service<Protocol> >+{+public:+  // The protocol type.+  typedef Protocol protocol_type;++  // The endpoint type.+  typedef typename Protocol::endpoint endpoint_type;++  // The native type of a socket.+  typedef int native_handle_type;++  // The implementation type of the socket.+  struct implementation_type+  {+  };++  // Constructor.+  null_socket_service(execution_context& context)+    : execution_context_service_base<null_socket_service<Protocol> >(context)+  {+  }++  // Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+  }++  // Construct a new socket implementation.+  void construct(implementation_type&)+  {+  }++  // Move-construct a new socket implementation.+  void move_construct(implementation_type&, implementation_type&)+  {+  }++  // Move-assign from another socket implementation.+  void move_assign(implementation_type&,+      null_socket_service&, implementation_type&)+  {+  }++  // Move-construct a new socket implementation from another protocol type.+  template <typename Protocol1>+  void converting_move_construct(implementation_type&,+      null_socket_service<Protocol1>&,+      typename null_socket_service<Protocol1>::implementation_type&)+  {+  }++  // Destroy a socket implementation.+  void destroy(implementation_type&)+  {+  }++  // Open a new socket implementation.+  asio::error_code open(implementation_type&,+      const protocol_type&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Assign a native socket to a socket implementation.+  asio::error_code assign(implementation_type&, const protocol_type&,+      const native_handle_type&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Determine whether the socket is open.+  bool is_open(const implementation_type&) const+  {+    return false;+  }++  // Destroy a socket implementation.+  asio::error_code close(implementation_type&,+      asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Release ownership of the socket.+  native_handle_type release(implementation_type&,+      asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Get the native socket representation.+  native_handle_type native_handle(implementation_type&)+  {+    return 0;+  }++  // Cancel all operations associated with the socket.+  asio::error_code cancel(implementation_type&,+      asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Determine whether the socket is at the out-of-band data mark.+  bool at_mark(const implementation_type&,+      asio::error_code& ec) const+  {+    ec = asio::error::operation_not_supported;+    return false;+  }++  // Determine the number of bytes available for reading.+  std::size_t available(const implementation_type&,+      asio::error_code& ec) const+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Place the socket into the state where it will listen for new connections.+  asio::error_code listen(implementation_type&,+      int, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Perform an IO control command on the socket.+  template <typename IO_Control_Command>+  asio::error_code io_control(implementation_type&,+      IO_Control_Command&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Gets the non-blocking mode of the socket.+  bool non_blocking(const implementation_type&) const+  {+    return false;+  }++  // Sets the non-blocking mode of the socket.+  asio::error_code non_blocking(implementation_type&,+      bool, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Gets the non-blocking mode of the native socket implementation.+  bool native_non_blocking(const implementation_type&) const+  {+    return false;+  }++  // Sets the non-blocking mode of the native socket implementation.+  asio::error_code native_non_blocking(implementation_type&,+      bool, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Disable sends or receives on the socket.+  asio::error_code shutdown(implementation_type&,+      socket_base::shutdown_type, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Bind the socket to the specified local endpoint.+  asio::error_code bind(implementation_type&,+      const endpoint_type&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Set a socket option.+  template <typename Option>+  asio::error_code set_option(implementation_type&,+      const Option&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Set a socket option.+  template <typename Option>+  asio::error_code get_option(const implementation_type&,+      Option&, asio::error_code& ec) const+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Get the local endpoint.+  endpoint_type local_endpoint(const implementation_type&,+      asio::error_code& ec) const+  {+    ec = asio::error::operation_not_supported;+    return endpoint_type();+  }++  // Get the remote endpoint.+  endpoint_type remote_endpoint(const implementation_type&,+      asio::error_code& ec) const+  {+    ec = asio::error::operation_not_supported;+    return endpoint_type();+  }++  // Send the given data to the peer.+  template <typename ConstBufferSequence>+  std::size_t send(implementation_type&, const ConstBufferSequence&,+      socket_base::message_flags, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Wait until data can be sent without blocking.+  std::size_t send(implementation_type&, const null_buffers&,+      socket_base::message_flags, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Start an asynchronous send. The data being sent must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_send(implementation_type&, const ConstBufferSequence&,+      socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Start an asynchronous wait until data can be sent without blocking.+  template <typename Handler, typename IoExecutor>+  void async_send(implementation_type&, const null_buffers&,+      socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Receive some data from the peer. Returns the number of bytes received.+  template <typename MutableBufferSequence>+  std::size_t receive(implementation_type&, const MutableBufferSequence&,+      socket_base::message_flags, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Wait until data can be received without blocking.+  std::size_t receive(implementation_type&, const null_buffers&,+      socket_base::message_flags, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received+  // must be valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive(implementation_type&, const MutableBufferSequence&,+      socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive(implementation_type&, const null_buffers&,+      socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Receive some data with associated flags. Returns the number of bytes+  // received.+  template <typename MutableBufferSequence>+  std::size_t receive_with_flags(implementation_type&,+      const MutableBufferSequence&, socket_base::message_flags,+      socket_base::message_flags&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Wait until data can be received without blocking.+  std::size_t receive_with_flags(implementation_type&,+      const null_buffers&, socket_base::message_flags,+      socket_base::message_flags&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received+  // must be valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive_with_flags(implementation_type&,+      const MutableBufferSequence&, socket_base::message_flags,+      socket_base::message_flags&, Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive_with_flags(implementation_type&, const null_buffers&,+      socket_base::message_flags, socket_base::message_flags&,+      Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Send a datagram to the specified endpoint. Returns the number of bytes+  // sent.+  template <typename ConstBufferSequence>+  std::size_t send_to(implementation_type&, const ConstBufferSequence&,+      const endpoint_type&, socket_base::message_flags,+      asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Wait until data can be sent without blocking.+  std::size_t send_to(implementation_type&, const null_buffers&,+      const endpoint_type&, socket_base::message_flags,+      asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Start an asynchronous send. The data being sent must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_send_to(implementation_type&, const ConstBufferSequence&,+      const endpoint_type&, socket_base::message_flags,+      Handler& handler)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Start an asynchronous wait until data can be sent without blocking.+  template <typename Handler, typename IoExecutor>+  void async_send_to(implementation_type&, const null_buffers&,+      const endpoint_type&, socket_base::message_flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Receive a datagram with the endpoint of the sender. Returns the number of+  // bytes received.+  template <typename MutableBufferSequence>+  std::size_t receive_from(implementation_type&, const MutableBufferSequence&,+      endpoint_type&, socket_base::message_flags,+      asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Wait until data can be received without blocking.+  std::size_t receive_from(implementation_type&, const null_buffers&,+      endpoint_type&, socket_base::message_flags,+      asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received and+  // the sender_endpoint object must both be valid for the lifetime of the+  // asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive_from(implementation_type&, const MutableBufferSequence&,+      endpoint_type&, socket_base::message_flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive_from(implementation_type&, const null_buffers&,+      endpoint_type&, socket_base::message_flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex, detail::bind_handler(+          handler, ec, bytes_transferred));+  }++  // Accept a new connection.+  template <typename Socket>+  asio::error_code accept(implementation_type&,+      Socket&, endpoint_type*, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Start an asynchronous accept. The peer and peer_endpoint objects+  // must be valid until the accept's handler is invoked.+  template <typename Socket, typename Handler, typename IoExecutor>+  void async_accept(implementation_type&, Socket&, endpoint_type*,+      Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    asio::post(io_ex, detail::bind_handler(handler, ec));+  }++  // Connect the socket to the specified endpoint.+  asio::error_code connect(implementation_type&,+      const endpoint_type&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Start an asynchronous connect.+  template <typename Handler, typename IoExecutor>+  void async_connect(implementation_type&, const endpoint_type&,+      Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    asio::post(io_ex, detail::bind_handler(handler, ec));+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_NULL_SOCKET_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_static_mutex.hpp view
@@ -0,0 +1,60 @@+//+// detail/null_static_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_STATIC_MUTEX_HPP+#define ASIO_DETAIL_NULL_STATIC_MUTEX_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_THREADS)++#include "asio/detail/scoped_lock.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct null_static_mutex+{+  typedef asio::detail::scoped_lock<null_static_mutex> scoped_lock;++  // Initialise the mutex.+  void init()+  {+  }++  // Lock the mutex.+  void lock()+  {+  }++  // Unlock the mutex.+  void unlock()+  {+  }++  int unused_;+};++#define ASIO_NULL_STATIC_MUTEX_INIT { 0 }++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_HAS_THREADS)++#endif // ASIO_DETAIL_NULL_STATIC_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_thread.hpp view
@@ -0,0 +1,67 @@+//+// detail/null_thread.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_THREAD_HPP+#define ASIO_DETAIL_NULL_THREAD_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_THREADS)++#include "asio/detail/noncopyable.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class null_thread+  : private noncopyable+{+public:+  // Constructor.+  template <typename Function>+  null_thread(Function, unsigned int = 0)+  {+    asio::detail::throw_error(+        asio::error::operation_not_supported, "thread");+  }++  // Destructor.+  ~null_thread()+  {+  }++  // Wait for the thread to exit.+  void join()+  {+  }++  // Get number of CPUs.+  static std::size_t hardware_concurrency()+  {+    return 1;+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_HAS_THREADS)++#endif // ASIO_DETAIL_NULL_THREAD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/null_tss_ptr.hpp view
@@ -0,0 +1,68 @@+//+// detail/null_tss_ptr.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_NULL_TSS_PTR_HPP+#define ASIO_DETAIL_NULL_TSS_PTR_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_THREADS)++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename T>+class null_tss_ptr+  : private noncopyable+{+public:+  // Constructor.+  null_tss_ptr()+    : value_(0)+  {+  }++  // Destructor.+  ~null_tss_ptr()+  {+  }++  // Get the value.+  operator T*() const+  {+    return value_;+  }++  // Set the value.+  void operator=(T* value)+  {+    value_ = value;+  }++private:+  T* value_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_HAS_THREADS)++#endif // ASIO_DETAIL_NULL_TSS_PTR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/object_pool.hpp view
@@ -0,0 +1,171 @@+//+// detail/object_pool.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_OBJECT_POOL_HPP+#define ASIO_DETAIL_OBJECT_POOL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Object>+class object_pool;++class object_pool_access+{+public:+  template <typename Object>+  static Object* create()+  {+    return new Object;+  }++  template <typename Object, typename Arg>+  static Object* create(Arg arg)+  {+    return new Object(arg);+  }++  template <typename Object>+  static void destroy(Object* o)+  {+    delete o;+  }++  template <typename Object>+  static Object*& next(Object* o)+  {+    return o->next_;+  }++  template <typename Object>+  static Object*& prev(Object* o)+  {+    return o->prev_;+  }+};++template <typename Object>+class object_pool+  : private noncopyable+{+public:+  // Constructor.+  object_pool()+    : live_list_(0),+      free_list_(0)+  {+  }++  // Destructor destroys all objects.+  ~object_pool()+  {+    destroy_list(live_list_);+    destroy_list(free_list_);+  }++  // Get the object at the start of the live list.+  Object* first()+  {+    return live_list_;+  }++  // Allocate a new object.+  Object* alloc()+  {+    Object* o = free_list_;+    if (o)+      free_list_ = object_pool_access::next(free_list_);+    else+      o = object_pool_access::create<Object>();++    object_pool_access::next(o) = live_list_;+    object_pool_access::prev(o) = 0;+    if (live_list_)+      object_pool_access::prev(live_list_) = o;+    live_list_ = o;++    return o;+  }++  // Allocate a new object with an argument.+  template <typename Arg>+  Object* alloc(Arg arg)+  {+    Object* o = free_list_;+    if (o)+      free_list_ = object_pool_access::next(free_list_);+    else+      o = object_pool_access::create<Object>(arg);++    object_pool_access::next(o) = live_list_;+    object_pool_access::prev(o) = 0;+    if (live_list_)+      object_pool_access::prev(live_list_) = o;+    live_list_ = o;++    return o;+  }++  // Free an object. Moves it to the free list. No destructors are run.+  void free(Object* o)+  {+    if (live_list_ == o)+      live_list_ = object_pool_access::next(o);++    if (object_pool_access::prev(o))+    {+      object_pool_access::next(object_pool_access::prev(o))+        = object_pool_access::next(o);+    }++    if (object_pool_access::next(o))+    {+      object_pool_access::prev(object_pool_access::next(o))+        = object_pool_access::prev(o);+    }++    object_pool_access::next(o) = free_list_;+    object_pool_access::prev(o) = 0;+    free_list_ = o;+  }++private:+  // Helper function to destroy all elements in a list.+  void destroy_list(Object* list)+  {+    while (list)+    {+      Object* o = list;+      list = object_pool_access::next(o);+      object_pool_access::destroy(o);+    }+  }++  // The list of live objects.+  Object* live_list_;++  // The free list.+  Object* free_list_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_OBJECT_POOL_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/old_win_sdk_compat.hpp view
@@ -0,0 +1,214 @@+//+// detail/old_win_sdk_compat.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP+#define ASIO_DETAIL_OLD_WIN_SDK_COMPAT_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_WINDOWS) || defined(__CYGWIN__)++// Guess whether we are building against on old Platform SDK.+#if !defined(IN6ADDR_ANY_INIT)+#define ASIO_HAS_OLD_WIN_SDK 1+#endif // !defined(IN6ADDR_ANY_INIT)++#if defined(ASIO_HAS_OLD_WIN_SDK)++// Emulation of types that are missing from old Platform SDKs.+//+// N.B. this emulation is also used if building for a Windows 2000 target with+// a recent (i.e. Vista or later) SDK, as the SDK does not provide IPv6 support+// in that case.++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++enum+{+  sockaddr_storage_maxsize = 128, // Maximum size.+  sockaddr_storage_alignsize = (sizeof(__int64)), // Desired alignment.+  sockaddr_storage_pad1size = (sockaddr_storage_alignsize - sizeof(short)),+  sockaddr_storage_pad2size = (sockaddr_storage_maxsize -+      (sizeof(short) + sockaddr_storage_pad1size + sockaddr_storage_alignsize))+};++struct sockaddr_storage_emulation+{+  short ss_family;+  char __ss_pad1[sockaddr_storage_pad1size];+  __int64 __ss_align;+  char __ss_pad2[sockaddr_storage_pad2size];+};++struct in6_addr_emulation+{+  union+  {+    u_char Byte[16];+    u_short Word[8];+  } u;+};++#if !defined(s6_addr)+# define _S6_un u+# define _S6_u8 Byte+# define s6_addr _S6_un._S6_u8+#endif // !defined(s6_addr)++struct sockaddr_in6_emulation+{+  short sin6_family;+  u_short sin6_port;+  u_long sin6_flowinfo;+  in6_addr_emulation sin6_addr;+  u_long sin6_scope_id;+};++struct ipv6_mreq_emulation+{+  in6_addr_emulation ipv6mr_multiaddr;+  unsigned int ipv6mr_interface;+};++struct addrinfo_emulation+{+  int ai_flags;+  int ai_family;+  int ai_socktype;+  int ai_protocol;+  size_t ai_addrlen;+  char* ai_canonname;+  sockaddr* ai_addr;+  addrinfo_emulation* ai_next;+};++#if !defined(AI_PASSIVE)+# define AI_PASSIVE 0x1+#endif++#if !defined(AI_CANONNAME)+# define AI_CANONNAME 0x2+#endif++#if !defined(AI_NUMERICHOST)+# define AI_NUMERICHOST 0x4+#endif++#if !defined(EAI_AGAIN)+# define EAI_AGAIN WSATRY_AGAIN+#endif++#if !defined(EAI_BADFLAGS)+# define EAI_BADFLAGS WSAEINVAL+#endif++#if !defined(EAI_FAIL)+# define EAI_FAIL WSANO_RECOVERY+#endif++#if !defined(EAI_FAMILY)+# define EAI_FAMILY WSAEAFNOSUPPORT+#endif++#if !defined(EAI_MEMORY)+# define EAI_MEMORY WSA_NOT_ENOUGH_MEMORY+#endif++#if !defined(EAI_NODATA)+# define EAI_NODATA WSANO_DATA+#endif++#if !defined(EAI_NONAME)+# define EAI_NONAME WSAHOST_NOT_FOUND+#endif++#if !defined(EAI_SERVICE)+# define EAI_SERVICE WSATYPE_NOT_FOUND+#endif++#if !defined(EAI_SOCKTYPE)+# define EAI_SOCKTYPE WSAESOCKTNOSUPPORT+#endif++#if !defined(NI_NOFQDN)+# define NI_NOFQDN 0x01+#endif++#if !defined(NI_NUMERICHOST)+# define NI_NUMERICHOST 0x02+#endif++#if !defined(NI_NAMEREQD)+# define NI_NAMEREQD 0x04+#endif++#if !defined(NI_NUMERICSERV)+# define NI_NUMERICSERV 0x08+#endif++#if !defined(NI_DGRAM)+# define NI_DGRAM 0x10+#endif++#if !defined(IPPROTO_IPV6)+# define IPPROTO_IPV6 41+#endif++#if !defined(IPV6_UNICAST_HOPS)+# define IPV6_UNICAST_HOPS 4+#endif++#if !defined(IPV6_MULTICAST_IF)+# define IPV6_MULTICAST_IF 9+#endif++#if !defined(IPV6_MULTICAST_HOPS)+# define IPV6_MULTICAST_HOPS 10+#endif++#if !defined(IPV6_MULTICAST_LOOP)+# define IPV6_MULTICAST_LOOP 11+#endif++#if !defined(IPV6_JOIN_GROUP)+# define IPV6_JOIN_GROUP 12+#endif++#if !defined(IPV6_LEAVE_GROUP)+# define IPV6_LEAVE_GROUP 13+#endif++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_OLD_WIN_SDK)++// Even newer Platform SDKs that support IPv6 may not define IPV6_V6ONLY.+#if !defined(IPV6_V6ONLY)+# define IPV6_V6ONLY 27+#endif++// Some SDKs (e.g. Windows CE) don't define IPPROTO_ICMPV6.+#if !defined(IPPROTO_ICMPV6)+# define IPPROTO_ICMPV6 58+#endif++#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++#endif // ASIO_DETAIL_OLD_WIN_SDK_COMPAT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/op_queue.hpp view
@@ -0,0 +1,162 @@+//+// detail/op_queue.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_OP_QUEUE_HPP+#define ASIO_DETAIL_OP_QUEUE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Operation>+class op_queue;++class op_queue_access+{+public:+  template <typename Operation>+  static Operation* next(Operation* o)+  {+    return static_cast<Operation*>(o->next_);+  }++  template <typename Operation1, typename Operation2>+  static void next(Operation1*& o1, Operation2* o2)+  {+    o1->next_ = o2;+  }++  template <typename Operation>+  static void destroy(Operation* o)+  {+    o->destroy();+  }++  template <typename Operation>+  static Operation*& front(op_queue<Operation>& q)+  {+    return q.front_;+  }++  template <typename Operation>+  static Operation*& back(op_queue<Operation>& q)+  {+    return q.back_;+  }+};++template <typename Operation>+class op_queue+  : private noncopyable+{+public:+  // Constructor.+  op_queue()+    : front_(0),+      back_(0)+  {+  }++  // Destructor destroys all operations.+  ~op_queue()+  {+    while (Operation* op = front_)+    {+      pop();+      op_queue_access::destroy(op);+    }+  }++  // Get the operation at the front of the queue.+  Operation* front()+  {+    return front_;+  }++  // Pop an operation from the front of the queue.+  void pop()+  {+    if (front_)+    {+      Operation* tmp = front_;+      front_ = op_queue_access::next(front_);+      if (front_ == 0)+        back_ = 0;+      op_queue_access::next(tmp, static_cast<Operation*>(0));+    }+  }++  // Push an operation on to the back of the queue.+  void push(Operation* h)+  {+    op_queue_access::next(h, static_cast<Operation*>(0));+    if (back_)+    {+      op_queue_access::next(back_, h);+      back_ = h;+    }+    else+    {+      front_ = back_ = h;+    }+  }++  // Push all operations from another queue on to the back of the queue. The+  // source queue may contain operations of a derived type.+  template <typename OtherOperation>+  void push(op_queue<OtherOperation>& q)+  {+    if (Operation* other_front = op_queue_access::front(q))+    {+      if (back_)+        op_queue_access::next(back_, other_front);+      else+        front_ = other_front;+      back_ = op_queue_access::back(q);+      op_queue_access::front(q) = 0;+      op_queue_access::back(q) = 0;+    }+  }++  // Whether the queue is empty.+  bool empty() const+  {+    return front_ == 0;+  }++  // Test whether an operation is already enqueued.+  bool is_enqueued(Operation* o) const+  {+    return op_queue_access::next(o) != 0 || back_ == o;+  }++private:+  friend class op_queue_access;++  // The front of the queue.+  Operation* front_;++  // The back of the queue.+  Operation* back_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_OP_QUEUE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/operation.hpp view
@@ -0,0 +1,38 @@+//+// detail/operation.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_OPERATION_HPP+#define ASIO_DETAIL_OPERATION_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_IOCP)+# include "asio/detail/win_iocp_operation.hpp"+#else+# include "asio/detail/scheduler_operation.hpp"+#endif++namespace asio {+namespace detail {++#if defined(ASIO_HAS_IOCP)+typedef win_iocp_operation operation;+#else+typedef scheduler_operation operation;+#endif++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_OPERATION_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/pipe_select_interrupter.hpp view
@@ -0,0 +1,89 @@+//+// detail/pipe_select_interrupter.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP+#define ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_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_WINDOWS)+#if !defined(ASIO_WINDOWS_RUNTIME)+#if !defined(__CYGWIN__)+#if !defined(__SYMBIAN32__)+#if !defined(ASIO_HAS_EVENTFD)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class pipe_select_interrupter+{+public:+  // Constructor.+  ASIO_DECL pipe_select_interrupter();++  // Destructor.+  ASIO_DECL ~pipe_select_interrupter();++  // Recreate the interrupter's descriptors. Used after a fork.+  ASIO_DECL void recreate();++  // Interrupt the select call.+  ASIO_DECL void interrupt();++  // Reset the select interrupter. Returns true if the reset was successful.+  ASIO_DECL bool reset();++  // Get the read descriptor to be passed to select.+  int read_descriptor() const+  {+    return read_descriptor_;+  }++private:+  // Open the descriptors. Throws on error.+  ASIO_DECL void open_descriptors();++  // Close the descriptors.+  ASIO_DECL void close_descriptors();++  // The read end of a connection used to interrupt the select call. This file+  // descriptor is passed to select such that when it is time to stop, a single+  // byte will be written on the other end of the connection and this+  // descriptor will become readable.+  int read_descriptor_;++  // The write end of a connection used to interrupt the select call. A single+  // byte may be written to this to wake up the select which is waiting for the+  // other end to become readable.+  int write_descriptor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/pipe_select_interrupter.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // !defined(ASIO_HAS_EVENTFD)+#endif // !defined(__SYMBIAN32__)+#endif // !defined(__CYGWIN__)+#endif // !defined(ASIO_WINDOWS_RUNTIME)+#endif // !defined(ASIO_WINDOWS)++#endif // ASIO_DETAIL_PIPE_SELECT_INTERRUPTER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/pop_options.hpp view
@@ -0,0 +1,141 @@+//+// detail/pop_options.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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)+//++// No header guard++#if defined(__COMO__)++// Comeau C++++#elif defined(__DMC__)++// Digital Mars C++++#elif defined(__INTEL_COMPILER) || defined(__ICL) \+  || defined(__ICC) || defined(__ECC)++// Intel C++++# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)+#  if !defined(ASIO_DISABLE_VISIBILITY)+#   pragma GCC visibility pop+#  endif // !defined(ASIO_DISABLE_VISIBILITY)+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)++#elif defined(__clang__)++// Clang++# if defined(__OBJC__)+#  if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1)+#   if defined(ASIO_OBJC_WORKAROUND)+#    undef Protocol+#    undef id+#    undef ASIO_OBJC_WORKAROUND+#   endif+#  endif+# endif++# if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32)+#  if !defined(ASIO_DISABLE_VISIBILITY)+#   pragma GCC visibility pop+#  endif // !defined(ASIO_DISABLE_VISIBILITY)+# endif // !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32)++# pragma GCC diagnostic pop++#elif defined(__GNUC__)++// GNU C++++# if defined(__MINGW32__) || defined(__CYGWIN__)+#  pragma pack (pop)+# endif++# if defined(__OBJC__)+#  if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1)+#   if defined(ASIO_OBJC_WORKAROUND)+#    undef Protocol+#    undef id+#    undef ASIO_OBJC_WORKAROUND+#   endif+#  endif+# endif++# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)+#  if !defined(ASIO_DISABLE_VISIBILITY)+#   pragma GCC visibility pop+#  endif // !defined(ASIO_DISABLE_VISIBILITY)+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)++# pragma GCC diagnostic pop++#elif defined(__KCC)++// Kai C++++#elif defined(__sgi)++// SGI MIPSpro C++++#elif defined(__DECCXX)++// Compaq Tru64 Unix cxx++#elif defined(__ghs)++// Greenhills C++++#elif defined(__BORLANDC__) && !defined(__clang__)++// Borland C++++# pragma option pop+# pragma nopushoptwarn+# pragma nopackwarning++#elif defined(__MWERKS__)++// Metrowerks CodeWarrior++#elif defined(__SUNPRO_CC)++// Sun Workshop Compiler C++++#elif defined(__HP_aCC)++// HP aCC++#elif defined(__MRC__) || defined(__SC__)++// MPW MrCpp or SCpp++#elif defined(__IBMCPP__)++// IBM Visual Age++#elif defined(_MSC_VER)++// Microsoft Visual C+++//+// Must remain the last #elif since some other vendors (Metrowerks, for example)+// also #define _MSC_VER++# pragma warning (pop)+# pragma pack (pop)++# if defined(__cplusplus_cli) || defined(__cplusplus_winrt)+#  if defined(ASIO_CLR_WORKAROUND)+#   undef generic+#   undef ASIO_CLR_WORKAROUND+#  endif+# endif++#endif
+ link/modules/asio-standalone/asio/include/asio/detail/posix_event.hpp view
@@ -0,0 +1,175 @@+//+// detail/posix_event.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_POSIX_EVENT_HPP+#define ASIO_DETAIL_POSIX_EVENT_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_PTHREADS)++#include <cstddef>+#include <pthread.h>+#include "asio/detail/assert.hpp"+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class posix_event+  : private noncopyable+{+public:+  // Constructor.+  ASIO_DECL posix_event();++  // Destructor.+  ~posix_event()+  {+    ::pthread_cond_destroy(&cond_);+  }++  // Signal the event. (Retained for backward compatibility.)+  template <typename Lock>+  void signal(Lock& lock)+  {+    this->signal_all(lock);+  }++  // Signal all waiters.+  template <typename Lock>+  void signal_all(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    (void)lock;+    state_ |= 1;+    ::pthread_cond_broadcast(&cond_); // Ignore EINVAL.+  }++  // Unlock the mutex and signal one waiter.+  template <typename Lock>+  void unlock_and_signal_one(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    state_ |= 1;+    bool have_waiters = (state_ > 1);+    lock.unlock();+    if (have_waiters)+      ::pthread_cond_signal(&cond_); // Ignore EINVAL.+  }++  // Unlock the mutex and signal one waiter who may destroy us.+  template <typename Lock>+  void unlock_and_signal_one_for_destruction(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    state_ |= 1;+    bool have_waiters = (state_ > 1);+    if (have_waiters)+      ::pthread_cond_signal(&cond_); // Ignore EINVAL.+    lock.unlock();+  }++  // If there's a waiter, unlock the mutex and signal it.+  template <typename Lock>+  bool maybe_unlock_and_signal_one(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    state_ |= 1;+    if (state_ > 1)+    {+      lock.unlock();+      ::pthread_cond_signal(&cond_); // Ignore EINVAL.+      return true;+    }+    return false;+  }++  // Reset the event.+  template <typename Lock>+  void clear(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    (void)lock;+    state_ &= ~std::size_t(1);+  }++  // Wait for the event to become signalled.+  template <typename Lock>+  void wait(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    while ((state_ & 1) == 0)+    {+      state_ += 2;+      ::pthread_cond_wait(&cond_, &lock.mutex().mutex_); // Ignore EINVAL.+      state_ -= 2;+    }+  }++  // Timed wait for the event to become signalled.+  template <typename Lock>+  bool wait_for_usec(Lock& lock, long usec)+  {+    ASIO_ASSERT(lock.locked());+    if ((state_ & 1) == 0)+    {+      state_ += 2;+      timespec ts;+#if (defined(__MACH__) && defined(__APPLE__)) \+      || (defined(__ANDROID__) && (__ANDROID_API__ < 21) \+          && defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE))+      ts.tv_sec = usec / 1000000;+      ts.tv_nsec = (usec % 1000000) * 1000;+      ::pthread_cond_timedwait_relative_np(+          &cond_, &lock.mutex().mutex_, &ts); // Ignore EINVAL.+#else // (defined(__MACH__) && defined(__APPLE__))+      // || (defined(__ANDROID__) && (__ANDROID_API__ < 21)+      //     && defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE))+      if (::clock_gettime(CLOCK_MONOTONIC, &ts) == 0)+      {+        ts.tv_sec += usec / 1000000;+        ts.tv_nsec += (usec % 1000000) * 1000;+        ts.tv_sec += ts.tv_nsec / 1000000000;+        ts.tv_nsec = ts.tv_nsec % 1000000000;+        ::pthread_cond_timedwait(&cond_,+            &lock.mutex().mutex_, &ts); // Ignore EINVAL.+      }+#endif // (defined(__MACH__) && defined(__APPLE__))+       // || (defined(__ANDROID__) && (__ANDROID_API__ < 21)+       //     && defined(HAVE_PTHREAD_COND_TIMEDWAIT_RELATIVE))+      state_ -= 2;+    }+    return (state_ & 1) != 0;+  }++private:+  ::pthread_cond_t cond_;+  std::size_t state_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/posix_event.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_POSIX_EVENT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/posix_fd_set_adapter.hpp view
@@ -0,0 +1,118 @@+//+// detail/posix_fd_set_adapter.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP+#define ASIO_DETAIL_POSIX_FD_SET_ADAPTER_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_WINDOWS) \+  && !defined(__CYGWIN__) \+  && !defined(ASIO_WINDOWS_RUNTIME)++#include <cstring>+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/reactor_op_queue.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements.+class posix_fd_set_adapter : noncopyable+{+public:+  posix_fd_set_adapter()+    : max_descriptor_(invalid_socket)+  {+    using namespace std; // Needed for memset on Solaris.+    FD_ZERO(&fd_set_);+  }++  void reset()+  {+    using namespace std; // Needed for memset on Solaris.+    FD_ZERO(&fd_set_);+  }++  bool set(socket_type descriptor)+  {+    if (descriptor < (socket_type)FD_SETSIZE)+    {+      if (max_descriptor_ == invalid_socket || descriptor > max_descriptor_)+        max_descriptor_ = descriptor;+      FD_SET(descriptor, &fd_set_);+      return true;+    }+    return false;+  }++  void set(reactor_op_queue<socket_type>& operations, op_queue<operation>& ops)+  {+    reactor_op_queue<socket_type>::iterator i = operations.begin();+    while (i != operations.end())+    {+      reactor_op_queue<socket_type>::iterator op_iter = i++;+      if (!set(op_iter->first))+      {+        asio::error_code ec(error::fd_set_failure);+        operations.cancel_operations(op_iter, ops, ec);+      }+    }+  }++  bool is_set(socket_type descriptor) const+  {+    return FD_ISSET(descriptor, &fd_set_) != 0;+  }++  operator fd_set*()+  {+    return &fd_set_;+  }++  socket_type max_descriptor() const+  {+    return max_descriptor_;+  }++  void perform(reactor_op_queue<socket_type>& operations,+      op_queue<operation>& ops) const+  {+    reactor_op_queue<socket_type>::iterator i = operations.begin();+    while (i != operations.end())+    {+      reactor_op_queue<socket_type>::iterator op_iter = i++;+      if (is_set(op_iter->first))+        operations.perform_operations(op_iter, ops);+    }+  }++private:+  mutable fd_set fd_set_;+  socket_type max_descriptor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS)+       // && !defined(__CYGWIN__)+       // && !defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_POSIX_FD_SET_ADAPTER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/posix_global.hpp view
@@ -0,0 +1,80 @@+//+// detail/posix_global.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_POSIX_GLOBAL_HPP+#define ASIO_DETAIL_POSIX_GLOBAL_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_PTHREADS)++#include <exception>+#include <pthread.h>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename T>+struct posix_global_impl+{+  // Helper function to perform initialisation.+  static void do_init()+  {+    instance_.static_ptr_ = instance_.ptr_ = new T;+  }++  // Destructor automatically cleans up the global.+  ~posix_global_impl()+  {+    delete static_ptr_;+  }++  static ::pthread_once_t init_once_;+  static T* static_ptr_;+  static posix_global_impl instance_;+  T* ptr_;+};++template <typename T>+::pthread_once_t posix_global_impl<T>::init_once_ = PTHREAD_ONCE_INIT;++template <typename T>+T* posix_global_impl<T>::static_ptr_ = 0;++template <typename T>+posix_global_impl<T> posix_global_impl<T>::instance_;++template <typename T>+T& posix_global()+{+  int result = ::pthread_once(+      &posix_global_impl<T>::init_once_,+      &posix_global_impl<T>::do_init);++  if (result != 0)+    std::terminate();++  return *posix_global_impl<T>::instance_.ptr_;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_POSIX_GLOBAL_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/posix_mutex.hpp view
@@ -0,0 +1,76 @@+//+// detail/posix_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_POSIX_MUTEX_HPP+#define ASIO_DETAIL_POSIX_MUTEX_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_PTHREADS)++#include <pthread.h>+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/scoped_lock.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class posix_event;++class posix_mutex+  : private noncopyable+{+public:+  typedef asio::detail::scoped_lock<posix_mutex> scoped_lock;++  // Constructor.+  ASIO_DECL posix_mutex();++  // Destructor.+  ~posix_mutex()+  {+    ::pthread_mutex_destroy(&mutex_); // Ignore EBUSY.+  }++  // Lock the mutex.+  void lock()+  {+    (void)::pthread_mutex_lock(&mutex_); // Ignore EINVAL.+  }++  // Unlock the mutex.+  void unlock()+  {+    (void)::pthread_mutex_unlock(&mutex_); // Ignore EINVAL.+  }++private:+  friend class posix_event;+  ::pthread_mutex_t mutex_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/posix_mutex.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_POSIX_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/posix_signal_blocker.hpp view
@@ -0,0 +1,85 @@+//+// detail/posix_signal_blocker.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP+#define ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_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_PTHREADS)++#include <csignal>+#include <pthread.h>+#include <signal.h>+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class posix_signal_blocker+  : private noncopyable+{+public:+  // Constructor blocks all signals for the calling thread.+  posix_signal_blocker()+    : blocked_(false)+  {+    sigset_t new_mask;+    sigfillset(&new_mask);+    blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0);+  }++  // Destructor restores the previous signal mask.+  ~posix_signal_blocker()+  {+    if (blocked_)+      pthread_sigmask(SIG_SETMASK, &old_mask_, 0);+  }++  // Block all signals for the calling thread.+  void block()+  {+    if (!blocked_)+    {+      sigset_t new_mask;+      sigfillset(&new_mask);+      blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0);+    }+  }++  // Restore the previous signal mask.+  void unblock()+  {+    if (blocked_)+      blocked_ = (pthread_sigmask(SIG_SETMASK, &old_mask_, 0) != 0);+  }++private:+  // Have signals been blocked.+  bool blocked_;++  // The previous signal mask.+  sigset_t old_mask_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_POSIX_SIGNAL_BLOCKER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/posix_static_mutex.hpp view
@@ -0,0 +1,64 @@+//+// detail/posix_static_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_POSIX_STATIC_MUTEX_HPP+#define ASIO_DETAIL_POSIX_STATIC_MUTEX_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_PTHREADS)++#include <pthread.h>+#include "asio/detail/scoped_lock.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct posix_static_mutex+{+  typedef asio::detail::scoped_lock<posix_static_mutex> scoped_lock;++  // Initialise the mutex.+  void init()+  {+    // Nothing to do.+  }++  // Lock the mutex.+  void lock()+  {+    (void)::pthread_mutex_lock(&mutex_); // Ignore EINVAL.+  }++  // Unlock the mutex.+  void unlock()+  {+    (void)::pthread_mutex_unlock(&mutex_); // Ignore EINVAL.+  }++  ::pthread_mutex_t mutex_;+};++#define ASIO_POSIX_STATIC_MUTEX_INIT { PTHREAD_MUTEX_INITIALIZER }++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_POSIX_STATIC_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/posix_thread.hpp view
@@ -0,0 +1,109 @@+//+// detail/posix_thread.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_POSIX_THREAD_HPP+#define ASIO_DETAIL_POSIX_THREAD_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_PTHREADS)++#include <cstddef>+#include <pthread.h>+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++extern "C"+{+  ASIO_DECL void* asio_detail_posix_thread_function(void* arg);+}++class posix_thread+  : private noncopyable+{+public:+  // Constructor.+  template <typename Function>+  posix_thread(Function f, unsigned int = 0)+    : joined_(false)+  {+    start_thread(new func<Function>(f));+  }++  // Destructor.+  ASIO_DECL ~posix_thread();++  // Wait for the thread to exit.+  ASIO_DECL void join();++  // Get number of CPUs.+  ASIO_DECL static std::size_t hardware_concurrency();++private:+  friend void* asio_detail_posix_thread_function(void* arg);++  class func_base+  {+  public:+    virtual ~func_base() {}+    virtual void run() = 0;+  };++  struct auto_func_base_ptr+  {+    func_base* ptr;+    ~auto_func_base_ptr() { delete ptr; }+  };++  template <typename Function>+  class func+    : public func_base+  {+  public:+    func(Function f)+      : f_(f)+    {+    }++    virtual void run()+    {+      f_();+    }++  private:+    Function f_;+  };++  ASIO_DECL void start_thread(func_base* arg);++  ::pthread_t thread_;+  bool joined_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/posix_thread.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_POSIX_THREAD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/posix_tss_ptr.hpp view
@@ -0,0 +1,79 @@+//+// detail/posix_tss_ptr.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_POSIX_TSS_PTR_HPP+#define ASIO_DETAIL_POSIX_TSS_PTR_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_PTHREADS)++#include <pthread.h>+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper function to create thread-specific storage.+ASIO_DECL void posix_tss_ptr_create(pthread_key_t& key);++template <typename T>+class posix_tss_ptr+  : private noncopyable+{+public:+  // Constructor.+  posix_tss_ptr()+  {+    posix_tss_ptr_create(tss_key_);+  }++  // Destructor.+  ~posix_tss_ptr()+  {+    ::pthread_key_delete(tss_key_);+  }++  // Get the value.+  operator T*() const+  {+    return static_cast<T*>(::pthread_getspecific(tss_key_));+  }++  // Set the value.+  void operator=(T* value)+  {+    ::pthread_setspecific(tss_key_, value);+  }++private:+  // Thread-specific storage to allow unlocked access to determine whether a+  // thread is a member of the pool.+  pthread_key_t tss_key_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/posix_tss_ptr.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_PTHREADS)++#endif // ASIO_DETAIL_POSIX_TSS_PTR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/push_options.hpp view
@@ -0,0 +1,185 @@+//+// detail/push_options.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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)+//++// No header guard++#if defined(__COMO__)++// Comeau C++++#elif defined(__DMC__)++// Digital Mars C++++#elif defined(__INTEL_COMPILER) || defined(__ICL) \+  || defined(__ICC) || defined(__ECC)++// Intel C++++# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)+#  if !defined(ASIO_DISABLE_VISIBILITY)+#   pragma GCC visibility push (default)+#  endif // !defined(ASIO_DISABLE_VISIBILITY)+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)++#elif defined(__clang__)++// Clang++# if defined(__OBJC__)+#  if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1)+#   if !defined(ASIO_DISABLE_OBJC_WORKAROUND)+#    if !defined(Protocol) && !defined(id)+#     define Protocol cpp_Protocol+#     define id cpp_id+#     define ASIO_OBJC_WORKAROUND+#    endif+#   endif+#  endif+# endif++# if !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32)+#  if !defined(ASIO_DISABLE_VISIBILITY)+#   pragma GCC visibility push (default)+#  endif // !defined(ASIO_DISABLE_VISIBILITY)+# endif // !defined(_WIN32) && !defined(__WIN32__) && !defined(WIN32)++# pragma GCC diagnostic push+# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"++#elif defined(__GNUC__)++// GNU C++++# if defined(__MINGW32__) || defined(__CYGWIN__)+#  pragma pack (push, 8)+# endif++# if defined(__OBJC__)+#  if !defined(__APPLE_CC__) || (__APPLE_CC__ <= 1)+#   if !defined(ASIO_DISABLE_OBJC_WORKAROUND)+#    if !defined(Protocol) && !defined(id)+#     define Protocol cpp_Protocol+#     define id cpp_id+#     define ASIO_OBJC_WORKAROUND+#    endif+#   endif+#  endif+# endif++# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)+#  if !defined(ASIO_DISABLE_VISIBILITY)+#   pragma GCC visibility push (default)+#  endif // !defined(ASIO_DISABLE_VISIBILITY)+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4)++# pragma GCC diagnostic push+# pragma GCC diagnostic ignored "-Wnon-virtual-dtor"+# if (__GNUC__ >= 7)+#  pragma GCC diagnostic ignored "-Wimplicit-fallthrough"+# endif // (__GNUC__ >= 7)++#elif defined(__KCC)++// Kai C++++#elif defined(__sgi)++// SGI MIPSpro C++++#elif defined(__DECCXX)++// Compaq Tru64 Unix cxx++#elif defined(__ghs)++// Greenhills C++++#elif defined(__BORLANDC__) && !defined(__clang__)++// Borland C++++# pragma option push -a8 -b -Ve- -Vx- -w-inl -vi-+# pragma nopushoptwarn+# pragma nopackwarning+# if !defined(__MT__)+#  error Multithreaded RTL must be selected.+# endif // !defined(__MT__)++#elif defined(__MWERKS__)++// Metrowerks CodeWarrior++#elif defined(__SUNPRO_CC)++// Sun Workshop Compiler C++++#elif defined(__HP_aCC)++// HP aCC++#elif defined(__MRC__) || defined(__SC__)++// MPW MrCpp or SCpp++#elif defined(__IBMCPP__)++// IBM Visual Age++#elif defined(_MSC_VER)++// Microsoft Visual C+++//+// Must remain the last #elif since some other vendors (Metrowerks, for example)+// also #define _MSC_VER++# pragma warning (disable:4103)+# pragma warning (push)+# pragma warning (disable:4127)+# pragma warning (disable:4180)+# pragma warning (disable:4244)+# pragma warning (disable:4355)+# pragma warning (disable:4510)+# pragma warning (disable:4512)+# pragma warning (disable:4610)+# pragma warning (disable:4675)+# if (_MSC_VER < 1600)+// Visual Studio 2008 generates spurious warnings about unused parameters.+#  pragma warning (disable:4100)+# endif // (_MSC_VER < 1600)+# if defined(_M_IX86) && defined(_Wp64)+// The /Wp64 option is broken. If you want to check 64 bit portability, use a+// 64 bit compiler!+#  pragma warning (disable:4311)+#  pragma warning (disable:4312)+# endif // defined(_M_IX86) && defined(_Wp64)+# pragma pack (push, 8)+// Note that if the /Og optimisation flag is enabled with MSVC6, the compiler+// has a tendency to incorrectly optimise away some calls to member template+// functions, even though those functions contain code that should not be+// optimised away! Therefore we will always disable this optimisation option+// for the MSVC6 compiler.+# if (_MSC_VER < 1300)+#  pragma optimize ("g", off)+# endif+# if !defined(_MT)+#  error Multithreaded RTL must be selected.+# endif // !defined(_MT)++# if defined(__cplusplus_cli) || defined(__cplusplus_winrt)+#  if !defined(ASIO_DISABLE_CLR_WORKAROUND)+#   if !defined(generic)+#    define generic cpp_generic+#    define ASIO_CLR_WORKAROUND+#   endif+#  endif+# endif++#endif
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_descriptor_service.hpp view
@@ -0,0 +1,416 @@+//+// detail/reactive_descriptor_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP+#define ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_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_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)++#include "asio/buffer.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/descriptor_read_op.hpp"+#include "asio/detail/descriptor_write_op.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/reactive_null_buffers_op.hpp"+#include "asio/detail/reactive_wait_op.hpp"+#include "asio/detail/reactor.hpp"+#include "asio/posix/descriptor_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class reactive_descriptor_service :+  public execution_context_service_base<reactive_descriptor_service>+{+public:+  // The native type of a descriptor.+  typedef int native_handle_type;++  // The implementation type of the descriptor.+  class implementation_type+    : private asio::detail::noncopyable+  {+  public:+    // Default constructor.+    implementation_type()+      : descriptor_(-1),+        state_(0)+    {+    }++  private:+    // Only this service will have access to the internal values.+    friend class reactive_descriptor_service;++    // The native descriptor representation.+    int descriptor_;++    // The current state of the descriptor.+    descriptor_ops::state_type state_;++    // Per-descriptor data used by the reactor.+    reactor::per_descriptor_data reactor_data_;+  };++  // Constructor.+  ASIO_DECL reactive_descriptor_service(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Construct a new descriptor implementation.+  ASIO_DECL void construct(implementation_type& impl);++  // Move-construct a new descriptor implementation.+  ASIO_DECL void move_construct(implementation_type& impl,+      implementation_type& other_impl) ASIO_NOEXCEPT;++  // Move-assign from another descriptor implementation.+  ASIO_DECL void move_assign(implementation_type& impl,+      reactive_descriptor_service& other_service,+      implementation_type& other_impl);++  // Destroy a descriptor implementation.+  ASIO_DECL void destroy(implementation_type& impl);++  // Assign a native descriptor to a descriptor implementation.+  ASIO_DECL asio::error_code assign(implementation_type& impl,+      const native_handle_type& native_descriptor,+      asio::error_code& ec);++  // Determine whether the descriptor is open.+  bool is_open(const implementation_type& impl) const+  {+    return impl.descriptor_ != -1;+  }++  // Destroy a descriptor implementation.+  ASIO_DECL asio::error_code close(implementation_type& impl,+      asio::error_code& ec);++  // Get the native descriptor representation.+  native_handle_type native_handle(const implementation_type& impl) const+  {+    return impl.descriptor_;+  }++  // Release ownership of the native descriptor representation.+  ASIO_DECL native_handle_type release(implementation_type& impl);++  // Cancel all operations associated with the descriptor.+  ASIO_DECL asio::error_code cancel(implementation_type& impl,+      asio::error_code& ec);++  // Perform an IO control command on the descriptor.+  template <typename IO_Control_Command>+  asio::error_code io_control(implementation_type& impl,+      IO_Control_Command& command, asio::error_code& ec)+  {+    descriptor_ops::ioctl(impl.descriptor_, impl.state_,+        command.name(), static_cast<ioctl_arg_type*>(command.data()), ec);+    return ec;+  }++  // Gets the non-blocking mode of the descriptor.+  bool non_blocking(const implementation_type& impl) const+  {+    return (impl.state_ & descriptor_ops::user_set_non_blocking) != 0;+  }++  // Sets the non-blocking mode of the descriptor.+  asio::error_code non_blocking(implementation_type& impl,+      bool mode, asio::error_code& ec)+  {+    descriptor_ops::set_user_non_blocking(+        impl.descriptor_, impl.state_, mode, ec);+    return ec;+  }++  // Gets the non-blocking mode of the native descriptor implementation.+  bool native_non_blocking(const implementation_type& impl) const+  {+    return (impl.state_ & descriptor_ops::internal_non_blocking) != 0;+  }++  // Sets the non-blocking mode of the native descriptor implementation.+  asio::error_code native_non_blocking(implementation_type& impl,+      bool mode, asio::error_code& ec)+  {+    descriptor_ops::set_internal_non_blocking(+        impl.descriptor_, impl.state_, mode, ec);+    return ec;+  }++  // Wait for the descriptor to become ready to read, ready to write, or to have+  // pending error conditions.+  asio::error_code wait(implementation_type& impl,+      posix::descriptor_base::wait_type w, asio::error_code& ec)+  {+    switch (w)+    {+    case posix::descriptor_base::wait_read:+      descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec);+      break;+    case posix::descriptor_base::wait_write:+      descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec);+      break;+    case posix::descriptor_base::wait_error:+      descriptor_ops::poll_error(impl.descriptor_, impl.state_, ec);+      break;+    default:+      ec = asio::error::invalid_argument;+      break;+    }++    return ec;+  }++  // Asynchronously wait for the descriptor to become ready to read, ready to+  // write, or to have pending error conditions.+  template <typename Handler, typename IoExecutor>+  void async_wait(implementation_type& impl,+      posix::descriptor_base::wait_type w,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_wait_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",+          &impl, impl.descriptor_, "async_wait"));++    int op_type;+    switch (w)+    {+    case posix::descriptor_base::wait_read:+        op_type = reactor::read_op;+        break;+    case posix::descriptor_base::wait_write:+        op_type = reactor::write_op;+        break;+    case posix::descriptor_base::wait_error:+        op_type = reactor::except_op;+        break;+      default:+        p.p->ec_ = asio::error::invalid_argument;+        reactor_.post_immediate_completion(p.p, is_continuation);+        p.v = p.p = 0;+        return;+    }++    start_op(impl, op_type, p.p, is_continuation, false, false);+    p.v = p.p = 0;+  }++  // Write some data to the descriptor.+  template <typename ConstBufferSequence>+  size_t write_some(implementation_type& impl,+      const ConstBufferSequence& buffers, asio::error_code& ec)+  {+    typedef buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs_type;++    if (bufs_type::is_single_buffer)+    {+      return descriptor_ops::sync_write1(impl.descriptor_,+          impl.state_, bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), ec);+    }+    else+    {+      bufs_type bufs(buffers);++      return descriptor_ops::sync_write(impl.descriptor_, impl.state_,+          bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+    }+  }++  // Wait until data can be written without blocking.+  size_t write_some(implementation_type& impl,+      const null_buffers&, asio::error_code& ec)+  {+    // Wait for descriptor to become ready.+    descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec);++    return 0;+  }++  // Start an asynchronous write. The data being sent must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_write_some(implementation_type& impl,+      const ConstBufferSequence& buffers, Handler& handler,+      const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef descriptor_write_op<ConstBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, impl.descriptor_, buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",+          &impl, impl.descriptor_, "async_write_some"));++    start_op(impl, reactor::write_op, p.p, is_continuation, true,+        buffer_sequence_adapter<asio::const_buffer,+          ConstBufferSequence>::all_empty(buffers));+    p.v = p.p = 0;+  }++  // Start an asynchronous wait until data can be written without blocking.+  template <typename Handler, typename IoExecutor>+  void async_write_some(implementation_type& impl,+      const null_buffers&, Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",+          &impl, impl.descriptor_, "async_write_some(null_buffers)"));++    start_op(impl, reactor::write_op, p.p, is_continuation, false, false);+    p.v = p.p = 0;+  }++  // Read some data from the stream. Returns the number of bytes read.+  template <typename MutableBufferSequence>+  size_t read_some(implementation_type& impl,+      const MutableBufferSequence& buffers, asio::error_code& ec)+  {+    typedef buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs_type;++    if (bufs_type::is_single_buffer)+    {+      return descriptor_ops::sync_read1(impl.descriptor_,+          impl.state_, bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), ec);+    }+    else+    {+      bufs_type bufs(buffers);++      return descriptor_ops::sync_read(impl.descriptor_, impl.state_,+          bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+    }+  }++  // Wait until data can be read without blocking.+  size_t read_some(implementation_type& impl,+      const null_buffers&, asio::error_code& ec)+  {+    // Wait for descriptor to become ready.+    descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec);++    return 0;+  }++  // Start an asynchronous read. The buffer for the data being read must be+  // valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_read_some(implementation_type& impl,+      const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef descriptor_read_op<MutableBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, impl.descriptor_, buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",+          &impl, impl.descriptor_, "async_read_some"));++    start_op(impl, reactor::read_op, p.p, is_continuation, true,+        buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::all_empty(buffers));+    p.v = p.p = 0;+  }++  // Wait until data can be read without blocking.+  template <typename Handler, typename IoExecutor>+  void async_read_some(implementation_type& impl,+      const null_buffers&, Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "descriptor",+          &impl, impl.descriptor_, "async_read_some(null_buffers)"));++    start_op(impl, reactor::read_op, p.p, is_continuation, false, false);+    p.v = p.p = 0;+  }++private:+  // Start the asynchronous operation.+  ASIO_DECL void start_op(implementation_type& impl, int op_type,+      reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);++  // The selector that performs event demultiplexing for the service.+  reactor& reactor_;++  // Cached success value to avoid accessing category singleton.+  const asio::error_code success_ec_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/reactive_descriptor_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)++#endif // ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_null_buffers_op.hpp view
@@ -0,0 +1,98 @@+//+// detail/reactive_null_buffers_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP+#define ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_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/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class reactive_null_buffers_op : public reactor_op+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op);++  reactive_null_buffers_op(const asio::error_code& success_ec,+      Handler& handler, const IoExecutor& io_ex)+    : reactor_op(success_ec, &reactive_null_buffers_op::do_perform,+        &reactive_null_buffers_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static status do_perform(reactor_op*)+  {+    return done;+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTIVE_NULL_BUFFERS_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_serial_port_service.hpp view
@@ -0,0 +1,237 @@+//+// detail/reactive_serial_port_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP+#define ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_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)+#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++#include <string>+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/serial_port_base.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/reactive_descriptor_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Extend reactive_descriptor_service to provide serial port support.+class reactive_serial_port_service :+  public execution_context_service_base<reactive_serial_port_service>+{+public:+  // The native type of a serial port.+  typedef reactive_descriptor_service::native_handle_type native_handle_type;++  // The implementation type of the serial port.+  typedef reactive_descriptor_service::implementation_type implementation_type;++  ASIO_DECL reactive_serial_port_service(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Construct a new serial port implementation.+  void construct(implementation_type& impl)+  {+    descriptor_service_.construct(impl);+  }++  // Move-construct a new serial port implementation.+  void move_construct(implementation_type& impl,+      implementation_type& other_impl)+  {+    descriptor_service_.move_construct(impl, other_impl);+  }++  // Move-assign from another serial port implementation.+  void move_assign(implementation_type& impl,+      reactive_serial_port_service& other_service,+      implementation_type& other_impl)+  {+    descriptor_service_.move_assign(impl,+        other_service.descriptor_service_, other_impl);+  }++  // Destroy a serial port implementation.+  void destroy(implementation_type& impl)+  {+    descriptor_service_.destroy(impl);+  }++  // Open the serial port using the specified device name.+  ASIO_DECL asio::error_code open(implementation_type& impl,+      const std::string& device, asio::error_code& ec);++  // Assign a native descriptor to a serial port implementation.+  asio::error_code assign(implementation_type& impl,+      const native_handle_type& native_descriptor,+      asio::error_code& ec)+  {+    return descriptor_service_.assign(impl, native_descriptor, ec);+  }++  // Determine whether the serial port is open.+  bool is_open(const implementation_type& impl) const+  {+    return descriptor_service_.is_open(impl);+  }++  // Destroy a serial port implementation.+  asio::error_code close(implementation_type& impl,+      asio::error_code& ec)+  {+    return descriptor_service_.close(impl, ec);+  }++  // Get the native serial port representation.+  native_handle_type native_handle(implementation_type& impl)+  {+    return descriptor_service_.native_handle(impl);+  }++  // Cancel all operations associated with the serial port.+  asio::error_code cancel(implementation_type& impl,+      asio::error_code& ec)+  {+    return descriptor_service_.cancel(impl, ec);+  }++  // Set an option on the serial port.+  template <typename SettableSerialPortOption>+  asio::error_code set_option(implementation_type& impl,+      const SettableSerialPortOption& option, asio::error_code& ec)+  {+    return do_set_option(impl,+        &reactive_serial_port_service::store_option<SettableSerialPortOption>,+        &option, ec);+  }++  // Get an option from the serial port.+  template <typename GettableSerialPortOption>+  asio::error_code get_option(const implementation_type& impl,+      GettableSerialPortOption& option, asio::error_code& ec) const+  {+    return do_get_option(impl,+        &reactive_serial_port_service::load_option<GettableSerialPortOption>,+        &option, ec);+  }++  // Send a break sequence to the serial port.+  asio::error_code send_break(implementation_type& impl,+      asio::error_code& ec)+  {+    int result = ::tcsendbreak(descriptor_service_.native_handle(impl), 0);+    descriptor_ops::get_last_error(ec, result < 0);+    return ec;+  }++  // Write the given data. Returns the number of bytes sent.+  template <typename ConstBufferSequence>+  size_t write_some(implementation_type& impl,+      const ConstBufferSequence& buffers, asio::error_code& ec)+  {+    return descriptor_service_.write_some(impl, buffers, ec);+  }++  // Start an asynchronous write. The data being written must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_write_some(implementation_type& impl,+      const ConstBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    descriptor_service_.async_write_some(impl, buffers, handler, io_ex);+  }++  // Read some data. Returns the number of bytes received.+  template <typename MutableBufferSequence>+  size_t read_some(implementation_type& impl,+      const MutableBufferSequence& buffers, asio::error_code& ec)+  {+    return descriptor_service_.read_some(impl, buffers, ec);+  }++  // Start an asynchronous read. The buffer for the data being received must be+  // valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_read_some(implementation_type& impl,+      const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    descriptor_service_.async_read_some(impl, buffers, handler, io_ex);+  }++private:+  // Function pointer type for storing a serial port option.+  typedef asio::error_code (*store_function_type)(+      const void*, termios&, asio::error_code&);++  // Helper function template to store a serial port option.+  template <typename SettableSerialPortOption>+  static asio::error_code store_option(const void* option,+      termios& storage, asio::error_code& ec)+  {+    static_cast<const SettableSerialPortOption*>(option)->store(storage, ec);+    return ec;+  }++  // Helper function to set a serial port option.+  ASIO_DECL asio::error_code do_set_option(+      implementation_type& impl, store_function_type store,+      const void* option, asio::error_code& ec);++  // Function pointer type for loading a serial port option.+  typedef asio::error_code (*load_function_type)(+      void*, const termios&, asio::error_code&);++  // Helper function template to load a serial port option.+  template <typename GettableSerialPortOption>+  static asio::error_code load_option(void* option,+      const termios& storage, asio::error_code& ec)+  {+    static_cast<GettableSerialPortOption*>(option)->load(storage, ec);+    return ec;+  }++  // Helper function to get a serial port option.+  ASIO_DECL asio::error_code do_get_option(+      const implementation_type& impl, load_function_type load,+      void* option, asio::error_code& ec) const;++  // The implementation used for initiating asynchronous operations.+  reactive_descriptor_service descriptor_service_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/reactive_serial_port_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+#endif // defined(ASIO_HAS_SERIAL_PORT)++#endif // ASIO_DETAIL_REACTIVE_SERIAL_PORT_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_accept_op.hpp view
@@ -0,0 +1,242 @@+//+// detail/reactive_socket_accept_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP+#define ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_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/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_holder.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Socket, typename Protocol>+class reactive_socket_accept_op_base : public reactor_op+{+public:+  reactive_socket_accept_op_base(const asio::error_code& success_ec,+      socket_type socket, socket_ops::state_type state, Socket& peer,+      const Protocol& protocol, typename Protocol::endpoint* peer_endpoint,+      func_type complete_func)+    : reactor_op(success_ec,+        &reactive_socket_accept_op_base::do_perform, complete_func),+      socket_(socket),+      state_(state),+      peer_(peer),+      protocol_(protocol),+      peer_endpoint_(peer_endpoint),+      addrlen_(peer_endpoint ? peer_endpoint->capacity() : 0)+  {+  }++  static status do_perform(reactor_op* base)+  {+    reactive_socket_accept_op_base* o(+        static_cast<reactive_socket_accept_op_base*>(base));++    socket_type new_socket = invalid_socket;+    status result = socket_ops::non_blocking_accept(o->socket_,+        o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,+        o->peer_endpoint_ ? &o->addrlen_ : 0, o->ec_, new_socket)+    ? done : not_done;+    o->new_socket_.reset(new_socket);++    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_accept", o->ec_));++    return result;+  }++  void do_assign()+  {+    if (new_socket_.get() != invalid_socket)+    {+      if (peer_endpoint_)+        peer_endpoint_->resize(addrlen_);+      peer_.assign(protocol_, new_socket_.get(), ec_);+      if (!ec_)+        new_socket_.release();+    }+  }++private:+  socket_type socket_;+  socket_ops::state_type state_;+  socket_holder new_socket_;+  Socket& peer_;+  Protocol protocol_;+  typename Protocol::endpoint* peer_endpoint_;+  std::size_t addrlen_;+};++template <typename Socket, typename Protocol,+    typename Handler, typename IoExecutor>+class reactive_socket_accept_op :+  public reactive_socket_accept_op_base<Socket, Protocol>+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op);++  reactive_socket_accept_op(const asio::error_code& success_ec,+      socket_type socket, socket_ops::state_type state, Socket& peer,+      const Protocol& protocol, typename Protocol::endpoint* peer_endpoint,+      Handler& handler, const IoExecutor& io_ex)+    : reactive_socket_accept_op_base<Socket, Protocol>(+        success_ec, socket, state, peer, protocol, peer_endpoint,+        &reactive_socket_accept_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    // On success, assign new connection to peer socket object.+    if (owner)+      o->do_assign();++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder1<Handler, asio::error_code>+      handler(o->handler_, o->ec_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++#if defined(ASIO_HAS_MOVE)++template <typename Protocol, typename PeerIoExecutor,+    typename Handler, typename IoExecutor>+class reactive_socket_move_accept_op :+  private Protocol::socket::template rebind_executor<PeerIoExecutor>::other,+  public reactive_socket_accept_op_base<+    typename Protocol::socket::template rebind_executor<PeerIoExecutor>::other,+    Protocol>+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op);++  reactive_socket_move_accept_op(const asio::error_code& success_ec,+      const PeerIoExecutor& peer_io_ex, socket_type socket,+      socket_ops::state_type state, const Protocol& protocol,+      typename Protocol::endpoint* peer_endpoint, Handler& handler,+      const IoExecutor& io_ex)+    : peer_socket_type(peer_io_ex),+      reactive_socket_accept_op_base<peer_socket_type, Protocol>(+        success_ec, socket, state, *this, protocol, peer_endpoint,+        &reactive_socket_move_accept_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_socket_move_accept_op* o(+        static_cast<reactive_socket_move_accept_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    // On success, assign new connection to peer socket object.+    if (owner)+      o->do_assign();++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::move_binder2<Handler,+      asio::error_code, peer_socket_type>+        handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), o->ec_,+          ASIO_MOVE_CAST(peer_socket_type)(*o));+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  typedef typename Protocol::socket::template+    rebind_executor<PeerIoExecutor>::other peer_socket_type;++  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++#endif // defined(ASIO_HAS_MOVE)++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTIVE_SOCKET_ACCEPT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_connect_op.hpp view
@@ -0,0 +1,123 @@+//+// detail/reactive_socket_connect_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP+#define ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_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/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class reactive_socket_connect_op_base : public reactor_op+{+public:+  reactive_socket_connect_op_base(const asio::error_code& success_ec,+      socket_type socket, func_type complete_func)+    : reactor_op(success_ec,+        &reactive_socket_connect_op_base::do_perform, complete_func),+      socket_(socket)+  {+  }++  static status do_perform(reactor_op* base)+  {+    reactive_socket_connect_op_base* o(+        static_cast<reactive_socket_connect_op_base*>(base));++    status result = socket_ops::non_blocking_connect(+        o->socket_, o->ec_) ? done : not_done;++    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_connect", o->ec_));++    return result;+  }++private:+  socket_type socket_;+};++template <typename Handler, typename IoExecutor>+class reactive_socket_connect_op : public reactive_socket_connect_op_base+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op);++  reactive_socket_connect_op(const asio::error_code& success_ec,+      socket_type socket, Handler& handler, const IoExecutor& io_ex)+    : reactive_socket_connect_op_base(success_ec, socket,+        &reactive_socket_connect_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_socket_connect_op* o+      (static_cast<reactive_socket_connect_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder1<Handler, asio::error_code>+      handler(o->handler_, o->ec_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTIVE_SOCKET_CONNECT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recv_op.hpp view
@@ -0,0 +1,159 @@+//+// detail/reactive_socket_recv_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP+#define ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_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/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class reactive_socket_recv_op_base : public reactor_op+{+public:+  reactive_socket_recv_op_base(const asio::error_code& success_ec,+      socket_type socket, socket_ops::state_type state,+      const MutableBufferSequence& buffers,+      socket_base::message_flags flags, func_type complete_func)+    : reactor_op(success_ec,+        &reactive_socket_recv_op_base::do_perform, complete_func),+      socket_(socket),+      state_(state),+      buffers_(buffers),+      flags_(flags)+  {+  }++  static status do_perform(reactor_op* base)+  {+    reactive_socket_recv_op_base* o(+        static_cast<reactive_socket_recv_op_base*>(base));++    typedef buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs_type;++    status result;+    if (bufs_type::is_single_buffer)+    {+      result = socket_ops::non_blocking_recv1(o->socket_,+          bufs_type::first(o->buffers_).data(),+          bufs_type::first(o->buffers_).size(), o->flags_,+          (o->state_ & socket_ops::stream_oriented) != 0,+          o->ec_, o->bytes_transferred_) ? done : not_done;+    }+    else+    {+      bufs_type bufs(o->buffers_);+      result = socket_ops::non_blocking_recv(o->socket_,+          bufs.buffers(), bufs.count(), o->flags_,+          (o->state_ & socket_ops::stream_oriented) != 0,+          o->ec_, o->bytes_transferred_) ? done : not_done;+    }++    if (result == done)+      if ((o->state_ & socket_ops::stream_oriented) != 0)+        if (o->bytes_transferred_ == 0)+          result = done_and_exhausted;++    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recv",+          o->ec_, o->bytes_transferred_));++    return result;+  }++private:+  socket_type socket_;+  socket_ops::state_type state_;+  MutableBufferSequence buffers_;+  socket_base::message_flags flags_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class reactive_socket_recv_op :+  public reactive_socket_recv_op_base<MutableBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op);++  reactive_socket_recv_op(const asio::error_code& success_ec,+      socket_type socket, socket_ops::state_type state,+      const MutableBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+    : reactive_socket_recv_op_base<MutableBufferSequence>(success_ec, socket,+        state, buffers, flags, &reactive_socket_recv_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECV_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp view
@@ -0,0 +1,164 @@+//+// detail/reactive_socket_recvfrom_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP+#define ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_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/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence, typename Endpoint>+class reactive_socket_recvfrom_op_base : public reactor_op+{+public:+  reactive_socket_recvfrom_op_base(const asio::error_code& success_ec,+      socket_type socket, int protocol_type,+      const MutableBufferSequence& buffers, Endpoint& endpoint,+      socket_base::message_flags flags, func_type complete_func)+    : reactor_op(success_ec,+        &reactive_socket_recvfrom_op_base::do_perform, complete_func),+      socket_(socket),+      protocol_type_(protocol_type),+      buffers_(buffers),+      sender_endpoint_(endpoint),+      flags_(flags)+  {+  }++  static status do_perform(reactor_op* base)+  {+    reactive_socket_recvfrom_op_base* o(+        static_cast<reactive_socket_recvfrom_op_base*>(base));++    typedef buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs_type;++    std::size_t addr_len = o->sender_endpoint_.capacity();+    status result;+    if (bufs_type::is_single_buffer)+    {+      result = socket_ops::non_blocking_recvfrom1(+          o->socket_, bufs_type::first(o->buffers_).data(),+          bufs_type::first(o->buffers_).size(), o->flags_,+          o->sender_endpoint_.data(), &addr_len,+          o->ec_, o->bytes_transferred_) ? done : not_done;+    }+    else+    {+      bufs_type bufs(o->buffers_);+      result = socket_ops::non_blocking_recvfrom(o->socket_,+          bufs.buffers(), bufs.count(), o->flags_,+          o->sender_endpoint_.data(), &addr_len,+          o->ec_, o->bytes_transferred_) ? done : not_done;+    }++    if (result && !o->ec_)+      o->sender_endpoint_.resize(addr_len);++    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvfrom",+          o->ec_, o->bytes_transferred_));++    return result;+  }++private:+  socket_type socket_;+  int protocol_type_;+  MutableBufferSequence buffers_;+  Endpoint& sender_endpoint_;+  socket_base::message_flags flags_;+};++template <typename MutableBufferSequence, typename Endpoint,+    typename Handler, typename IoExecutor>+class reactive_socket_recvfrom_op :+  public reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op);++  reactive_socket_recvfrom_op(const asio::error_code& success_ec,+      socket_type socket, int protocol_type,+      const MutableBufferSequence& buffers, Endpoint& endpoint,+      socket_base::message_flags flags, Handler& handler,+      const IoExecutor& io_ex)+    : reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>(+        success_ec, socket, protocol_type, buffers, endpoint, flags,+        &reactive_socket_recvfrom_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_socket_recvfrom_op* o(+        static_cast<reactive_socket_recvfrom_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECVFROM_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp view
@@ -0,0 +1,145 @@+//+// detail/reactive_socket_recvmsg_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP+#define ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_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/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/socket_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class reactive_socket_recvmsg_op_base : public reactor_op+{+public:+  reactive_socket_recvmsg_op_base(const asio::error_code& success_ec,+      socket_type socket, const MutableBufferSequence& buffers,+      socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags, func_type complete_func)+    : reactor_op(success_ec,+        &reactive_socket_recvmsg_op_base::do_perform, complete_func),+      socket_(socket),+      buffers_(buffers),+      in_flags_(in_flags),+      out_flags_(out_flags)+  {+  }++  static status do_perform(reactor_op* base)+  {+    reactive_socket_recvmsg_op_base* o(+        static_cast<reactive_socket_recvmsg_op_base*>(base));++    buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs(o->buffers_);++    status result = socket_ops::non_blocking_recvmsg(o->socket_,+        bufs.buffers(), bufs.count(),+        o->in_flags_, o->out_flags_,+        o->ec_, o->bytes_transferred_) ? done : not_done;++    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_recvmsg",+          o->ec_, o->bytes_transferred_));++    return result;+  }++private:+  socket_type socket_;+  MutableBufferSequence buffers_;+  socket_base::message_flags in_flags_;+  socket_base::message_flags& out_flags_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class reactive_socket_recvmsg_op :+  public reactive_socket_recvmsg_op_base<MutableBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op);++  reactive_socket_recvmsg_op(const asio::error_code& success_ec,+      socket_type socket, const MutableBufferSequence& buffers,+      socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags, Handler& handler,+      const IoExecutor& io_ex)+    : reactive_socket_recvmsg_op_base<MutableBufferSequence>(+        success_ec, socket, buffers, in_flags, out_flags,+        &reactive_socket_recvmsg_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_socket_recvmsg_op* o(+        static_cast<reactive_socket_recvmsg_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTIVE_SOCKET_RECVMSG_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_send_op.hpp view
@@ -0,0 +1,162 @@+//+// detail/reactive_socket_send_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP+#define ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_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/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence>+class reactive_socket_send_op_base : public reactor_op+{+public:+  reactive_socket_send_op_base(const asio::error_code& success_ec,+      socket_type socket, socket_ops::state_type state,+      const ConstBufferSequence& buffers,+      socket_base::message_flags flags, func_type complete_func)+    : reactor_op(success_ec,+        &reactive_socket_send_op_base::do_perform, complete_func),+      socket_(socket),+      state_(state),+      buffers_(buffers),+      flags_(flags)+  {+  }++  static status do_perform(reactor_op* base)+  {+    reactive_socket_send_op_base* o(+        static_cast<reactive_socket_send_op_base*>(base));++    typedef buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs_type;++    status result;+    if (bufs_type::is_single_buffer)+    {+      result = socket_ops::non_blocking_send1(o->socket_,+          bufs_type::first(o->buffers_).data(),+          bufs_type::first(o->buffers_).size(), o->flags_,+          o->ec_, o->bytes_transferred_) ? done : not_done;++      if (result == done)+        if ((o->state_ & socket_ops::stream_oriented) != 0)+          if (o->bytes_transferred_ < bufs_type::first(o->buffers_).size())+            result = done_and_exhausted;+    }+    else+    {+      bufs_type bufs(o->buffers_);+      result = socket_ops::non_blocking_send(o->socket_,+            bufs.buffers(), bufs.count(), o->flags_,+            o->ec_, o->bytes_transferred_) ? done : not_done;++      if (result == done)+        if ((o->state_ & socket_ops::stream_oriented) != 0)+          if (o->bytes_transferred_ < bufs.total_size())+            result = done_and_exhausted;+    }++    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_send",+          o->ec_, o->bytes_transferred_));++    return result;+  }++private:+  socket_type socket_;+  socket_ops::state_type state_;+  ConstBufferSequence buffers_;+  socket_base::message_flags flags_;+};++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class reactive_socket_send_op :+  public reactive_socket_send_op_base<ConstBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op);++  reactive_socket_send_op(const asio::error_code& success_ec,+      socket_type socket, socket_ops::state_type state,+      const ConstBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+    : reactive_socket_send_op_base<ConstBufferSequence>(success_ec, socket,+        state, buffers, flags, &reactive_socket_send_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTIVE_SOCKET_SEND_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_sendto_op.hpp view
@@ -0,0 +1,156 @@+//+// detail/reactive_socket_sendto_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP+#define ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_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/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence, typename Endpoint>+class reactive_socket_sendto_op_base : public reactor_op+{+public:+  reactive_socket_sendto_op_base(const asio::error_code& success_ec,+      socket_type socket, const ConstBufferSequence& buffers,+      const Endpoint& endpoint, socket_base::message_flags flags,+      func_type complete_func)+    : reactor_op(success_ec,+        &reactive_socket_sendto_op_base::do_perform, complete_func),+      socket_(socket),+      buffers_(buffers),+      destination_(endpoint),+      flags_(flags)+  {+  }++  static status do_perform(reactor_op* base)+  {+    reactive_socket_sendto_op_base* o(+        static_cast<reactive_socket_sendto_op_base*>(base));++    typedef buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs_type;++    status result;+    if (bufs_type::is_single_buffer)+    {+      result = socket_ops::non_blocking_sendto1(o->socket_,+          bufs_type::first(o->buffers_).data(),+          bufs_type::first(o->buffers_).size(), o->flags_,+          o->destination_.data(), o->destination_.size(),+          o->ec_, o->bytes_transferred_) ? done : not_done;+    }+    else+    {+      bufs_type bufs(o->buffers_);+      result = socket_ops::non_blocking_sendto(o->socket_,+          bufs.buffers(), bufs.count(), o->flags_,+          o->destination_.data(), o->destination_.size(),+          o->ec_, o->bytes_transferred_) ? done : not_done;+    }++    ASIO_HANDLER_REACTOR_OPERATION((*o, "non_blocking_sendto",+          o->ec_, o->bytes_transferred_));++    return result;+  }++private:+  socket_type socket_;+  ConstBufferSequence buffers_;+  Endpoint destination_;+  socket_base::message_flags flags_;+};++template <typename ConstBufferSequence, typename Endpoint,+    typename Handler, typename IoExecutor>+class reactive_socket_sendto_op :+  public reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_socket_sendto_op);++  reactive_socket_sendto_op(const asio::error_code& success_ec,+      socket_type socket, const ConstBufferSequence& buffers,+      const Endpoint& endpoint, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+    : reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint>(+        success_ec, socket, buffers, endpoint, flags,+        &reactive_socket_sendto_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTIVE_SOCKET_SENDTO_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service.hpp view
@@ -0,0 +1,528 @@+//+// detail/reactive_socket_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP+#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_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_IOCP)++#include "asio/buffer.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/socket_base.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/reactive_null_buffers_op.hpp"+#include "asio/detail/reactive_socket_accept_op.hpp"+#include "asio/detail/reactive_socket_connect_op.hpp"+#include "asio/detail/reactive_socket_recvfrom_op.hpp"+#include "asio/detail/reactive_socket_sendto_op.hpp"+#include "asio/detail/reactive_socket_service_base.hpp"+#include "asio/detail/reactor.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_holder.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol>+class reactive_socket_service :+  public execution_context_service_base<reactive_socket_service<Protocol> >,+  public reactive_socket_service_base+{+public:+  // The protocol type.+  typedef Protocol protocol_type;++  // The endpoint type.+  typedef typename Protocol::endpoint endpoint_type;++  // The native type of a socket.+  typedef socket_type native_handle_type;++  // The implementation type of the socket.+  struct implementation_type :+    reactive_socket_service_base::base_implementation_type+  {+    // Default constructor.+    implementation_type()+      : protocol_(endpoint_type().protocol())+    {+    }++    // The protocol associated with the socket.+    protocol_type protocol_;+  };++  // Constructor.+  reactive_socket_service(execution_context& context)+    : execution_context_service_base<+        reactive_socket_service<Protocol> >(context),+      reactive_socket_service_base(context)+  {+  }++  // Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+    this->base_shutdown();+  }++  // Move-construct a new socket implementation.+  void move_construct(implementation_type& impl,+      implementation_type& other_impl) ASIO_NOEXCEPT+  {+    this->base_move_construct(impl, other_impl);++    impl.protocol_ = other_impl.protocol_;+    other_impl.protocol_ = endpoint_type().protocol();+  }++  // Move-assign from another socket implementation.+  void move_assign(implementation_type& impl,+      reactive_socket_service_base& other_service,+      implementation_type& other_impl)+  {+    this->base_move_assign(impl, other_service, other_impl);++    impl.protocol_ = other_impl.protocol_;+    other_impl.protocol_ = endpoint_type().protocol();+  }++  // Move-construct a new socket implementation from another protocol type.+  template <typename Protocol1>+  void converting_move_construct(implementation_type& impl,+      reactive_socket_service<Protocol1>&,+      typename reactive_socket_service<+        Protocol1>::implementation_type& other_impl)+  {+    this->base_move_construct(impl, other_impl);++    impl.protocol_ = protocol_type(other_impl.protocol_);+    other_impl.protocol_ = typename Protocol1::endpoint().protocol();+  }++  // Open a new socket implementation.+  asio::error_code open(implementation_type& impl,+      const protocol_type& protocol, asio::error_code& ec)+  {+    if (!do_open(impl, protocol.family(),+          protocol.type(), protocol.protocol(), ec))+      impl.protocol_ = protocol;+    return ec;+  }++  // Assign a native socket to a socket implementation.+  asio::error_code assign(implementation_type& impl,+      const protocol_type& protocol, const native_handle_type& native_socket,+      asio::error_code& ec)+  {+    if (!do_assign(impl, protocol.type(), native_socket, ec))+      impl.protocol_ = protocol;+    return ec;+  }++  // Get the native socket representation.+  native_handle_type native_handle(implementation_type& impl)+  {+    return impl.socket_;+  }++  // Bind the socket to the specified local endpoint.+  asio::error_code bind(implementation_type& impl,+      const endpoint_type& endpoint, asio::error_code& ec)+  {+    socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);+    return ec;+  }++  // Set a socket option.+  template <typename Option>+  asio::error_code set_option(implementation_type& impl,+      const Option& option, asio::error_code& ec)+  {+    socket_ops::setsockopt(impl.socket_, impl.state_,+        option.level(impl.protocol_), option.name(impl.protocol_),+        option.data(impl.protocol_), option.size(impl.protocol_), ec);+    return ec;+  }++  // Set a socket option.+  template <typename Option>+  asio::error_code get_option(const implementation_type& impl,+      Option& option, asio::error_code& ec) const+  {+    std::size_t size = option.size(impl.protocol_);+    socket_ops::getsockopt(impl.socket_, impl.state_,+        option.level(impl.protocol_), option.name(impl.protocol_),+        option.data(impl.protocol_), &size, ec);+    if (!ec)+      option.resize(impl.protocol_, size);+    return ec;+  }++  // Get the local endpoint.+  endpoint_type local_endpoint(const implementation_type& impl,+      asio::error_code& ec) const+  {+    endpoint_type endpoint;+    std::size_t addr_len = endpoint.capacity();+    if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))+      return endpoint_type();+    endpoint.resize(addr_len);+    return endpoint;+  }++  // Get the remote endpoint.+  endpoint_type remote_endpoint(const implementation_type& impl,+      asio::error_code& ec) const+  {+    endpoint_type endpoint;+    std::size_t addr_len = endpoint.capacity();+    if (socket_ops::getpeername(impl.socket_,+          endpoint.data(), &addr_len, false, ec))+      return endpoint_type();+    endpoint.resize(addr_len);+    return endpoint;+  }++  // Disable sends or receives on the socket.+  asio::error_code shutdown(base_implementation_type& impl,+      socket_base::shutdown_type what, asio::error_code& ec)+  {+    socket_ops::shutdown(impl.socket_, what, ec);+    return ec;+  }++  // Send a datagram to the specified endpoint. Returns the number of bytes+  // sent.+  template <typename ConstBufferSequence>+  size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,+      const endpoint_type& destination, socket_base::message_flags flags,+      asio::error_code& ec)+  {+    typedef buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs_type;++    if (bufs_type::is_single_buffer)+    {+      return socket_ops::sync_sendto1(impl.socket_, impl.state_,+          bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), flags,+          destination.data(), destination.size(), ec);+    }+    else+    {+      bufs_type bufs(buffers);+      return socket_ops::sync_sendto(impl.socket_, impl.state_,+          bufs.buffers(), bufs.count(), flags,+          destination.data(), destination.size(), ec);+    }+  }++  // Wait until data can be sent without blocking.+  size_t send_to(implementation_type& impl, const null_buffers&,+      const endpoint_type&, socket_base::message_flags,+      asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);++    return 0;+  }++  // Start an asynchronous send. The data being sent must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_send_to(implementation_type& impl,+      const ConstBufferSequence& buffers,+      const endpoint_type& destination, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_socket_sendto_op<ConstBufferSequence,+        endpoint_type, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, impl.socket_,+        buffers, destination, flags, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_send_to"));++    start_op(impl, reactor::write_op, p.p, is_continuation, true, false);+    p.v = p.p = 0;+  }++  // Start an asynchronous wait until data can be sent without blocking.+  template <typename Handler, typename IoExecutor>+  void async_send_to(implementation_type& impl, const null_buffers&,+      const endpoint_type&, socket_base::message_flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_send_to(null_buffers)"));++    start_op(impl, reactor::write_op, p.p, is_continuation, false, false);+    p.v = p.p = 0;+  }++  // Receive a datagram with the endpoint of the sender. Returns the number of+  // bytes received.+  template <typename MutableBufferSequence>+  size_t receive_from(implementation_type& impl,+      const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint, socket_base::message_flags flags,+      asio::error_code& ec)+  {+    typedef buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs_type;++    std::size_t addr_len = sender_endpoint.capacity();+    std::size_t bytes_recvd;+    if (bufs_type::is_single_buffer)+    {+      bytes_recvd = socket_ops::sync_recvfrom1(impl.socket_,+          impl.state_, bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), flags,+          sender_endpoint.data(), &addr_len, ec);+    }+    else+    {+      bufs_type bufs(buffers);+      bytes_recvd = socket_ops::sync_recvfrom(+          impl.socket_, impl.state_, bufs.buffers(), bufs.count(),+          flags, sender_endpoint.data(), &addr_len, ec);+    }++    if (!ec)+      sender_endpoint.resize(addr_len);++    return bytes_recvd;+  }++  // Wait until data can be received without blocking.+  size_t receive_from(implementation_type& impl, const null_buffers&,+      endpoint_type& sender_endpoint, socket_base::message_flags,+      asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);++    // Reset endpoint since it can be given no sensible value at this time.+    sender_endpoint = endpoint_type();++    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received and+  // the sender_endpoint object must both be valid for the lifetime of the+  // asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive_from(implementation_type& impl,+      const MutableBufferSequence& buffers, endpoint_type& sender_endpoint,+      socket_base::message_flags flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_socket_recvfrom_op<MutableBufferSequence,+        endpoint_type, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    int protocol = impl.protocol_.type();+    p.p = new (p.v) op(success_ec_, impl.socket_, protocol,+        buffers, sender_endpoint, flags, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_receive_from"));++    start_op(impl,+        (flags & socket_base::message_out_of_band)+          ? reactor::except_op : reactor::read_op,+        p.p, is_continuation, true, false);+    p.v = p.p = 0;+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive_from(implementation_type& impl, const null_buffers&,+      endpoint_type& sender_endpoint, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_receive_from(null_buffers)"));++    // Reset endpoint since it can be given no sensible value at this time.+    sender_endpoint = endpoint_type();++    start_op(impl,+        (flags & socket_base::message_out_of_band)+          ? reactor::except_op : reactor::read_op,+        p.p, is_continuation, false, false);+    p.v = p.p = 0;+  }++  // Accept a new connection.+  template <typename Socket>+  asio::error_code accept(implementation_type& impl,+      Socket& peer, endpoint_type* peer_endpoint, asio::error_code& ec)+  {+    // We cannot accept a socket that is already open.+    if (peer.is_open())+    {+      ec = asio::error::already_open;+      return ec;+    }++    std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;+    socket_holder new_socket(socket_ops::sync_accept(impl.socket_,+          impl.state_, peer_endpoint ? peer_endpoint->data() : 0,+          peer_endpoint ? &addr_len : 0, ec));++    // On success, assign new connection to peer socket object.+    if (new_socket.get() != invalid_socket)+    {+      if (peer_endpoint)+        peer_endpoint->resize(addr_len);+      peer.assign(impl.protocol_, new_socket.get(), ec);+      if (!ec)+        new_socket.release();+    }++    return ec;+  }++  // Start an asynchronous accept. The peer and peer_endpoint objects must be+  // valid until the accept's handler is invoked.+  template <typename Socket, typename Handler, typename IoExecutor>+  void async_accept(implementation_type& impl, Socket& peer,+      endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_socket_accept_op<Socket, Protocol, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_,+        peer, impl.protocol_, peer_endpoint, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_accept"));++    start_accept_op(impl, p.p, is_continuation, peer.is_open());+    p.v = p.p = 0;+  }++#if defined(ASIO_HAS_MOVE)+  // Start an asynchronous accept. The peer_endpoint object must be valid until+  // the accept's handler is invoked.+  template <typename PeerIoExecutor, typename Handler, typename IoExecutor>+  void async_move_accept(implementation_type& impl,+      const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_socket_move_accept_op<Protocol,+        PeerIoExecutor, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_,+        impl.state_, impl.protocol_, peer_endpoint, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_accept"));++    start_accept_op(impl, p.p, is_continuation, false);+    p.v = p.p = 0;+  }+#endif // defined(ASIO_HAS_MOVE)++  // Connect the socket to the specified endpoint.+  asio::error_code connect(implementation_type& impl,+      const endpoint_type& peer_endpoint, asio::error_code& ec)+  {+    socket_ops::sync_connect(impl.socket_,+        peer_endpoint.data(), peer_endpoint.size(), ec);+    return ec;+  }++  // Start an asynchronous connect.+  template <typename Handler, typename IoExecutor>+  void async_connect(implementation_type& impl,+      const endpoint_type& peer_endpoint,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_socket_connect_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, impl.socket_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_connect"));++    start_connect_op(impl, p.p, is_continuation,+        peer_endpoint.data(), peer_endpoint.size());+    p.v = p.p = 0;+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service_base.hpp view
@@ -0,0 +1,541 @@+//+// detail/reactive_socket_service_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP+#define ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_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_IOCP) \+  && !defined(ASIO_WINDOWS_RUNTIME)++#include "asio/buffer.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/socket_base.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactive_null_buffers_op.hpp"+#include "asio/detail/reactive_socket_recv_op.hpp"+#include "asio/detail/reactive_socket_recvmsg_op.hpp"+#include "asio/detail/reactive_socket_send_op.hpp"+#include "asio/detail/reactive_wait_op.hpp"+#include "asio/detail/reactor.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_holder.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class reactive_socket_service_base+{+public:+  // The native type of a socket.+  typedef socket_type native_handle_type;++  // The implementation type of the socket.+  struct base_implementation_type+  {+    // The native socket representation.+    socket_type socket_;++    // The current state of the socket.+    socket_ops::state_type state_;++    // Per-descriptor data used by the reactor.+    reactor::per_descriptor_data reactor_data_;+  };++  // Constructor.+  ASIO_DECL reactive_socket_service_base(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void base_shutdown();++  // Construct a new socket implementation.+  ASIO_DECL void construct(base_implementation_type& impl);++  // Move-construct a new socket implementation.+  ASIO_DECL void base_move_construct(base_implementation_type& impl,+      base_implementation_type& other_impl) ASIO_NOEXCEPT;++  // Move-assign from another socket implementation.+  ASIO_DECL void base_move_assign(base_implementation_type& impl,+      reactive_socket_service_base& other_service,+      base_implementation_type& other_impl);++  // Destroy a socket implementation.+  ASIO_DECL void destroy(base_implementation_type& impl);++  // Determine whether the socket is open.+  bool is_open(const base_implementation_type& impl) const+  {+    return impl.socket_ != invalid_socket;+  }++  // Destroy a socket implementation.+  ASIO_DECL asio::error_code close(+      base_implementation_type& impl, asio::error_code& ec);++  // Release ownership of the socket.+  ASIO_DECL socket_type release(+      base_implementation_type& impl, asio::error_code& ec);++  // Get the native socket representation.+  native_handle_type native_handle(base_implementation_type& impl)+  {+    return impl.socket_;+  }++  // Cancel all operations associated with the socket.+  ASIO_DECL asio::error_code cancel(+      base_implementation_type& impl, asio::error_code& ec);++  // Determine whether the socket is at the out-of-band data mark.+  bool at_mark(const base_implementation_type& impl,+      asio::error_code& ec) const+  {+    return socket_ops::sockatmark(impl.socket_, ec);+  }++  // Determine the number of bytes available for reading.+  std::size_t available(const base_implementation_type& impl,+      asio::error_code& ec) const+  {+    return socket_ops::available(impl.socket_, ec);+  }++  // Place the socket into the state where it will listen for new connections.+  asio::error_code listen(base_implementation_type& impl,+      int backlog, asio::error_code& ec)+  {+    socket_ops::listen(impl.socket_, backlog, ec);+    return ec;+  }++  // Perform an IO control command on the socket.+  template <typename IO_Control_Command>+  asio::error_code io_control(base_implementation_type& impl,+      IO_Control_Command& command, asio::error_code& ec)+  {+    socket_ops::ioctl(impl.socket_, impl.state_, command.name(),+        static_cast<ioctl_arg_type*>(command.data()), ec);+    return ec;+  }++  // Gets the non-blocking mode of the socket.+  bool non_blocking(const base_implementation_type& impl) const+  {+    return (impl.state_ & socket_ops::user_set_non_blocking) != 0;+  }++  // Sets the non-blocking mode of the socket.+  asio::error_code non_blocking(base_implementation_type& impl,+      bool mode, asio::error_code& ec)+  {+    socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);+    return ec;+  }++  // Gets the non-blocking mode of the native socket implementation.+  bool native_non_blocking(const base_implementation_type& impl) const+  {+    return (impl.state_ & socket_ops::internal_non_blocking) != 0;+  }++  // Sets the non-blocking mode of the native socket implementation.+  asio::error_code native_non_blocking(base_implementation_type& impl,+      bool mode, asio::error_code& ec)+  {+    socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);+    return ec;+  }++  // Wait for the socket to become ready to read, ready to write, or to have+  // pending error conditions.+  asio::error_code wait(base_implementation_type& impl,+      socket_base::wait_type w, asio::error_code& ec)+  {+    switch (w)+    {+    case socket_base::wait_read:+      socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);+      break;+    case socket_base::wait_write:+      socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);+      break;+    case socket_base::wait_error:+      socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);+      break;+    default:+      ec = asio::error::invalid_argument;+      break;+    }++    return ec;+  }++  // Asynchronously wait for the socket to become ready to read, ready to+  // write, or to have pending error conditions.+  template <typename Handler, typename IoExecutor>+  void async_wait(base_implementation_type& impl,+      socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_wait_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_wait"));++    int op_type;+    switch (w)+    {+      case socket_base::wait_read:+        op_type = reactor::read_op;+        break;+      case socket_base::wait_write:+        op_type = reactor::write_op;+        break;+      case socket_base::wait_error:+        op_type = reactor::except_op;+        break;+      default:+        p.p->ec_ = asio::error::invalid_argument;+        reactor_.post_immediate_completion(p.p, is_continuation);+        p.v = p.p = 0;+        return;+    }++    start_op(impl, op_type, p.p, is_continuation, false, false);+    p.v = p.p = 0;+  }++  // Send the given data to the peer.+  template <typename ConstBufferSequence>+  size_t send(base_implementation_type& impl,+      const ConstBufferSequence& buffers,+      socket_base::message_flags flags, asio::error_code& ec)+  {+    typedef buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs_type;++    if (bufs_type::is_single_buffer)+    {+      return socket_ops::sync_send1(impl.socket_,+          impl.state_, bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), flags, ec);+    }+    else+    {+      bufs_type bufs(buffers);+      return socket_ops::sync_send(impl.socket_, impl.state_,+          bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);+    }+  }++  // Wait until data can be sent without blocking.+  size_t send(base_implementation_type& impl, const null_buffers&,+      socket_base::message_flags, asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);++    return 0;+  }++  // Start an asynchronous send. The data being sent must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_send(base_implementation_type& impl,+      const ConstBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_socket_send_op<+        ConstBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, impl.socket_,+        impl.state_, buffers, flags, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_send"));++    start_op(impl, reactor::write_op, p.p, is_continuation, true,+        ((impl.state_ & socket_ops::stream_oriented)+          && buffer_sequence_adapter<asio::const_buffer,+            ConstBufferSequence>::all_empty(buffers)));+    p.v = p.p = 0;+  }++  // Start an asynchronous wait until data can be sent without blocking.+  template <typename Handler, typename IoExecutor>+  void async_send(base_implementation_type& impl, const null_buffers&,+      socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_send(null_buffers)"));++    start_op(impl, reactor::write_op, p.p, is_continuation, false, false);+    p.v = p.p = 0;+  }++  // Receive some data from the peer. Returns the number of bytes received.+  template <typename MutableBufferSequence>+  size_t receive(base_implementation_type& impl,+      const MutableBufferSequence& buffers,+      socket_base::message_flags flags, asio::error_code& ec)+  {+    typedef buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs_type;++    if (bufs_type::is_single_buffer)+    {+      return socket_ops::sync_recv1(impl.socket_,+          impl.state_, bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), flags, ec);+    }+    else+    {+      bufs_type bufs(buffers);+      return socket_ops::sync_recv(impl.socket_, impl.state_,+          bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);+    }+  }++  // Wait until data can be received without blocking.+  size_t receive(base_implementation_type& impl, const null_buffers&,+      socket_base::message_flags, asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);++    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received+  // must be valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive(base_implementation_type& impl,+      const MutableBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_socket_recv_op<+        MutableBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, impl.socket_,+        impl.state_, buffers, flags, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_receive"));++    start_op(impl,+        (flags & socket_base::message_out_of_band)+          ? reactor::except_op : reactor::read_op,+        p.p, is_continuation,+        (flags & socket_base::message_out_of_band) == 0,+        ((impl.state_ & socket_ops::stream_oriented)+          && buffer_sequence_adapter<asio::mutable_buffer,+            MutableBufferSequence>::all_empty(buffers)));+    p.v = p.p = 0;+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive(base_implementation_type& impl,+      const null_buffers&, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_receive(null_buffers)"));++    start_op(impl,+        (flags & socket_base::message_out_of_band)+          ? reactor::except_op : reactor::read_op,+        p.p, is_continuation, false, false);+    p.v = p.p = 0;+  }++  // Receive some data with associated flags. Returns the number of bytes+  // received.+  template <typename MutableBufferSequence>+  size_t receive_with_flags(base_implementation_type& impl,+      const MutableBufferSequence& buffers,+      socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags, asio::error_code& ec)+  {+    buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs(buffers);++    return socket_ops::sync_recvmsg(impl.socket_, impl.state_,+        bufs.buffers(), bufs.count(), in_flags, out_flags, ec);+  }++  // Wait until data can be received without blocking.+  size_t receive_with_flags(base_implementation_type& impl,+      const null_buffers&, socket_base::message_flags,+      socket_base::message_flags& out_flags, asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);++    // Clear out_flags, since we cannot give it any other sensible value when+    // performing a null_buffers operation.+    out_flags = 0;++    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received+  // must be valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive_with_flags(base_implementation_type& impl,+      const MutableBufferSequence& buffers, socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_socket_recvmsg_op<+        MutableBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, impl.socket_,+        buffers, in_flags, out_flags, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_receive_with_flags"));++    start_op(impl,+        (in_flags & socket_base::message_out_of_band)+          ? reactor::except_op : reactor::read_op,+        p.p, is_continuation,+        (in_flags & socket_base::message_out_of_band) == 0, false);+    p.v = p.p = 0;+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive_with_flags(base_implementation_type& impl,+      const null_buffers&, socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef reactive_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(success_ec_, handler, io_ex);++    ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));++    // Clear out_flags, since we cannot give it any other sensible value when+    // performing a null_buffers operation.+    out_flags = 0;++    start_op(impl,+        (in_flags & socket_base::message_out_of_band)+          ? reactor::except_op : reactor::read_op,+        p.p, is_continuation, false, false);+    p.v = p.p = 0;+  }++protected:+  // Open a new socket implementation.+  ASIO_DECL asio::error_code do_open(+      base_implementation_type& impl, int af,+      int type, int protocol, asio::error_code& ec);++  // Assign a native socket to a socket implementation.+  ASIO_DECL asio::error_code do_assign(+      base_implementation_type& impl, int type,+      const native_handle_type& native_socket, asio::error_code& ec);++  // Start the asynchronous read or write operation.+  ASIO_DECL void start_op(base_implementation_type& impl, int op_type,+      reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop);++  // Start the asynchronous accept operation.+  ASIO_DECL void start_accept_op(base_implementation_type& impl,+      reactor_op* op, bool is_continuation, bool peer_is_open);++  // Start the asynchronous connect operation.+  ASIO_DECL void start_connect_op(base_implementation_type& impl,+      reactor_op* op, bool is_continuation,+      const socket_addr_type* addr, size_t addrlen);++  // The selector that performs event demultiplexing for the service.+  reactor& reactor_;++  // Cached success value to avoid accessing category singleton.+  const asio::error_code success_ec_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/reactive_socket_service_base.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // !defined(ASIO_HAS_IOCP)+       //   && !defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactive_wait_op.hpp view
@@ -0,0 +1,98 @@+//+// detail/reactive_wait_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTIVE_WAIT_OP_HPP+#define ASIO_DETAIL_REACTIVE_WAIT_OP_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/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class reactive_wait_op : public reactor_op+{+public:+  ASIO_DEFINE_HANDLER_PTR(reactive_wait_op);++  reactive_wait_op(const asio::error_code& success_ec,+      Handler& handler, const IoExecutor& io_ex)+    : reactor_op(success_ec, &reactive_wait_op::do_perform,+        &reactive_wait_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static status do_perform(reactor_op*)+  {+    return done;+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    reactive_wait_op* o(static_cast<reactive_wait_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder1<Handler, asio::error_code>+      handler(o->handler_, o->ec_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTIVE_WAIT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactor.hpp view
@@ -0,0 +1,32 @@+//+// detail/reactor.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTOR_HPP+#define ASIO_DETAIL_REACTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/reactor_fwd.hpp"++#if defined(ASIO_HAS_EPOLL)+# include "asio/detail/epoll_reactor.hpp"+#elif defined(ASIO_HAS_KQUEUE)+# include "asio/detail/kqueue_reactor.hpp"+#elif defined(ASIO_HAS_DEV_POLL)+# include "asio/detail/dev_poll_reactor.hpp"+#elif defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/null_reactor.hpp"+#else+# include "asio/detail/select_reactor.hpp"+#endif++#endif // ASIO_DETAIL_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactor_fwd.hpp view
@@ -0,0 +1,40 @@+//+// detail/reactor_fwd.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTOR_FWD_HPP+#define ASIO_DETAIL_REACTOR_FWD_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+typedef class null_reactor reactor;+#elif defined(ASIO_HAS_IOCP)+typedef class select_reactor reactor;+#elif defined(ASIO_HAS_EPOLL)+typedef class epoll_reactor reactor;+#elif defined(ASIO_HAS_KQUEUE)+typedef class kqueue_reactor reactor;+#elif defined(ASIO_HAS_DEV_POLL)+typedef class dev_poll_reactor reactor;+#else+typedef class select_reactor reactor;+#endif++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_REACTOR_FWD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactor_op.hpp view
@@ -0,0 +1,67 @@+//+// detail/reactor_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTOR_OP_HPP+#define ASIO_DETAIL_REACTOR_OP_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/operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class reactor_op+  : public operation+{+public:+  // The error code to be passed to the completion handler.+  asio::error_code ec_;++  // The number of bytes transferred, to be passed to the completion handler.+  std::size_t bytes_transferred_;++  // Status returned by perform function. May be used to decide whether it is+  // worth performing more operations on the descriptor immediately.+  enum status { not_done, done, done_and_exhausted };++  // Perform the operation. Returns true if it is finished.+  status perform()+  {+    return perform_func_(this);+  }++protected:+  typedef status (*perform_func_type)(reactor_op*);++  reactor_op(const asio::error_code& success_ec,+      perform_func_type perform_func, func_type complete_func)+    : operation(complete_func),+      ec_(success_ec),+      bytes_transferred_(0),+      perform_func_(perform_func)+  {+  }++private:+  perform_func_type perform_func_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTOR_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/reactor_op_queue.hpp view
@@ -0,0 +1,168 @@+//+// detail/reactor_op_queue.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REACTOR_OP_QUEUE_HPP+#define ASIO_DETAIL_REACTOR_OP_QUEUE_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/hash_map.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Descriptor>+class reactor_op_queue+  : private noncopyable+{+public:+  typedef Descriptor key_type;++  struct mapped_type : op_queue<reactor_op>+  {+    mapped_type() {}+    mapped_type(const mapped_type&) {}+    void operator=(const mapped_type&) {}+  };++  typedef typename hash_map<key_type, mapped_type>::value_type value_type;+  typedef typename hash_map<key_type, mapped_type>::iterator iterator;++  // Constructor.+  reactor_op_queue()+    : operations_()+  {+  }++  // Obtain iterators to all registered descriptors.+  iterator begin() { return operations_.begin(); }+  iterator end() { return operations_.end(); }++  // Add a new operation to the queue. Returns true if this is the only+  // operation for the given descriptor, in which case the reactor's event+  // demultiplexing function call may need to be interrupted and restarted.+  bool enqueue_operation(Descriptor descriptor, reactor_op* op)+  {+    std::pair<iterator, bool> entry =+      operations_.insert(value_type(descriptor, mapped_type()));+    entry.first->second.push(op);+    return entry.second;+  }++  // Cancel all operations associated with the descriptor identified by the+  // supplied iterator. Any operations pending for the descriptor will be+  // cancelled. Returns true if any operations were cancelled, in which case+  // the reactor's event demultiplexing function may need to be interrupted and+  // restarted.+  bool cancel_operations(iterator i, op_queue<operation>& ops,+      const asio::error_code& ec =+        asio::error::operation_aborted)+  {+    if (i != operations_.end())+    {+      while (reactor_op* op = i->second.front())+      {+        op->ec_ = ec;+        i->second.pop();+        ops.push(op);+      }+      operations_.erase(i);+      return true;+    }++    return false;+  }++  // Cancel all operations associated with the descriptor. Any operations+  // pending for the descriptor will be cancelled. Returns true if any+  // operations were cancelled, in which case the reactor's event+  // demultiplexing function may need to be interrupted and restarted.+  bool cancel_operations(Descriptor descriptor, op_queue<operation>& ops,+      const asio::error_code& ec =+        asio::error::operation_aborted)+  {+    return this->cancel_operations(operations_.find(descriptor), ops, ec);+  }++  // Whether there are no operations in the queue.+  bool empty() const+  {+    return operations_.empty();+  }++  // Determine whether there are any operations associated with the descriptor.+  bool has_operation(Descriptor descriptor) const+  {+    return operations_.find(descriptor) != operations_.end();+  }++  // Perform the operations corresponding to the descriptor identified by the+  // supplied iterator. Returns true if there are still unfinished operations+  // queued for the descriptor.+  bool perform_operations(iterator i, op_queue<operation>& ops)+  {+    if (i != operations_.end())+    {+      while (reactor_op* op = i->second.front())+      {+        if (op->perform())+        {+          i->second.pop();+          ops.push(op);+        }+        else+        {+          return true;+        }+      }+      operations_.erase(i);+    }+    return false;+  }++  // Perform the operations corresponding to the descriptor. Returns true if+  // there are still unfinished operations queued for the descriptor.+  bool perform_operations(Descriptor descriptor, op_queue<operation>& ops)+  {+    return this->perform_operations(operations_.find(descriptor), ops);+  }++  // Get all operations owned by the queue.+  void get_all_operations(op_queue<operation>& ops)+  {+    iterator i = operations_.begin();+    while (i != operations_.end())+    {+      iterator op_iter = i++;+      ops.push(op_iter->second);+      operations_.erase(op_iter);+    }+  }++private:+  // The operations that are currently executing asynchronously.+  hash_map<key_type, mapped_type> operations_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_REACTOR_OP_QUEUE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/recycling_allocator.hpp view
@@ -0,0 +1,106 @@+//+// detail/recycling_allocator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_RECYCLING_ALLOCATOR_HPP+#define ASIO_DETAIL_RECYCLING_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/memory.hpp"+#include "asio/detail/thread_context.hpp"+#include "asio/detail/thread_info_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename T, typename Purpose = thread_info_base::default_tag>+class recycling_allocator+{+public:+  typedef T value_type;++  template <typename U>+  struct rebind+  {+    typedef recycling_allocator<U, Purpose> other;+  };++  recycling_allocator()+  {+  }++  template <typename U>+  recycling_allocator(const recycling_allocator<U, Purpose>&)+  {+  }++  T* allocate(std::size_t n)+  {+    typedef thread_context::thread_call_stack call_stack;+    void* p = thread_info_base::allocate(Purpose(),+        call_stack::top(), sizeof(T) * n);+    return static_cast<T*>(p);+  }++  void deallocate(T* p, std::size_t n)+  {+    typedef thread_context::thread_call_stack call_stack;+    thread_info_base::deallocate(Purpose(),+        call_stack::top(), p, sizeof(T) * n);+  }+};++template <typename Purpose>+class recycling_allocator<void, Purpose>+{+public:+  typedef void value_type;++  template <typename U>+  struct rebind+  {+    typedef recycling_allocator<U, Purpose> other;+  };++  recycling_allocator()+  {+  }++  template <typename U>+  recycling_allocator(const recycling_allocator<U, Purpose>&)+  {+  }+};++template <typename Allocator, typename Purpose>+struct get_recycling_allocator+{+  typedef Allocator type;+  static type get(const Allocator& a) { return a; }+};++template <typename T, typename Purpose>+struct get_recycling_allocator<std::allocator<T>, Purpose>+{+  typedef recycling_allocator<T, Purpose> type;+  static type get(const std::allocator<T>&) { return type(); }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_RECYCLING_ALLOCATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/regex_fwd.hpp view
@@ -0,0 +1,35 @@+//+// detail/regex_fwd.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_REGEX_FWD_HPP+#define ASIO_DETAIL_REGEX_FWD_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if defined(ASIO_HAS_BOOST_REGEX)++#include <boost/regex_fwd.hpp>+#include <boost/regex/v4/match_flags.hpp>++namespace boost {++template <class BidiIterator>+struct sub_match;++template <class BidiIterator, class Allocator>+class match_results;++} // namespace boost++#endif // defined(ASIO_HAS_BOOST_REGEX)++#endif // ASIO_DETAIL_REGEX_FWD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/resolve_endpoint_op.hpp view
@@ -0,0 +1,140 @@+//+// detail/resolve_endpoint_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP+#define ASIO_DETAIL_RESOLVER_ENDPOINT_OP_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/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/resolve_op.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"+#include "asio/ip/basic_resolver_results.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol, typename Handler, typename IoExecutor>+class resolve_endpoint_op : public resolve_op+{+public:+  ASIO_DEFINE_HANDLER_PTR(resolve_endpoint_op);++  typedef typename Protocol::endpoint endpoint_type;+  typedef asio::ip::basic_resolver_results<Protocol> results_type;++#if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_impl;+#else+  typedef class scheduler scheduler_impl;+#endif++  resolve_endpoint_op(socket_ops::weak_cancel_token_type cancel_token,+      const endpoint_type& endpoint, scheduler_impl& sched,+      Handler& handler, const IoExecutor& io_ex)+    : resolve_op(&resolve_endpoint_op::do_complete),+      cancel_token_(cancel_token),+      endpoint_(endpoint),+      scheduler_(sched),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the operation object.+    resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    if (owner && owner != &o->scheduler_)+    {+      // The operation is being run on the worker io_context. Time to perform+      // the resolver operation.+    +      // Perform the blocking endpoint resolution operation.+      char host_name[NI_MAXHOST];+      char service_name[NI_MAXSERV];+      socket_ops::background_getnameinfo(o->cancel_token_, o->endpoint_.data(),+          o->endpoint_.size(), host_name, NI_MAXHOST, service_name, NI_MAXSERV,+          o->endpoint_.protocol().type(), o->ec_);+      o->results_ = results_type::create(o->endpoint_, host_name, service_name);++      // Pass operation back to main io_context for completion.+      o->scheduler_.post_deferred_completion(o);+      p.v = p.p = 0;+    }+    else+    {+      // The operation has been returned to the main io_context. The completion+      // handler is ready to be delivered.++      ASIO_HANDLER_COMPLETION((*o));++      // Take ownership of the operation's outstanding work.+      handler_work<Handler, IoExecutor> w(+          ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+            o->work_));++      // Make a copy of the handler so that the memory can be deallocated+      // before the upcall is made. Even if we're not about to make an upcall,+      // a sub-object of the handler may be the true owner of the memory+      // associated with the handler. Consequently, a local copy of the handler+      // is required to ensure that any owning sub-object remains valid until+      // after we have deallocated the memory here.+      detail::binder2<Handler, asio::error_code, results_type>+        handler(o->handler_, o->ec_, o->results_);+      p.h = asio::detail::addressof(handler.handler_);+      p.reset();++      if (owner)+      {+        fenced_block b(fenced_block::half);+        ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));+        w.complete(handler, handler.handler_);+        ASIO_HANDLER_INVOCATION_END;+      }+    }+  }++private:+  socket_ops::weak_cancel_token_type cancel_token_;+  endpoint_type endpoint_;+  scheduler_impl& scheduler_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+  results_type results_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_RESOLVER_ENDPOINT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/resolve_op.hpp view
@@ -0,0 +1,45 @@+//+// detail/resolve_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_RESOLVE_OP_HPP+#define ASIO_DETAIL_RESOLVE_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/error.hpp"+#include "asio/detail/operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class resolve_op : public operation+{+public:+  // The error code to be passed to the completion handler.+  asio::error_code ec_;++protected:+  resolve_op(func_type complete_func)+    : operation(complete_func)+  {+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_RESOLVE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/resolve_query_op.hpp view
@@ -0,0 +1,150 @@+//+// detail/resolve_query_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_RESOLVE_QUERY_OP_HPP+#define ASIO_DETAIL_RESOLVE_QUERY_OP_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/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/resolve_op.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"+#include "asio/ip/basic_resolver_query.hpp"+#include "asio/ip/basic_resolver_results.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol, typename Handler, typename IoExecutor>+class resolve_query_op : public resolve_op+{+public:+  ASIO_DEFINE_HANDLER_PTR(resolve_query_op);++  typedef asio::ip::basic_resolver_query<Protocol> query_type;+  typedef asio::ip::basic_resolver_results<Protocol> results_type;++#if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_impl;+#else+  typedef class scheduler scheduler_impl;+#endif++  resolve_query_op(socket_ops::weak_cancel_token_type cancel_token,+      const query_type& query, scheduler_impl& sched,+      Handler& handler, const IoExecutor& io_ex)+    : resolve_op(&resolve_query_op::do_complete),+      cancel_token_(cancel_token),+      query_(query),+      scheduler_(sched),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex),+      addrinfo_(0)+  {+  }++  ~resolve_query_op()+  {+    if (addrinfo_)+      socket_ops::freeaddrinfo(addrinfo_);+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the operation object.+    resolve_query_op* o(static_cast<resolve_query_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    if (owner && owner != &o->scheduler_)+    {+      // The operation is being run on the worker io_context. Time to perform+      // the resolver operation.+    +      // Perform the blocking host resolution operation.+      socket_ops::background_getaddrinfo(o->cancel_token_,+          o->query_.host_name().c_str(), o->query_.service_name().c_str(),+          o->query_.hints(), &o->addrinfo_, o->ec_);++      // Pass operation back to main io_context for completion.+      o->scheduler_.post_deferred_completion(o);+      p.v = p.p = 0;+    }+    else+    {+      // The operation has been returned to the main io_context. The completion+      // handler is ready to be delivered.++      ASIO_HANDLER_COMPLETION((*o));++      // Take ownership of the operation's outstanding work.+      handler_work<Handler, IoExecutor> w(+          ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+            o->work_));++      // Make a copy of the handler so that the memory can be deallocated+      // before the upcall is made. Even if we're not about to make an upcall,+      // a sub-object of the handler may be the true owner of the memory+      // associated with the handler. Consequently, a local copy of the handler+      // is required to ensure that any owning sub-object remains valid until+      // after we have deallocated the memory here.+      detail::binder2<Handler, asio::error_code, results_type>+        handler(o->handler_, o->ec_, results_type());+      p.h = asio::detail::addressof(handler.handler_);+      if (o->addrinfo_)+      {+        handler.arg2_ = results_type::create(o->addrinfo_,+            o->query_.host_name(), o->query_.service_name());+      }+      p.reset();++      if (owner)+      {+        fenced_block b(fenced_block::half);+        ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));+        w.complete(handler, handler.handler_);+        ASIO_HANDLER_INVOCATION_END;+      }+    }+  }++private:+  socket_ops::weak_cancel_token_type cancel_token_;+  query_type query_;+  scheduler_impl& scheduler_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+  asio::detail::addrinfo_type* addrinfo_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_RESOLVE_QUERY_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/resolver_service.hpp view
@@ -0,0 +1,145 @@+//+// detail/resolver_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_RESOLVER_SERVICE_HPP+#define ASIO_DETAIL_RESOLVER_SERVICE_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_WINDOWS_RUNTIME)++#include "asio/ip/basic_resolver_query.hpp"+#include "asio/ip/basic_resolver_results.hpp"+#include "asio/detail/concurrency_hint.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/resolve_endpoint_op.hpp"+#include "asio/detail/resolve_query_op.hpp"+#include "asio/detail/resolver_service_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol>+class resolver_service :+  public execution_context_service_base<resolver_service<Protocol> >,+  public resolver_service_base+{+public:+  // The implementation type of the resolver. A cancellation token is used to+  // indicate to the background thread that the operation has been cancelled.+  typedef socket_ops::shared_cancel_token_type implementation_type;++  // The endpoint type.+  typedef typename Protocol::endpoint endpoint_type;++  // The query type.+  typedef asio::ip::basic_resolver_query<Protocol> query_type;++  // The results type.+  typedef asio::ip::basic_resolver_results<Protocol> results_type;++  // Constructor.+  resolver_service(execution_context& context)+    : execution_context_service_base<resolver_service<Protocol> >(context),+      resolver_service_base(context)+  {+  }++  // Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+    this->base_shutdown();+  }++  // Perform any fork-related housekeeping.+  void notify_fork(execution_context::fork_event fork_ev)+  {+    this->base_notify_fork(fork_ev);+  }++  // Resolve a query to a list of entries.+  results_type resolve(implementation_type&, const query_type& query,+      asio::error_code& ec)+  {+    asio::detail::addrinfo_type* address_info = 0;++    socket_ops::getaddrinfo(query.host_name().c_str(),+        query.service_name().c_str(), query.hints(), &address_info, ec);+    auto_addrinfo auto_address_info(address_info);++    return ec ? results_type() : results_type::create(+        address_info, query.host_name(), query.service_name());+  }++  // Asynchronously resolve a query to a list of entries.+  template <typename Handler, typename IoExecutor>+  void async_resolve(implementation_type& impl, const query_type& query,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef resolve_query_op<Protocol, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl, query, scheduler_, handler, io_ex);++    ASIO_HANDLER_CREATION((scheduler_.context(),+          *p.p, "resolver", &impl, 0, "async_resolve"));++    start_resolve_op(p.p);+    p.v = p.p = 0;+  }++  // Resolve an endpoint to a list of entries.+  results_type resolve(implementation_type&,+      const endpoint_type& endpoint, asio::error_code& ec)+  {+    char host_name[NI_MAXHOST];+    char service_name[NI_MAXSERV];+    socket_ops::sync_getnameinfo(endpoint.data(), endpoint.size(),+        host_name, NI_MAXHOST, service_name, NI_MAXSERV,+        endpoint.protocol().type(), ec);++    return ec ? results_type() : results_type::create(+        endpoint, host_name, service_name);+  }++  // Asynchronously resolve an endpoint to a list of entries.+  template <typename Handler, typename IoExecutor>+  void async_resolve(implementation_type& impl, const endpoint_type& endpoint,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef resolve_endpoint_op<Protocol, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl, endpoint, scheduler_, handler, io_ex);++    ASIO_HANDLER_CREATION((scheduler_.context(),+          *p.p, "resolver", &impl, 0, "async_resolve"));++    start_resolve_op(p.p);+    p.v = p.p = 0;+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_RESOLVER_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/resolver_service_base.hpp view
@@ -0,0 +1,143 @@+//+// detail/resolver_service_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP+#define ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/resolve_op.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/scoped_ptr.hpp"+#include "asio/detail/thread.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class resolver_service_base+{+public:+  // The implementation type of the resolver. A cancellation token is used to+  // indicate to the background thread that the operation has been cancelled.+  typedef socket_ops::shared_cancel_token_type implementation_type;++  // Constructor.+  ASIO_DECL resolver_service_base(execution_context& context);++  // Destructor.+  ASIO_DECL ~resolver_service_base();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void base_shutdown();++  // Perform any fork-related housekeeping.+  ASIO_DECL void base_notify_fork(+      execution_context::fork_event fork_ev);++  // Construct a new resolver implementation.+  ASIO_DECL void construct(implementation_type& impl);++  // Destroy a resolver implementation.+  ASIO_DECL void destroy(implementation_type&);++  // Move-construct a new resolver implementation.+  ASIO_DECL void move_construct(implementation_type& impl,+      implementation_type& other_impl);++  // Move-assign from another resolver implementation.+  ASIO_DECL void move_assign(implementation_type& impl,+      resolver_service_base& other_service,+      implementation_type& other_impl);++  // Cancel pending asynchronous operations.+  ASIO_DECL void cancel(implementation_type& impl);++protected:+  // Helper function to start an asynchronous resolve operation.+  ASIO_DECL void start_resolve_op(resolve_op* op);++#if !defined(ASIO_WINDOWS_RUNTIME)+  // Helper class to perform exception-safe cleanup of addrinfo objects.+  class auto_addrinfo+    : private asio::detail::noncopyable+  {+  public:+    explicit auto_addrinfo(asio::detail::addrinfo_type* ai)+      : ai_(ai)+    {+    }++    ~auto_addrinfo()+    {+      if (ai_)+        socket_ops::freeaddrinfo(ai_);+    }++    operator asio::detail::addrinfo_type*()+    {+      return ai_;+    }++  private:+    asio::detail::addrinfo_type* ai_;+  };+#endif // !defined(ASIO_WINDOWS_RUNTIME)++  // Helper class to run the work scheduler in a thread.+  class work_scheduler_runner;++  // Start the work scheduler if it's not already running.+  ASIO_DECL void start_work_thread();++  // The scheduler implementation used to post completions.+#if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_impl;+#else+  typedef class scheduler scheduler_impl;+#endif+  scheduler_impl& scheduler_;++private:+  // Mutex to protect access to internal data.+  asio::detail::mutex mutex_;++  // Private scheduler used for performing asynchronous host resolution.+  asio::detail::scoped_ptr<scheduler_impl> work_scheduler_;++  // Thread used for running the work io_context's run loop.+  asio::detail::scoped_ptr<asio::detail::thread> work_thread_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/resolver_service_base.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_RESOLVER_SERVICE_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/scheduler.hpp view
@@ -0,0 +1,232 @@+//+// detail/scheduler.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SCHEDULER_HPP+#define ASIO_DETAIL_SCHEDULER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/error_code.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/atomic_count.hpp"+#include "asio/detail/conditionally_enabled_event.hpp"+#include "asio/detail/conditionally_enabled_mutex.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/reactor_fwd.hpp"+#include "asio/detail/scheduler_operation.hpp"+#include "asio/detail/thread.hpp"+#include "asio/detail/thread_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct scheduler_thread_info;++class scheduler+  : public execution_context_service_base<scheduler>,+    public thread_context+{+public:+  typedef scheduler_operation operation;++  // Constructor. Specifies the number of concurrent threads that are likely to+  // run the scheduler. If set to 1 certain optimisation are performed.+  ASIO_DECL scheduler(asio::execution_context& ctx,+      int concurrency_hint = 0, bool own_thread = true);++  // Destructor.+  ASIO_DECL ~scheduler();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Initialise the task, if required.+  ASIO_DECL void init_task();++  // Run the event loop until interrupted or no more work.+  ASIO_DECL std::size_t run(asio::error_code& ec);++  // Run until interrupted or one operation is performed.+  ASIO_DECL std::size_t run_one(asio::error_code& ec);++  // Run until timeout, interrupted, or one operation is performed.+  ASIO_DECL std::size_t wait_one(+      long usec, asio::error_code& ec);++  // Poll for operations without blocking.+  ASIO_DECL std::size_t poll(asio::error_code& ec);++  // Poll for one operation without blocking.+  ASIO_DECL std::size_t poll_one(asio::error_code& ec);++  // Interrupt the event processing loop.+  ASIO_DECL void stop();++  // Determine whether the scheduler is stopped.+  ASIO_DECL bool stopped() const;++  // Restart in preparation for a subsequent run invocation.+  ASIO_DECL void restart();++  // Notify that some work has started.+  void work_started()+  {+    ++outstanding_work_;+  }++  // Used to compensate for a forthcoming work_finished call. Must be called+  // from within a scheduler-owned thread.+  ASIO_DECL void compensating_work_started();++  // Notify that some work has finished.+  void work_finished()+  {+    if (--outstanding_work_ == 0)+      stop();+  }++  // Return whether a handler can be dispatched immediately.+  bool can_dispatch()+  {+    return thread_call_stack::contains(this) != 0;+  }++  /// Capture the current exception so it can be rethrown from a run function.+  ASIO_DECL void capture_current_exception();++  // Request invocation of the given operation and return immediately. Assumes+  // that work_started() has not yet been called for the operation.+  ASIO_DECL void post_immediate_completion(+      operation* op, bool is_continuation);++  // Request invocation of the given operations and return immediately. Assumes+  // that work_started() has not yet been called for the operations.+  ASIO_DECL void post_immediate_completions(std::size_t n,+      op_queue<operation>& ops, bool is_continuation);++  // Request invocation of the given operation and return immediately. Assumes+  // that work_started() was previously called for the operation.+  ASIO_DECL void post_deferred_completion(operation* op);++  // Request invocation of the given operations and return immediately. Assumes+  // that work_started() was previously called for each operation.+  ASIO_DECL void post_deferred_completions(op_queue<operation>& ops);++  // Enqueue the given operation following a failed attempt to dispatch the+  // operation for immediate invocation.+  ASIO_DECL void do_dispatch(operation* op);++  // Process unfinished operations as part of a shutdownoperation. Assumes that+  // work_started() was previously called for the operations.+  ASIO_DECL void abandon_operations(op_queue<operation>& ops);++  // Get the concurrency hint that was used to initialise the scheduler.+  int concurrency_hint() const+  {+    return concurrency_hint_;+  }++private:+  // The mutex type used by this scheduler.+  typedef conditionally_enabled_mutex mutex;++  // The event type used by this scheduler.+  typedef conditionally_enabled_event event;++  // Structure containing thread-specific data.+  typedef scheduler_thread_info thread_info;++  // Run at most one operation. May block.+  ASIO_DECL std::size_t do_run_one(mutex::scoped_lock& lock,+      thread_info& this_thread, const asio::error_code& ec);++  // Run at most one operation with a timeout. May block.+  ASIO_DECL std::size_t do_wait_one(mutex::scoped_lock& lock,+      thread_info& this_thread, long usec, const asio::error_code& ec);++  // Poll for at most one operation.+  ASIO_DECL std::size_t do_poll_one(mutex::scoped_lock& lock,+      thread_info& this_thread, const asio::error_code& ec);++  // Stop the task and all idle threads.+  ASIO_DECL void stop_all_threads(mutex::scoped_lock& lock);++  // Wake a single idle thread, or the task, and always unlock the mutex.+  ASIO_DECL void wake_one_thread_and_unlock(+      mutex::scoped_lock& lock);++  // Helper class to run the scheduler in its own thread.+  class thread_function;+  friend class thread_function;++  // Helper class to perform task-related operations on block exit.+  struct task_cleanup;+  friend struct task_cleanup;++  // Helper class to call work-related operations on block exit.+  struct work_cleanup;+  friend struct work_cleanup;++  // Whether to optimise for single-threaded use cases.+  const bool one_thread_;++  // Mutex to protect access to internal data.+  mutable mutex mutex_;++  // Event to wake up blocked threads.+  event wakeup_event_;++  // The task to be run by this service.+  reactor* task_;++  // Operation object to represent the position of the task in the queue.+  struct task_operation : operation+  {+    task_operation() : operation(0) {}+  } task_operation_;++  // Whether the task has been interrupted.+  bool task_interrupted_;++  // The count of unfinished work.+  atomic_count outstanding_work_;++  // The queue of handlers that are ready to be delivered.+  op_queue<operation> op_queue_;++  // Flag to indicate that the dispatcher has been stopped.+  bool stopped_;++  // Flag to indicate that the dispatcher has been shut down.+  bool shutdown_;++  // The concurrency hint used to initialise the scheduler.+  const int concurrency_hint_;++  // The thread that is running the scheduler.+  asio::detail::thread* thread_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/scheduler.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_SCHEDULER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/scheduler_operation.hpp view
@@ -0,0 +1,78 @@+//+// detail/scheduler_operation.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SCHEDULER_OPERATION_HPP+#define ASIO_DETAIL_SCHEDULER_OPERATION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/error_code.hpp"+#include "asio/detail/handler_tracking.hpp"+#include "asio/detail/op_queue.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class scheduler;++// Base class for all operations. A function pointer is used instead of virtual+// functions to avoid the associated overhead.+class scheduler_operation ASIO_INHERIT_TRACKED_HANDLER+{+public:+  typedef scheduler_operation operation_type;++  void complete(void* owner, const asio::error_code& ec,+      std::size_t bytes_transferred)+  {+    func_(owner, this, ec, bytes_transferred);+  }++  void destroy()+  {+    func_(0, this, asio::error_code(), 0);+  }++protected:+  typedef void (*func_type)(void*,+      scheduler_operation*,+      const asio::error_code&, std::size_t);++  scheduler_operation(func_type func)+    : next_(0),+      func_(func),+      task_result_(0)+  {+  }++  // Prevents deletion through this type.+  ~scheduler_operation()+  {+  }++private:+  friend class op_queue_access;+  scheduler_operation* next_;+  func_type func_;+protected:+  friend class scheduler;+  unsigned int task_result_; // Passed into bytes transferred.+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SCHEDULER_OPERATION_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/scheduler_thread_info.hpp view
@@ -0,0 +1,40 @@+//+// detail/scheduler_thread_info.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SCHEDULER_THREAD_INFO_HPP+#define ASIO_DETAIL_SCHEDULER_THREAD_INFO_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/op_queue.hpp"+#include "asio/detail/thread_info_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class scheduler;+class scheduler_operation;++struct scheduler_thread_info : public thread_info_base+{+  op_queue<scheduler_operation> private_op_queue;+  long private_outstanding_work;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SCHEDULER_THREAD_INFO_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/scoped_lock.hpp view
@@ -0,0 +1,101 @@+//+// detail/scoped_lock.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SCOPED_LOCK_HPP+#define ASIO_DETAIL_SCOPED_LOCK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper class to lock and unlock a mutex automatically.+template <typename Mutex>+class scoped_lock+  : private noncopyable+{+public:+  // Tag type used to distinguish constructors.+  enum adopt_lock_t { adopt_lock };++  // Constructor adopts a lock that is already held.+  scoped_lock(Mutex& m, adopt_lock_t)+    : mutex_(m),+      locked_(true)+  {+  }++  // Constructor acquires the lock.+  explicit scoped_lock(Mutex& m)+    : mutex_(m)+  {+    mutex_.lock();+    locked_ = true;+  }++  // Destructor releases the lock.+  ~scoped_lock()+  {+    if (locked_)+      mutex_.unlock();+  }++  // Explicitly acquire the lock.+  void lock()+  {+    if (!locked_)+    {+      mutex_.lock();+      locked_ = true;+    }+  }++  // Explicitly release the lock.+  void unlock()+  {+    if (locked_)+    {+      mutex_.unlock();+      locked_ = false;+    }+  }++  // Test whether the lock is held.+  bool locked() const+  {+    return locked_;+  }++  // Get the underlying mutex.+  Mutex& mutex()+  {+    return mutex_;+  }++private:+  // The underlying mutex.+  Mutex& mutex_;++  // Whether the mutex is currently locked or unlocked.+  bool locked_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SCOPED_LOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/scoped_ptr.hpp view
@@ -0,0 +1,87 @@+//+// detail/scoped_ptr.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SCOPED_PTR_HPP+#define ASIO_DETAIL_SCOPED_PTR_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 {+namespace detail {++template <typename T>+class scoped_ptr+{+public:+  // Constructor.+  explicit scoped_ptr(T* p = 0)+    : p_(p)+  {+  }++  // Destructor.+  ~scoped_ptr()+  {+    delete p_;+  }++  // Access.+  T* get()+  {+    return p_;+  }++  // Access.+  T* operator->()+  {+    return p_;+  }++  // Dereference.+  T& operator*()+  {+    return *p_;+  }++  // Reset pointer.+  void reset(T* p = 0)+  {+    delete p_;+    p_ = p;+  }++  // Release ownership of the pointer.+  T* release()+  {+    T* tmp = p_;+    p_ = 0;+    return tmp;+  }++private:+  // Disallow copying and assignment.+  scoped_ptr(const scoped_ptr&);+  scoped_ptr& operator=(const scoped_ptr&);++  T* p_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SCOPED_PTR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/select_interrupter.hpp view
@@ -0,0 +1,46 @@+//+// detail/select_interrupter.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SELECT_INTERRUPTER_HPP+#define ASIO_DETAIL_SELECT_INTERRUPTER_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_WINDOWS_RUNTIME)++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)+# include "asio/detail/socket_select_interrupter.hpp"+#elif defined(ASIO_HAS_EVENTFD)+# include "asio/detail/eventfd_select_interrupter.hpp"+#else+# include "asio/detail/pipe_select_interrupter.hpp"+#endif++namespace asio {+namespace detail {++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__) || defined(__SYMBIAN32__)+typedef socket_select_interrupter select_interrupter;+#elif defined(ASIO_HAS_EVENTFD)+typedef eventfd_select_interrupter select_interrupter;+#else+typedef pipe_select_interrupter select_interrupter;+#endif++} // namespace detail+} // namespace asio++#endif // !defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_SELECT_INTERRUPTER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/select_reactor.hpp view
@@ -0,0 +1,238 @@+//+// detail/select_reactor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SELECT_REACTOR_HPP+#define ASIO_DETAIL_SELECT_REACTOR_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_IOCP) \+  || (!defined(ASIO_HAS_DEV_POLL) \+      && !defined(ASIO_HAS_EPOLL) \+      && !defined(ASIO_HAS_KQUEUE) \+      && !defined(ASIO_WINDOWS_RUNTIME))++#include <cstddef>+#include "asio/detail/fd_set_adapter.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/reactor_op_queue.hpp"+#include "asio/detail/select_interrupter.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/timer_queue_base.hpp"+#include "asio/detail/timer_queue_set.hpp"+#include "asio/detail/wait_op.hpp"+#include "asio/execution_context.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/thread.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class select_reactor+  : public execution_context_service_base<select_reactor>+{+public:+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  enum op_types { read_op = 0, write_op = 1, except_op = 2,+    max_select_ops = 3, connect_op = 3, max_ops = 4 };+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  enum op_types { read_op = 0, write_op = 1, except_op = 2,+    max_select_ops = 3, connect_op = 1, max_ops = 3 };+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++  // Per-descriptor data.+  struct per_descriptor_data+  {+  };++  // Constructor.+  ASIO_DECL select_reactor(asio::execution_context& ctx);++  // Destructor.+  ASIO_DECL ~select_reactor();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Recreate internal descriptors following a fork.+  ASIO_DECL void notify_fork(+      asio::execution_context::fork_event fork_ev);++  // Initialise the task, but only if the reactor is not in its own thread.+  ASIO_DECL void init_task();++  // Register a socket with the reactor. Returns 0 on success, system error+  // code on failure.+  ASIO_DECL int register_descriptor(socket_type, per_descriptor_data&);++  // Register a descriptor with an associated single operation. Returns 0 on+  // success, system error code on failure.+  ASIO_DECL int register_internal_descriptor(+      int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op);++  // Post a reactor operation for immediate completion.+  void post_immediate_completion(reactor_op* op, bool is_continuation)+  {+    scheduler_.post_immediate_completion(op, is_continuation);+  }++  // Start a new operation. The reactor operation will be performed when the+  // given descriptor is flagged as ready, or an error has occurred.+  ASIO_DECL void start_op(int op_type, socket_type descriptor,+      per_descriptor_data&, reactor_op* op, bool is_continuation, bool);++  // Cancel all operations associated with the given descriptor. The+  // handlers associated with the descriptor will be invoked with the+  // operation_aborted error.+  ASIO_DECL void cancel_ops(socket_type descriptor, per_descriptor_data&);++  // Cancel any operations that are running against the descriptor and remove+  // its registration from the reactor. The reactor resources associated with+  // the descriptor must be released by calling cleanup_descriptor_data.+  ASIO_DECL void deregister_descriptor(socket_type descriptor,+      per_descriptor_data&, bool closing);++  // Remove the descriptor's registration from the reactor. The reactor+  // resources associated with the descriptor must be released by calling+  // cleanup_descriptor_data.+  ASIO_DECL void deregister_internal_descriptor(+      socket_type descriptor, per_descriptor_data&);++  // Perform any post-deregistration cleanup tasks associated with the+  // descriptor data.+  ASIO_DECL void cleanup_descriptor_data(per_descriptor_data&);++  // Move descriptor registration from one descriptor_data object to another.+  ASIO_DECL void move_descriptor(socket_type descriptor,+      per_descriptor_data& target_descriptor_data,+      per_descriptor_data& source_descriptor_data);++  // Add a new timer queue to the reactor.+  template <typename Time_Traits>+  void add_timer_queue(timer_queue<Time_Traits>& queue);++  // Remove a timer queue from the reactor.+  template <typename Time_Traits>+  void remove_timer_queue(timer_queue<Time_Traits>& queue);++  // Schedule a new operation in the given timer queue to expire at the+  // specified absolute time.+  template <typename Time_Traits>+  void schedule_timer(timer_queue<Time_Traits>& queue,+      const typename Time_Traits::time_type& time,+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);++  // Cancel the timer operations associated with the given token. Returns the+  // number of operations that have been posted or dispatched.+  template <typename Time_Traits>+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& timer,+      std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++  // Move the timer operations associated with the given timer.+  template <typename Time_Traits>+  void move_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& target,+      typename timer_queue<Time_Traits>::per_timer_data& source);++  // Run select once until interrupted or events are ready to be dispatched.+  ASIO_DECL void run(long usec, op_queue<operation>& ops);++  // Interrupt the select loop.+  ASIO_DECL void interrupt();++private:+#if defined(ASIO_HAS_IOCP)+  // Run the select loop in the thread.+  ASIO_DECL void run_thread();+#endif // defined(ASIO_HAS_IOCP)++  // Helper function to add a new timer queue.+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);++  // Helper function to remove a timer queue.+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);++  // Get the timeout value for the select call.+  ASIO_DECL timeval* get_timeout(long usec, timeval& tv);++  // Cancel all operations associated with the given descriptor. This function+  // does not acquire the select_reactor's mutex.+  ASIO_DECL void cancel_ops_unlocked(socket_type descriptor,+      const asio::error_code& ec);++  // The scheduler implementation used to post completions.+# if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_type;+# else // defined(ASIO_HAS_IOCP)+  typedef class scheduler scheduler_type;+# endif // defined(ASIO_HAS_IOCP)+  scheduler_type& scheduler_;++  // Mutex to protect access to internal data.+  asio::detail::mutex mutex_;++  // The interrupter is used to break a blocking select call.+  select_interrupter interrupter_;++  // The queues of read, write and except operations.+  reactor_op_queue<socket_type> op_queue_[max_ops];++  // The file descriptor sets to be passed to the select system call.+  fd_set_adapter fd_sets_[max_select_ops];++  // The timer queues.+  timer_queue_set timer_queues_;++#if defined(ASIO_HAS_IOCP)+  // Helper class to run the reactor loop in a thread.+  class thread_function;+  friend class thread_function;++  // Does the reactor loop thread need to stop.+  bool stop_thread_;++  // The thread that is running the reactor loop.+  asio::detail::thread* thread_;+#endif // defined(ASIO_HAS_IOCP)++  // Whether the service has been shut down.+  bool shutdown_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/select_reactor.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/select_reactor.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IOCP)+       //   || (!defined(ASIO_HAS_DEV_POLL)+       //       && !defined(ASIO_HAS_EPOLL)+       //       && !defined(ASIO_HAS_KQUEUE)+       //       && !defined(ASIO_WINDOWS_RUNTIME))++#endif // ASIO_DETAIL_SELECT_REACTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/service_registry.hpp view
@@ -0,0 +1,164 @@+//+// detail/service_registry.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SERVICE_REGISTRY_HPP+#define ASIO_DETAIL_SERVICE_REGISTRY_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <typeinfo>+#include "asio/detail/mutex.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++class io_context;++namespace detail {++template <typename T>+class typeid_wrapper {};++class service_registry+  : private noncopyable+{+public:+  // Constructor.+  ASIO_DECL service_registry(execution_context& owner);++  // Destructor.+  ASIO_DECL ~service_registry();++  // Shutdown all services.+  ASIO_DECL void shutdown_services();++  // Destroy all services.+  ASIO_DECL void destroy_services();++  // Notify all services of a fork event.+  ASIO_DECL void notify_fork(execution_context::fork_event fork_ev);++  // Get the service object corresponding to the specified service type. Will+  // create a new service object automatically if no such object already+  // exists. Ownership of the service object is not transferred to the caller.+  template <typename Service>+  Service& use_service();++  // Get the service object corresponding to the specified service type. Will+  // create a new service object automatically if no such object already+  // exists. Ownership of the service object is not transferred to the caller.+  // This overload is used for backwards compatibility with services that+  // inherit from io_context::service.+  template <typename Service>+  Service& use_service(io_context& owner);++  // Add a service object. Throws on error, in which case ownership of the+  // object is retained by the caller.+  template <typename Service>+  void add_service(Service* new_service);++  // Check whether a service object of the specified type already exists.+  template <typename Service>+  bool has_service() const;++private:+  // Initalise a service's key when the key_type typedef is not available.+  template <typename Service>+  static void init_key(execution_context::service::key& key, ...);++#if !defined(ASIO_NO_TYPEID)+  // Initalise a service's key when the key_type typedef is available.+  template <typename Service>+  static void init_key(execution_context::service::key& key,+      typename enable_if<+        is_base_of<typename Service::key_type, Service>::value>::type*);+#endif // !defined(ASIO_NO_TYPEID)++  // Initialise a service's key based on its id.+  ASIO_DECL static void init_key_from_id(+      execution_context::service::key& key,+      const execution_context::id& id);++#if !defined(ASIO_NO_TYPEID)+  // Initialise a service's key based on its id.+  template <typename Service>+  static void init_key_from_id(execution_context::service::key& key,+      const service_id<Service>& /*id*/);+#endif // !defined(ASIO_NO_TYPEID)++  // Check if a service matches the given id.+  ASIO_DECL static bool keys_match(+      const execution_context::service::key& key1,+      const execution_context::service::key& key2);++  // The type of a factory function used for creating a service instance.+  typedef execution_context::service*(*factory_type)(void*);++  // Factory function for creating a service instance.+  template <typename Service, typename Owner>+  static execution_context::service* create(void* owner);++  // Destroy a service instance.+  ASIO_DECL static void destroy(execution_context::service* service);++  // Helper class to manage service pointers.+  struct auto_service_ptr;+  friend struct auto_service_ptr;+  struct auto_service_ptr+  {+    execution_context::service* ptr_;+    ~auto_service_ptr() { destroy(ptr_); }+  };++  // Get the service object corresponding to the specified service key. Will+  // create a new service object automatically if no such object already+  // exists. Ownership of the service object is not transferred to the caller.+  ASIO_DECL execution_context::service* do_use_service(+      const execution_context::service::key& key,+      factory_type factory, void* owner);++  // Add a service object. Throws on error, in which case ownership of the+  // object is retained by the caller.+  ASIO_DECL void do_add_service(+      const execution_context::service::key& key,+      execution_context::service* new_service);++  // Check whether a service object with the specified key already exists.+  ASIO_DECL bool do_has_service(+      const execution_context::service::key& key) const;++  // Mutex to protect access to internal data.+  mutable asio::detail::mutex mutex_;++  // The owner of this service registry and the services it contains.+  execution_context& owner_;++  // The first service in the list of contained services.+  execution_context::service* first_service_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/service_registry.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/service_registry.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_SERVICE_REGISTRY_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/signal_blocker.hpp view
@@ -0,0 +1,44 @@+//+// detail/signal_blocker.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SIGNAL_BLOCKER_HPP+#define ASIO_DETAIL_SIGNAL_BLOCKER_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_THREADS) || defined(ASIO_WINDOWS) \+  || defined(ASIO_WINDOWS_RUNTIME) \+  || defined(__CYGWIN__) || defined(__SYMBIAN32__)+# include "asio/detail/null_signal_blocker.hpp"+#elif defined(ASIO_HAS_PTHREADS)+# include "asio/detail/posix_signal_blocker.hpp"+#else+# error Only Windows and POSIX are supported!+#endif++namespace asio {+namespace detail {++#if !defined(ASIO_HAS_THREADS) || defined(ASIO_WINDOWS) \+  || defined(ASIO_WINDOWS_RUNTIME) \+  || defined(__CYGWIN__) || defined(__SYMBIAN32__)+typedef null_signal_blocker signal_blocker;+#elif defined(ASIO_HAS_PTHREADS)+typedef posix_signal_blocker signal_blocker;+#endif++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_SIGNAL_BLOCKER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/signal_handler.hpp view
@@ -0,0 +1,90 @@+//+// detail/signal_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SIGNAL_HANDLER_HPP+#define ASIO_DETAIL_SIGNAL_HANDLER_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/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/signal_op.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class signal_handler : public signal_op+{+public:+  ASIO_DEFINE_HANDLER_PTR(signal_handler);++  signal_handler(Handler& h, const IoExecutor& io_ex)+    : signal_op(&signal_handler::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(h)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    signal_handler* h(static_cast<signal_handler*>(base));+    ptr p = { asio::detail::addressof(h->handler_), h, h };++    ASIO_HANDLER_COMPLETION((*h));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          h->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, int>+      handler(h->handler_, h->ec_, h->signal_number_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SIGNAL_HANDLER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/signal_init.hpp view
@@ -0,0 +1,47 @@+//+// detail/signal_init.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SIGNAL_INIT_HPP+#define ASIO_DETAIL_SIGNAL_INIT_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_WINDOWS) && !defined(__CYGWIN__)++#include <csignal>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <int Signal = SIGPIPE>+class signal_init+{+public:+  // Constructor.+  signal_init()+  {+    std::signal(Signal, SIG_IGN);+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++#endif // ASIO_DETAIL_SIGNAL_INIT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/signal_op.hpp view
@@ -0,0 +1,49 @@+//+// detail/signal_op.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SIGNAL_OP_HPP+#define ASIO_DETAIL_SIGNAL_OP_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/operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class signal_op+  : public operation+{+public:+  // The error code to be passed to the completion handler.+  asio::error_code ec_;++  // The signal number to be passed to the completion handler.+  int signal_number_;++protected:+  signal_op(func_type func)+    : operation(func),+      signal_number_(0)+  {+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SIGNAL_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/signal_set_service.hpp view
@@ -0,0 +1,229 @@+//+// detail/signal_set_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SIGNAL_SET_SERVICE_HPP+#define ASIO_DETAIL_SIGNAL_SET_SERVICE_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 <signal.h>+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/signal_handler.hpp"+#include "asio/detail/signal_op.hpp"+#include "asio/detail/socket_types.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)++#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+# include "asio/detail/reactor.hpp"+#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if defined(NSIG) && (NSIG > 0)+enum { max_signal_number = NSIG };+#else+enum { max_signal_number = 128 };+#endif++extern ASIO_DECL struct signal_state* get_signal_state();++extern "C" ASIO_DECL void asio_signal_handler(int signal_number);++class signal_set_service :+  public execution_context_service_base<signal_set_service>+{+public:+  // Type used for tracking an individual signal registration.+  class registration+  {+  public:+    // Default constructor.+    registration()+      : signal_number_(0),+        queue_(0),+        undelivered_(0),+        next_in_table_(0),+        prev_in_table_(0),+        next_in_set_(0)+    {+    }++  private:+    // Only this service will have access to the internal values.+    friend class signal_set_service;++    // The signal number that is registered.+    int signal_number_;++    // The waiting signal handlers.+    op_queue<signal_op>* queue_;++    // The number of undelivered signals.+    std::size_t undelivered_;++    // Pointers to adjacent registrations in the registrations_ table.+    registration* next_in_table_;+    registration* prev_in_table_;++    // Link to next registration in the signal set.+    registration* next_in_set_;+  };++  // The implementation type of the signal_set.+  class implementation_type+  {+  public:+    // Default constructor.+    implementation_type()+      : signals_(0)+    {+    }++  private:+    // Only this service will have access to the internal values.+    friend class signal_set_service;++    // The pending signal handlers.+    op_queue<signal_op> queue_;++    // Linked list of registered signals.+    registration* signals_;+  };++  // Constructor.+  ASIO_DECL signal_set_service(execution_context& context);++  // Destructor.+  ASIO_DECL ~signal_set_service();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Perform fork-related housekeeping.+  ASIO_DECL void notify_fork(+      asio::execution_context::fork_event fork_ev);++  // Construct a new signal_set implementation.+  ASIO_DECL void construct(implementation_type& impl);++  // Destroy a signal_set implementation.+  ASIO_DECL void destroy(implementation_type& impl);++  // Add a signal to a signal_set.+  ASIO_DECL asio::error_code add(implementation_type& impl,+      int signal_number, asio::error_code& ec);++  // Remove a signal to a signal_set.+  ASIO_DECL asio::error_code remove(implementation_type& impl,+      int signal_number, asio::error_code& ec);++  // Remove all signals from a signal_set.+  ASIO_DECL asio::error_code clear(implementation_type& impl,+      asio::error_code& ec);++  // Cancel all operations associated with the signal set.+  ASIO_DECL asio::error_code cancel(implementation_type& impl,+      asio::error_code& ec);++  // Start an asynchronous operation to wait for a signal to be delivered.+  template <typename Handler, typename IoExecutor>+  void async_wait(implementation_type& impl,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef signal_handler<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(handler, io_ex);++    ASIO_HANDLER_CREATION((scheduler_.context(),+          *p.p, "signal_set", &impl, 0, "async_wait"));++    start_wait_op(impl, p.p);+    p.v = p.p = 0;+  }++  // Deliver notification that a particular signal occurred.+  ASIO_DECL static void deliver_signal(int signal_number);++private:+  // Helper function to add a service to the global signal state.+  ASIO_DECL static void add_service(signal_set_service* service);++  // Helper function to remove a service from the global signal state.+  ASIO_DECL static void remove_service(signal_set_service* service);++  // Helper function to create the pipe descriptors.+  ASIO_DECL static void open_descriptors();++  // Helper function to close the pipe descriptors.+  ASIO_DECL static void close_descriptors();++  // Helper function to start a wait operation.+  ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op);++  // The scheduler used for dispatching handlers.+#if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_impl;+#else+  typedef class scheduler scheduler_impl;+#endif+  scheduler_impl& scheduler_;++#if !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+  // The type used for registering for pipe reactor notifications.+  class pipe_read_op;++  // The reactor used for waiting for pipe readiness.+  reactor& reactor_;++  // The per-descriptor reactor data used for the pipe.+  reactor::per_descriptor_data reactor_data_;+#endif // !defined(ASIO_WINDOWS)+       //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(__CYGWIN__)++  // A mapping from signal number to the registered signal sets.+  registration* registrations_[max_signal_number];++  // Pointers to adjacent services in linked list.+  signal_set_service* next_;+  signal_set_service* prev_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/signal_set_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_SIGNAL_SET_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/socket_holder.hpp view
@@ -0,0 +1,98 @@+//+// detail/socket_holder.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SOCKET_HOLDER_HPP+#define ASIO_DETAIL_SOCKET_HOLDER_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/noncopyable.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Implement the resource acquisition is initialisation idiom for sockets.+class socket_holder+  : private noncopyable+{+public:+  // Construct as an uninitialised socket.+  socket_holder()+    : socket_(invalid_socket)+  {+  }++  // Construct to take ownership of the specified socket.+  explicit socket_holder(socket_type s)+    : socket_(s)+  {+  }++  // Destructor.+  ~socket_holder()+  {+    if (socket_ != invalid_socket)+    {+      asio::error_code ec;+      socket_ops::state_type state = 0;+      socket_ops::close(socket_, state, true, ec);+    }+  }++  // Get the underlying socket.+  socket_type get() const+  {+    return socket_;+  }++  // Reset to an uninitialised socket.+  void reset()+  {+    if (socket_ != invalid_socket)+    {+      asio::error_code ec;+      socket_ops::state_type state = 0;+      socket_ops::close(socket_, state, true, ec);+      socket_ = invalid_socket;+    }+  }++  // Reset to take ownership of the specified socket.+  void reset(socket_type s)+  {+    reset();+    socket_ = s;+  }++  // Release ownership of the socket.+  socket_type release()+  {+    socket_type tmp = socket_;+    socket_ = invalid_socket;+    return tmp;+  }++private:+  // The underlying socket.+  socket_type socket_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SOCKET_HOLDER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/socket_ops.hpp view
@@ -0,0 +1,383 @@+//+// detail/socket_ops.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SOCKET_OPS_HPP+#define ASIO_DETAIL_SOCKET_OPS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/error_code.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {+namespace socket_ops {++// Socket state bits.+enum+{+  // The user wants a non-blocking socket.+  user_set_non_blocking = 1,++  // The socket has been set non-blocking.+  internal_non_blocking = 2,++  // Helper "state" used to determine whether the socket is non-blocking.+  non_blocking = user_set_non_blocking | internal_non_blocking,++  // User wants connection_aborted errors, which are disabled by default.+  enable_connection_aborted = 4,++  // The user set the linger option. Needs to be checked when closing.+  user_set_linger = 8,++  // The socket is stream-oriented.+  stream_oriented = 16,++  // The socket is datagram-oriented.+  datagram_oriented = 32,++  // The socket may have been dup()-ed.+  possible_dup = 64+};++typedef unsigned char state_type;++struct noop_deleter { void operator()(void*) {} };+typedef shared_ptr<void> shared_cancel_token_type;+typedef weak_ptr<void> weak_cancel_token_type;++#if !defined(ASIO_WINDOWS_RUNTIME)++ASIO_DECL socket_type accept(socket_type s, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec);++ASIO_DECL socket_type sync_accept(socket_type s,+    state_type state, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec);++#if defined(ASIO_HAS_IOCP)++ASIO_DECL void complete_iocp_accept(socket_type s,+    void* output_buffer, DWORD address_length,+    socket_addr_type* addr, std::size_t* addrlen,+    socket_type new_socket, asio::error_code& ec);++#else // defined(ASIO_HAS_IOCP)++ASIO_DECL bool non_blocking_accept(socket_type s,+    state_type state, socket_addr_type* addr, std::size_t* addrlen,+    asio::error_code& ec, socket_type& new_socket);++#endif // defined(ASIO_HAS_IOCP)++ASIO_DECL int bind(socket_type s, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec);++ASIO_DECL int close(socket_type s, state_type& state,+    bool destruction, asio::error_code& ec);++ASIO_DECL bool set_user_non_blocking(socket_type s,+    state_type& state, bool value, asio::error_code& ec);++ASIO_DECL bool set_internal_non_blocking(socket_type s,+    state_type& state, bool value, asio::error_code& ec);++ASIO_DECL int shutdown(socket_type s,+    int what, asio::error_code& ec);++ASIO_DECL int connect(socket_type s, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec);++ASIO_DECL void sync_connect(socket_type s, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec);++#if defined(ASIO_HAS_IOCP)++ASIO_DECL void complete_iocp_connect(socket_type s,+    asio::error_code& ec);++#endif // defined(ASIO_HAS_IOCP)++ASIO_DECL bool non_blocking_connect(socket_type s,+    asio::error_code& ec);++ASIO_DECL int socketpair(int af, int type, int protocol,+    socket_type sv[2], asio::error_code& ec);++ASIO_DECL bool sockatmark(socket_type s, asio::error_code& ec);++ASIO_DECL size_t available(socket_type s, asio::error_code& ec);++ASIO_DECL int listen(socket_type s,+    int backlog, asio::error_code& ec);++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+typedef WSABUF buf;+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+typedef iovec buf;+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++ASIO_DECL void init_buf(buf& b, void* data, size_t size);++ASIO_DECL void init_buf(buf& b, const void* data, size_t size);++ASIO_DECL signed_size_type recv(socket_type s, buf* bufs,+    size_t count, int flags, asio::error_code& ec);++ASIO_DECL signed_size_type recv1(socket_type s,+    void* data, size_t size, int flags, asio::error_code& ec);++ASIO_DECL size_t sync_recv(socket_type s, state_type state, buf* bufs,+    size_t count, int flags, bool all_empty, asio::error_code& ec);++ASIO_DECL size_t sync_recv1(socket_type s, state_type state,+    void* data, size_t size, int flags, asio::error_code& ec);++#if defined(ASIO_HAS_IOCP)++ASIO_DECL void complete_iocp_recv(state_type state,+    const weak_cancel_token_type& cancel_token, bool all_empty,+    asio::error_code& ec, size_t bytes_transferred);++#else // defined(ASIO_HAS_IOCP)++ASIO_DECL bool non_blocking_recv(socket_type s,+    buf* bufs, size_t count, int flags, bool is_stream,+    asio::error_code& ec, size_t& bytes_transferred);++ASIO_DECL bool non_blocking_recv1(socket_type s,+    void* data, size_t size, int flags, bool is_stream,+    asio::error_code& ec, size_t& bytes_transferred);++#endif // defined(ASIO_HAS_IOCP)++ASIO_DECL signed_size_type recvfrom(socket_type s, buf* bufs,+    size_t count, int flags, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec);++ASIO_DECL signed_size_type recvfrom1(socket_type s, void* data,+    size_t size, int flags, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec);++ASIO_DECL size_t sync_recvfrom(socket_type s, state_type state,+    buf* bufs, size_t count, int flags, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec);++ASIO_DECL size_t sync_recvfrom1(socket_type s, state_type state,+    void* data, size_t size, int flags, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec);++#if defined(ASIO_HAS_IOCP)++ASIO_DECL void complete_iocp_recvfrom(+    const weak_cancel_token_type& cancel_token,+    asio::error_code& ec);++#else // defined(ASIO_HAS_IOCP)++ASIO_DECL bool non_blocking_recvfrom(socket_type s,+    buf* bufs, size_t count, int flags,+    socket_addr_type* addr, std::size_t* addrlen,+    asio::error_code& ec, size_t& bytes_transferred);++ASIO_DECL bool non_blocking_recvfrom1(socket_type s,+    void* data, size_t size, int flags,+    socket_addr_type* addr, std::size_t* addrlen,+    asio::error_code& ec, size_t& bytes_transferred);++#endif // defined(ASIO_HAS_IOCP)++ASIO_DECL signed_size_type recvmsg(socket_type s, buf* bufs,+    size_t count, int in_flags, int& out_flags,+    asio::error_code& ec);++ASIO_DECL size_t sync_recvmsg(socket_type s, state_type state,+    buf* bufs, size_t count, int in_flags, int& out_flags,+    asio::error_code& ec);++#if defined(ASIO_HAS_IOCP)++ASIO_DECL void complete_iocp_recvmsg(+    const weak_cancel_token_type& cancel_token,+    asio::error_code& ec);++#else // defined(ASIO_HAS_IOCP)++ASIO_DECL bool non_blocking_recvmsg(socket_type s,+    buf* bufs, size_t count, int in_flags, int& out_flags,+    asio::error_code& ec, size_t& bytes_transferred);++#endif // defined(ASIO_HAS_IOCP)++ASIO_DECL signed_size_type send(socket_type s, const buf* bufs,+    size_t count, int flags, asio::error_code& ec);++ASIO_DECL signed_size_type send1(socket_type s,+    const void* data, size_t size, int flags, asio::error_code& ec);++ASIO_DECL size_t sync_send(socket_type s, state_type state,+    const buf* bufs, size_t count, int flags,+    bool all_empty, asio::error_code& ec);++ASIO_DECL size_t sync_send1(socket_type s, state_type state,+    const void* data, size_t size, int flags, asio::error_code& ec);++#if defined(ASIO_HAS_IOCP)++ASIO_DECL void complete_iocp_send(+    const weak_cancel_token_type& cancel_token,+    asio::error_code& ec);++#else // defined(ASIO_HAS_IOCP)++ASIO_DECL bool non_blocking_send(socket_type s,+    const buf* bufs, size_t count, int flags,+    asio::error_code& ec, size_t& bytes_transferred);++ASIO_DECL bool non_blocking_send1(socket_type s,+    const void* data, size_t size, int flags,+    asio::error_code& ec, size_t& bytes_transferred);++#endif // defined(ASIO_HAS_IOCP)++ASIO_DECL signed_size_type sendto(socket_type s, const buf* bufs,+    size_t count, int flags, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec);++ASIO_DECL signed_size_type sendto1(socket_type s, const void* data,+    size_t size, int flags, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec);++ASIO_DECL size_t sync_sendto(socket_type s, state_type state,+    const buf* bufs, size_t count, int flags, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec);++ASIO_DECL size_t sync_sendto1(socket_type s, state_type state,+    const void* data, size_t size, int flags, const socket_addr_type* addr,+    std::size_t addrlen, asio::error_code& ec);++#if !defined(ASIO_HAS_IOCP)++ASIO_DECL bool non_blocking_sendto(socket_type s,+    const buf* bufs, size_t count, int flags,+    const socket_addr_type* addr, std::size_t addrlen,+    asio::error_code& ec, size_t& bytes_transferred);++ASIO_DECL bool non_blocking_sendto1(socket_type s,+    const void* data, size_t size, int flags,+    const socket_addr_type* addr, std::size_t addrlen,+    asio::error_code& ec, size_t& bytes_transferred);++#endif // !defined(ASIO_HAS_IOCP)++ASIO_DECL socket_type socket(int af, int type, int protocol,+    asio::error_code& ec);++ASIO_DECL int setsockopt(socket_type s, state_type& state,+    int level, int optname, const void* optval,+    std::size_t optlen, asio::error_code& ec);++ASIO_DECL int getsockopt(socket_type s, state_type state,+    int level, int optname, void* optval,+    size_t* optlen, asio::error_code& ec);++ASIO_DECL int getpeername(socket_type s, socket_addr_type* addr,+    std::size_t* addrlen, bool cached, asio::error_code& ec);++ASIO_DECL int getsockname(socket_type s, socket_addr_type* addr,+    std::size_t* addrlen, asio::error_code& ec);++ASIO_DECL int ioctl(socket_type s, state_type& state,+    int cmd, ioctl_arg_type* arg, asio::error_code& ec);++ASIO_DECL int select(int nfds, fd_set* readfds, fd_set* writefds,+    fd_set* exceptfds, timeval* timeout, asio::error_code& ec);++ASIO_DECL int poll_read(socket_type s,+    state_type state, int msec, asio::error_code& ec);++ASIO_DECL int poll_write(socket_type s,+    state_type state, int msec, asio::error_code& ec);++ASIO_DECL int poll_error(socket_type s,+    state_type state, int msec, asio::error_code& ec);++ASIO_DECL int poll_connect(socket_type s,+    int msec, asio::error_code& ec);++#endif // !defined(ASIO_WINDOWS_RUNTIME)++ASIO_DECL const char* inet_ntop(int af, const void* src, char* dest,+    size_t length, unsigned long scope_id, asio::error_code& ec);++ASIO_DECL int inet_pton(int af, const char* src, void* dest,+    unsigned long* scope_id, asio::error_code& ec);++ASIO_DECL int gethostname(char* name,+    int namelen, asio::error_code& ec);++#if !defined(ASIO_WINDOWS_RUNTIME)++ASIO_DECL asio::error_code getaddrinfo(const char* host,+    const char* service, const addrinfo_type& hints,+    addrinfo_type** result, asio::error_code& ec);++ASIO_DECL asio::error_code background_getaddrinfo(+    const weak_cancel_token_type& cancel_token, const char* host,+    const char* service, const addrinfo_type& hints,+    addrinfo_type** result, asio::error_code& ec);++ASIO_DECL void freeaddrinfo(addrinfo_type* ai);++ASIO_DECL asio::error_code getnameinfo(+    const socket_addr_type* addr, std::size_t addrlen,+    char* host, std::size_t hostlen, char* serv,+    std::size_t servlen, int flags, asio::error_code& ec);++ASIO_DECL asio::error_code sync_getnameinfo(+    const socket_addr_type* addr, std::size_t addrlen,+    char* host, std::size_t hostlen, char* serv,+    std::size_t servlen, int sock_type, asio::error_code& ec);++ASIO_DECL asio::error_code background_getnameinfo(+    const weak_cancel_token_type& cancel_token,+    const socket_addr_type* addr, std::size_t addrlen,+    char* host, std::size_t hostlen, char* serv,+    std::size_t servlen, int sock_type, asio::error_code& ec);++#endif // !defined(ASIO_WINDOWS_RUNTIME)++ASIO_DECL u_long_type network_to_host_long(u_long_type value);++ASIO_DECL u_long_type host_to_network_long(u_long_type value);++ASIO_DECL u_short_type network_to_host_short(u_short_type value);++ASIO_DECL u_short_type host_to_network_short(u_short_type value);++} // namespace socket_ops+} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/socket_ops.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_SOCKET_OPS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/socket_option.hpp view
@@ -0,0 +1,316 @@+//+// detail/socket_option.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SOCKET_OPTION_HPP+#define ASIO_DETAIL_SOCKET_OPTION_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 <stdexcept>+#include "asio/detail/socket_types.hpp"+#include "asio/detail/throw_exception.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {+namespace socket_option {++// Helper template for implementing boolean-based options.+template <int Level, int Name>+class boolean+{+public:+  // Default constructor.+  boolean()+    : value_(0)+  {+  }++  // Construct with a specific option value.+  explicit boolean(bool v)+    : value_(v ? 1 : 0)+  {+  }++  // Set the current value of the boolean.+  boolean& operator=(bool v)+  {+    value_ = v ? 1 : 0;+    return *this;+  }++  // Get the current value of the boolean.+  bool value() const+  {+    return !!value_;+  }++  // Convert to bool.+  operator bool() const+  {+    return !!value_;+  }++  // Test for false.+  bool operator!() const+  {+    return !value_;+  }++  // Get the level of the socket option.+  template <typename Protocol>+  int level(const Protocol&) const+  {+    return Level;+  }++  // Get the name of the socket option.+  template <typename Protocol>+  int name(const Protocol&) const+  {+    return Name;+  }++  // Get the address of the boolean data.+  template <typename Protocol>+  int* data(const Protocol&)+  {+    return &value_;+  }++  // Get the address of the boolean data.+  template <typename Protocol>+  const int* data(const Protocol&) const+  {+    return &value_;+  }++  // Get the size of the boolean data.+  template <typename Protocol>+  std::size_t size(const Protocol&) const+  {+    return sizeof(value_);+  }++  // Set the size of the boolean data.+  template <typename Protocol>+  void resize(const Protocol&, std::size_t s)+  {+    // On some platforms (e.g. Windows Vista), the getsockopt function will+    // return the size of a boolean socket option as one byte, even though a+    // four byte integer was passed in.+    switch (s)+    {+    case sizeof(char):+      value_ = *reinterpret_cast<char*>(&value_) ? 1 : 0;+      break;+    case sizeof(value_):+      break;+    default:+      {+        std::length_error ex("boolean socket option resize");+        asio::detail::throw_exception(ex);+      }+    }+  }++private:+  int value_;+};++// Helper template for implementing integer options.+template <int Level, int Name>+class integer+{+public:+  // Default constructor.+  integer()+    : value_(0)+  {+  }++  // Construct with a specific option value.+  explicit integer(int v)+    : value_(v)+  {+  }++  // Set the value of the int option.+  integer& operator=(int v)+  {+    value_ = v;+    return *this;+  }++  // Get the current value of the int option.+  int value() const+  {+    return value_;+  }++  // Get the level of the socket option.+  template <typename Protocol>+  int level(const Protocol&) const+  {+    return Level;+  }++  // Get the name of the socket option.+  template <typename Protocol>+  int name(const Protocol&) const+  {+    return Name;+  }++  // Get the address of the int data.+  template <typename Protocol>+  int* data(const Protocol&)+  {+    return &value_;+  }++  // Get the address of the int data.+  template <typename Protocol>+  const int* data(const Protocol&) const+  {+    return &value_;+  }++  // Get the size of the int data.+  template <typename Protocol>+  std::size_t size(const Protocol&) const+  {+    return sizeof(value_);+  }++  // Set the size of the int data.+  template <typename Protocol>+  void resize(const Protocol&, std::size_t s)+  {+    if (s != sizeof(value_))+    {+      std::length_error ex("integer socket option resize");+      asio::detail::throw_exception(ex);+    }+  }++private:+  int value_;+};++// Helper template for implementing linger options.+template <int Level, int Name>+class linger+{+public:+  // Default constructor.+  linger()+  {+    value_.l_onoff = 0;+    value_.l_linger = 0;+  }++  // Construct with specific option values.+  linger(bool e, int t)+  {+    enabled(e);+    timeout ASIO_PREVENT_MACRO_SUBSTITUTION(t);+  }++  // Set the value for whether linger is enabled.+  void enabled(bool value)+  {+    value_.l_onoff = value ? 1 : 0;+  }++  // Get the value for whether linger is enabled.+  bool enabled() const+  {+    return value_.l_onoff != 0;+  }++  // Set the value for the linger timeout.+  void timeout ASIO_PREVENT_MACRO_SUBSTITUTION(int value)+  {+#if defined(WIN32)+    value_.l_linger = static_cast<u_short>(value);+#else+    value_.l_linger = value;+#endif+  }++  // Get the value for the linger timeout.+  int timeout ASIO_PREVENT_MACRO_SUBSTITUTION() const+  {+    return static_cast<int>(value_.l_linger);+  }++  // Get the level of the socket option.+  template <typename Protocol>+  int level(const Protocol&) const+  {+    return Level;+  }++  // Get the name of the socket option.+  template <typename Protocol>+  int name(const Protocol&) const+  {+    return Name;+  }++  // Get the address of the linger data.+  template <typename Protocol>+  detail::linger_type* data(const Protocol&)+  {+    return &value_;+  }++  // Get the address of the linger data.+  template <typename Protocol>+  const detail::linger_type* data(const Protocol&) const+  {+    return &value_;+  }++  // Get the size of the linger data.+  template <typename Protocol>+  std::size_t size(const Protocol&) const+  {+    return sizeof(value_);+  }++  // Set the size of the int data.+  template <typename Protocol>+  void resize(const Protocol&, std::size_t s)+  {+    if (s != sizeof(value_))+    {+      std::length_error ex("linger socket option resize");+      asio::detail::throw_exception(ex);+    }+  }++private:+  detail::linger_type value_;+};++} // namespace socket_option+} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SOCKET_OPTION_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/socket_select_interrupter.hpp view
@@ -0,0 +1,91 @@+//+// detail/socket_select_interrupter.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP+#define ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_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_WINDOWS_RUNTIME)++#if defined(ASIO_WINDOWS) \+  || defined(__CYGWIN__) \+  || defined(__SYMBIAN32__)++#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class socket_select_interrupter+{+public:+  // Constructor.+  ASIO_DECL socket_select_interrupter();++  // Destructor.+  ASIO_DECL ~socket_select_interrupter();++  // Recreate the interrupter's descriptors. Used after a fork.+  ASIO_DECL void recreate();++  // Interrupt the select call.+  ASIO_DECL void interrupt();++  // Reset the select interrupter. Returns true if the reset was successful.+  ASIO_DECL bool reset();++  // Get the read descriptor to be passed to select.+  socket_type read_descriptor() const+  {+    return read_descriptor_;+  }++private:+  // Open the descriptors. Throws on error.+  ASIO_DECL void open_descriptors();++  // Close the descriptors.+  ASIO_DECL void close_descriptors();++  // The read end of a connection used to interrupt the select call. This file+  // descriptor is passed to select such that when it is time to stop, a single+  // byte will be written on the other end of the connection and this+  // descriptor will become readable.+  socket_type read_descriptor_;++  // The write end of a connection used to interrupt the select call. A single+  // byte may be written to this to wake up the select which is waiting for the+  // other end to become readable.+  socket_type write_descriptor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/socket_select_interrupter.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_WINDOWS)+       // || defined(__CYGWIN__)+       // || defined(__SYMBIAN32__)++#endif // !defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_SOCKET_SELECT_INTERRUPTER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/socket_types.hpp view
@@ -0,0 +1,416 @@+//+// detail/socket_types.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SOCKET_TYPES_HPP+#define ASIO_DETAIL_SOCKET_TYPES_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_WINDOWS_RUNTIME)+// Empty.+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# if defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)+#  error WinSock.h has already been included+# endif // defined(_WINSOCKAPI_) && !defined(_WINSOCK2API_)+# if defined(__BORLANDC__)+#  include <stdlib.h> // Needed for __errno+#  if !defined(_WSPIAPI_H_)+#   define _WSPIAPI_H_+#   define ASIO_WSPIAPI_H_DEFINED+#  endif // !defined(_WSPIAPI_H_)+# endif // defined(__BORLANDC__)+# include <winsock2.h>+# include <ws2tcpip.h>+# if defined(WINAPI_FAMILY)+#  if ((WINAPI_FAMILY & WINAPI_PARTITION_DESKTOP) != 0)+#   include <windows.h>+#  endif // ((WINAPI_FAMILY & WINAPI_PARTITION_DESKTOP) != 0)+# endif // defined(WINAPI_FAMILY)+# if !defined(ASIO_WINDOWS_APP)+#  include <mswsock.h>+# endif // !defined(ASIO_WINDOWS_APP)+# if defined(ASIO_WSPIAPI_H_DEFINED)+#  undef _WSPIAPI_H_+#  undef ASIO_WSPIAPI_H_DEFINED+# endif // defined(ASIO_WSPIAPI_H_DEFINED)+# if !defined(ASIO_NO_DEFAULT_LINKED_LIBS)+#  if defined(UNDER_CE)+#   pragma comment(lib, "ws2.lib")+#  elif defined(_MSC_VER) || defined(__BORLANDC__)+#   pragma comment(lib, "ws2_32.lib")+#   if !defined(ASIO_WINDOWS_APP)+#    pragma comment(lib, "mswsock.lib")+#   endif // !defined(ASIO_WINDOWS_APP)+#  endif // defined(_MSC_VER) || defined(__BORLANDC__)+# endif // !defined(ASIO_NO_DEFAULT_LINKED_LIBS)+# include "asio/detail/old_win_sdk_compat.hpp"+#else+# include <sys/ioctl.h>+# if (defined(__MACH__) && defined(__APPLE__)) \+   || defined(__FreeBSD__) || defined(__NetBSD__) \+   || defined(__OpenBSD__) || defined(__linux__) \+   || defined(__EMSCRIPTEN__)+#  include <poll.h>+# elif !defined(__SYMBIAN32__)+#  include <sys/poll.h>+# endif+# include <sys/types.h>+# include <sys/stat.h>+# include <fcntl.h>+# if defined(__hpux)+#  include <sys/time.h>+# endif+# if !defined(__hpux) || defined(__SELECT)+#  include <sys/select.h>+# endif+# include <sys/socket.h>+# include <sys/uio.h>+# include <sys/un.h>+# include <netinet/in.h>+# if !defined(__SYMBIAN32__)+#  include <netinet/tcp.h>+# endif+# include <arpa/inet.h>+# include <netdb.h>+# include <net/if.h>+# include <limits.h>+# if defined(__sun)+#  include <sys/filio.h>+#  include <sys/sockio.h>+# endif+#endif++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_WINDOWS_RUNTIME)+const int max_addr_v4_str_len = 256;+const int max_addr_v6_str_len = 256;+typedef unsigned __int32 u_long_type;+typedef unsigned __int16 u_short_type;+struct in4_addr_type { u_long_type s_addr; };+struct in4_mreq_type { in4_addr_type imr_multiaddr, imr_interface; };+struct in6_addr_type { unsigned char s6_addr[16]; };+struct in6_mreq_type { in6_addr_type ipv6mr_multiaddr;+  unsigned long ipv6mr_interface; };+struct socket_addr_type { int sa_family; };+struct sockaddr_in4_type { int sin_family;+  in4_addr_type sin_addr; u_short_type sin_port; };+struct sockaddr_in6_type { int sin6_family;+  in6_addr_type sin6_addr; u_short_type sin6_port;+  u_long_type sin6_flowinfo; u_long_type sin6_scope_id; };+struct sockaddr_storage_type { int ss_family;+  unsigned char ss_bytes[128 - sizeof(int)]; };+struct addrinfo_type { int ai_flags;+  int ai_family, ai_socktype, ai_protocol;+  int ai_addrlen; const void* ai_addr;+  const char* ai_canonname; addrinfo_type* ai_next; };+struct linger_type { u_short_type l_onoff, l_linger; };+typedef u_long_type ioctl_arg_type;+typedef int signed_size_type;+# define ASIO_OS_DEF(c) ASIO_OS_DEF_##c+# define ASIO_OS_DEF_AF_UNSPEC 0+# define ASIO_OS_DEF_AF_INET 2+# define ASIO_OS_DEF_AF_INET6 23+# define ASIO_OS_DEF_SOCK_STREAM 1+# define ASIO_OS_DEF_SOCK_DGRAM 2+# define ASIO_OS_DEF_SOCK_RAW 3+# define ASIO_OS_DEF_SOCK_SEQPACKET 5+# define ASIO_OS_DEF_IPPROTO_IP 0+# define ASIO_OS_DEF_IPPROTO_IPV6 41+# define ASIO_OS_DEF_IPPROTO_TCP 6+# define ASIO_OS_DEF_IPPROTO_UDP 17+# define ASIO_OS_DEF_IPPROTO_ICMP 1+# define ASIO_OS_DEF_IPPROTO_ICMPV6 58+# define ASIO_OS_DEF_FIONBIO 1+# define ASIO_OS_DEF_FIONREAD 2+# define ASIO_OS_DEF_INADDR_ANY 0+# define ASIO_OS_DEF_MSG_OOB 0x1+# define ASIO_OS_DEF_MSG_PEEK 0x2+# define ASIO_OS_DEF_MSG_DONTROUTE 0x4+# define ASIO_OS_DEF_MSG_EOR 0 // Not supported.+# define ASIO_OS_DEF_SHUT_RD 0x0+# define ASIO_OS_DEF_SHUT_WR 0x1+# define ASIO_OS_DEF_SHUT_RDWR 0x2+# define ASIO_OS_DEF_SOMAXCONN 0x7fffffff+# define ASIO_OS_DEF_SOL_SOCKET 0xffff+# define ASIO_OS_DEF_SO_BROADCAST 0x20+# define ASIO_OS_DEF_SO_DEBUG 0x1+# define ASIO_OS_DEF_SO_DONTROUTE 0x10+# define ASIO_OS_DEF_SO_KEEPALIVE 0x8+# define ASIO_OS_DEF_SO_LINGER 0x80+# define ASIO_OS_DEF_SO_OOBINLINE 0x100+# define ASIO_OS_DEF_SO_SNDBUF 0x1001+# define ASIO_OS_DEF_SO_RCVBUF 0x1002+# define ASIO_OS_DEF_SO_SNDLOWAT 0x1003+# define ASIO_OS_DEF_SO_RCVLOWAT 0x1004+# define ASIO_OS_DEF_SO_REUSEADDR 0x4+# define ASIO_OS_DEF_TCP_NODELAY 0x1+# define ASIO_OS_DEF_IP_MULTICAST_IF 2+# define ASIO_OS_DEF_IP_MULTICAST_TTL 3+# define ASIO_OS_DEF_IP_MULTICAST_LOOP 4+# define ASIO_OS_DEF_IP_ADD_MEMBERSHIP 5+# define ASIO_OS_DEF_IP_DROP_MEMBERSHIP 6+# define ASIO_OS_DEF_IP_TTL 7+# define ASIO_OS_DEF_IPV6_UNICAST_HOPS 4+# define ASIO_OS_DEF_IPV6_MULTICAST_IF 9+# define ASIO_OS_DEF_IPV6_MULTICAST_HOPS 10+# define ASIO_OS_DEF_IPV6_MULTICAST_LOOP 11+# define ASIO_OS_DEF_IPV6_JOIN_GROUP 12+# define ASIO_OS_DEF_IPV6_LEAVE_GROUP 13+# define ASIO_OS_DEF_AI_CANONNAME 0x2+# define ASIO_OS_DEF_AI_PASSIVE 0x1+# define ASIO_OS_DEF_AI_NUMERICHOST 0x4+# define ASIO_OS_DEF_AI_NUMERICSERV 0x8+# define ASIO_OS_DEF_AI_V4MAPPED 0x800+# define ASIO_OS_DEF_AI_ALL 0x100+# define ASIO_OS_DEF_AI_ADDRCONFIG 0x400+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+typedef SOCKET socket_type;+const SOCKET invalid_socket = INVALID_SOCKET;+const int socket_error_retval = SOCKET_ERROR;+const int max_addr_v4_str_len = 256;+const int max_addr_v6_str_len = 256;+typedef sockaddr socket_addr_type;+typedef in_addr in4_addr_type;+typedef ip_mreq in4_mreq_type;+typedef sockaddr_in sockaddr_in4_type;+# if defined(ASIO_HAS_OLD_WIN_SDK)+typedef in6_addr_emulation in6_addr_type;+typedef ipv6_mreq_emulation in6_mreq_type;+typedef sockaddr_in6_emulation sockaddr_in6_type;+typedef sockaddr_storage_emulation sockaddr_storage_type;+typedef addrinfo_emulation addrinfo_type;+# else+typedef in6_addr in6_addr_type;+typedef ipv6_mreq in6_mreq_type;+typedef sockaddr_in6 sockaddr_in6_type;+typedef sockaddr_storage sockaddr_storage_type;+typedef addrinfo addrinfo_type;+# endif+typedef ::linger linger_type;+typedef unsigned long ioctl_arg_type;+typedef u_long u_long_type;+typedef u_short u_short_type;+typedef int signed_size_type;+# define ASIO_OS_DEF(c) ASIO_OS_DEF_##c+# define ASIO_OS_DEF_AF_UNSPEC AF_UNSPEC+# define ASIO_OS_DEF_AF_INET AF_INET+# define ASIO_OS_DEF_AF_INET6 AF_INET6+# define ASIO_OS_DEF_SOCK_STREAM SOCK_STREAM+# define ASIO_OS_DEF_SOCK_DGRAM SOCK_DGRAM+# define ASIO_OS_DEF_SOCK_RAW SOCK_RAW+# define ASIO_OS_DEF_SOCK_SEQPACKET SOCK_SEQPACKET+# define ASIO_OS_DEF_IPPROTO_IP IPPROTO_IP+# define ASIO_OS_DEF_IPPROTO_IPV6 IPPROTO_IPV6+# define ASIO_OS_DEF_IPPROTO_TCP IPPROTO_TCP+# define ASIO_OS_DEF_IPPROTO_UDP IPPROTO_UDP+# define ASIO_OS_DEF_IPPROTO_ICMP IPPROTO_ICMP+# define ASIO_OS_DEF_IPPROTO_ICMPV6 IPPROTO_ICMPV6+# define ASIO_OS_DEF_FIONBIO FIONBIO+# define ASIO_OS_DEF_FIONREAD FIONREAD+# define ASIO_OS_DEF_INADDR_ANY INADDR_ANY+# define ASIO_OS_DEF_MSG_OOB MSG_OOB+# define ASIO_OS_DEF_MSG_PEEK MSG_PEEK+# define ASIO_OS_DEF_MSG_DONTROUTE MSG_DONTROUTE+# define ASIO_OS_DEF_MSG_EOR 0 // Not supported on Windows.+# define ASIO_OS_DEF_SHUT_RD SD_RECEIVE+# define ASIO_OS_DEF_SHUT_WR SD_SEND+# define ASIO_OS_DEF_SHUT_RDWR SD_BOTH+# define ASIO_OS_DEF_SOMAXCONN SOMAXCONN+# define ASIO_OS_DEF_SOL_SOCKET SOL_SOCKET+# define ASIO_OS_DEF_SO_BROADCAST SO_BROADCAST+# define ASIO_OS_DEF_SO_DEBUG SO_DEBUG+# define ASIO_OS_DEF_SO_DONTROUTE SO_DONTROUTE+# define ASIO_OS_DEF_SO_KEEPALIVE SO_KEEPALIVE+# define ASIO_OS_DEF_SO_LINGER SO_LINGER+# define ASIO_OS_DEF_SO_OOBINLINE SO_OOBINLINE+# define ASIO_OS_DEF_SO_SNDBUF SO_SNDBUF+# define ASIO_OS_DEF_SO_RCVBUF SO_RCVBUF+# define ASIO_OS_DEF_SO_SNDLOWAT SO_SNDLOWAT+# define ASIO_OS_DEF_SO_RCVLOWAT SO_RCVLOWAT+# define ASIO_OS_DEF_SO_REUSEADDR SO_REUSEADDR+# define ASIO_OS_DEF_TCP_NODELAY TCP_NODELAY+# define ASIO_OS_DEF_IP_MULTICAST_IF IP_MULTICAST_IF+# define ASIO_OS_DEF_IP_MULTICAST_TTL IP_MULTICAST_TTL+# define ASIO_OS_DEF_IP_MULTICAST_LOOP IP_MULTICAST_LOOP+# define ASIO_OS_DEF_IP_ADD_MEMBERSHIP IP_ADD_MEMBERSHIP+# define ASIO_OS_DEF_IP_DROP_MEMBERSHIP IP_DROP_MEMBERSHIP+# define ASIO_OS_DEF_IP_TTL IP_TTL+# define ASIO_OS_DEF_IPV6_UNICAST_HOPS IPV6_UNICAST_HOPS+# define ASIO_OS_DEF_IPV6_MULTICAST_IF IPV6_MULTICAST_IF+# define ASIO_OS_DEF_IPV6_MULTICAST_HOPS IPV6_MULTICAST_HOPS+# define ASIO_OS_DEF_IPV6_MULTICAST_LOOP IPV6_MULTICAST_LOOP+# define ASIO_OS_DEF_IPV6_JOIN_GROUP IPV6_JOIN_GROUP+# define ASIO_OS_DEF_IPV6_LEAVE_GROUP IPV6_LEAVE_GROUP+# define ASIO_OS_DEF_AI_CANONNAME AI_CANONNAME+# define ASIO_OS_DEF_AI_PASSIVE AI_PASSIVE+# define ASIO_OS_DEF_AI_NUMERICHOST AI_NUMERICHOST+# if defined(AI_NUMERICSERV)+#  define ASIO_OS_DEF_AI_NUMERICSERV AI_NUMERICSERV+# else+#  define ASIO_OS_DEF_AI_NUMERICSERV 0+# endif+# if defined(AI_V4MAPPED)+#  define ASIO_OS_DEF_AI_V4MAPPED AI_V4MAPPED+# else+#  define ASIO_OS_DEF_AI_V4MAPPED 0+# endif+# if defined(AI_ALL)+#  define ASIO_OS_DEF_AI_ALL AI_ALL+# else+#  define ASIO_OS_DEF_AI_ALL 0+# endif+# if defined(AI_ADDRCONFIG)+#  define ASIO_OS_DEF_AI_ADDRCONFIG AI_ADDRCONFIG+# else+#  define ASIO_OS_DEF_AI_ADDRCONFIG 0+# endif+# if defined (_WIN32_WINNT)+const int max_iov_len = 64;+# else+const int max_iov_len = 16;+# endif+#else+typedef int socket_type;+const int invalid_socket = -1;+const int socket_error_retval = -1;+const int max_addr_v4_str_len = INET_ADDRSTRLEN;+#if defined(INET6_ADDRSTRLEN)+const int max_addr_v6_str_len = INET6_ADDRSTRLEN + 1 + IF_NAMESIZE;+#else // defined(INET6_ADDRSTRLEN)+const int max_addr_v6_str_len = 256;+#endif // defined(INET6_ADDRSTRLEN)+typedef sockaddr socket_addr_type;+typedef in_addr in4_addr_type;+# if defined(__hpux)+// HP-UX doesn't provide ip_mreq when _XOPEN_SOURCE_EXTENDED is defined.+struct in4_mreq_type+{+  struct in_addr imr_multiaddr;+  struct in_addr imr_interface;+};+# else+typedef ip_mreq in4_mreq_type;+# endif+typedef sockaddr_in sockaddr_in4_type;+typedef in6_addr in6_addr_type;+typedef ipv6_mreq in6_mreq_type;+typedef sockaddr_in6 sockaddr_in6_type;+typedef sockaddr_storage sockaddr_storage_type;+typedef sockaddr_un sockaddr_un_type;+typedef addrinfo addrinfo_type;+typedef ::linger linger_type;+typedef int ioctl_arg_type;+typedef uint32_t u_long_type;+typedef uint16_t u_short_type;+#if defined(ASIO_HAS_SSIZE_T)+typedef ssize_t signed_size_type;+#else // defined(ASIO_HAS_SSIZE_T)+typedef int signed_size_type;+#endif // defined(ASIO_HAS_SSIZE_T)+# define ASIO_OS_DEF(c) ASIO_OS_DEF_##c+# define ASIO_OS_DEF_AF_UNSPEC AF_UNSPEC+# define ASIO_OS_DEF_AF_INET AF_INET+# define ASIO_OS_DEF_AF_INET6 AF_INET6+# define ASIO_OS_DEF_SOCK_STREAM SOCK_STREAM+# define ASIO_OS_DEF_SOCK_DGRAM SOCK_DGRAM+# define ASIO_OS_DEF_SOCK_RAW SOCK_RAW+# define ASIO_OS_DEF_SOCK_SEQPACKET SOCK_SEQPACKET+# define ASIO_OS_DEF_IPPROTO_IP IPPROTO_IP+# define ASIO_OS_DEF_IPPROTO_IPV6 IPPROTO_IPV6+# define ASIO_OS_DEF_IPPROTO_TCP IPPROTO_TCP+# define ASIO_OS_DEF_IPPROTO_UDP IPPROTO_UDP+# define ASIO_OS_DEF_IPPROTO_ICMP IPPROTO_ICMP+# define ASIO_OS_DEF_IPPROTO_ICMPV6 IPPROTO_ICMPV6+# define ASIO_OS_DEF_FIONBIO FIONBIO+# define ASIO_OS_DEF_FIONREAD FIONREAD+# define ASIO_OS_DEF_INADDR_ANY INADDR_ANY+# define ASIO_OS_DEF_MSG_OOB MSG_OOB+# define ASIO_OS_DEF_MSG_PEEK MSG_PEEK+# define ASIO_OS_DEF_MSG_DONTROUTE MSG_DONTROUTE+# define ASIO_OS_DEF_MSG_EOR MSG_EOR+# define ASIO_OS_DEF_SHUT_RD SHUT_RD+# define ASIO_OS_DEF_SHUT_WR SHUT_WR+# define ASIO_OS_DEF_SHUT_RDWR SHUT_RDWR+# define ASIO_OS_DEF_SOMAXCONN SOMAXCONN+# define ASIO_OS_DEF_SOL_SOCKET SOL_SOCKET+# define ASIO_OS_DEF_SO_BROADCAST SO_BROADCAST+# define ASIO_OS_DEF_SO_DEBUG SO_DEBUG+# define ASIO_OS_DEF_SO_DONTROUTE SO_DONTROUTE+# define ASIO_OS_DEF_SO_KEEPALIVE SO_KEEPALIVE+# define ASIO_OS_DEF_SO_LINGER SO_LINGER+# define ASIO_OS_DEF_SO_OOBINLINE SO_OOBINLINE+# define ASIO_OS_DEF_SO_SNDBUF SO_SNDBUF+# define ASIO_OS_DEF_SO_RCVBUF SO_RCVBUF+# define ASIO_OS_DEF_SO_SNDLOWAT SO_SNDLOWAT+# define ASIO_OS_DEF_SO_RCVLOWAT SO_RCVLOWAT+# define ASIO_OS_DEF_SO_REUSEADDR SO_REUSEADDR+# define ASIO_OS_DEF_TCP_NODELAY TCP_NODELAY+# define ASIO_OS_DEF_IP_MULTICAST_IF IP_MULTICAST_IF+# define ASIO_OS_DEF_IP_MULTICAST_TTL IP_MULTICAST_TTL+# define ASIO_OS_DEF_IP_MULTICAST_LOOP IP_MULTICAST_LOOP+# define ASIO_OS_DEF_IP_ADD_MEMBERSHIP IP_ADD_MEMBERSHIP+# define ASIO_OS_DEF_IP_DROP_MEMBERSHIP IP_DROP_MEMBERSHIP+# define ASIO_OS_DEF_IP_TTL IP_TTL+# define ASIO_OS_DEF_IPV6_UNICAST_HOPS IPV6_UNICAST_HOPS+# define ASIO_OS_DEF_IPV6_MULTICAST_IF IPV6_MULTICAST_IF+# define ASIO_OS_DEF_IPV6_MULTICAST_HOPS IPV6_MULTICAST_HOPS+# define ASIO_OS_DEF_IPV6_MULTICAST_LOOP IPV6_MULTICAST_LOOP+# define ASIO_OS_DEF_IPV6_JOIN_GROUP IPV6_JOIN_GROUP+# define ASIO_OS_DEF_IPV6_LEAVE_GROUP IPV6_LEAVE_GROUP+# define ASIO_OS_DEF_AI_CANONNAME AI_CANONNAME+# define ASIO_OS_DEF_AI_PASSIVE AI_PASSIVE+# define ASIO_OS_DEF_AI_NUMERICHOST AI_NUMERICHOST+# if defined(AI_NUMERICSERV)+#  define ASIO_OS_DEF_AI_NUMERICSERV AI_NUMERICSERV+# else+#  define ASIO_OS_DEF_AI_NUMERICSERV 0+# endif+// Note: QNX Neutrino 6.3 defines AI_V4MAPPED, AI_ALL and AI_ADDRCONFIG but+// does not implement them. Therefore they are specifically excluded here.+# if defined(AI_V4MAPPED) && !defined(__QNXNTO__)+#  define ASIO_OS_DEF_AI_V4MAPPED AI_V4MAPPED+# else+#  define ASIO_OS_DEF_AI_V4MAPPED 0+# endif+# if defined(AI_ALL) && !defined(__QNXNTO__)+#  define ASIO_OS_DEF_AI_ALL AI_ALL+# else+#  define ASIO_OS_DEF_AI_ALL 0+# endif+# if defined(AI_ADDRCONFIG) && !defined(__QNXNTO__)+#  define ASIO_OS_DEF_AI_ADDRCONFIG AI_ADDRCONFIG+# else+#  define ASIO_OS_DEF_AI_ADDRCONFIG 0+# endif+# if defined(IOV_MAX)+const int max_iov_len = IOV_MAX;+# else+// POSIX platforms are not required to define IOV_MAX.+const int max_iov_len = 16;+# endif+#endif+const int custom_socket_option_level = 0xA5100000;+const int enable_connection_aborted_option = 1;+const int always_fail_option = 2;++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SOCKET_TYPES_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/solaris_fenced_block.hpp view
@@ -0,0 +1,62 @@+//+// detail/solaris_fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP+#define ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(__sun)++#include <atomic.h>+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class solaris_fenced_block+  : private noncopyable+{+public:+  enum half_t { half };+  enum full_t { full };++  // Constructor for a half fenced block.+  explicit solaris_fenced_block(half_t)+  {+  }++  // Constructor for a full fenced block.+  explicit solaris_fenced_block(full_t)+  {+    membar_consumer();+  }++  // Destructor.+  ~solaris_fenced_block()+  {+    membar_producer();+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(__sun)++#endif // ASIO_DETAIL_SOLARIS_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/source_location.hpp view
@@ -0,0 +1,45 @@+//+// detail/source_location.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_SOURCE_LOCATION_HPP+#define ASIO_DETAIL_SOURCE_LOCATION_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_SOURCE_LOCATION)++#if defined(ASIO_HAS_STD_SOURCE_LOCATION)+# include <source_location>+#elif defined(ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION)+# include <experimental/source_location>+#else // defined(ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION)+# error ASIO_HAS_SOURCE_LOCATION is set \+  but no source_location is available+#endif // defined(ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION)++namespace asio {+namespace detail {++#if defined(ASIO_HAS_STD_SOURCE_LOCATION)+using std::source_location;+#elif defined(ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION)+using std::experimental::source_location;+#endif // defined(ASIO_HAS_STD_EXPERIMENTAL_SOURCE_LOCATION)++} // namespace detail+} // namespace asio++#endif // defined(ASIO_HAS_SOURCE_LOCATION)++#endif // ASIO_DETAIL_SOURCE_LOCATION_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/static_mutex.hpp view
@@ -0,0 +1,52 @@+//+// detail/static_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STATIC_MUTEX_HPP+#define ASIO_DETAIL_STATIC_MUTEX_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_THREADS)+# include "asio/detail/null_static_mutex.hpp"+#elif defined(ASIO_WINDOWS)+# include "asio/detail/win_static_mutex.hpp"+#elif defined(ASIO_HAS_PTHREADS)+# include "asio/detail/posix_static_mutex.hpp"+#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)+# include "asio/detail/std_static_mutex.hpp"+#else+# error Only Windows and POSIX are supported!+#endif++namespace asio {+namespace detail {++#if !defined(ASIO_HAS_THREADS)+typedef null_static_mutex static_mutex;+# define ASIO_STATIC_MUTEX_INIT ASIO_NULL_STATIC_MUTEX_INIT+#elif defined(ASIO_WINDOWS)+typedef win_static_mutex static_mutex;+# define ASIO_STATIC_MUTEX_INIT ASIO_WIN_STATIC_MUTEX_INIT+#elif defined(ASIO_HAS_PTHREADS)+typedef posix_static_mutex static_mutex;+# define ASIO_STATIC_MUTEX_INIT ASIO_POSIX_STATIC_MUTEX_INIT+#elif defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)+typedef std_static_mutex static_mutex;+# define ASIO_STATIC_MUTEX_INIT ASIO_STD_STATIC_MUTEX_INIT+#endif++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_STATIC_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/std_event.hpp view
@@ -0,0 +1,188 @@+//+// detail/std_event.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STD_EVENT_HPP+#define ASIO_DETAIL_STD_EVENT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)++#include <chrono>+#include <condition_variable>+#include "asio/detail/assert.hpp"+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class std_event+  : private noncopyable+{+public:+  // Constructor.+  std_event()+    : state_(0)+  {+  }++  // Destructor.+  ~std_event()+  {+  }++  // Signal the event. (Retained for backward compatibility.)+  template <typename Lock>+  void signal(Lock& lock)+  {+    this->signal_all(lock);+  }++  // Signal all waiters.+  template <typename Lock>+  void signal_all(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    (void)lock;+    state_ |= 1;+    cond_.notify_all();+  }++  // Unlock the mutex and signal one waiter.+  template <typename Lock>+  void unlock_and_signal_one(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    state_ |= 1;+    bool have_waiters = (state_ > 1);+    lock.unlock();+    if (have_waiters)+      cond_.notify_one();+  }++  // Unlock the mutex and signal one waiter who may destroy us.+  template <typename Lock>+  void unlock_and_signal_one(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    state_ |= 1;+    bool have_waiters = (state_ > 1);+    if (have_waiters)+      cond_.notify_one();+    lock.unlock();+  }++  // If there's a waiter, unlock the mutex and signal it.+  template <typename Lock>+  bool maybe_unlock_and_signal_one(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    state_ |= 1;+    if (state_ > 1)+    {+      lock.unlock();+      cond_.notify_one();+      return true;+    }+    return false;+  }++  // Reset the event.+  template <typename Lock>+  void clear(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    (void)lock;+    state_ &= ~std::size_t(1);+  }++  // Wait for the event to become signalled.+  template <typename Lock>+  void wait(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    unique_lock_adapter u_lock(lock);+    while ((state_ & 1) == 0)+    {+      waiter w(state_);+      cond_.wait(u_lock.unique_lock_);+    }+  }++  // Timed wait for the event to become signalled.+  template <typename Lock>+  bool wait_for_usec(Lock& lock, long usec)+  {+    ASIO_ASSERT(lock.locked());+    unique_lock_adapter u_lock(lock);+    if ((state_ & 1) == 0)+    {+      waiter w(state_);+      cond_.wait_for(u_lock.unique_lock_, std::chrono::microseconds(usec));+    }+    return (state_ & 1) != 0;+  }++private:+  // Helper class to temporarily adapt a scoped_lock into a unique_lock so that+  // it can be passed to std::condition_variable::wait().+  struct unique_lock_adapter+  {+    template <typename Lock>+    explicit unique_lock_adapter(Lock& lock)+      : unique_lock_(lock.mutex().mutex_, std::adopt_lock)+    {+    }++    ~unique_lock_adapter()+    {+      unique_lock_.release();+    }++    std::unique_lock<std::mutex> unique_lock_;+  };++  // Helper to increment and decrement the state to track outstanding waiters.+  class waiter+  {+  public:+    explicit waiter(std::size_t& state)+      : state_(state)+    {+      state_ += 2;+    }++    ~waiter()+    {+      state_ -= 2;+    }++  private:+    std::size_t& state_;+  };++  std::condition_variable cond_;+  std::size_t state_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)++#endif // ASIO_DETAIL_STD_EVENT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/std_fenced_block.hpp view
@@ -0,0 +1,62 @@+//+// detail/std_fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STD_FENCED_BLOCK_HPP+#define ASIO_DETAIL_STD_FENCED_BLOCK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_ATOMIC)++#include <atomic>+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class std_fenced_block+  : private noncopyable+{+public:+  enum half_t { half };+  enum full_t { full };++  // Constructor for a half fenced block.+  explicit std_fenced_block(half_t)+  {+  }++  // Constructor for a full fenced block.+  explicit std_fenced_block(full_t)+  {+    std::atomic_thread_fence(std::memory_order_acquire);+  }++  // Destructor.+  ~std_fenced_block()+  {+    std::atomic_thread_fence(std::memory_order_release);+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_STD_ATOMIC)++#endif // ASIO_DETAIL_STD_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/std_global.hpp view
@@ -0,0 +1,70 @@+//+// detail/std_global.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STD_GLOBAL_HPP+#define ASIO_DETAIL_STD_GLOBAL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_CALL_ONCE)++#include <exception>+#include <mutex>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename T>+struct std_global_impl+{+  // Helper function to perform initialisation.+  static void do_init()+  {+    instance_.ptr_ = new T;+  }++  // Destructor automatically cleans up the global.+  ~std_global_impl()+  {+    delete ptr_;+  }++  static std::once_flag init_once_;+  static std_global_impl instance_;+  T* ptr_;+};++template <typename T>+std::once_flag std_global_impl<T>::init_once_;++template <typename T>+std_global_impl<T> std_global_impl<T>::instance_;++template <typename T>+T& std_global()+{+  std::call_once(std_global_impl<T>::init_once_, &std_global_impl<T>::do_init);+  return *std_global_impl<T>::instance_.ptr_;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_STD_CALL_ONCE)++#endif // ASIO_DETAIL_STD_GLOBAL_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/std_mutex.hpp view
@@ -0,0 +1,73 @@+//+// detail/std_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STD_MUTEX_HPP+#define ASIO_DETAIL_STD_MUTEX_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)++#include <mutex>+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/scoped_lock.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class std_event;++class std_mutex+  : private noncopyable+{+public:+  typedef asio::detail::scoped_lock<std_mutex> scoped_lock;++  // Constructor.+  std_mutex()+  {+  }++  // Destructor.+  ~std_mutex()+  {+  }++  // Lock the mutex.+  void lock()+  {+    mutex_.lock();+  }++  // Unlock the mutex.+  void unlock()+  {+    mutex_.unlock();+  }++private:+  friend class std_event;+  std::mutex mutex_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)++#endif // ASIO_DETAIL_STD_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/std_static_mutex.hpp view
@@ -0,0 +1,81 @@+//+// detail/std_static_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STD_STATIC_MUTEX_HPP+#define ASIO_DETAIL_STD_STATIC_MUTEX_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)++#include <mutex>+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/scoped_lock.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class std_event;++class std_static_mutex+  : private noncopyable+{+public:+  typedef asio::detail::scoped_lock<std_static_mutex> scoped_lock;++  // Constructor.+  std_static_mutex(int)+  {+  }++  // Destructor.+  ~std_static_mutex()+  {+  }++  // Initialise the mutex.+  void init()+  {+    // Nothing to do.+  }++  // Lock the mutex.+  void lock()+  {+    mutex_.lock();+  }++  // Unlock the mutex.+  void unlock()+  {+    mutex_.unlock();+  }++private:+  friend class std_event;+  std::mutex mutex_;+};++#define ASIO_STD_STATIC_MUTEX_INIT 0++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_STD_MUTEX_AND_CONDVAR)++#endif // ASIO_DETAIL_STD_STATIC_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/std_thread.hpp view
@@ -0,0 +1,71 @@+//+// detail/std_thread.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STD_THREAD_HPP+#define ASIO_DETAIL_STD_THREAD_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_THREAD)++#include <thread>+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class std_thread+  : private noncopyable+{+public:+  // Constructor.+  template <typename Function>+  std_thread(Function f, unsigned int = 0)+    : thread_(f)+  {+  }++  // Destructor.+  ~std_thread()+  {+    join();+  }++  // Wait for the thread to exit.+  void join()+  {+    if (thread_.joinable())+      thread_.join();+  }++  // Get number of CPUs.+  static std::size_t hardware_concurrency()+  {+    return std::thread::hardware_concurrency();+  }++private:+  std::thread thread_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_STD_THREAD)++#endif // ASIO_DETAIL_STD_THREAD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/strand_executor_service.hpp view
@@ -0,0 +1,166 @@+//+// detail/strand_executor_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STRAND_EXECUTOR_SERVICE_HPP+#define ASIO_DETAIL_STRAND_EXECUTOR_SERVICE_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/atomic_count.hpp"+#include "asio/detail/executor_op.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/scheduler_operation.hpp"+#include "asio/detail/scoped_ptr.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Default service implementation for a strand.+class strand_executor_service+  : public execution_context_service_base<strand_executor_service>+{+public:+  // The underlying implementation of a strand.+  class strand_impl+  {+  public:+    ASIO_DECL ~strand_impl();++  private:+    friend class strand_executor_service;++    // Mutex to protect access to internal data.+    mutex* mutex_;++    // Indicates whether the strand is currently "locked" by a handler. This+    // means that there is a handler upcall in progress, or that the strand+    // itself has been scheduled in order to invoke some pending handlers.+    bool locked_;++    // Indicates that the strand has been shut down and will accept no further+    // handlers.+    bool shutdown_;++    // The handlers that are waiting on the strand but should not be run until+    // after the next time the strand is scheduled. This queue must only be+    // modified while the mutex is locked.+    op_queue<scheduler_operation> waiting_queue_;++    // The handlers that are ready to be run. Logically speaking, these are the+    // handlers that hold the strand's lock. The ready queue is only modified+    // from within the strand and so may be accessed without locking the mutex.+    op_queue<scheduler_operation> ready_queue_;++    // Pointers to adjacent handle implementations in linked list.+    strand_impl* next_;+    strand_impl* prev_;++    // The strand service in where the implementation is held.+    strand_executor_service* service_;+  };++  typedef shared_ptr<strand_impl> implementation_type;++  // Construct a new strand service for the specified context.+  ASIO_DECL explicit strand_executor_service(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Create a new strand_executor implementation.+  ASIO_DECL implementation_type create_implementation();++  // Request invocation of the given function.+  template <typename Executor, typename Function>+  static void execute(const implementation_type& impl, Executor& ex,+      ASIO_MOVE_ARG(Function) function,+      typename enable_if<+        can_query<Executor, execution::allocator_t<void> >::value+      >::type* = 0);++  // Request invocation of the given function.+  template <typename Executor, typename Function>+  static void execute(const implementation_type& impl, Executor& ex,+      ASIO_MOVE_ARG(Function) function,+      typename enable_if<+        !can_query<Executor, execution::allocator_t<void> >::value+      >::type* = 0);++  // Request invocation of the given function.+  template <typename Executor, typename Function, typename Allocator>+  static void dispatch(const implementation_type& impl, Executor& ex,+      ASIO_MOVE_ARG(Function) function, const Allocator& a);++  // Request invocation of the given function and return immediately.+  template <typename Executor, typename Function, typename Allocator>+  static void post(const implementation_type& impl, Executor& ex,+      ASIO_MOVE_ARG(Function) function, const Allocator& a);++  // Request invocation of the given function and return immediately.+  template <typename Executor, typename Function, typename Allocator>+  static void defer(const implementation_type& impl, Executor& ex,+      ASIO_MOVE_ARG(Function) function, const Allocator& a);++  // Determine whether the strand is running in the current thread.+  ASIO_DECL static bool running_in_this_thread(+      const implementation_type& impl);++private:+  friend class strand_impl;+  template <typename F, typename Allocator> class allocator_binder;+  template <typename Executor, typename = void> class invoker;++  // Adds a function to the strand. Returns true if it acquires the lock.+  ASIO_DECL static bool enqueue(const implementation_type& impl,+      scheduler_operation* op);++  // Helper function to request invocation of the given function.+  template <typename Executor, typename Function, typename Allocator>+  static void do_execute(const implementation_type& impl, Executor& ex,+      ASIO_MOVE_ARG(Function) function, const Allocator& a);++  // Mutex to protect access to the service-wide state.+  mutex mutex_;++  // Number of mutexes shared between all strand objects.+  enum { num_mutexes = 193 };++  // Pool of mutexes.+  scoped_ptr<mutex> mutexes_[num_mutexes];++  // Extra value used when hashing to prevent recycled memory locations from+  // getting the same mutex.+  std::size_t salt_;++  // The head of a linked list of all implementations.+  strand_impl* impl_list_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/strand_executor_service.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/strand_executor_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_STRAND_EXECUTOR_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/strand_service.hpp view
@@ -0,0 +1,145 @@+//+// detail/strand_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STRAND_SERVICE_HPP+#define ASIO_DETAIL_STRAND_SERVICE_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/mutex.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/operation.hpp"+#include "asio/detail/scoped_ptr.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Default service implementation for a strand.+class strand_service+  : public asio::detail::service_base<strand_service>+{+private:+  // Helper class to re-post the strand on exit.+  struct on_do_complete_exit;++  // Helper class to re-post the strand on exit.+  struct on_dispatch_exit;++public:++  // The underlying implementation of a strand.+  class strand_impl+    : public operation+  {+  public:+    strand_impl();++  private:+    // Only this service will have access to the internal values.+    friend class strand_service;+    friend struct on_do_complete_exit;+    friend struct on_dispatch_exit;++    // Mutex to protect access to internal data.+    asio::detail::mutex mutex_;++    // Indicates whether the strand is currently "locked" by a handler. This+    // means that there is a handler upcall in progress, or that the strand+    // itself has been scheduled in order to invoke some pending handlers.+    bool locked_;++    // The handlers that are waiting on the strand but should not be run until+    // after the next time the strand is scheduled. This queue must only be+    // modified while the mutex is locked.+    op_queue<operation> waiting_queue_;++    // The handlers that are ready to be run. Logically speaking, these are the+    // handlers that hold the strand's lock. The ready queue is only modified+    // from within the strand and so may be accessed without locking the mutex.+    op_queue<operation> ready_queue_;+  };++  typedef strand_impl* implementation_type;++  // Construct a new strand service for the specified io_context.+  ASIO_DECL explicit strand_service(asio::io_context& io_context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Construct a new strand implementation.+  ASIO_DECL void construct(implementation_type& impl);++  // Request the io_context to invoke the given handler.+  template <typename Handler>+  void dispatch(implementation_type& impl, Handler& handler);++  // Request the io_context to invoke the given handler and return immediately.+  template <typename Handler>+  void post(implementation_type& impl, Handler& handler);++  // Determine whether the strand is running in the current thread.+  ASIO_DECL bool running_in_this_thread(+      const implementation_type& impl) const;++private:+  // Helper function to dispatch a handler. Returns true if the handler should+  // be dispatched immediately.+  ASIO_DECL bool do_dispatch(implementation_type& impl, operation* op);++  // Helper fiunction to post a handler.+  ASIO_DECL void do_post(implementation_type& impl,+      operation* op, bool is_continuation);++  ASIO_DECL static void do_complete(void* owner,+      operation* base, const asio::error_code& ec,+      std::size_t bytes_transferred);++  // The io_context used to obtain an I/O executor.+  io_context& io_context_;++  // The io_context implementation used to post completions.+  io_context_impl& io_context_impl_;++  // Mutex to protect access to the array of implementations.+  asio::detail::mutex mutex_;++  // Number of implementations shared between all strand objects.+#if defined(ASIO_STRAND_IMPLEMENTATIONS)+  enum { num_implementations = ASIO_STRAND_IMPLEMENTATIONS };+#else // defined(ASIO_STRAND_IMPLEMENTATIONS)+  enum { num_implementations = 193 };+#endif // defined(ASIO_STRAND_IMPLEMENTATIONS)++  // Pool of implementations.+  scoped_ptr<strand_impl> implementations_[num_implementations];++  // Extra value used when hashing to prevent recycled memory locations from+  // getting the same strand implementation.+  std::size_t salt_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/strand_service.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/strand_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_STRAND_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/string_view.hpp view
@@ -0,0 +1,47 @@+//+// detail/string_view.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_STRING_VIEW_HPP+#define ASIO_DETAIL_STRING_VIEW_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_STRING_VIEW)++#if defined(ASIO_HAS_STD_STRING_VIEW)+# include <string_view>+#elif defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)+# include <experimental/string_view>+#else // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)+# error ASIO_HAS_STRING_VIEW is set but no string_view is available+#endif // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)++namespace asio {++#if defined(ASIO_HAS_STD_STRING_VIEW)+using std::basic_string_view;+using std::string_view;+#elif defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)+using std::experimental::basic_string_view;+using std::experimental::string_view;+#endif // defined(ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW)++} // namespace asio++# define ASIO_STRING_VIEW_PARAM asio::string_view+#else // defined(ASIO_HAS_STRING_VIEW)+# define ASIO_STRING_VIEW_PARAM const std::string&+#endif // defined(ASIO_HAS_STRING_VIEW)++#endif // ASIO_DETAIL_STRING_VIEW_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/thread.hpp view
@@ -0,0 +1,60 @@+//+// detail/thread.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_THREAD_HPP+#define ASIO_DETAIL_THREAD_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_THREADS)+# include "asio/detail/null_thread.hpp"+#elif defined(ASIO_WINDOWS)+# if defined(UNDER_CE)+#  include "asio/detail/wince_thread.hpp"+# elif defined(ASIO_WINDOWS_APP)+#  include "asio/detail/winapp_thread.hpp"+# else+#  include "asio/detail/win_thread.hpp"+# endif+#elif defined(ASIO_HAS_PTHREADS)+# include "asio/detail/posix_thread.hpp"+#elif defined(ASIO_HAS_STD_THREAD)+# include "asio/detail/std_thread.hpp"+#else+# error Only Windows, POSIX and std::thread are supported!+#endif++namespace asio {+namespace detail {++#if !defined(ASIO_HAS_THREADS)+typedef null_thread thread;+#elif defined(ASIO_WINDOWS)+# if defined(UNDER_CE)+typedef wince_thread thread;+# elif defined(ASIO_WINDOWS_APP)+typedef winapp_thread thread;+# else+typedef win_thread thread;+# endif+#elif defined(ASIO_HAS_PTHREADS)+typedef posix_thread thread;+#elif defined(ASIO_HAS_STD_THREAD)+typedef std_thread thread;+#endif++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_THREAD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/thread_context.hpp view
@@ -0,0 +1,42 @@+//+// detail/thread_context.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_THREAD_CONTEXT_HPP+#define ASIO_DETAIL_THREAD_CONTEXT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include <climits>+#include <cstddef>+#include "asio/detail/call_stack.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class thread_info_base;++// Base class for things that manage threads (scheduler, win_iocp_io_context).+class thread_context+{+public:+  // Per-thread call stack to track the state of each thread in the context.+  typedef call_stack<thread_context, thread_info_base> thread_call_stack;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_THREAD_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/thread_group.hpp view
@@ -0,0 +1,95 @@+//+// detail/thread_group.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_THREAD_GROUP_HPP+#define ASIO_DETAIL_THREAD_GROUP_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/scoped_ptr.hpp"+#include "asio/detail/thread.hpp"++namespace asio {+namespace detail {++class thread_group+{+public:+  // Constructor initialises an empty thread group.+  thread_group()+    : first_(0)+  {+  }++  // Destructor joins any remaining threads in the group.+  ~thread_group()+  {+    join();+  }++  // Create a new thread in the group.+  template <typename Function>+  void create_thread(Function f)+  {+    first_ = new item(f, first_);+  }++  // Create new threads in the group.+  template <typename Function>+  void create_threads(Function f, std::size_t num_threads)+  {+    for (std::size_t i = 0; i < num_threads; ++i)+      create_thread(f);+  }++  // Wait for all threads in the group to exit.+  void join()+  {+    while (first_)+    {+      first_->thread_.join();+      item* tmp = first_;+      first_ = first_->next_;+      delete tmp;+    }+  }++  // Test whether the group is empty.+  bool empty() const+  {+    return first_ == 0;+  }++private:+  // Structure used to track a single thread in the group.+  struct item+  {+    template <typename Function>+    explicit item(Function f, item* next)+      : thread_(f),+        next_(next)+    {+    }++    asio::detail::thread thread_;+    item* next_;+  };++  // The first thread in the group.+  item* first_;+};++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_THREAD_GROUP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/thread_info_base.hpp view
@@ -0,0 +1,189 @@+//+// detail/thread_info_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_THREAD_INFO_BASE_HPP+#define ASIO_DETAIL_THREAD_INFO_BASE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <climits>+#include <cstddef>+#include "asio/detail/noncopyable.hpp"++#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  && !defined(ASIO_NO_EXCEPTIONS)+# include <exception>+# include "asio/multiple_exceptions.hpp"+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       // && !defined(ASIO_NO_EXCEPTIONS)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class thread_info_base+  : private noncopyable+{+public:+  struct default_tag+  {+    enum { mem_index = 0 };+  };++  struct awaitable_frame_tag+  {+    enum { mem_index = 1 };+  };++  struct executor_function_tag+  {+    enum { mem_index = 2 };+  };++  thread_info_base()+#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  && !defined(ASIO_NO_EXCEPTIONS)+    : has_pending_exception_(0)+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       // && !defined(ASIO_NO_EXCEPTIONS)+  {+    for (int i = 0; i < max_mem_index; ++i)+    {+      // The following test for non-null pointers is technically redundant, but+      // it is significantly faster when using a tight io_context::poll() loop+      // in latency sensitive applications.+      if (reusable_memory_[i])+        reusable_memory_[i] = 0;+    }+  }++  ~thread_info_base()+  {+    for (int i = 0; i < max_mem_index; ++i)+      ::operator delete(reusable_memory_[i]);+  }++  static void* allocate(thread_info_base* this_thread, std::size_t size)+  {+    return allocate(default_tag(), this_thread, size);+  }++  static void deallocate(thread_info_base* this_thread,+      void* pointer, std::size_t size)+  {+    deallocate(default_tag(), this_thread, pointer, size);+  }++  template <typename Purpose>+  static void* allocate(Purpose, thread_info_base* this_thread,+      std::size_t size)+  {+    std::size_t chunks = (size + chunk_size - 1) / chunk_size;++    if (this_thread && this_thread->reusable_memory_[Purpose::mem_index])+    {+      void* const pointer = this_thread->reusable_memory_[Purpose::mem_index];+      this_thread->reusable_memory_[Purpose::mem_index] = 0;++      unsigned char* const mem = static_cast<unsigned char*>(pointer);+      if (static_cast<std::size_t>(mem[0]) >= chunks)+      {+        mem[size] = mem[0];+        return pointer;+      }++      ::operator delete(pointer);+    }++    void* const pointer = ::operator new(chunks * chunk_size + 1);+    unsigned char* const mem = static_cast<unsigned char*>(pointer);+    mem[size] = (chunks <= UCHAR_MAX) ? static_cast<unsigned char>(chunks) : 0;+    return pointer;+  }++  template <typename Purpose>+  static void deallocate(Purpose, thread_info_base* this_thread,+      void* pointer, std::size_t size)+  {+    if (size <= chunk_size * UCHAR_MAX)+    {+      if (this_thread && this_thread->reusable_memory_[Purpose::mem_index] == 0)+      {+        unsigned char* const mem = static_cast<unsigned char*>(pointer);+        mem[0] = mem[size];+        this_thread->reusable_memory_[Purpose::mem_index] = pointer;+        return;+      }+    }++    ::operator delete(pointer);+  }++  void capture_current_exception()+  {+#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  && !defined(ASIO_NO_EXCEPTIONS)+    switch (has_pending_exception_)+    {+    case 0:+      has_pending_exception_ = 1;+      pending_exception_ = std::current_exception();+      break;+    case 1:+      has_pending_exception_ = 2;+      pending_exception_ =+        std::make_exception_ptr<multiple_exceptions>(+            multiple_exceptions(pending_exception_));+    default:+      break;+    }+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       // && !defined(ASIO_NO_EXCEPTIONS)+  }++  void rethrow_pending_exception()+  {+#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  && !defined(ASIO_NO_EXCEPTIONS)+    if (has_pending_exception_ > 0)+    {+      has_pending_exception_ = 0;+      std::exception_ptr ex(+          ASIO_MOVE_CAST(std::exception_ptr)(+            pending_exception_));+      std::rethrow_exception(ex);+    }+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       // && !defined(ASIO_NO_EXCEPTIONS)+  }++private:+  enum { chunk_size = 4 };+  enum { max_mem_index = 3 };+  void* reusable_memory_[max_mem_index];++#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  && !defined(ASIO_NO_EXCEPTIONS)+  int has_pending_exception_;+  std::exception_ptr pending_exception_;+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       // && !defined(ASIO_NO_EXCEPTIONS)+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_THREAD_INFO_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/throw_error.hpp view
@@ -0,0 +1,53 @@+//+// detail/throw_error.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_THROW_ERROR_HPP+#define ASIO_DETAIL_THROW_ERROR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/error_code.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++ASIO_DECL void do_throw_error(const asio::error_code& err);++ASIO_DECL void do_throw_error(const asio::error_code& err,+    const char* location);++inline void throw_error(const asio::error_code& err)+{+  if (err)+    do_throw_error(err);+}++inline void throw_error(const asio::error_code& err,+    const char* location)+{+  if (err)+    do_throw_error(err, location);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/throw_error.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_THROW_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/throw_exception.hpp view
@@ -0,0 +1,51 @@+//+// detail/throw_exception.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_THROW_EXCEPTION_HPP+#define ASIO_DETAIL_THROW_EXCEPTION_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_THROW_EXCEPTION)+# include <boost/throw_exception.hpp>+#endif // defined(ASIO_BOOST_THROW_EXCEPTION)++namespace asio {+namespace detail {++#if defined(ASIO_HAS_BOOST_THROW_EXCEPTION)+using boost::throw_exception;+#else // defined(ASIO_HAS_BOOST_THROW_EXCEPTION)++// Declare the throw_exception function for all targets.+template <typename Exception>+void throw_exception(const Exception& e);++// Only define the throw_exception function when exceptions are enabled.+// Otherwise, it is up to the application to provide a definition of this+// function.+# if !defined(ASIO_NO_EXCEPTIONS)+template <typename Exception>+void throw_exception(const Exception& e)+{+  throw e;+}+# endif // !defined(ASIO_NO_EXCEPTIONS)++#endif // defined(ASIO_HAS_BOOST_THROW_EXCEPTION)++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_THROW_EXCEPTION_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/timer_queue.hpp view
@@ -0,0 +1,360 @@+//+// detail/timer_queue.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_TIMER_QUEUE_HPP+#define ASIO_DETAIL_TIMER_QUEUE_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 <vector>+#include "asio/detail/cstdint.hpp"+#include "asio/detail/date_time_fwd.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/timer_queue_base.hpp"+#include "asio/detail/wait_op.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Time_Traits>+class timer_queue+  : public timer_queue_base+{+public:+  // The time type.+  typedef typename Time_Traits::time_type time_type;++  // The duration type.+  typedef typename Time_Traits::duration_type duration_type;++  // Per-timer data.+  class per_timer_data+  {+  public:+    per_timer_data() :+      heap_index_((std::numeric_limits<std::size_t>::max)()),+      next_(0), prev_(0)+    {+    }++  private:+    friend class timer_queue;++    // The operations waiting on the timer.+    op_queue<wait_op> op_queue_;++    // The index of the timer in the heap.+    std::size_t heap_index_;++    // Pointers to adjacent timers in a linked list.+    per_timer_data* next_;+    per_timer_data* prev_;+  };++  // Constructor.+  timer_queue()+    : timers_(),+      heap_()+  {+  }++  // Add a new timer to the queue. Returns true if this is the timer that is+  // earliest in the queue, in which case the reactor's event demultiplexing+  // function call may need to be interrupted and restarted.+  bool enqueue_timer(const time_type& time, per_timer_data& timer, wait_op* op)+  {+    // Enqueue the timer object.+    if (timer.prev_ == 0 && &timer != timers_)+    {+      if (this->is_positive_infinity(time))+      {+        // No heap entry is required for timers that never expire.+        timer.heap_index_ = (std::numeric_limits<std::size_t>::max)();+      }+      else+      {+        // Put the new timer at the correct position in the heap. This is done+        // first since push_back() can throw due to allocation failure.+        timer.heap_index_ = heap_.size();+        heap_entry entry = { time, &timer };+        heap_.push_back(entry);+        up_heap(heap_.size() - 1);+      }++      // Insert the new timer into the linked list of active timers.+      timer.next_ = timers_;+      timer.prev_ = 0;+      if (timers_)+        timers_->prev_ = &timer;+      timers_ = &timer;+    }++    // Enqueue the individual timer operation.+    timer.op_queue_.push(op);++    // Interrupt reactor only if newly added timer is first to expire.+    return timer.heap_index_ == 0 && timer.op_queue_.front() == op;+  }++  // Whether there are no timers in the queue.+  virtual bool empty() const+  {+    return timers_ == 0;+  }++  // Get the time for the timer that is earliest in the queue.+  virtual long wait_duration_msec(long max_duration) const+  {+    if (heap_.empty())+      return max_duration;++    return this->to_msec(+        Time_Traits::to_posix_duration(+          Time_Traits::subtract(heap_[0].time_, Time_Traits::now())),+        max_duration);+  }++  // Get the time for the timer that is earliest in the queue.+  virtual long wait_duration_usec(long max_duration) const+  {+    if (heap_.empty())+      return max_duration;++    return this->to_usec(+        Time_Traits::to_posix_duration(+          Time_Traits::subtract(heap_[0].time_, Time_Traits::now())),+        max_duration);+  }++  // Dequeue all timers not later than the current time.+  virtual void get_ready_timers(op_queue<operation>& ops)+  {+    if (!heap_.empty())+    {+      const time_type now = Time_Traits::now();+      while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0].time_))+      {+        per_timer_data* timer = heap_[0].timer_;+        ops.push(timer->op_queue_);+        remove_timer(*timer);+      }+    }+  }++  // Dequeue all timers.+  virtual void get_all_timers(op_queue<operation>& ops)+  {+    while (timers_)+    {+      per_timer_data* timer = timers_;+      timers_ = timers_->next_;+      ops.push(timer->op_queue_);+      timer->next_ = 0;+      timer->prev_ = 0;+    }++    heap_.clear();+  }++  // Cancel and dequeue operations for the given timer.+  std::size_t cancel_timer(per_timer_data& timer, op_queue<operation>& ops,+      std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)())+  {+    std::size_t num_cancelled = 0;+    if (timer.prev_ != 0 || &timer == timers_)+    {+      while (wait_op* op = (num_cancelled != max_cancelled)+          ? timer.op_queue_.front() : 0)+      {+        op->ec_ = asio::error::operation_aborted;+        timer.op_queue_.pop();+        ops.push(op);+        ++num_cancelled;+      }+      if (timer.op_queue_.empty())+        remove_timer(timer);+    }+    return num_cancelled;+  }++  // Move operations from one timer to another, empty timer.+  void move_timer(per_timer_data& target, per_timer_data& source)+  {+    target.op_queue_.push(source.op_queue_);++    target.heap_index_ = source.heap_index_;+    source.heap_index_ = (std::numeric_limits<std::size_t>::max)();++    if (target.heap_index_ < heap_.size())+      heap_[target.heap_index_].timer_ = &target;++    if (timers_ == &source)+      timers_ = &target;+    if (source.prev_)+      source.prev_->next_ = &target;+    if (source.next_)+      source.next_->prev_= &target;+    target.next_ = source.next_;+    target.prev_ = source.prev_;+    source.next_ = 0;+    source.prev_ = 0;+  }++private:+  // Move the item at the given index up the heap to its correct position.+  void up_heap(std::size_t index)+  {+    while (index > 0)+    {+      std::size_t parent = (index - 1) / 2;+      if (!Time_Traits::less_than(heap_[index].time_, heap_[parent].time_))+        break;+      swap_heap(index, parent);+      index = parent;+    }+  }++  // Move the item at the given index down the heap to its correct position.+  void down_heap(std::size_t index)+  {+    std::size_t child = index * 2 + 1;+    while (child < heap_.size())+    {+      std::size_t min_child = (child + 1 == heap_.size()+          || Time_Traits::less_than(+            heap_[child].time_, heap_[child + 1].time_))+        ? child : child + 1;+      if (Time_Traits::less_than(heap_[index].time_, heap_[min_child].time_))+        break;+      swap_heap(index, min_child);+      index = min_child;+      child = index * 2 + 1;+    }+  }++  // Swap two entries in the heap.+  void swap_heap(std::size_t index1, std::size_t index2)+  {+    heap_entry tmp = heap_[index1];+    heap_[index1] = heap_[index2];+    heap_[index2] = tmp;+    heap_[index1].timer_->heap_index_ = index1;+    heap_[index2].timer_->heap_index_ = index2;+  }++  // Remove a timer from the heap and list of timers.+  void remove_timer(per_timer_data& timer)+  {+    // Remove the timer from the heap.+    std::size_t index = timer.heap_index_;+    if (!heap_.empty() && index < heap_.size())+    {+      if (index == heap_.size() - 1)+      {+        timer.heap_index_ = (std::numeric_limits<std::size_t>::max)();+        heap_.pop_back();+      }+      else+      {+        swap_heap(index, heap_.size() - 1);+        timer.heap_index_ = (std::numeric_limits<std::size_t>::max)();+        heap_.pop_back();+        if (index > 0 && Time_Traits::less_than(+              heap_[index].time_, heap_[(index - 1) / 2].time_))+          up_heap(index);+        else+          down_heap(index);+      }+    }++    // Remove the timer from the linked list of active timers.+    if (timers_ == &timer)+      timers_ = timer.next_;+    if (timer.prev_)+      timer.prev_->next_ = timer.next_;+    if (timer.next_)+      timer.next_->prev_= timer.prev_;+    timer.next_ = 0;+    timer.prev_ = 0;+  }++  // Determine if the specified absolute time is positive infinity.+  template <typename Time_Type>+  static bool is_positive_infinity(const Time_Type&)+  {+    return false;+  }++  // Determine if the specified absolute time is positive infinity.+  template <typename T, typename TimeSystem>+  static bool is_positive_infinity(+      const boost::date_time::base_time<T, TimeSystem>& time)+  {+    return time.is_pos_infinity();+  }++  // Helper function to convert a duration into milliseconds.+  template <typename Duration>+  long to_msec(const Duration& d, long max_duration) const+  {+    if (d.ticks() <= 0)+      return 0;+    int64_t msec = d.total_milliseconds();+    if (msec == 0)+      return 1;+    if (msec > max_duration)+      return max_duration;+    return static_cast<long>(msec);+  }++  // Helper function to convert a duration into microseconds.+  template <typename Duration>+  long to_usec(const Duration& d, long max_duration) const+  {+    if (d.ticks() <= 0)+      return 0;+    int64_t usec = d.total_microseconds();+    if (usec == 0)+      return 1;+    if (usec > max_duration)+      return max_duration;+    return static_cast<long>(usec);+  }++  // The head of a linked list of all active timers.+  per_timer_data* timers_;++  struct heap_entry+  {+    // The time when the timer should fire.+    time_type time_;++    // The associated timer with enqueued operations.+    per_timer_data* timer_;+  };++  // The heap of timers, with the earliest timer at the front.+  std::vector<heap_entry> heap_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_TIMER_QUEUE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/timer_queue_base.hpp view
@@ -0,0 +1,68 @@+//+// detail/timer_queue_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_TIMER_QUEUE_BASE_HPP+#define ASIO_DETAIL_TIMER_QUEUE_BASE_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/noncopyable.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class timer_queue_base+  : private noncopyable+{+public:+  // Constructor.+  timer_queue_base() : next_(0) {}++  // Destructor.+  virtual ~timer_queue_base() {}++  // Whether there are no timers in the queue.+  virtual bool empty() const = 0;++  // Get the time to wait until the next timer.+  virtual long wait_duration_msec(long max_duration) const = 0;++  // Get the time to wait until the next timer.+  virtual long wait_duration_usec(long max_duration) const = 0;++  // Dequeue all ready timers.+  virtual void get_ready_timers(op_queue<operation>& ops) = 0;++  // Dequeue all timers.+  virtual void get_all_timers(op_queue<operation>& ops) = 0;++private:+  friend class timer_queue_set;++  // Next timer queue in the set.+  timer_queue_base* next_;+};++template <typename Time_Traits>+class timer_queue;++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_TIMER_QUEUE_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/timer_queue_ptime.hpp view
@@ -0,0 +1,99 @@+//+// detail/timer_queue_ptime.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_TIMER_QUEUE_PTIME_HPP+#define ASIO_DETAIL_TIMER_QUEUE_PTIME_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)++#include "asio/time_traits.hpp"+#include "asio/detail/timer_queue.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct forwarding_posix_time_traits : time_traits<boost::posix_time::ptime> {};++// Template specialisation for the commonly used instantation.+template <>+class timer_queue<time_traits<boost::posix_time::ptime> >+  : public timer_queue_base+{+public:+  // The time type.+  typedef boost::posix_time::ptime time_type;++  // The duration type.+  typedef boost::posix_time::time_duration duration_type;++  // Per-timer data.+  typedef timer_queue<forwarding_posix_time_traits>::per_timer_data+    per_timer_data;++  // Constructor.+  ASIO_DECL timer_queue();++  // Destructor.+  ASIO_DECL virtual ~timer_queue();++  // Add a new timer to the queue. Returns true if this is the timer that is+  // earliest in the queue, in which case the reactor's event demultiplexing+  // function call may need to be interrupted and restarted.+  ASIO_DECL bool enqueue_timer(const time_type& time,+      per_timer_data& timer, wait_op* op);++  // Whether there are no timers in the queue.+  ASIO_DECL virtual bool empty() const;++  // Get the time for the timer that is earliest in the queue.+  ASIO_DECL virtual long wait_duration_msec(long max_duration) const;++  // Get the time for the timer that is earliest in the queue.+  ASIO_DECL virtual long wait_duration_usec(long max_duration) const;++  // Dequeue all timers not later than the current time.+  ASIO_DECL virtual void get_ready_timers(op_queue<operation>& ops);++  // Dequeue all timers.+  ASIO_DECL virtual void get_all_timers(op_queue<operation>& ops);++  // Cancel and dequeue operations for the given timer.+  ASIO_DECL std::size_t cancel_timer(+      per_timer_data& timer, op_queue<operation>& ops,+      std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++  // Move operations from one timer to another, empty timer.+  ASIO_DECL void move_timer(per_timer_data& target,+      per_timer_data& source);++private:+  timer_queue<forwarding_posix_time_traits> impl_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/timer_queue_ptime.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_BOOST_DATE_TIME)++#endif // ASIO_DETAIL_TIMER_QUEUE_PTIME_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/timer_queue_set.hpp view
@@ -0,0 +1,66 @@+//+// detail/timer_queue_set.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_TIMER_QUEUE_SET_HPP+#define ASIO_DETAIL_TIMER_QUEUE_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/detail/timer_queue_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class timer_queue_set+{+public:+  // Constructor.+  ASIO_DECL timer_queue_set();++  // Add a timer queue to the set.+  ASIO_DECL void insert(timer_queue_base* q);++  // Remove a timer queue from the set.+  ASIO_DECL void erase(timer_queue_base* q);++  // Determine whether all queues are empty.+  ASIO_DECL bool all_empty() const;++  // Get the wait duration in milliseconds.+  ASIO_DECL long wait_duration_msec(long max_duration) const;++  // Get the wait duration in microseconds.+  ASIO_DECL long wait_duration_usec(long max_duration) const;++  // Dequeue all ready timers.+  ASIO_DECL void get_ready_timers(op_queue<operation>& ops);++  // Dequeue all timers.+  ASIO_DECL void get_all_timers(op_queue<operation>& ops);++private:+  timer_queue_base* first_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/timer_queue_set.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_DETAIL_TIMER_QUEUE_SET_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler.hpp view
@@ -0,0 +1,35 @@+//+// detail/timer_scheduler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_TIMER_SCHEDULER_HPP+#define ASIO_DETAIL_TIMER_SCHEDULER_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/timer_scheduler_fwd.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/winrt_timer_scheduler.hpp"+#elif defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#elif defined(ASIO_HAS_EPOLL)+# include "asio/detail/epoll_reactor.hpp"+#elif defined(ASIO_HAS_KQUEUE)+# include "asio/detail/kqueue_reactor.hpp"+#elif defined(ASIO_HAS_DEV_POLL)+# include "asio/detail/dev_poll_reactor.hpp"+#else+# include "asio/detail/select_reactor.hpp"+#endif++#endif // ASIO_DETAIL_TIMER_SCHEDULER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler_fwd.hpp view
@@ -0,0 +1,40 @@+//+// detail/timer_scheduler_fwd.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_TIMER_SCHEDULER_FWD_HPP+#define ASIO_DETAIL_TIMER_SCHEDULER_FWD_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_WINDOWS_RUNTIME)+typedef class winrt_timer_scheduler timer_scheduler;+#elif defined(ASIO_HAS_IOCP)+typedef class win_iocp_io_context timer_scheduler;+#elif defined(ASIO_HAS_EPOLL)+typedef class epoll_reactor timer_scheduler;+#elif defined(ASIO_HAS_KQUEUE)+typedef class kqueue_reactor timer_scheduler;+#elif defined(ASIO_HAS_DEV_POLL)+typedef class dev_poll_reactor timer_scheduler;+#else+typedef class select_reactor timer_scheduler;+#endif++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_TIMER_SCHEDULER_FWD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/tss_ptr.hpp view
@@ -0,0 +1,69 @@+//+// detail/tss_ptr.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_TSS_PTR_HPP+#define ASIO_DETAIL_TSS_PTR_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_THREADS)+# include "asio/detail/null_tss_ptr.hpp"+#elif defined(ASIO_HAS_THREAD_KEYWORD_EXTENSION)+# include "asio/detail/keyword_tss_ptr.hpp"+#elif defined(ASIO_WINDOWS)+# include "asio/detail/win_tss_ptr.hpp"+#elif defined(ASIO_HAS_PTHREADS)+# include "asio/detail/posix_tss_ptr.hpp"+#else+# error Only Windows and POSIX are supported!+#endif++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename T>+class tss_ptr+#if !defined(ASIO_HAS_THREADS)+  : public null_tss_ptr<T>+#elif defined(ASIO_HAS_THREAD_KEYWORD_EXTENSION)+  : public keyword_tss_ptr<T>+#elif defined(ASIO_WINDOWS)+  : public win_tss_ptr<T>+#elif defined(ASIO_HAS_PTHREADS)+  : public posix_tss_ptr<T>+#endif+{+public:+  void operator=(T* value)+  {+#if !defined(ASIO_HAS_THREADS)+    null_tss_ptr<T>::operator=(value);+#elif defined(ASIO_HAS_THREAD_KEYWORD_EXTENSION)+    keyword_tss_ptr<T>::operator=(value);+#elif defined(ASIO_WINDOWS)+    win_tss_ptr<T>::operator=(value);+#elif defined(ASIO_HAS_PTHREADS)+    posix_tss_ptr<T>::operator=(value);+#endif+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_TSS_PTR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/type_traits.hpp view
@@ -0,0 +1,148 @@+//+// detail/type_traits.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_TYPE_TRAITS_HPP+#define ASIO_DETAIL_TYPE_TRAITS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_TYPE_TRAITS)+# include <type_traits>+#else // defined(ASIO_HAS_STD_TYPE_TRAITS)+# include <boost/type_traits/add_const.hpp>+# include <boost/type_traits/add_lvalue_reference.hpp>+# include <boost/type_traits/aligned_storage.hpp>+# include <boost/type_traits/alignment_of.hpp>+# include <boost/type_traits/conditional.hpp>+# include <boost/type_traits/decay.hpp>+# include <boost/type_traits/has_nothrow_copy.hpp>+# include <boost/type_traits/has_nothrow_destructor.hpp>+# include <boost/type_traits/integral_constant.hpp>+# include <boost/type_traits/is_base_of.hpp>+# include <boost/type_traits/is_class.hpp>+# include <boost/type_traits/is_const.hpp>+# include <boost/type_traits/is_convertible.hpp>+# include <boost/type_traits/is_constructible.hpp>+# include <boost/type_traits/is_copy_constructible.hpp>+# include <boost/type_traits/is_destructible.hpp>+# include <boost/type_traits/is_function.hpp>+# include <boost/type_traits/is_object.hpp>+# include <boost/type_traits/is_same.hpp>+# include <boost/type_traits/remove_cv.hpp>+# include <boost/type_traits/remove_pointer.hpp>+# include <boost/type_traits/remove_reference.hpp>+# include <boost/utility/declval.hpp>+# include <boost/utility/enable_if.hpp>+# include <boost/utility/result_of.hpp>+#endif // defined(ASIO_HAS_STD_TYPE_TRAITS)++namespace asio {++#if defined(ASIO_HAS_STD_TYPE_TRAITS)+using std::add_const;+using std::add_lvalue_reference;+using std::aligned_storage;+using std::alignment_of;+using std::conditional;+using std::decay;+using std::declval;+using std::enable_if;+using std::false_type;+using std::integral_constant;+using std::is_base_of;+using std::is_class;+using std::is_const;+using std::is_constructible;+using std::is_convertible;+using std::is_copy_constructible;+using std::is_destructible;+using std::is_function;+using std::is_move_constructible;+using std::is_nothrow_copy_constructible;+using std::is_nothrow_destructible;+using std::is_object;+using std::is_reference;+using std::is_same;+using std::is_scalar;+using std::remove_cv;+template <typename T>+struct remove_cvref : remove_cv<typename std::remove_reference<T>::type> {};+using std::remove_pointer;+using std::remove_reference;+#if defined(ASIO_HAS_STD_INVOKE_RESULT)+template <typename> struct result_of;+template <typename F, typename... Args>+struct result_of<F(Args...)> : std::invoke_result<F, Args...> {};+#else // defined(ASIO_HAS_STD_INVOKE_RESULT)+using std::result_of;+#endif // defined(ASIO_HAS_STD_INVOKE_RESULT)+using std::true_type;+#else // defined(ASIO_HAS_STD_TYPE_TRAITS)+using boost::add_const;+using boost::add_lvalue_reference;+using boost::aligned_storage;+using boost::alignment_of;+template <bool Condition, typename Type = void>+struct enable_if : boost::enable_if_c<Condition, Type> {};+using boost::conditional;+using boost::decay;+using boost::declval;+using boost::false_type;+using boost::integral_constant;+using boost::is_base_of;+using boost::is_class;+using boost::is_const;+using boost::is_constructible;+using boost::is_convertible;+using boost::is_copy_constructible;+using boost::is_destructible;+using boost::is_function;+#if defined(ASIO_HAS_MOVE)+template <typename T>+struct is_move_constructible : false_type {};+#else // defined(ASIO_HAS_MOVE)+template <typename T>+struct is_move_constructible : is_copy_constructible<T> {};+#endif // defined(ASIO_HAS_MOVE)+template <typename T>+struct is_nothrow_copy_constructible : boost::has_nothrow_copy<T> {};+template <typename T>+struct is_nothrow_destructible : boost::has_nothrow_destructor<T> {};+using boost::is_object;+using boost::is_reference;+using boost::is_same;+using boost::is_scalar;+using boost::remove_cv;+template <typename T>+struct remove_cvref : remove_cv<typename boost::remove_reference<T>::type> {};+using boost::remove_pointer;+using boost::remove_reference;+using boost::result_of;+using boost::true_type;+#endif // defined(ASIO_HAS_STD_TYPE_TRAITS)++template <typename> struct void_type { typedef void type; };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename...> struct conjunction : true_type {};+template <typename T> struct conjunction<T> : T {};+template <typename Head, typename... Tail> struct conjunction<Head, Tail...> :+  conditional<Head::value, conjunction<Tail...>, Head>::type {};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace asio++#endif // ASIO_DETAIL_TYPE_TRAITS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/variadic_templates.hpp view
@@ -0,0 +1,294 @@+//+// detail/variadic_templates.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_VARIADIC_TEMPLATES_HPP+#define ASIO_DETAIL_VARIADIC_TEMPLATES_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_VARIADIC_TEMPLATES)++# define ASIO_VARIADIC_TPARAMS(n) ASIO_VARIADIC_TPARAMS_##n++# define ASIO_VARIADIC_TPARAMS_1 \+  typename T1+# define ASIO_VARIADIC_TPARAMS_2 \+  typename T1, typename T2+# define ASIO_VARIADIC_TPARAMS_3 \+  typename T1, typename T2, typename T3+# define ASIO_VARIADIC_TPARAMS_4 \+  typename T1, typename T2, typename T3, typename T4+# define ASIO_VARIADIC_TPARAMS_5 \+  typename T1, typename T2, typename T3, typename T4, typename T5+# define ASIO_VARIADIC_TPARAMS_6 \+  typename T1, typename T2, typename T3, typename T4, typename T5, \+  typename T6+# define ASIO_VARIADIC_TPARAMS_7 \+  typename T1, typename T2, typename T3, typename T4, typename T5, \+  typename T6, typename T7+# define ASIO_VARIADIC_TPARAMS_8 \+  typename T1, typename T2, typename T3, typename T4, typename T5, \+  typename T6, typename T7, typename T8++# define ASIO_VARIADIC_TARGS(n) ASIO_VARIADIC_TARGS_##n++# define ASIO_VARIADIC_TARGS_1 T1+# define ASIO_VARIADIC_TARGS_2 T1, T2+# define ASIO_VARIADIC_TARGS_3 T1, T2, T3+# define ASIO_VARIADIC_TARGS_4 T1, T2, T3, T4+# define ASIO_VARIADIC_TARGS_5 T1, T2, T3, T4, T5+# define ASIO_VARIADIC_TARGS_6 T1, T2, T3, T4, T5, T6+# define ASIO_VARIADIC_TARGS_7 T1, T2, T3, T4, T5, T6, T7+# define ASIO_VARIADIC_TARGS_8 T1, T2, T3, T4, T5, T6, T7, T8++# define ASIO_VARIADIC_BYVAL_PARAMS(n) \+  ASIO_VARIADIC_BYVAL_PARAMS_##n++# define ASIO_VARIADIC_BYVAL_PARAMS_1 T1 x1+# define ASIO_VARIADIC_BYVAL_PARAMS_2 T1 x1, T2 x2+# define ASIO_VARIADIC_BYVAL_PARAMS_3 T1 x1, T2 x2, T3 x3+# define ASIO_VARIADIC_BYVAL_PARAMS_4 T1 x1, T2 x2, T3 x3, T4 x4+# define ASIO_VARIADIC_BYVAL_PARAMS_5 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5+# define ASIO_VARIADIC_BYVAL_PARAMS_6 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, \+  T6 x6+# define ASIO_VARIADIC_BYVAL_PARAMS_7 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, \+  T6 x6, T7 x7+# define ASIO_VARIADIC_BYVAL_PARAMS_8 T1 x1, T2 x2, T3 x3, T4 x4, T5 x5, \+  T6 x6, T7 x7, T8 x8++# define ASIO_VARIADIC_BYVAL_ARGS(n) \+  ASIO_VARIADIC_BYVAL_ARGS_##n++# define ASIO_VARIADIC_BYVAL_ARGS_1 x1+# define ASIO_VARIADIC_BYVAL_ARGS_2 x1, x2+# define ASIO_VARIADIC_BYVAL_ARGS_3 x1, x2, x3+# define ASIO_VARIADIC_BYVAL_ARGS_4 x1, x2, x3, x4+# define ASIO_VARIADIC_BYVAL_ARGS_5 x1, x2, x3, x4, x5+# define ASIO_VARIADIC_BYVAL_ARGS_6 x1, x2, x3, x4, x5, x6+# define ASIO_VARIADIC_BYVAL_ARGS_7 x1, x2, x3, x4, x5, x6, x7+# define ASIO_VARIADIC_BYVAL_ARGS_8 x1, x2, x3, x4, x5, x6, x7, x8++# define ASIO_VARIADIC_CONSTREF_PARAMS(n) \+  ASIO_VARIADIC_CONSTREF_PARAMS_##n++# define ASIO_VARIADIC_CONSTREF_PARAMS_1 \+  const T1& x1+# define ASIO_VARIADIC_CONSTREF_PARAMS_2 \+  const T1& x1, const T2& x2+# define ASIO_VARIADIC_CONSTREF_PARAMS_3 \+  const T1& x1, const T2& x2, const T3& x3+# define ASIO_VARIADIC_CONSTREF_PARAMS_4 \+  const T1& x1, const T2& x2, const T3& x3, const T4& x4+# define ASIO_VARIADIC_CONSTREF_PARAMS_5 \+  const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5+# define ASIO_VARIADIC_CONSTREF_PARAMS_6 \+  const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5, \+  const T6& x6+# define ASIO_VARIADIC_CONSTREF_PARAMS_7 \+  const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5, \+  const T6& x6, const T7& x7+# define ASIO_VARIADIC_CONSTREF_PARAMS_8 \+  const T1& x1, const T2& x2, const T3& x3, const T4& x4, const T5& x5, \+  const T6& x6, const T7& x7, const T8& x8++# define ASIO_VARIADIC_MOVE_PARAMS(n) \+  ASIO_VARIADIC_MOVE_PARAMS_##n++# define ASIO_VARIADIC_MOVE_PARAMS_1 \+  ASIO_MOVE_ARG(T1) x1+# define ASIO_VARIADIC_MOVE_PARAMS_2 \+  ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2+# define ASIO_VARIADIC_MOVE_PARAMS_3 \+  ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \+  ASIO_MOVE_ARG(T3) x3+# define ASIO_VARIADIC_MOVE_PARAMS_4 \+  ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \+  ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4+# define ASIO_VARIADIC_MOVE_PARAMS_5 \+  ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \+  ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4, \+  ASIO_MOVE_ARG(T5) x5+# define ASIO_VARIADIC_MOVE_PARAMS_6 \+  ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \+  ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4, \+  ASIO_MOVE_ARG(T5) x5, ASIO_MOVE_ARG(T6) x6+# define ASIO_VARIADIC_MOVE_PARAMS_7 \+  ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \+  ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4, \+  ASIO_MOVE_ARG(T5) x5, ASIO_MOVE_ARG(T6) x6, \+  ASIO_MOVE_ARG(T7) x7+# define ASIO_VARIADIC_MOVE_PARAMS_8 \+  ASIO_MOVE_ARG(T1) x1, ASIO_MOVE_ARG(T2) x2, \+  ASIO_MOVE_ARG(T3) x3, ASIO_MOVE_ARG(T4) x4, \+  ASIO_MOVE_ARG(T5) x5, ASIO_MOVE_ARG(T6) x6, \+  ASIO_MOVE_ARG(T7) x7, ASIO_MOVE_ARG(T8) x8++# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS(n) \+  ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_##n++# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_1 \+  ASIO_MOVE_ARG(T1)+# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_2 \+  ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2)+# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_3 \+  ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \+  ASIO_MOVE_ARG(T3)+# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_4 \+  ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \+  ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4)+# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_5 \+  ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \+  ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4), \+  ASIO_MOVE_ARG(T5)+# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_6 \+  ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \+  ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4), \+  ASIO_MOVE_ARG(T5), ASIO_MOVE_ARG(T6)+# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_7 \+  ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \+  ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4), \+  ASIO_MOVE_ARG(T5), ASIO_MOVE_ARG(T6), \+  ASIO_MOVE_ARG(T7)+# define ASIO_VARIADIC_UNNAMED_MOVE_PARAMS_8 \+  ASIO_MOVE_ARG(T1), ASIO_MOVE_ARG(T2), \+  ASIO_MOVE_ARG(T3), ASIO_MOVE_ARG(T4), \+  ASIO_MOVE_ARG(T5), ASIO_MOVE_ARG(T6), \+  ASIO_MOVE_ARG(T7), ASIO_MOVE_ARG(T8)++# define ASIO_VARIADIC_MOVE_ARGS(n) \+  ASIO_VARIADIC_MOVE_ARGS_##n++# define ASIO_VARIADIC_MOVE_ARGS_1 \+  ASIO_MOVE_CAST(T1)(x1)+# define ASIO_VARIADIC_MOVE_ARGS_2 \+  ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2)+# define ASIO_VARIADIC_MOVE_ARGS_3 \+  ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \+  ASIO_MOVE_CAST(T3)(x3)+# define ASIO_VARIADIC_MOVE_ARGS_4 \+  ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \+  ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4)+# define ASIO_VARIADIC_MOVE_ARGS_5 \+  ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \+  ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4), \+  ASIO_MOVE_CAST(T5)(x5)+# define ASIO_VARIADIC_MOVE_ARGS_6 \+  ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \+  ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4), \+  ASIO_MOVE_CAST(T5)(x5), ASIO_MOVE_CAST(T6)(x6)+# define ASIO_VARIADIC_MOVE_ARGS_7 \+  ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \+  ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4), \+  ASIO_MOVE_CAST(T5)(x5), ASIO_MOVE_CAST(T6)(x6), \+  ASIO_MOVE_CAST(T7)(x7)+# define ASIO_VARIADIC_MOVE_ARGS_8 \+  ASIO_MOVE_CAST(T1)(x1), ASIO_MOVE_CAST(T2)(x2), \+  ASIO_MOVE_CAST(T3)(x3), ASIO_MOVE_CAST(T4)(x4), \+  ASIO_MOVE_CAST(T5)(x5), ASIO_MOVE_CAST(T6)(x6), \+  ASIO_MOVE_CAST(T7)(x7), ASIO_MOVE_CAST(T8)(x8)++# define ASIO_VARIADIC_DECLVAL(n) \+  ASIO_VARIADIC_DECLVAL_##n++# define ASIO_VARIADIC_DECLVAL_1 \+  declval<T1>()+# define ASIO_VARIADIC_DECLVAL_2 \+  declval<T1>(), declval<T2>()+# define ASIO_VARIADIC_DECLVAL_3 \+  declval<T1>(), declval<T2>(), declval<T3>()+# define ASIO_VARIADIC_DECLVAL_4 \+  declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>()+# define ASIO_VARIADIC_DECLVAL_5 \+  declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>(), \+  declval<T5>()+# define ASIO_VARIADIC_DECLVAL_6 \+  declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>(), \+  declval<T5>(), declval<T6>()+# define ASIO_VARIADIC_DECLVAL_7 \+  declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>(), \+  declval<T5>(), declval<T6>(), declval<T7>()+# define ASIO_VARIADIC_DECLVAL_8 \+  declval<T1>(), declval<T2>(), declval<T3>(), declval<T4>(), \+  declval<T5>(), declval<T6>(), declval<T7>(), declval<T8>()++# define ASIO_VARIADIC_MOVE_DECLVAL(n) \+  ASIO_VARIADIC_MOVE_DECLVAL_##n++# define ASIO_VARIADIC_MOVE_DECLVAL_1 \+  declval<ASIO_MOVE_ARG(T1)>()+# define ASIO_VARIADIC_MOVE_DECLVAL_2 \+  declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>()+# define ASIO_VARIADIC_MOVE_DECLVAL_3 \+  declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \+  declval<ASIO_MOVE_ARG(T3)>()+# define ASIO_VARIADIC_MOVE_DECLVAL_4 \+  declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \+  declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>()+# define ASIO_VARIADIC_MOVE_DECLVAL_5 \+  declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \+  declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>(), \+  declval<ASIO_MOVE_ARG(T5)>()+# define ASIO_VARIADIC_MOVE_DECLVAL_6 \+  declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \+  declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>(), \+  declval<ASIO_MOVE_ARG(T5)>(), declval<ASIO_MOVE_ARG(T6)>()+# define ASIO_VARIADIC_MOVE_DECLVAL_7 \+  declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \+  declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>(), \+  declval<ASIO_MOVE_ARG(T5)>(), declval<ASIO_MOVE_ARG(T6)>(), \+  declval<ASIO_MOVE_ARG(T7)>()+# define ASIO_VARIADIC_MOVE_DECLVAL_8 \+  declval<ASIO_MOVE_ARG(T1)>(), declval<ASIO_MOVE_ARG(T2)>(), \+  declval<ASIO_MOVE_ARG(T3)>(), declval<ASIO_MOVE_ARG(T4)>(), \+  declval<ASIO_MOVE_ARG(T5)>(), declval<ASIO_MOVE_ARG(T6)>(), \+  declval<ASIO_MOVE_ARG(T7)>(), declval<ASIO_MOVE_ARG(T8)>()++# define ASIO_VARIADIC_DECAY(n) \+  ASIO_VARIADIC_DECAY_##n++# define ASIO_VARIADIC_DECAY_1 \+  typename decay<T1>::type+# define ASIO_VARIADIC_DECAY_2 \+  typename decay<T1>::type, typename decay<T2>::type+# define ASIO_VARIADIC_DECAY_3 \+  typename decay<T1>::type, typename decay<T2>::type, \+  typename decay<T3>::type+# define ASIO_VARIADIC_DECAY_4 \+  typename decay<T1>::type, typename decay<T2>::type, \+  typename decay<T3>::type, typename decay<T4>::type+# define ASIO_VARIADIC_DECAY_5 \+  typename decay<T1>::type, typename decay<T2>::type, \+  typename decay<T3>::type, typename decay<T4>::type, \+  typename decay<T5>::type+# define ASIO_VARIADIC_DECAY_6 \+  typename decay<T1>::type, typename decay<T2>::type, \+  typename decay<T3>::type, typename decay<T4>::type, \+  typename decay<T5>::type, typename decay<T6>::type+# define ASIO_VARIADIC_DECAY_7 \+  typename decay<T1>::type, typename decay<T2>::type, \+  typename decay<T3>::type, typename decay<T4>::type, \+  typename decay<T5>::type, typename decay<T6>::type, \+  typename decay<T7>::type+# define ASIO_VARIADIC_DECAY_8 \+  typename decay<T1>::type, typename decay<T2>::type, \+  typename decay<T3>::type, typename decay<T4>::type, \+  typename decay<T5>::type, typename decay<T6>::type, \+  typename decay<T7>::type, typename decay<T8>::type++# define ASIO_VARIADIC_GENERATE(m) m(1) m(2) m(3) m(4) m(5) m(6) m(7) m(8)+# define ASIO_VARIADIC_GENERATE_5(m) m(1) m(2) m(3) m(4) m(5)++#endif // !defined(ASIO_HAS_VARIADIC_TEMPLATES)++#endif // ASIO_DETAIL_VARIADIC_TEMPLATES_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/wait_handler.hpp view
@@ -0,0 +1,90 @@+//+// detail/wait_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WAIT_HANDLER_HPP+#define ASIO_DETAIL_WAIT_HANDLER_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/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/wait_op.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class wait_handler : public wait_op+{+public:+  ASIO_DEFINE_HANDLER_PTR(wait_handler);++  wait_handler(Handler& h, const IoExecutor& io_ex)+    : wait_op(&wait_handler::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(h)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    wait_handler* h(static_cast<wait_handler*>(base));+    ptr p = { asio::detail::addressof(h->handler_), h, h };++    ASIO_HANDLER_COMPLETION((*h));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          h->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder1<Handler, asio::error_code>+      handler(h->handler_, h->ec_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_WAIT_HANDLER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/wait_op.hpp view
@@ -0,0 +1,45 @@+//+// detail/wait_op.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WAIT_OP_HPP+#define ASIO_DETAIL_WAIT_OP_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/operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class wait_op+  : public operation+{+public:+  // The error code to be passed to the completion handler.+  asio::error_code ec_;++protected:+  wait_op(func_type func)+    : operation(func)+  {+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_WAIT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_event.hpp view
@@ -0,0 +1,164 @@+//+// detail/win_event.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_EVENT_HPP+#define ASIO_DETAIL_WIN_EVENT_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_WINDOWS)++#include <cstddef>+#include "asio/detail/assert.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class win_event+  : private noncopyable+{+public:+  // Constructor.+  ASIO_DECL win_event();++  // Destructor.+  ASIO_DECL ~win_event();++  // Signal the event. (Retained for backward compatibility.)+  template <typename Lock>+  void signal(Lock& lock)+  {+    this->signal_all(lock);+  }++  // Signal all waiters.+  template <typename Lock>+  void signal_all(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    (void)lock;+    state_ |= 1;+    ::SetEvent(events_[0]);+  }++  // Unlock the mutex and signal one waiter.+  template <typename Lock>+  void unlock_and_signal_one(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    state_ |= 1;+    bool have_waiters = (state_ > 1);+    lock.unlock();+    if (have_waiters)+      ::SetEvent(events_[1]);+  }++  // Unlock the mutex and signal one waiter who may destroy us.+  template <typename Lock>+  void unlock_and_signal_one_for_destruction(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    state_ |= 1;+    bool have_waiters = (state_ > 1);+    if (have_waiters)+      ::SetEvent(events_[1]);+    lock.unlock();+  }++  // If there's a waiter, unlock the mutex and signal it.+  template <typename Lock>+  bool maybe_unlock_and_signal_one(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    state_ |= 1;+    if (state_ > 1)+    {+      lock.unlock();+      ::SetEvent(events_[1]);+      return true;+    }+    return false;+  }++  // Reset the event.+  template <typename Lock>+  void clear(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    (void)lock;+    ::ResetEvent(events_[0]);+    state_ &= ~std::size_t(1);+  }++  // Wait for the event to become signalled.+  template <typename Lock>+  void wait(Lock& lock)+  {+    ASIO_ASSERT(lock.locked());+    while ((state_ & 1) == 0)+    {+      state_ += 2;+      lock.unlock();+#if defined(ASIO_WINDOWS_APP)+      ::WaitForMultipleObjectsEx(2, events_, false, INFINITE, false);+#else // defined(ASIO_WINDOWS_APP)+      ::WaitForMultipleObjects(2, events_, false, INFINITE);+#endif // defined(ASIO_WINDOWS_APP)+      lock.lock();+      state_ -= 2;+    }+  }++  // Timed wait for the event to become signalled.+  template <typename Lock>+  bool wait_for_usec(Lock& lock, long usec)+  {+    ASIO_ASSERT(lock.locked());+    if ((state_ & 1) == 0)+    {+      state_ += 2;+      lock.unlock();+      DWORD msec = usec > 0 ? (usec < 1000 ? 1 : usec / 1000) : 0;+#if defined(ASIO_WINDOWS_APP)+      ::WaitForMultipleObjectsEx(2, events_, false, msec, false);+#else // defined(ASIO_WINDOWS_APP)+      ::WaitForMultipleObjects(2, events_, false, msec);+#endif // defined(ASIO_WINDOWS_APP)+      lock.lock();+      state_ -= 2;+    }+    return (state_ & 1) != 0;+  }++private:+  HANDLE events_[2];+  std::size_t state_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_event.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_WINDOWS)++#endif // ASIO_DETAIL_WIN_EVENT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_fd_set_adapter.hpp view
@@ -0,0 +1,149 @@+//+// detail/win_fd_set_adapter.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP+#define ASIO_DETAIL_WIN_FD_SET_ADAPTER_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_WINDOWS) || defined(__CYGWIN__)++#include "asio/detail/noncopyable.hpp"+#include "asio/detail/reactor_op_queue.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Adapts the FD_SET type to meet the Descriptor_Set concept's requirements.+class win_fd_set_adapter : noncopyable+{+public:+  enum { default_fd_set_size = 1024 };++  win_fd_set_adapter()+    : capacity_(default_fd_set_size),+      max_descriptor_(invalid_socket)+  {+    fd_set_ = static_cast<win_fd_set*>(::operator new(+          sizeof(win_fd_set) - sizeof(SOCKET)+          + sizeof(SOCKET) * (capacity_)));+    fd_set_->fd_count = 0;+  }++  ~win_fd_set_adapter()+  {+    ::operator delete(fd_set_);+  }++  void reset()+  {+    fd_set_->fd_count = 0;+    max_descriptor_ = invalid_socket;+  }++  bool set(socket_type descriptor)+  {+    for (u_int i = 0; i < fd_set_->fd_count; ++i)+      if (fd_set_->fd_array[i] == descriptor)+        return true;++    reserve(fd_set_->fd_count + 1);+    fd_set_->fd_array[fd_set_->fd_count++] = descriptor;+    return true;+  }++  void set(reactor_op_queue<socket_type>& operations, op_queue<operation>&)+  {+    reactor_op_queue<socket_type>::iterator i = operations.begin();+    while (i != operations.end())+    {+      reactor_op_queue<socket_type>::iterator op_iter = i++;+      reserve(fd_set_->fd_count + 1);+      fd_set_->fd_array[fd_set_->fd_count++] = op_iter->first;+    }+  }++  bool is_set(socket_type descriptor) const+  {+    return !!__WSAFDIsSet(descriptor,+        const_cast<fd_set*>(reinterpret_cast<const fd_set*>(fd_set_)));+  }++  operator fd_set*()+  {+    return reinterpret_cast<fd_set*>(fd_set_);+  }++  socket_type max_descriptor() const+  {+    return max_descriptor_;+  }++  void perform(reactor_op_queue<socket_type>& operations,+      op_queue<operation>& ops) const+  {+    for (u_int i = 0; i < fd_set_->fd_count; ++i)+      operations.perform_operations(fd_set_->fd_array[i], ops);+  }++private:+  // This structure is defined to be compatible with the Windows API fd_set+  // structure, but without being dependent on the value of FD_SETSIZE. We use+  // the "struct hack" to allow the number of descriptors to be varied at+  // runtime.+  struct win_fd_set+  {+    u_int fd_count;+    SOCKET fd_array[1];+  };++  // Increase the fd_set_ capacity to at least the specified number of elements.+  void reserve(u_int n)+  {+    if (n <= capacity_)+      return;++    u_int new_capacity = capacity_ + capacity_ / 2;+    if (new_capacity < n)+      new_capacity = n;++    win_fd_set* new_fd_set = static_cast<win_fd_set*>(::operator new(+          sizeof(win_fd_set) - sizeof(SOCKET)+          + sizeof(SOCKET) * (new_capacity)));++    new_fd_set->fd_count = fd_set_->fd_count;+    for (u_int i = 0; i < fd_set_->fd_count; ++i)+      new_fd_set->fd_array[i] = fd_set_->fd_array[i];++    ::operator delete(fd_set_);+    fd_set_ = new_fd_set;+    capacity_ = new_capacity;+  }++  win_fd_set* fd_set_;+  u_int capacity_;+  socket_type max_descriptor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++#endif // ASIO_DETAIL_WIN_FD_SET_ADAPTER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_fenced_block.hpp view
@@ -0,0 +1,90 @@+//+// detail/win_fenced_block.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_FENCED_BLOCK_HPP+#define ASIO_DETAIL_WIN_FENCED_BLOCK_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_WINDOWS) && !defined(UNDER_CE)++#include "asio/detail/socket_types.hpp"+#include "asio/detail/noncopyable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class win_fenced_block+  : private noncopyable+{+public:+  enum half_t { half };+  enum full_t { full };++  // Constructor for a half fenced block.+  explicit win_fenced_block(half_t)+  {+  }++  // Constructor for a full fenced block.+  explicit win_fenced_block(full_t)+  {+#if defined(__BORLANDC__)+    LONG barrier = 0;+    ::InterlockedExchange(&barrier, 1);+#elif defined(ASIO_MSVC) \+  && ((ASIO_MSVC < 1400) || !defined(MemoryBarrier))+# if defined(_M_IX86)+#  pragma warning(push)+#  pragma warning(disable:4793)+    LONG barrier;+    __asm { xchg barrier, eax }+#  pragma warning(pop)+# endif // defined(_M_IX86)+#else+    MemoryBarrier();+#endif+  }++  // Destructor.+  ~win_fenced_block()+  {+#if defined(__BORLANDC__)+    LONG barrier = 0;+    ::InterlockedExchange(&barrier, 1);+#elif defined(ASIO_MSVC) \+  && ((ASIO_MSVC < 1400) || !defined(MemoryBarrier))+# if defined(_M_IX86)+#  pragma warning(push)+#  pragma warning(disable:4793)+    LONG barrier;+    __asm { xchg barrier, eax }+#  pragma warning(pop)+# endif // defined(_M_IX86)+#else+    MemoryBarrier();+#endif+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS) && !defined(UNDER_CE)++#endif // ASIO_DETAIL_WIN_FENCED_BLOCK_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_global.hpp view
@@ -0,0 +1,71 @@+//+// detail/win_global.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_GLOBAL_HPP+#define ASIO_DETAIL_WIN_GLOBAL_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/static_mutex.hpp"+#include "asio/detail/tss_ptr.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename T>+struct win_global_impl+{+  // Destructor automatically cleans up the global.+  ~win_global_impl()+  {+    delete ptr_;+  }++  static win_global_impl instance_;+  static static_mutex mutex_;+  T* ptr_;+  static tss_ptr<T> tss_ptr_;+};++template <typename T>+win_global_impl<T> win_global_impl<T>::instance_ = { 0 };++template <typename T>+static_mutex win_global_impl<T>::mutex_ = ASIO_STATIC_MUTEX_INIT;++template <typename T>+tss_ptr<T> win_global_impl<T>::tss_ptr_;++template <typename T>+T& win_global()+{+  if (static_cast<T*>(win_global_impl<T>::tss_ptr_) == 0)+  {+    win_global_impl<T>::mutex_.init();+    static_mutex::scoped_lock lock(win_global_impl<T>::mutex_);+    if (win_global_impl<T>::instance_.ptr_ == 0)+      win_global_impl<T>::instance_.ptr_ = new T;+    win_global_impl<T>::tss_ptr_ = win_global_impl<T>::instance_.ptr_;+  }++  return *win_global_impl<T>::tss_ptr_;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_WIN_GLOBAL_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_read_op.hpp view
@@ -0,0 +1,117 @@+//+// detail/win_iocp_handle_read_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DETAIL_WIN_IOCP_HANDLE_READ_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_HANDLE_READ_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/operation.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class win_iocp_handle_read_op : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_read_op);++  win_iocp_handle_read_op(const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+    : operation(&win_iocp_handle_read_op::do_complete),+      buffers_(buffers),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t bytes_transferred)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    if (owner)+    {+      // Check whether buffers are still valid.+      buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::validate(o->buffers_);+    }+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++    // Map non-portable errors to their portable counterparts.+    if (ec.value() == ERROR_HANDLE_EOF)+      ec = asio::error::eof;++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, ec, bytes_transferred);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  MutableBufferSequence buffers_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_READ_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_service.hpp view
@@ -0,0 +1,335 @@+//+// detail/win_iocp_handle_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP+#define ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_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_IOCP)++#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/cstdint.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/operation.hpp"+#include "asio/detail/win_iocp_handle_read_op.hpp"+#include "asio/detail/win_iocp_handle_write_op.hpp"+#include "asio/detail/win_iocp_io_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class win_iocp_handle_service :+  public execution_context_service_base<win_iocp_handle_service>+{+public:+  // The native type of a stream handle.+  typedef HANDLE native_handle_type;++  // The implementation type of the stream handle.+  class implementation_type+  {+  public:+    // Default constructor.+    implementation_type()+      : handle_(INVALID_HANDLE_VALUE),+        safe_cancellation_thread_id_(0),+        next_(0),+        prev_(0)+    {+    }++  private:+    // Only this service will have access to the internal values.+    friend class win_iocp_handle_service;++    // The native stream handle representation.+    native_handle_type handle_;++    // The ID of the thread from which it is safe to cancel asynchronous+    // operations. 0 means no asynchronous operations have been started yet.+    // ~0 means asynchronous operations have been started from more than one+    // thread, and cancellation is not supported for the handle.+    DWORD safe_cancellation_thread_id_;++    // Pointers to adjacent handle implementations in linked list.+    implementation_type* next_;+    implementation_type* prev_;+  };++  ASIO_DECL win_iocp_handle_service(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Construct a new handle implementation.+  ASIO_DECL void construct(implementation_type& impl);++  // Move-construct a new handle implementation.+  ASIO_DECL void move_construct(implementation_type& impl,+      implementation_type& other_impl);++  // Move-assign from another handle implementation.+  ASIO_DECL void move_assign(implementation_type& impl,+      win_iocp_handle_service& other_service,+      implementation_type& other_impl);++  // Destroy a handle implementation.+  ASIO_DECL void destroy(implementation_type& impl);++  // Assign a native handle to a handle implementation.+  ASIO_DECL asio::error_code assign(implementation_type& impl,+      const native_handle_type& handle, asio::error_code& ec);++  // Determine whether the handle is open.+  bool is_open(const implementation_type& impl) const+  {+    return impl.handle_ != INVALID_HANDLE_VALUE;+  }++  // Destroy a handle implementation.+  ASIO_DECL asio::error_code close(implementation_type& impl,+      asio::error_code& ec);++  // Get the native handle representation.+  native_handle_type native_handle(const implementation_type& impl) const+  {+    return impl.handle_;+  }++  // Cancel all operations associated with the handle.+  ASIO_DECL asio::error_code cancel(implementation_type& impl,+      asio::error_code& ec);++  // Write the given data. Returns the number of bytes written.+  template <typename ConstBufferSequence>+  size_t write_some(implementation_type& impl,+      const ConstBufferSequence& buffers, asio::error_code& ec)+  {+    return write_some_at(impl, 0, buffers, ec);+  }++  // Write the given data at the specified offset. Returns the number of bytes+  // written.+  template <typename ConstBufferSequence>+  size_t write_some_at(implementation_type& impl, uint64_t offset,+      const ConstBufferSequence& buffers, asio::error_code& ec)+  {+    asio::const_buffer buffer =+      buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence>::first(buffers);++    return do_write(impl, offset, buffer, ec);+  }++  // Start an asynchronous write. The data being written must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_write_some(implementation_type& impl,+      const ConstBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_handle_write_op<+        ConstBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,+          reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some"));++    start_write_op(impl, 0,+        buffer_sequence_adapter<asio::const_buffer,+          ConstBufferSequence>::first(buffers), p.p);+    p.v = p.p = 0;+  }++  // Start an asynchronous write at a specified offset. The data being written+  // must be valid for the lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_write_some_at(implementation_type& impl,+      uint64_t offset, const ConstBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_handle_write_op<+        ConstBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,+          reinterpret_cast<uintmax_t>(impl.handle_), "async_write_some_at"));++    start_write_op(impl, offset,+        buffer_sequence_adapter<asio::const_buffer,+          ConstBufferSequence>::first(buffers), p.p);+    p.v = p.p = 0;+  }++  // Read some data. Returns the number of bytes received.+  template <typename MutableBufferSequence>+  size_t read_some(implementation_type& impl,+      const MutableBufferSequence& buffers, asio::error_code& ec)+  {+    return read_some_at(impl, 0, buffers, ec);+  }++  // Read some data at a specified offset. Returns the number of bytes received.+  template <typename MutableBufferSequence>+  size_t read_some_at(implementation_type& impl, uint64_t offset,+      const MutableBufferSequence& buffers, asio::error_code& ec)+  {+    asio::mutable_buffer buffer =+      buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence>::first(buffers);++    return do_read(impl, offset, buffer, ec);+  }++  // Start an asynchronous read. The buffer for the data being received must be+  // valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_read_some(implementation_type& impl,+      const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_handle_read_op<+        MutableBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,+          reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some"));++    start_read_op(impl, 0,+        buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::first(buffers), p.p);+    p.v = p.p = 0;+  }++  // Start an asynchronous read at a specified offset. The buffer for the data+  // being received must be valid for the lifetime of the asynchronous+  // operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_read_some_at(implementation_type& impl,+      uint64_t offset, const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_handle_read_op<+        MutableBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((iocp_service_.context(), *p.p, "handle", &impl,+          reinterpret_cast<uintmax_t>(impl.handle_), "async_read_some_at"));++    start_read_op(impl, offset,+        buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::first(buffers), p.p);+    p.v = p.p = 0;+  }++private:+  // Prevent the use of the null_buffers type with this service.+  size_t write_some(implementation_type& impl,+      const null_buffers& buffers, asio::error_code& ec);+  size_t write_some_at(implementation_type& impl, uint64_t offset,+      const null_buffers& buffers, asio::error_code& ec);+  template <typename Handler, typename IoExecutor>+  void async_write_some(implementation_type& impl,+      const null_buffers& buffers, Handler& handler,+      const IoExecutor& io_ex);+  template <typename Handler, typename IoExecutor>+  void async_write_some_at(implementation_type& impl, uint64_t offset,+      const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex);+  size_t read_some(implementation_type& impl,+      const null_buffers& buffers, asio::error_code& ec);+  size_t read_some_at(implementation_type& impl, uint64_t offset,+      const null_buffers& buffers, asio::error_code& ec);+  template <typename Handler, typename IoExecutor>+  void async_read_some(implementation_type& impl,+      const null_buffers& buffers, Handler& handler,+      const IoExecutor& io_ex);+  template <typename Handler, typename IoExecutor>+  void async_read_some_at(implementation_type& impl, uint64_t offset,+      const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex);++  // Helper class for waiting for synchronous operations to complete.+  class overlapped_wrapper;++  // Helper function to perform a synchronous write operation.+  ASIO_DECL size_t do_write(implementation_type& impl,+      uint64_t offset, const asio::const_buffer& buffer,+      asio::error_code& ec);++  // Helper function to start a write operation.+  ASIO_DECL void start_write_op(implementation_type& impl,+      uint64_t offset, const asio::const_buffer& buffer,+      operation* op);++  // Helper function to perform a synchronous write operation.+  ASIO_DECL size_t do_read(implementation_type& impl,+      uint64_t offset, const asio::mutable_buffer& buffer,+      asio::error_code& ec);++  // Helper function to start a read operation.+  ASIO_DECL void start_read_op(implementation_type& impl,+      uint64_t offset, const asio::mutable_buffer& buffer,+      operation* op);++  // Update the ID of the thread from which cancellation is safe.+  ASIO_DECL void update_cancellation_thread_id(implementation_type& impl);++  // Helper function to close a handle when the associated object is being+  // destroyed.+  ASIO_DECL void close_for_destruction(implementation_type& impl);++  // The IOCP service used for running asynchronous operations and dispatching+  // handlers.+  win_iocp_io_context& iocp_service_;++  // Mutex to protect access to the linked list of implementations.+  mutex mutex_;++  // The head of a linked list of all implementations.+  implementation_type* impl_list_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_iocp_handle_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_write_op.hpp view
@@ -0,0 +1,110 @@+//+// detail/win_iocp_handle_write_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DETAIL_WIN_IOCP_HANDLE_WRITE_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_HANDLE_WRITE_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/operation.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class win_iocp_handle_write_op : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_handle_write_op);++  win_iocp_handle_write_op(const ConstBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+    : operation(&win_iocp_handle_write_op::do_complete),+      buffers_(buffers),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& ec, std::size_t bytes_transferred)+  {+    // Take ownership of the operation object.+    win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    if (owner)+    {+      // Check whether buffers are still valid.+      buffer_sequence_adapter<asio::const_buffer,+          ConstBufferSequence>::validate(o->buffers_);+    }+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, ec, bytes_transferred);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  ConstBufferSequence buffers_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_HANDLE_WRITE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_io_context.hpp view
@@ -0,0 +1,342 @@+//+// detail/win_iocp_io_context.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_IO_CONTEXT_HPP+#define ASIO_DETAIL_WIN_IOCP_IO_CONTEXT_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_IOCP)++#include "asio/detail/limits.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/scoped_ptr.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/thread.hpp"+#include "asio/detail/thread_context.hpp"+#include "asio/detail/timer_queue_base.hpp"+#include "asio/detail/timer_queue_set.hpp"+#include "asio/detail/wait_op.hpp"+#include "asio/detail/win_iocp_operation.hpp"+#include "asio/detail/win_iocp_thread_info.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class wait_op;++class win_iocp_io_context+  : public execution_context_service_base<win_iocp_io_context>,+    public thread_context+{+public:+  // Constructor. Specifies a concurrency hint that is passed through to the+  // underlying I/O completion port.+  ASIO_DECL win_iocp_io_context(asio::execution_context& ctx,+      int concurrency_hint = -1, bool own_thread = true);++  // Destructor.+  ASIO_DECL ~win_iocp_io_context();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Initialise the task. Nothing to do here.+  void init_task()+  {+  }++  // Register a handle with the IO completion port.+  ASIO_DECL asio::error_code register_handle(+      HANDLE handle, asio::error_code& ec);++  // Run the event loop until stopped or no more work.+  ASIO_DECL size_t run(asio::error_code& ec);++  // Run until stopped or one operation is performed.+  ASIO_DECL size_t run_one(asio::error_code& ec);++  // Run until timeout, interrupted, or one operation is performed.+  ASIO_DECL size_t wait_one(long usec, asio::error_code& ec);++  // Poll for operations without blocking.+  ASIO_DECL size_t poll(asio::error_code& ec);++  // Poll for one operation without blocking.+  ASIO_DECL size_t poll_one(asio::error_code& ec);++  // Stop the event processing loop.+  ASIO_DECL void stop();++  // Determine whether the io_context is stopped.+  bool stopped() const+  {+    return ::InterlockedExchangeAdd(&stopped_, 0) != 0;+  }++  // Restart in preparation for a subsequent run invocation.+  void restart()+  {+    ::InterlockedExchange(&stopped_, 0);+  }++  // Notify that some work has started.+  void work_started()+  {+    ::InterlockedIncrement(&outstanding_work_);+  }++  // Notify that some work has finished.+  void work_finished()+  {+    if (::InterlockedDecrement(&outstanding_work_) == 0)+      stop();+  }++  // Return whether a handler can be dispatched immediately.+  bool can_dispatch()+  {+    return thread_call_stack::contains(this) != 0;+  }++  /// Capture the current exception so it can be rethrown from a run function.+  ASIO_DECL void capture_current_exception();++  // Request invocation of the given operation and return immediately. Assumes+  // that work_started() has not yet been called for the operation.+  void post_immediate_completion(win_iocp_operation* op, bool)+  {+    work_started();+    post_deferred_completion(op);+  }++  // Request invocation of the given operation and return immediately. Assumes+  // that work_started() was previously called for the operation.+  ASIO_DECL void post_deferred_completion(win_iocp_operation* op);++  // Request invocation of the given operation and return immediately. Assumes+  // that work_started() was previously called for the operations.+  ASIO_DECL void post_deferred_completions(+      op_queue<win_iocp_operation>& ops);++  // Request invocation of the given operation using the thread-private queue+  // and return immediately. Assumes that work_started() has not yet been+  // called for the operation.+  void post_private_immediate_completion(win_iocp_operation* op)+  {+    post_immediate_completion(op, false);+  }++  // Request invocation of the given operation using the thread-private queue+  // and return immediately. Assumes that work_started() was previously called+  // for the operation.+  void post_private_deferred_completion(win_iocp_operation* op)+  {+    post_deferred_completion(op);+  }++  // Enqueue the given operation following a failed attempt to dispatch the+  // operation for immediate invocation.+  void do_dispatch(operation* op)+  {+    post_immediate_completion(op, false);+  }++  // Process unfinished operations as part of a shutdown operation. Assumes+  // that work_started() was previously called for the operations.+  ASIO_DECL void abandon_operations(op_queue<operation>& ops);++  // Called after starting an overlapped I/O operation that did not complete+  // immediately. The caller must have already called work_started() prior to+  // starting the operation.+  ASIO_DECL void on_pending(win_iocp_operation* op);++  // Called after starting an overlapped I/O operation that completed+  // immediately. The caller must have already called work_started() prior to+  // starting the operation.+  ASIO_DECL void on_completion(win_iocp_operation* op,+      DWORD last_error = 0, DWORD bytes_transferred = 0);++  // Called after starting an overlapped I/O operation that completed+  // immediately. The caller must have already called work_started() prior to+  // starting the operation.+  ASIO_DECL void on_completion(win_iocp_operation* op,+      const asio::error_code& ec, DWORD bytes_transferred = 0);++  // Add a new timer queue to the service.+  template <typename Time_Traits>+  void add_timer_queue(timer_queue<Time_Traits>& timer_queue);++  // Remove a timer queue from the service.+  template <typename Time_Traits>+  void remove_timer_queue(timer_queue<Time_Traits>& timer_queue);++  // Schedule a new operation in the given timer queue to expire at the+  // specified absolute time.+  template <typename Time_Traits>+  void schedule_timer(timer_queue<Time_Traits>& queue,+      const typename Time_Traits::time_type& time,+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);++  // Cancel the timer associated with the given token. Returns the number of+  // handlers that have been posted or dispatched.+  template <typename Time_Traits>+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& timer,+      std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++  // Move the timer operations associated with the given timer.+  template <typename Time_Traits>+  void move_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& to,+      typename timer_queue<Time_Traits>::per_timer_data& from);++  // Get the concurrency hint that was used to initialise the io_context.+  int concurrency_hint() const+  {+    return concurrency_hint_;+  }++private:+#if defined(WINVER) && (WINVER < 0x0500)+  typedef DWORD dword_ptr_t;+  typedef ULONG ulong_ptr_t;+#else // defined(WINVER) && (WINVER < 0x0500)+  typedef DWORD_PTR dword_ptr_t;+  typedef ULONG_PTR ulong_ptr_t;+#endif // defined(WINVER) && (WINVER < 0x0500)++  // Dequeues at most one operation from the I/O completion port, and then+  // executes it. Returns the number of operations that were dequeued (i.e.+  // either 0 or 1).+  ASIO_DECL size_t do_one(DWORD msec,+      win_iocp_thread_info& this_thread, asio::error_code& ec);++  // Helper to calculate the GetQueuedCompletionStatus timeout.+  ASIO_DECL static DWORD get_gqcs_timeout();++  // Helper function to add a new timer queue.+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);++  // Helper function to remove a timer queue.+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);++  // Called to recalculate and update the timeout.+  ASIO_DECL void update_timeout();++  // Helper class to call work_finished() on block exit.+  struct work_finished_on_block_exit;++  // Helper class for managing a HANDLE.+  struct auto_handle+  {+    HANDLE handle;+    auto_handle() : handle(0) {}+    ~auto_handle() { if (handle) ::CloseHandle(handle); }+  };++  // The IO completion port used for queueing operations.+  auto_handle iocp_;++  // The count of unfinished work.+  long outstanding_work_;++  // Flag to indicate whether the event loop has been stopped.+  mutable long stopped_;++  // Flag to indicate whether there is an in-flight stop event. Every event+  // posted using PostQueuedCompletionStatus consumes non-paged pool, so to+  // avoid exhausting this resouce we limit the number of outstanding events.+  long stop_event_posted_;++  // Flag to indicate whether the service has been shut down.+  long shutdown_;++  enum+  {+    // Timeout to use with GetQueuedCompletionStatus on older versions of+    // Windows. Some versions of windows have a "bug" where a call to+    // GetQueuedCompletionStatus can appear stuck even though there are events+    // waiting on the queue. Using a timeout helps to work around the issue.+    default_gqcs_timeout = 500,++    // Maximum waitable timer timeout, in milliseconds.+    max_timeout_msec = 5 * 60 * 1000,++    // Maximum waitable timer timeout, in microseconds.+    max_timeout_usec = max_timeout_msec * 1000,++    // Completion key value used to wake up a thread to dispatch timers or+    // completed operations.+    wake_for_dispatch = 1,++    // Completion key value to indicate that an operation has posted with the+    // original last_error and bytes_transferred values stored in the fields of+    // the OVERLAPPED structure.+    overlapped_contains_result = 2+  };++  // Timeout to use with GetQueuedCompletionStatus.+  const DWORD gqcs_timeout_;++  // Helper class to run the scheduler in its own thread.+  struct thread_function;+  friend struct thread_function;++  // Function object for processing timeouts in a background thread.+  struct timer_thread_function;+  friend struct timer_thread_function;++  // Background thread used for processing timeouts.+  scoped_ptr<thread> timer_thread_;++  // A waitable timer object used for waiting for timeouts.+  auto_handle waitable_timer_;++  // Non-zero if timers or completed operations need to be dispatched.+  long dispatch_required_;++  // Mutex for protecting access to the timer queues and completed operations.+  mutex dispatch_mutex_;++  // The timer queues.+  timer_queue_set timer_queues_;++  // The operations that are ready to dispatch.+  op_queue<win_iocp_operation> completed_ops_;++  // The concurrency hint used to initialise the io_context.+  const int concurrency_hint_;++  // The thread that is running the io_context.+  scoped_ptr<thread> thread_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/win_iocp_io_context.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_iocp_io_context.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_IO_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_null_buffers_op.hpp view
@@ -0,0 +1,127 @@+//+// detail/win_iocp_null_buffers_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_NULL_BUFFERS_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_NULL_BUFFERS_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class win_iocp_null_buffers_op : public reactor_op+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_null_buffers_op);++  win_iocp_null_buffers_op(socket_ops::weak_cancel_token_type cancel_token,+      Handler& handler, const IoExecutor& io_ex)+    : reactor_op(asio::error_code(),+        &win_iocp_null_buffers_op::do_perform,+        &win_iocp_null_buffers_op::do_complete),+      cancel_token_(cancel_token),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static status do_perform(reactor_op*)+  {+    return done;+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t bytes_transferred)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // The reactor may have stored a result in the operation object.+    if (o->ec_)+      ec = o->ec_;++    // Map non-portable errors to their portable counterparts.+    if (ec.value() == ERROR_NETNAME_DELETED)+    {+      if (o->cancel_token_.expired())+        ec = asio::error::operation_aborted;+      else+        ec = asio::error::connection_reset;+    }+    else if (ec.value() == ERROR_PORT_UNREACHABLE)+    {+      ec = asio::error::connection_refused;+    }++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, ec, bytes_transferred);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  socket_ops::weak_cancel_token_type cancel_token_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_NULL_BUFFERS_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_operation.hpp view
@@ -0,0 +1,96 @@+//+// detail/win_iocp_operation.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_OPERATION_HPP+#define ASIO_DETAIL_WIN_IOCP_OPERATION_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_IOCP)++#include "asio/detail/handler_tracking.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/error_code.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class win_iocp_io_context;++// Base class for all operations. A function pointer is used instead of virtual+// functions to avoid the associated overhead.+class win_iocp_operation+  : public OVERLAPPED+    ASIO_ALSO_INHERIT_TRACKED_HANDLER+{+public:+  typedef win_iocp_operation operation_type;++  void complete(void* owner, const asio::error_code& ec,+      std::size_t bytes_transferred)+  {+    func_(owner, this, ec, bytes_transferred);+  }++  void destroy()+  {+    func_(0, this, asio::error_code(), 0);+  }++protected:+  typedef void (*func_type)(+      void*, win_iocp_operation*,+      const asio::error_code&, std::size_t);++  win_iocp_operation(func_type func)+    : next_(0),+      func_(func)+  {+    reset();+  }++  // Prevents deletion through this type.+  ~win_iocp_operation()+  {+  }++  void reset()+  {+    Internal = 0;+    InternalHigh = 0;+    Offset = 0;+    OffsetHigh = 0;+    hEvent = 0;+    ready_ = 0;+  }++private:+  friend class op_queue_access;+  friend class win_iocp_io_context;+  win_iocp_operation* next_;+  func_type func_;+  long ready_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_OPERATION_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_op.hpp view
@@ -0,0 +1,96 @@+//+// detail/win_iocp_overlapped_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_OVERLAPPED_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_OVERLAPPED_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/operation.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class win_iocp_overlapped_op : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_overlapped_op);++  win_iocp_overlapped_op(Handler& handler, const IoExecutor& io_ex)+    : operation(&win_iocp_overlapped_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& ec, std::size_t bytes_transferred)+  {+    // Take ownership of the operation object.+    win_iocp_overlapped_op* o(static_cast<win_iocp_overlapped_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, ec, bytes_transferred);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_OVERLAPPED_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp view
@@ -0,0 +1,171 @@+//+// detail/win_iocp_overlapped_ptr.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_OVERLAPPED_PTR_HPP+#define ASIO_DETAIL_WIN_IOCP_OVERLAPPED_PTR_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_IOCP)++#include "asio/io_context.hpp"+#include "asio/query.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/win_iocp_overlapped_op.hpp"+#include "asio/detail/win_iocp_io_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Wraps a handler to create an OVERLAPPED object for use with overlapped I/O.+class win_iocp_overlapped_ptr+  : private noncopyable+{+public:+  // Construct an empty win_iocp_overlapped_ptr.+  win_iocp_overlapped_ptr()+    : ptr_(0),+      iocp_service_(0)+  {+  }++  // Construct an win_iocp_overlapped_ptr to contain the specified handler.+  template <typename Executor, typename Handler>+  explicit win_iocp_overlapped_ptr(const Executor& ex,+      ASIO_MOVE_ARG(Handler) handler)+    : ptr_(0),+      iocp_service_(0)+  {+    this->reset(ex, ASIO_MOVE_CAST(Handler)(handler));+  }++  // Destructor automatically frees the OVERLAPPED object unless released.+  ~win_iocp_overlapped_ptr()+  {+    reset();+  }++  // Reset to empty.+  void reset()+  {+    if (ptr_)+    {+      ptr_->destroy();+      ptr_ = 0;+      iocp_service_->work_finished();+      iocp_service_ = 0;+    }+  }++  // Reset to contain the specified handler, freeing any current OVERLAPPED+  // object.+  template <typename Executor, typename Handler>+  void reset(const Executor& ex, Handler handler)+  {+    win_iocp_io_context* iocp_service = this->get_iocp_service(ex);++    typedef win_iocp_overlapped_op<Handler, Executor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(handler, ex);++    ASIO_HANDLER_CREATION((ex.context(), *p.p,+          "iocp_service", iocp_service, 0, "overlapped"));++    iocp_service->work_started();+    reset();+    ptr_ = p.p;+    p.v = p.p = 0;+    iocp_service_ = iocp_service;+  }++  // Get the contained OVERLAPPED object.+  OVERLAPPED* get()+  {+    return ptr_;+  }++  // Get the contained OVERLAPPED object.+  const OVERLAPPED* get() const+  {+    return ptr_;+  }++  // Release ownership of the OVERLAPPED object.+  OVERLAPPED* release()+  {+    if (ptr_)+      iocp_service_->on_pending(ptr_);++    OVERLAPPED* tmp = ptr_;+    ptr_ = 0;+    iocp_service_ = 0;+    return tmp;+  }++  // Post completion notification for overlapped operation. Releases ownership.+  void complete(const asio::error_code& ec,+      std::size_t bytes_transferred)+  {+    if (ptr_)+    {+      iocp_service_->on_completion(ptr_, ec,+          static_cast<DWORD>(bytes_transferred));+      ptr_ = 0;+      iocp_service_ = 0;+    }+  }++private:+  template <typename Executor>+  static win_iocp_io_context* get_iocp_service(const Executor& ex,+      typename enable_if<+        can_query<const Executor&, execution::context_t>::value+      >::type* = 0)+  {+    return &use_service<win_iocp_io_context>(+        asio::query(ex, execution::context));+  }++  template <typename Executor>+  static win_iocp_io_context* get_iocp_service(const Executor& ex,+      typename enable_if<+        !can_query<const Executor&, execution::context_t>::value+      >::type* = 0)+  {+    return &use_service<win_iocp_io_context>(ex.context());+  }++  static win_iocp_io_context* get_iocp_service(+      const io_context::executor_type& ex)+  {+    return &asio::query(ex, execution::context).impl_;+  }++  win_iocp_operation* ptr_;+  win_iocp_io_context* iocp_service_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_OVERLAPPED_PTR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_serial_port_service.hpp view
@@ -0,0 +1,232 @@+//+// detail/win_iocp_serial_port_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP+#define ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_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_IOCP) && defined(ASIO_HAS_SERIAL_PORT)++#include <string>+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/win_iocp_handle_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Extend win_iocp_handle_service to provide serial port support.+class win_iocp_serial_port_service :+  public execution_context_service_base<win_iocp_serial_port_service>+{+public:+  // The native type of a serial port.+  typedef win_iocp_handle_service::native_handle_type native_handle_type;++  // The implementation type of the serial port.+  typedef win_iocp_handle_service::implementation_type implementation_type;++  // Constructor.+  ASIO_DECL win_iocp_serial_port_service(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Construct a new serial port implementation.+  void construct(implementation_type& impl)+  {+    handle_service_.construct(impl);+  }++  // Move-construct a new serial port implementation.+  void move_construct(implementation_type& impl,+      implementation_type& other_impl)+  {+    handle_service_.move_construct(impl, other_impl);+  }++  // Move-assign from another serial port implementation.+  void move_assign(implementation_type& impl,+      win_iocp_serial_port_service& other_service,+      implementation_type& other_impl)+  {+    handle_service_.move_assign(impl,+        other_service.handle_service_, other_impl);+  }++  // Destroy a serial port implementation.+  void destroy(implementation_type& impl)+  {+    handle_service_.destroy(impl);+  }++  // Open the serial port using the specified device name.+  ASIO_DECL asio::error_code open(implementation_type& impl,+      const std::string& device, asio::error_code& ec);++  // Assign a native handle to a serial port implementation.+  asio::error_code assign(implementation_type& impl,+      const native_handle_type& handle, asio::error_code& ec)+  {+    return handle_service_.assign(impl, handle, ec);+  }++  // Determine whether the serial port is open.+  bool is_open(const implementation_type& impl) const+  {+    return handle_service_.is_open(impl);+  }++  // Destroy a serial port implementation.+  asio::error_code close(implementation_type& impl,+      asio::error_code& ec)+  {+    return handle_service_.close(impl, ec);+  }++  // Get the native serial port representation.+  native_handle_type native_handle(implementation_type& impl)+  {+    return handle_service_.native_handle(impl);+  }++  // Cancel all operations associated with the handle.+  asio::error_code cancel(implementation_type& impl,+      asio::error_code& ec)+  {+    return handle_service_.cancel(impl, ec);+  }++  // Set an option on the serial port.+  template <typename SettableSerialPortOption>+  asio::error_code set_option(implementation_type& impl,+      const SettableSerialPortOption& option, asio::error_code& ec)+  {+    return do_set_option(impl,+        &win_iocp_serial_port_service::store_option<SettableSerialPortOption>,+        &option, ec);+  }++  // Get an option from the serial port.+  template <typename GettableSerialPortOption>+  asio::error_code get_option(const implementation_type& impl,+      GettableSerialPortOption& option, asio::error_code& ec) const+  {+    return do_get_option(impl,+        &win_iocp_serial_port_service::load_option<GettableSerialPortOption>,+        &option, ec);+  }++  // Send a break sequence to the serial port.+  asio::error_code send_break(implementation_type&,+      asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Write the given data. Returns the number of bytes sent.+  template <typename ConstBufferSequence>+  size_t write_some(implementation_type& impl,+      const ConstBufferSequence& buffers, asio::error_code& ec)+  {+    return handle_service_.write_some(impl, buffers, ec);+  }++  // Start an asynchronous write. The data being written must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_write_some(implementation_type& impl,+      const ConstBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    handle_service_.async_write_some(impl, buffers, handler, io_ex);+  }++  // Read some data. Returns the number of bytes received.+  template <typename MutableBufferSequence>+  size_t read_some(implementation_type& impl,+      const MutableBufferSequence& buffers, asio::error_code& ec)+  {+    return handle_service_.read_some(impl, buffers, ec);+  }++  // Start an asynchronous read. The buffer for the data being received must be+  // valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_read_some(implementation_type& impl,+      const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    handle_service_.async_read_some(impl, buffers, handler, io_ex);+  }++private:+  // Function pointer type for storing a serial port option.+  typedef asio::error_code (*store_function_type)(+      const void*, ::DCB&, asio::error_code&);++  // Helper function template to store a serial port option.+  template <typename SettableSerialPortOption>+  static asio::error_code store_option(const void* option,+      ::DCB& storage, asio::error_code& ec)+  {+    static_cast<const SettableSerialPortOption*>(option)->store(storage, ec);+    return ec;+  }++  // Helper function to set a serial port option.+  ASIO_DECL asio::error_code do_set_option(+      implementation_type& impl, store_function_type store,+      const void* option, asio::error_code& ec);++  // Function pointer type for loading a serial port option.+  typedef asio::error_code (*load_function_type)(+      void*, const ::DCB&, asio::error_code&);++  // Helper function template to load a serial port option.+  template <typename GettableSerialPortOption>+  static asio::error_code load_option(void* option,+      const ::DCB& storage, asio::error_code& ec)+  {+    static_cast<GettableSerialPortOption*>(option)->load(storage, ec);+    return ec;+  }++  // Helper function to get a serial port option.+  ASIO_DECL asio::error_code do_get_option(+      const implementation_type& impl, load_function_type load,+      void* option, asio::error_code& ec) const;++  // The implementation used for initiating asynchronous operations.+  win_iocp_handle_service handle_service_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_iocp_serial_port_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_SERIAL_PORT)++#endif // ASIO_DETAIL_WIN_IOCP_SERIAL_PORT_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_accept_op.hpp view
@@ -0,0 +1,312 @@+//+// detail/win_iocp_socket_accept_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/operation.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/win_iocp_socket_service_base.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Socket, typename Protocol,+    typename Handler, typename IoExecutor>+class win_iocp_socket_accept_op : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_accept_op);++  win_iocp_socket_accept_op(win_iocp_socket_service_base& socket_service,+      socket_type socket, Socket& peer, const Protocol& protocol,+      typename Protocol::endpoint* peer_endpoint,+      bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex)+    : operation(&win_iocp_socket_accept_op::do_complete),+      socket_service_(socket_service),+      socket_(socket),+      peer_(peer),+      protocol_(protocol),+      peer_endpoint_(peer_endpoint),+      enable_connection_aborted_(enable_connection_aborted),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  socket_holder& new_socket()+  {+    return new_socket_;+  }++  void* output_buffer()+  {+    return output_buffer_;+  }++  DWORD address_length()+  {+    return sizeof(sockaddr_storage_type) + 16;+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t /*bytes_transferred*/)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    if (owner)+    {+      typename Protocol::endpoint peer_endpoint;+      std::size_t addr_len = peer_endpoint.capacity();+      socket_ops::complete_iocp_accept(o->socket_,+          o->output_buffer(), o->address_length(),+          peer_endpoint.data(), &addr_len,+          o->new_socket_.get(), ec);++      // Restart the accept operation if we got the connection_aborted error+      // and the enable_connection_aborted socket option is not set.+      if (ec == asio::error::connection_aborted+          && !o->enable_connection_aborted_)+      {+        o->reset();+        o->socket_service_.restart_accept_op(o->socket_,+            o->new_socket_, o->protocol_.family(),+            o->protocol_.type(), o->protocol_.protocol(),+            o->output_buffer(), o->address_length(), o);+        p.v = p.p = 0;+        return;+      }++      // If the socket was successfully accepted, transfer ownership of the+      // socket to the peer object.+      if (!ec)+      {+        o->peer_.assign(o->protocol_,+            typename Socket::native_handle_type(+              o->new_socket_.get(), peer_endpoint), ec);+        if (!ec)+          o->new_socket_.release();+      }++      // Pass endpoint back to caller.+      if (o->peer_endpoint_)+        *o->peer_endpoint_ = peer_endpoint;+    }++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder1<Handler, asio::error_code>+      handler(o->handler_, ec);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  win_iocp_socket_service_base& socket_service_;+  socket_type socket_;+  socket_holder new_socket_;+  Socket& peer_;+  Protocol protocol_;+  typename Protocol::endpoint* peer_endpoint_;+  unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];+  bool enable_connection_aborted_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++#if defined(ASIO_HAS_MOVE)++template <typename Protocol, typename PeerIoExecutor,+    typename Handler, typename IoExecutor>+class win_iocp_socket_move_accept_op : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_move_accept_op);++  win_iocp_socket_move_accept_op(+      win_iocp_socket_service_base& socket_service, socket_type socket,+      const Protocol& protocol, const PeerIoExecutor& peer_io_ex,+      typename Protocol::endpoint* peer_endpoint,+      bool enable_connection_aborted, Handler& handler, const IoExecutor& io_ex)+    : operation(&win_iocp_socket_move_accept_op::do_complete),+      socket_service_(socket_service),+      socket_(socket),+      peer_(peer_io_ex),+      protocol_(protocol),+      peer_endpoint_(peer_endpoint),+      enable_connection_aborted_(enable_connection_aborted),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  socket_holder& new_socket()+  {+    return new_socket_;+  }++  void* output_buffer()+  {+    return output_buffer_;+  }++  DWORD address_length()+  {+    return sizeof(sockaddr_storage_type) + 16;+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t /*bytes_transferred*/)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_socket_move_accept_op* o(+        static_cast<win_iocp_socket_move_accept_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    if (owner)+    {+      typename Protocol::endpoint peer_endpoint;+      std::size_t addr_len = peer_endpoint.capacity();+      socket_ops::complete_iocp_accept(o->socket_,+          o->output_buffer(), o->address_length(),+          peer_endpoint.data(), &addr_len,+          o->new_socket_.get(), ec);++      // Restart the accept operation if we got the connection_aborted error+      // and the enable_connection_aborted socket option is not set.+      if (ec == asio::error::connection_aborted+          && !o->enable_connection_aborted_)+      {+        o->reset();+        o->socket_service_.restart_accept_op(o->socket_,+            o->new_socket_, o->protocol_.family(),+            o->protocol_.type(), o->protocol_.protocol(),+            o->output_buffer(), o->address_length(), o);+        p.v = p.p = 0;+        return;+      }++      // If the socket was successfully accepted, transfer ownership of the+      // socket to the peer object.+      if (!ec)+      {+        o->peer_.assign(o->protocol_,+            typename Protocol::socket::native_handle_type(+              o->new_socket_.get(), peer_endpoint), ec);+        if (!ec)+          o->new_socket_.release();+      }++      // Pass endpoint back to caller.+      if (o->peer_endpoint_)+        *o->peer_endpoint_ = peer_endpoint;+    }++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::move_binder2<Handler,+      asio::error_code, peer_socket_type>+        handler(0, ASIO_MOVE_CAST(Handler)(o->handler_), ec,+          ASIO_MOVE_CAST(peer_socket_type)(o->peer_));+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  typedef typename Protocol::socket::template+    rebind_executor<PeerIoExecutor>::other peer_socket_type;++  win_iocp_socket_service_base& socket_service_;+  socket_type socket_;+  socket_holder new_socket_;+  peer_socket_type peer_;+  Protocol protocol_;+  typename Protocol::endpoint* peer_endpoint_;+  unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];+  bool enable_connection_aborted_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++#endif // defined(ASIO_HAS_MOVE)++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_ACCEPT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_connect_op.hpp view
@@ -0,0 +1,135 @@+//+// detail/win_iocp_socket_connect_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_CONNECT_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_SOCKET_CONNECT_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class win_iocp_socket_connect_op_base : public reactor_op+{+public:+  win_iocp_socket_connect_op_base(socket_type socket, func_type complete_func)+    : reactor_op(asio::error_code(),+        &win_iocp_socket_connect_op_base::do_perform, complete_func),+      socket_(socket),+      connect_ex_(false)+  {+  }++  static status do_perform(reactor_op* base)+  {+    win_iocp_socket_connect_op_base* o(+        static_cast<win_iocp_socket_connect_op_base*>(base));++    return socket_ops::non_blocking_connect(+        o->socket_, o->ec_) ? done : not_done;+  }++  socket_type socket_;+  bool connect_ex_;+};++template <typename Handler, typename IoExecutor>+class win_iocp_socket_connect_op : public win_iocp_socket_connect_op_base+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_connect_op);++  win_iocp_socket_connect_op(socket_type socket,+      Handler& handler, const IoExecutor& io_ex)+    : win_iocp_socket_connect_op_base(socket,+        &win_iocp_socket_connect_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t /*bytes_transferred*/)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_socket_connect_op* o(+        static_cast<win_iocp_socket_connect_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    if (owner)+    {+      if (o->connect_ex_)+        socket_ops::complete_iocp_connect(o->socket_, ec);+      else+        ec = o->ec_;+    }++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder1<Handler, asio::error_code>+      handler(o->handler_, ec);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_CONNECT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recv_op.hpp view
@@ -0,0 +1,124 @@+//+// detail/win_iocp_socket_recv_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_RECV_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_SOCKET_RECV_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/operation.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class win_iocp_socket_recv_op : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_recv_op);++  win_iocp_socket_recv_op(socket_ops::state_type state,+      socket_ops::weak_cancel_token_type cancel_token,+      const MutableBufferSequence& buffers, Handler& handler,+      const IoExecutor& io_ex)+    : operation(&win_iocp_socket_recv_op::do_complete),+      state_(state),+      cancel_token_(cancel_token),+      buffers_(buffers),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t bytes_transferred)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    // Check whether buffers are still valid.+    if (owner)+    {+      buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::validate(o->buffers_);+    }+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++    socket_ops::complete_iocp_recv(o->state_, o->cancel_token_,+        buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::all_empty(o->buffers_),+        ec, bytes_transferred);++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, ec, bytes_transferred);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  socket_ops::state_type state_;+  socket_ops::weak_cancel_token_type cancel_token_;+  MutableBufferSequence buffers_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_RECV_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp view
@@ -0,0 +1,133 @@+//+// detail/win_iocp_socket_recvfrom_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_RECVFROM_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_SOCKET_RECVFROM_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/operation.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence, typename Endpoint,+    typename Handler, typename IoExecutor>+class win_iocp_socket_recvfrom_op : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_recvfrom_op);++  win_iocp_socket_recvfrom_op(Endpoint& endpoint,+      socket_ops::weak_cancel_token_type cancel_token,+      const MutableBufferSequence& buffers, Handler& handler,+      const IoExecutor& io_ex)+    : operation(&win_iocp_socket_recvfrom_op::do_complete),+      endpoint_(endpoint),+      endpoint_size_(static_cast<int>(endpoint.capacity())),+      cancel_token_(cancel_token),+      buffers_(buffers),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  int& endpoint_size()+  {+    return endpoint_size_;+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t bytes_transferred)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_socket_recvfrom_op* o(+        static_cast<win_iocp_socket_recvfrom_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    // Check whether buffers are still valid.+    if (owner)+    {+      buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::validate(o->buffers_);+    }+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++    socket_ops::complete_iocp_recvfrom(o->cancel_token_, ec);++    // Record the size of the endpoint returned by the operation.+    o->endpoint_.resize(o->endpoint_size_);++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, ec, bytes_transferred);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Endpoint& endpoint_;+  int endpoint_size_;+  socket_ops::weak_cancel_token_type cancel_token_;+  MutableBufferSequence buffers_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_RECVFROM_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp view
@@ -0,0 +1,125 @@+//+// detail/win_iocp_socket_recvmsg_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_RECVMSG_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_SOCKET_RECVMSG_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/operation.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"+#include "asio/socket_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class win_iocp_socket_recvmsg_op : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_recvmsg_op);++  win_iocp_socket_recvmsg_op(+      socket_ops::weak_cancel_token_type cancel_token,+      const MutableBufferSequence& buffers,+      socket_base::message_flags& out_flags,+      Handler& handler, const IoExecutor& io_ex)+    : operation(&win_iocp_socket_recvmsg_op::do_complete),+      cancel_token_(cancel_token),+      buffers_(buffers),+      out_flags_(out_flags),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t bytes_transferred)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_socket_recvmsg_op* o(+        static_cast<win_iocp_socket_recvmsg_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    // Check whether buffers are still valid.+    if (owner)+    {+      buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::validate(o->buffers_);+    }+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++    socket_ops::complete_iocp_recvmsg(o->cancel_token_, ec);+    o->out_flags_ = 0;++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, ec, bytes_transferred);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  socket_ops::weak_cancel_token_type cancel_token_;+  MutableBufferSequence buffers_;+  socket_base::message_flags& out_flags_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_RECVMSG_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_send_op.hpp view
@@ -0,0 +1,118 @@+//+// detail/win_iocp_socket_send_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_SEND_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_SOCKET_SEND_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/operation.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class win_iocp_socket_send_op : public operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_socket_send_op);++  win_iocp_socket_send_op(socket_ops::weak_cancel_token_type cancel_token,+      const ConstBufferSequence& buffers, Handler& handler,+      const IoExecutor& io_ex)+    : operation(&win_iocp_socket_send_op::do_complete),+      cancel_token_(cancel_token),+      buffers_(buffers),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t bytes_transferred)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    // Check whether buffers are still valid.+    if (owner)+    {+      buffer_sequence_adapter<asio::const_buffer,+          ConstBufferSequence>::validate(o->buffers_);+    }+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++    socket_ops::complete_iocp_send(o->cancel_token_, ec);++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, ec, bytes_transferred);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  socket_ops::weak_cancel_token_type cancel_token_;+  ConstBufferSequence buffers_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SEND_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service.hpp view
@@ -0,0 +1,581 @@+//+// detail/win_iocp_socket_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP+#define ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_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_IOCP)++#include <cstring>+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/socket_base.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/operation.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/select_reactor.hpp"+#include "asio/detail/socket_holder.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/win_iocp_io_context.hpp"+#include "asio/detail/win_iocp_null_buffers_op.hpp"+#include "asio/detail/win_iocp_socket_accept_op.hpp"+#include "asio/detail/win_iocp_socket_connect_op.hpp"+#include "asio/detail/win_iocp_socket_recvfrom_op.hpp"+#include "asio/detail/win_iocp_socket_send_op.hpp"+#include "asio/detail/win_iocp_socket_service_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol>+class win_iocp_socket_service :+  public execution_context_service_base<win_iocp_socket_service<Protocol> >,+  public win_iocp_socket_service_base+{+public:+  // The protocol type.+  typedef Protocol protocol_type;++  // The endpoint type.+  typedef typename Protocol::endpoint endpoint_type;++  // The native type of a socket.+  class native_handle_type+  {+  public:+    native_handle_type(socket_type s)+      : socket_(s),+        have_remote_endpoint_(false)+    {+    }++    native_handle_type(socket_type s, const endpoint_type& ep)+      : socket_(s),+        have_remote_endpoint_(true),+        remote_endpoint_(ep)+    {+    }++    void operator=(socket_type s)+    {+      socket_ = s;+      have_remote_endpoint_ = false;+      remote_endpoint_ = endpoint_type();+    }++    operator socket_type() const+    {+      return socket_;+    }++    bool have_remote_endpoint() const+    {+      return have_remote_endpoint_;+    }++    endpoint_type remote_endpoint() const+    {+      return remote_endpoint_;+    }++  private:+    socket_type socket_;+    bool have_remote_endpoint_;+    endpoint_type remote_endpoint_;+  };++  // The implementation type of the socket.+  struct implementation_type :+    win_iocp_socket_service_base::base_implementation_type+  {+    // Default constructor.+    implementation_type()+      : protocol_(endpoint_type().protocol()),+        have_remote_endpoint_(false),+        remote_endpoint_()+    {+    }++    // The protocol associated with the socket.+    protocol_type protocol_;++    // Whether we have a cached remote endpoint.+    bool have_remote_endpoint_;++    // A cached remote endpoint.+    endpoint_type remote_endpoint_;+  };++  // Constructor.+  win_iocp_socket_service(execution_context& context)+    : execution_context_service_base<+        win_iocp_socket_service<Protocol> >(context),+      win_iocp_socket_service_base(context)+  {+  }++  // Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+    this->base_shutdown();+  }++  // Move-construct a new socket implementation.+  void move_construct(implementation_type& impl,+      implementation_type& other_impl) ASIO_NOEXCEPT+  {+    this->base_move_construct(impl, other_impl);++    impl.protocol_ = other_impl.protocol_;+    other_impl.protocol_ = endpoint_type().protocol();++    impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;+    other_impl.have_remote_endpoint_ = false;++    impl.remote_endpoint_ = other_impl.remote_endpoint_;+    other_impl.remote_endpoint_ = endpoint_type();+  }++  // Move-assign from another socket implementation.+  void move_assign(implementation_type& impl,+      win_iocp_socket_service_base& other_service,+      implementation_type& other_impl)+  {+    this->base_move_assign(impl, other_service, other_impl);++    impl.protocol_ = other_impl.protocol_;+    other_impl.protocol_ = endpoint_type().protocol();++    impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;+    other_impl.have_remote_endpoint_ = false;++    impl.remote_endpoint_ = other_impl.remote_endpoint_;+    other_impl.remote_endpoint_ = endpoint_type();+  }++  // Move-construct a new socket implementation from another protocol type.+  template <typename Protocol1>+  void converting_move_construct(implementation_type& impl,+      win_iocp_socket_service<Protocol1>&,+      typename win_iocp_socket_service<+        Protocol1>::implementation_type& other_impl)+  {+    this->base_move_construct(impl, other_impl);++    impl.protocol_ = protocol_type(other_impl.protocol_);+    other_impl.protocol_ = typename Protocol1::endpoint().protocol();++    impl.have_remote_endpoint_ = other_impl.have_remote_endpoint_;+    other_impl.have_remote_endpoint_ = false;++    impl.remote_endpoint_ = other_impl.remote_endpoint_;+    other_impl.remote_endpoint_ = typename Protocol1::endpoint();+  }++  // Open a new socket implementation.+  asio::error_code open(implementation_type& impl,+      const protocol_type& protocol, asio::error_code& ec)+  {+    if (!do_open(impl, protocol.family(),+          protocol.type(), protocol.protocol(), ec))+    {+      impl.protocol_ = protocol;+      impl.have_remote_endpoint_ = false;+      impl.remote_endpoint_ = endpoint_type();+    }+    return ec;+  }++  // Assign a native socket to a socket implementation.+  asio::error_code assign(implementation_type& impl,+      const protocol_type& protocol, const native_handle_type& native_socket,+      asio::error_code& ec)+  {+    if (!do_assign(impl, protocol.type(), native_socket, ec))+    {+      impl.protocol_ = protocol;+      impl.have_remote_endpoint_ = native_socket.have_remote_endpoint();+      impl.remote_endpoint_ = native_socket.remote_endpoint();+    }+    return ec;+  }++  // Get the native socket representation.+  native_handle_type native_handle(implementation_type& impl)+  {+    if (impl.have_remote_endpoint_)+      return native_handle_type(impl.socket_, impl.remote_endpoint_);+    return native_handle_type(impl.socket_);+  }++  // Bind the socket to the specified local endpoint.+  asio::error_code bind(implementation_type& impl,+      const endpoint_type& endpoint, asio::error_code& ec)+  {+    socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);+    return ec;+  }++  // Set a socket option.+  template <typename Option>+  asio::error_code set_option(implementation_type& impl,+      const Option& option, asio::error_code& ec)+  {+    socket_ops::setsockopt(impl.socket_, impl.state_,+        option.level(impl.protocol_), option.name(impl.protocol_),+        option.data(impl.protocol_), option.size(impl.protocol_), ec);+    return ec;+  }++  // Set a socket option.+  template <typename Option>+  asio::error_code get_option(const implementation_type& impl,+      Option& option, asio::error_code& ec) const+  {+    std::size_t size = option.size(impl.protocol_);+    socket_ops::getsockopt(impl.socket_, impl.state_,+        option.level(impl.protocol_), option.name(impl.protocol_),+        option.data(impl.protocol_), &size, ec);+    if (!ec)+      option.resize(impl.protocol_, size);+    return ec;+  }++  // Get the local endpoint.+  endpoint_type local_endpoint(const implementation_type& impl,+      asio::error_code& ec) const+  {+    endpoint_type endpoint;+    std::size_t addr_len = endpoint.capacity();+    if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))+      return endpoint_type();+    endpoint.resize(addr_len);+    return endpoint;+  }++  // Get the remote endpoint.+  endpoint_type remote_endpoint(const implementation_type& impl,+      asio::error_code& ec) const+  {+    endpoint_type endpoint = impl.remote_endpoint_;+    std::size_t addr_len = endpoint.capacity();+    if (socket_ops::getpeername(impl.socket_, endpoint.data(),+          &addr_len, impl.have_remote_endpoint_, ec))+      return endpoint_type();+    endpoint.resize(addr_len);+    return endpoint;+  }++  // Disable sends or receives on the socket.+  asio::error_code shutdown(base_implementation_type& impl,+      socket_base::shutdown_type what, asio::error_code& ec)+  {+    socket_ops::shutdown(impl.socket_, what, ec);+    return ec;+  }++  // Send a datagram to the specified endpoint. Returns the number of bytes+  // sent.+  template <typename ConstBufferSequence>+  size_t send_to(implementation_type& impl, const ConstBufferSequence& buffers,+      const endpoint_type& destination, socket_base::message_flags flags,+      asio::error_code& ec)+  {+    buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs(buffers);++    return socket_ops::sync_sendto(impl.socket_, impl.state_,+        bufs.buffers(), bufs.count(), flags,+        destination.data(), destination.size(), ec);+  }++  // Wait until data can be sent without blocking.+  size_t send_to(implementation_type& impl, const null_buffers&,+      const endpoint_type&, socket_base::message_flags,+      asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);++    return 0;+  }++  // Start an asynchronous send. The data being sent must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_send_to(implementation_type& impl,+      const ConstBufferSequence& buffers, const endpoint_type& destination,+      socket_base::message_flags flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_socket_send_op<+        ConstBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_send_to"));++    buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs(buffers);++    start_send_to_op(impl, bufs.buffers(), bufs.count(),+        destination.data(), static_cast<int>(destination.size()),+        flags, p.p);+    p.v = p.p = 0;+  }++  // Start an asynchronous wait until data can be sent without blocking.+  template <typename Handler, typename IoExecutor>+  void async_send_to(implementation_type& impl, const null_buffers&,+      const endpoint_type&, socket_base::message_flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_send_to(null_buffers)"));++    start_reactor_op(impl, select_reactor::write_op, p.p);+    p.v = p.p = 0;+  }++  // Receive a datagram with the endpoint of the sender. Returns the number of+  // bytes received.+  template <typename MutableBufferSequence>+  size_t receive_from(implementation_type& impl,+      const MutableBufferSequence& buffers,+      endpoint_type& sender_endpoint, socket_base::message_flags flags,+      asio::error_code& ec)+  {+    buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs(buffers);++    std::size_t addr_len = sender_endpoint.capacity();+    std::size_t bytes_recvd = socket_ops::sync_recvfrom(+        impl.socket_, impl.state_, bufs.buffers(), bufs.count(),+        flags, sender_endpoint.data(), &addr_len, ec);++    if (!ec)+      sender_endpoint.resize(addr_len);++    return bytes_recvd;+  }++  // Wait until data can be received without blocking.+  size_t receive_from(implementation_type& impl,+      const null_buffers&, endpoint_type& sender_endpoint,+      socket_base::message_flags, asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);++    // Reset endpoint since it can be given no sensible value at this time.+    sender_endpoint = endpoint_type();++    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received and+  // the sender_endpoint object must both be valid for the lifetime of the+  // asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive_from(implementation_type& impl,+      const MutableBufferSequence& buffers, endpoint_type& sender_endp,+      socket_base::message_flags flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_socket_recvfrom_op<MutableBufferSequence,+        endpoint_type, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(sender_endp, impl.cancel_token_,+        buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_receive_from"));++    buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs(buffers);++    start_receive_from_op(impl, bufs.buffers(), bufs.count(),+        sender_endp.data(), flags, &p.p->endpoint_size(), p.p);+    p.v = p.p = 0;+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive_from(implementation_type& impl, const null_buffers&,+      endpoint_type& sender_endpoint, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_receive_from(null_buffers)"));++    // Reset endpoint since it can be given no sensible value at this time.+    sender_endpoint = endpoint_type();++    start_null_buffers_receive_op(impl, flags, p.p);+    p.v = p.p = 0;+  }++  // Accept a new connection.+  template <typename Socket>+  asio::error_code accept(implementation_type& impl, Socket& peer,+      endpoint_type* peer_endpoint, asio::error_code& ec)+  {+    // We cannot accept a socket that is already open.+    if (peer.is_open())+    {+      ec = asio::error::already_open;+      return ec;+    }++    std::size_t addr_len = peer_endpoint ? peer_endpoint->capacity() : 0;+    socket_holder new_socket(socket_ops::sync_accept(impl.socket_,+          impl.state_, peer_endpoint ? peer_endpoint->data() : 0,+          peer_endpoint ? &addr_len : 0, ec));++    // On success, assign new connection to peer socket object.+    if (new_socket.get() != invalid_socket)+    {+      if (peer_endpoint)+        peer_endpoint->resize(addr_len);+      peer.assign(impl.protocol_, new_socket.get(), ec);+      if (!ec)+        new_socket.release();+    }++    return ec;+  }++  // Start an asynchronous accept. The peer and peer_endpoint objects+  // must be valid until the accept's handler is invoked.+  template <typename Socket, typename Handler, typename IoExecutor>+  void async_accept(implementation_type& impl, Socket& peer,+      endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_socket_accept_op<Socket,+        protocol_type, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    bool enable_connection_aborted =+      (impl.state_ & socket_ops::enable_connection_aborted) != 0;+    p.p = new (p.v) op(*this, impl.socket_, peer, impl.protocol_,+        peer_endpoint, enable_connection_aborted, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_accept"));++    start_accept_op(impl, peer.is_open(), p.p->new_socket(),+        impl.protocol_.family(), impl.protocol_.type(),+        impl.protocol_.protocol(), p.p->output_buffer(),+        p.p->address_length(), p.p);+    p.v = p.p = 0;+  }++#if defined(ASIO_HAS_MOVE)+  // Start an asynchronous accept. The peer and peer_endpoint objects+  // must be valid until the accept's handler is invoked.+  template <typename PeerIoExecutor, typename Handler, typename IoExecutor>+  void async_move_accept(implementation_type& impl,+      const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_socket_move_accept_op<+        protocol_type, PeerIoExecutor, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    bool enable_connection_aborted =+      (impl.state_ & socket_ops::enable_connection_aborted) != 0;+    p.p = new (p.v) op(*this, impl.socket_, impl.protocol_,+        peer_io_ex, peer_endpoint, enable_connection_aborted,+        handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_accept"));++    start_accept_op(impl, false, p.p->new_socket(),+        impl.protocol_.family(), impl.protocol_.type(),+        impl.protocol_.protocol(), p.p->output_buffer(),+        p.p->address_length(), p.p);+    p.v = p.p = 0;+  }+#endif // defined(ASIO_HAS_MOVE)++  // Connect the socket to the specified endpoint.+  asio::error_code connect(implementation_type& impl,+      const endpoint_type& peer_endpoint, asio::error_code& ec)+  {+    socket_ops::sync_connect(impl.socket_,+        peer_endpoint.data(), peer_endpoint.size(), ec);+    return ec;+  }++  // Start an asynchronous connect.+  template <typename Handler, typename IoExecutor>+  void async_connect(implementation_type& impl,+      const endpoint_type& peer_endpoint, Handler& handler,+      const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_socket_connect_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.socket_, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_connect"));++    start_connect_op(impl, impl.protocol_.family(), impl.protocol_.type(),+        peer_endpoint.data(), static_cast<int>(peer_endpoint.size()), p.p);+    p.v = p.p = 0;+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service_base.hpp view
@@ -0,0 +1,600 @@+//+// detail/win_iocp_socket_service_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP+#define ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_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_IOCP)++#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/socket_base.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/operation.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/select_reactor.hpp"+#include "asio/detail/socket_holder.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/win_iocp_io_context.hpp"+#include "asio/detail/win_iocp_null_buffers_op.hpp"+#include "asio/detail/win_iocp_socket_connect_op.hpp"+#include "asio/detail/win_iocp_socket_send_op.hpp"+#include "asio/detail/win_iocp_socket_recv_op.hpp"+#include "asio/detail/win_iocp_socket_recvmsg_op.hpp"+#include "asio/detail/win_iocp_wait_op.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class win_iocp_socket_service_base+{+public:+  // The implementation type of the socket.+  struct base_implementation_type+  {+    // The native socket representation.+    socket_type socket_;++    // The current state of the socket.+    socket_ops::state_type state_;++    // We use a shared pointer as a cancellation token here to work around the+    // broken Windows support for cancellation. MSDN says that when you call+    // closesocket any outstanding WSARecv or WSASend operations will complete+    // with the error ERROR_OPERATION_ABORTED. In practice they complete with+    // ERROR_NETNAME_DELETED, which means you can't tell the difference between+    // a local cancellation and the socket being hard-closed by the peer.+    socket_ops::shared_cancel_token_type cancel_token_;++    // Per-descriptor data used by the reactor.+    select_reactor::per_descriptor_data reactor_data_;++#if defined(ASIO_ENABLE_CANCELIO)+    // The ID of the thread from which it is safe to cancel asynchronous+    // operations. 0 means no asynchronous operations have been started yet.+    // ~0 means asynchronous operations have been started from more than one+    // thread, and cancellation is not supported for the socket.+    DWORD safe_cancellation_thread_id_;+#endif // defined(ASIO_ENABLE_CANCELIO)++    // Pointers to adjacent socket implementations in linked list.+    base_implementation_type* next_;+    base_implementation_type* prev_;+  };++  // Constructor.+  ASIO_DECL win_iocp_socket_service_base(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void base_shutdown();++  // Construct a new socket implementation.+  ASIO_DECL void construct(base_implementation_type& impl);++  // Move-construct a new socket implementation.+  ASIO_DECL void base_move_construct(base_implementation_type& impl,+      base_implementation_type& other_impl) ASIO_NOEXCEPT;++  // Move-assign from another socket implementation.+  ASIO_DECL void base_move_assign(base_implementation_type& impl,+      win_iocp_socket_service_base& other_service,+      base_implementation_type& other_impl);++  // Destroy a socket implementation.+  ASIO_DECL void destroy(base_implementation_type& impl);++  // Determine whether the socket is open.+  bool is_open(const base_implementation_type& impl) const+  {+    return impl.socket_ != invalid_socket;+  }++  // Destroy a socket implementation.+  ASIO_DECL asio::error_code close(+      base_implementation_type& impl, asio::error_code& ec);++  // Release ownership of the socket.+  ASIO_DECL socket_type release(+      base_implementation_type& impl, asio::error_code& ec);++  // Cancel all operations associated with the socket.+  ASIO_DECL asio::error_code cancel(+      base_implementation_type& impl, asio::error_code& ec);++  // Determine whether the socket is at the out-of-band data mark.+  bool at_mark(const base_implementation_type& impl,+      asio::error_code& ec) const+  {+    return socket_ops::sockatmark(impl.socket_, ec);+  }++  // Determine the number of bytes available for reading.+  std::size_t available(const base_implementation_type& impl,+      asio::error_code& ec) const+  {+    return socket_ops::available(impl.socket_, ec);+  }++  // Place the socket into the state where it will listen for new connections.+  asio::error_code listen(base_implementation_type& impl,+      int backlog, asio::error_code& ec)+  {+    socket_ops::listen(impl.socket_, backlog, ec);+    return ec;+  }++  // Perform an IO control command on the socket.+  template <typename IO_Control_Command>+  asio::error_code io_control(base_implementation_type& impl,+      IO_Control_Command& command, asio::error_code& ec)+  {+    socket_ops::ioctl(impl.socket_, impl.state_, command.name(),+        static_cast<ioctl_arg_type*>(command.data()), ec);+    return ec;+  }++  // Gets the non-blocking mode of the socket.+  bool non_blocking(const base_implementation_type& impl) const+  {+    return (impl.state_ & socket_ops::user_set_non_blocking) != 0;+  }++  // Sets the non-blocking mode of the socket.+  asio::error_code non_blocking(base_implementation_type& impl,+      bool mode, asio::error_code& ec)+  {+    socket_ops::set_user_non_blocking(impl.socket_, impl.state_, mode, ec);+    return ec;+  }++  // Gets the non-blocking mode of the native socket implementation.+  bool native_non_blocking(const base_implementation_type& impl) const+  {+    return (impl.state_ & socket_ops::internal_non_blocking) != 0;+  }++  // Sets the non-blocking mode of the native socket implementation.+  asio::error_code native_non_blocking(base_implementation_type& impl,+      bool mode, asio::error_code& ec)+  {+    socket_ops::set_internal_non_blocking(impl.socket_, impl.state_, mode, ec);+    return ec;+  }++  // Wait for the socket to become ready to read, ready to write, or to have+  // pending error conditions.+  asio::error_code wait(base_implementation_type& impl,+      socket_base::wait_type w, asio::error_code& ec)+  {+    switch (w)+    {+    case socket_base::wait_read:+      socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);+      break;+    case socket_base::wait_write:+      socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);+      break;+    case socket_base::wait_error:+      socket_ops::poll_error(impl.socket_, impl.state_, -1, ec);+      break;+    default:+      ec = asio::error::invalid_argument;+      break;+    }++    return ec;+  }++  // Asynchronously wait for the socket to become ready to read, ready to+  // write, or to have pending error conditions.+  template <typename Handler, typename IoExecutor>+  void async_wait(base_implementation_type& impl,+      socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_wait_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_wait"));++    switch (w)+    {+      case socket_base::wait_read:+        start_null_buffers_receive_op(impl, 0, p.p);+        break;+      case socket_base::wait_write:+        start_reactor_op(impl, select_reactor::write_op, p.p);+        break;+      case socket_base::wait_error:+        start_reactor_op(impl, select_reactor::except_op, p.p);+        break;+      default:+        p.p->ec_ = asio::error::invalid_argument;+        iocp_service_.post_immediate_completion(p.p, is_continuation);+        break;+    }++    p.v = p.p = 0;+  }++  // Send the given data to the peer. Returns the number of bytes sent.+  template <typename ConstBufferSequence>+  size_t send(base_implementation_type& impl,+      const ConstBufferSequence& buffers,+      socket_base::message_flags flags, asio::error_code& ec)+  {+    buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs(buffers);++    return socket_ops::sync_send(impl.socket_, impl.state_,+        bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);+  }++  // Wait until data can be sent without blocking.+  size_t send(base_implementation_type& impl, const null_buffers&,+      socket_base::message_flags, asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);++    return 0;+  }++  // Start an asynchronous send. The data being sent must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_send(base_implementation_type& impl,+      const ConstBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_socket_send_op<+        ConstBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.cancel_token_, buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_send"));++    buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs(buffers);++    start_send_op(impl, bufs.buffers(), bufs.count(), flags,+        (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),+        p.p);+    p.v = p.p = 0;+  }++  // Start an asynchronous wait until data can be sent without blocking.+  template <typename Handler, typename IoExecutor>+  void async_send(base_implementation_type& impl, const null_buffers&,+      socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_send(null_buffers)"));++    start_reactor_op(impl, select_reactor::write_op, p.p);+    p.v = p.p = 0;+  }++  // Receive some data from the peer. Returns the number of bytes received.+  template <typename MutableBufferSequence>+  size_t receive(base_implementation_type& impl,+      const MutableBufferSequence& buffers,+      socket_base::message_flags flags, asio::error_code& ec)+  {+    buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs(buffers);++    return socket_ops::sync_recv(impl.socket_, impl.state_,+        bufs.buffers(), bufs.count(), flags, bufs.all_empty(), ec);+  }++  // Wait until data can be received without blocking.+  size_t receive(base_implementation_type& impl, const null_buffers&,+      socket_base::message_flags, asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);++    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received+  // must be valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive(base_implementation_type& impl,+      const MutableBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_socket_recv_op<+        MutableBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.state_, impl.cancel_token_,+        buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_receive"));++    buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs(buffers);++    start_receive_op(impl, bufs.buffers(), bufs.count(), flags,+        (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),+        p.p);+    p.v = p.p = 0;+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive(base_implementation_type& impl,+      const null_buffers&, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_receive(null_buffers)"));++    start_null_buffers_receive_op(impl, flags, p.p);+    p.v = p.p = 0;+  }++  // Receive some data with associated flags. Returns the number of bytes+  // received.+  template <typename MutableBufferSequence>+  size_t receive_with_flags(base_implementation_type& impl,+      const MutableBufferSequence& buffers,+      socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags, asio::error_code& ec)+  {+    buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs(buffers);++    return socket_ops::sync_recvmsg(impl.socket_, impl.state_,+        bufs.buffers(), bufs.count(), in_flags, out_flags, ec);+  }++  // Wait until data can be received without blocking.+  size_t receive_with_flags(base_implementation_type& impl,+      const null_buffers&, socket_base::message_flags,+      socket_base::message_flags& out_flags, asio::error_code& ec)+  {+    // Wait for socket to become ready.+    socket_ops::poll_read(impl.socket_, impl.state_, -1, ec);++    // Clear out_flags, since we cannot give it any other sensible value when+    // performing a null_buffers operation.+    out_flags = 0;++    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received+  // must be valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive_with_flags(base_implementation_type& impl,+      const MutableBufferSequence& buffers, socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_socket_recvmsg_op<+        MutableBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.cancel_token_,+        buffers, out_flags, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_receive_with_flags"));++    buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence> bufs(buffers);++    start_receive_op(impl, bufs.buffers(), bufs.count(), in_flags, false, p.p);+    p.v = p.p = 0;+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive_with_flags(base_implementation_type& impl,+      const null_buffers&, socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags, Handler& handler,+      const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef win_iocp_null_buffers_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(impl.cancel_token_, handler, io_ex);++    ASIO_HANDLER_CREATION((context_, *p.p, "socket",+          &impl, impl.socket_, "async_receive_with_flags(null_buffers)"));++    // Reset out_flags since it can be given no sensible value at this time.+    out_flags = 0;++    start_null_buffers_receive_op(impl, in_flags, p.p);+    p.v = p.p = 0;+  }++  // Helper function to restart an asynchronous accept operation.+  ASIO_DECL void restart_accept_op(socket_type s,+      socket_holder& new_socket, int family, int type, int protocol,+      void* output_buffer, DWORD address_length, operation* op);++protected:+  // Open a new socket implementation.+  ASIO_DECL asio::error_code do_open(+      base_implementation_type& impl, int family, int type,+      int protocol, asio::error_code& ec);++  // Assign a native socket to a socket implementation.+  ASIO_DECL asio::error_code do_assign(+      base_implementation_type& impl, int type,+      socket_type native_socket, asio::error_code& ec);++  // Helper function to start an asynchronous send operation.+  ASIO_DECL void start_send_op(base_implementation_type& impl,+      WSABUF* buffers, std::size_t buffer_count,+      socket_base::message_flags flags, bool noop, operation* op);++  // Helper function to start an asynchronous send_to operation.+  ASIO_DECL void start_send_to_op(base_implementation_type& impl,+      WSABUF* buffers, std::size_t buffer_count,+      const socket_addr_type* addr, int addrlen,+      socket_base::message_flags flags, operation* op);++  // Helper function to start an asynchronous receive operation.+  ASIO_DECL void start_receive_op(base_implementation_type& impl,+      WSABUF* buffers, std::size_t buffer_count,+      socket_base::message_flags flags, bool noop, operation* op);++  // Helper function to start an asynchronous null_buffers receive operation.+  ASIO_DECL void start_null_buffers_receive_op(+      base_implementation_type& impl,+      socket_base::message_flags flags, reactor_op* op);++  // Helper function to start an asynchronous receive_from operation.+  ASIO_DECL void start_receive_from_op(base_implementation_type& impl,+      WSABUF* buffers, std::size_t buffer_count, socket_addr_type* addr,+      socket_base::message_flags flags, int* addrlen, operation* op);++  // Helper function to start an asynchronous accept operation.+  ASIO_DECL void start_accept_op(base_implementation_type& impl,+      bool peer_is_open, socket_holder& new_socket, int family, int type,+      int protocol, void* output_buffer, DWORD address_length, operation* op);++  // Start an asynchronous read or write operation using the reactor.+  ASIO_DECL void start_reactor_op(base_implementation_type& impl,+      int op_type, reactor_op* op);++  // Start the asynchronous connect operation using the reactor.+  ASIO_DECL void start_connect_op(base_implementation_type& impl,+      int family, int type, const socket_addr_type* remote_addr,+      std::size_t remote_addrlen, win_iocp_socket_connect_op_base* op);++  // Helper function to close a socket when the associated object is being+  // destroyed.+  ASIO_DECL void close_for_destruction(base_implementation_type& impl);++  // Update the ID of the thread from which cancellation is safe.+  ASIO_DECL void update_cancellation_thread_id(+      base_implementation_type& impl);++  // Helper function to get the reactor. If no reactor has been created yet, a+  // new one is obtained from the execution context and a pointer to it is+  // cached in this service.+  ASIO_DECL select_reactor& get_reactor();++  // The type of a ConnectEx function pointer, as old SDKs may not provide it.+  typedef BOOL (PASCAL *connect_ex_fn)(SOCKET,+      const socket_addr_type*, int, void*, DWORD, DWORD*, OVERLAPPED*);++  // Helper function to get the ConnectEx pointer. If no ConnectEx pointer has+  // been obtained yet, one is obtained using WSAIoctl and the pointer is+  // cached. Returns a null pointer if ConnectEx is not available.+  ASIO_DECL connect_ex_fn get_connect_ex(+      base_implementation_type& impl, int type);++  // The type of a NtSetInformationFile function pointer.+  typedef LONG (NTAPI *nt_set_info_fn)(HANDLE, ULONG_PTR*, void*, ULONG, ULONG);++  // Helper function to get the NtSetInformationFile function pointer. If no+  // NtSetInformationFile pointer has been obtained yet, one is obtained using+  // GetProcAddress and the pointer is cached. Returns a null pointer if+  // NtSetInformationFile is not available.+  ASIO_DECL nt_set_info_fn get_nt_set_info();++  // Helper function to emulate InterlockedCompareExchangePointer functionality+  // for:+  // - very old Platform SDKs; and+  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.+  ASIO_DECL void* interlocked_compare_exchange_pointer(+      void** dest, void* exch, void* cmp);++  // Helper function to emulate InterlockedExchangePointer functionality for:+  // - very old Platform SDKs; and+  // - platform SDKs where MSVC's /Wp64 option causes spurious warnings.+  ASIO_DECL void* interlocked_exchange_pointer(void** dest, void* val);++  // The execution context used to obtain the reactor, if required.+  execution_context& context_;++  // The IOCP service used for running asynchronous operations and dispatching+  // handlers.+  win_iocp_io_context& iocp_service_;++  // The reactor used for performing connect operations. This object is created+  // only if needed.+  select_reactor* reactor_;++  // Pointer to ConnectEx implementation.+  void* connect_ex_;++  // Pointer to NtSetInformationFile implementation.+  void* nt_set_info_;++  // Mutex to protect access to the linked list of implementations. +  asio::detail::mutex mutex_;++  // The head of a linked list of all implementations.+  base_implementation_type* impl_list_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_iocp_socket_service_base.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_SOCKET_SERVICE_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_thread_info.hpp view
@@ -0,0 +1,34 @@+//+// detail/win_iocp_thread_info.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_THREAD_INFO_HPP+#define ASIO_DETAIL_WIN_IOCP_THREAD_INFO_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/thread_info_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct win_iocp_thread_info : public thread_info_base+{+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_WIN_IOCP_THREAD_INFO_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_wait_op.hpp view
@@ -0,0 +1,128 @@+//+// detail/win_iocp_wait_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_IOCP_WAIT_OP_HPP+#define ASIO_DETAIL_WIN_IOCP_WAIT_OP_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_IOCP)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class win_iocp_wait_op : public reactor_op+{+public:+  ASIO_DEFINE_HANDLER_PTR(win_iocp_wait_op);++  win_iocp_wait_op(socket_ops::weak_cancel_token_type cancel_token,+      Handler& handler, const IoExecutor& io_ex)+    : reactor_op(asio::error_code(),+        &win_iocp_wait_op::do_perform,+        &win_iocp_wait_op::do_complete),+      cancel_token_(cancel_token),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static status do_perform(reactor_op*)+  {+    return done;+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& result_ec,+      std::size_t /*bytes_transferred*/)+  {+    asio::error_code ec(result_ec);++    // Take ownership of the operation object.+    win_iocp_wait_op* o(static_cast<win_iocp_wait_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // The reactor may have stored a result in the operation object.+    if (o->ec_)+      ec = o->ec_;++    // Map non-portable errors to their portable counterparts.+    if (ec.value() == ERROR_NETNAME_DELETED)+    {+      if (o->cancel_token_.expired())+        ec = asio::error::operation_aborted;+      else+        ec = asio::error::connection_reset;+    }+    else if (ec.value() == ERROR_PORT_UNREACHABLE)+    {+      ec = asio::error::connection_refused;+    }++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder1<Handler, asio::error_code>+      handler(o->handler_, ec);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  socket_ops::weak_cancel_token_type cancel_token_;+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IOCP)++#endif // ASIO_DETAIL_WIN_IOCP_WAIT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_mutex.hpp view
@@ -0,0 +1,78 @@+//+// detail/win_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_MUTEX_HPP+#define ASIO_DETAIL_WIN_MUTEX_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_WINDOWS)++#include "asio/detail/noncopyable.hpp"+#include "asio/detail/scoped_lock.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class win_mutex+  : private noncopyable+{+public:+  typedef asio::detail::scoped_lock<win_mutex> scoped_lock;++  // Constructor.+  ASIO_DECL win_mutex();++  // Destructor.+  ~win_mutex()+  {+    ::DeleteCriticalSection(&crit_section_);+  }++  // Lock the mutex.+  void lock()+  {+    ::EnterCriticalSection(&crit_section_);+  }++  // Unlock the mutex.+  void unlock()+  {+    ::LeaveCriticalSection(&crit_section_);+  }++private:+  // Initialisation must be performed in a separate function to the constructor+  // since the compiler does not support the use of structured exceptions and+  // C++ exceptions in the same function.+  ASIO_DECL int do_init();++  ::CRITICAL_SECTION crit_section_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_mutex.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_WINDOWS)++#endif // ASIO_DETAIL_WIN_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_object_handle_service.hpp view
@@ -0,0 +1,195 @@+//+// detail/win_object_handle_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2011 Boris Schaeling (boris@highscore.de)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_OBJECT_HANDLE_SERVICE_HPP+#define ASIO_DETAIL_WIN_OBJECT_HANDLE_SERVICE_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_WINDOWS_OBJECT_HANDLE)++#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/wait_handler.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class win_object_handle_service :+  public execution_context_service_base<win_object_handle_service>+{+public:+  // The native type of an object handle.+  typedef HANDLE native_handle_type;++  // The implementation type of the object handle.+  class implementation_type+  {+   public:+    // Default constructor.+    implementation_type()+      : handle_(INVALID_HANDLE_VALUE),+        wait_handle_(INVALID_HANDLE_VALUE),+        owner_(0),+        next_(0),+        prev_(0)+    {+    }++  private:+    // Only this service will have access to the internal values.+    friend class win_object_handle_service;++    // The native object handle representation. May be accessed or modified+    // without locking the mutex.+    native_handle_type handle_;++    // The handle used to unregister the wait operation. The mutex must be+    // locked when accessing or modifying this member.+    HANDLE wait_handle_;++    // The operations waiting on the object handle. If there is a registered+    // wait then the mutex must be locked when accessing or modifying this+    // member+    op_queue<wait_op> op_queue_;++    // The service instance that owns the object handle implementation.+    win_object_handle_service* owner_;++    // Pointers to adjacent handle implementations in linked list. The mutex+    // must be locked when accessing or modifying these members.+    implementation_type* next_;+    implementation_type* prev_;+  };++  // Constructor.+  ASIO_DECL win_object_handle_service(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Construct a new handle implementation.+  ASIO_DECL void construct(implementation_type& impl);++  // Move-construct a new handle implementation.+  ASIO_DECL void move_construct(implementation_type& impl,+      implementation_type& other_impl);++  // Move-assign from another handle implementation.+  ASIO_DECL void move_assign(implementation_type& impl,+      win_object_handle_service& other_service,+      implementation_type& other_impl);++  // Destroy a handle implementation.+  ASIO_DECL void destroy(implementation_type& impl);++  // Assign a native handle to a handle implementation.+  ASIO_DECL asio::error_code assign(implementation_type& impl,+      const native_handle_type& handle, asio::error_code& ec);++  // Determine whether the handle is open.+  bool is_open(const implementation_type& impl) const+  {+    return impl.handle_ != INVALID_HANDLE_VALUE && impl.handle_ != 0;+  }++  // Destroy a handle implementation.+  ASIO_DECL asio::error_code close(implementation_type& impl,+      asio::error_code& ec);++  // Get the native handle representation.+  native_handle_type native_handle(const implementation_type& impl) const+  {+    return impl.handle_;+  }++  // Cancel all operations associated with the handle.+  ASIO_DECL asio::error_code cancel(implementation_type& impl,+      asio::error_code& ec);++  // Perform a synchronous wait for the object to enter a signalled state.+  ASIO_DECL void wait(implementation_type& impl,+      asio::error_code& ec);++  /// Start an asynchronous wait.+  template <typename Handler, typename IoExecutor>+  void async_wait(implementation_type& impl,+      Handler& handler, const IoExecutor& io_ex)+  {+    // Allocate and construct an operation to wrap the handler.+    typedef wait_handler<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(handler, io_ex);++    ASIO_HANDLER_CREATION((scheduler_.context(), *p.p, "object_handle",+          &impl, reinterpret_cast<uintmax_t>(impl.wait_handle_), "async_wait"));++    start_wait_op(impl, p.p);+    p.v = p.p = 0;+  }++private:+  // Helper function to start an asynchronous wait operation.+  ASIO_DECL void start_wait_op(implementation_type& impl, wait_op* op);++  // Helper function to register a wait operation.+  ASIO_DECL void register_wait_callback(+      implementation_type& impl, mutex::scoped_lock& lock);++  // Callback function invoked when the registered wait completes.+  static ASIO_DECL VOID CALLBACK wait_callback(+      PVOID param, BOOLEAN timeout);++  // The scheduler used to post completions.+#if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_impl;+#else+  typedef class scheduler scheduler_impl;+#endif+  scheduler_impl& scheduler_;++  // Mutex to protect access to internal state.+  mutex mutex_;++  // The head of a linked list of all implementations.+  implementation_type* impl_list_;++  // Flag to indicate that the dispatcher has been shut down.+  bool shutdown_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_object_handle_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE)++#endif // ASIO_DETAIL_WIN_OBJECT_HANDLE_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_static_mutex.hpp view
@@ -0,0 +1,74 @@+//+// detail/win_static_mutex.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_STATIC_MUTEX_HPP+#define ASIO_DETAIL_WIN_STATIC_MUTEX_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_WINDOWS)++#include "asio/detail/scoped_lock.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct win_static_mutex+{+  typedef asio::detail::scoped_lock<win_static_mutex> scoped_lock;++  // Initialise the mutex.+  ASIO_DECL void init();++  // Initialisation must be performed in a separate function to the "public"+  // init() function since the compiler does not support the use of structured+  // exceptions and C++ exceptions in the same function.+  ASIO_DECL int do_init();++  // Lock the mutex.+  void lock()+  {+    ::EnterCriticalSection(&crit_section_);+  }++  // Unlock the mutex.+  void unlock()+  {+    ::LeaveCriticalSection(&crit_section_);+  }++  bool initialised_;+  ::CRITICAL_SECTION crit_section_;+};++#if defined(UNDER_CE)+# define ASIO_WIN_STATIC_MUTEX_INIT { false, { 0, 0, 0, 0, 0 } }+#else // defined(UNDER_CE)+# define ASIO_WIN_STATIC_MUTEX_INIT { false, { 0, 0, 0, 0, 0, 0 } }+#endif // defined(UNDER_CE)++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_static_mutex.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_WINDOWS)++#endif // ASIO_DETAIL_WIN_STATIC_MUTEX_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_thread.hpp view
@@ -0,0 +1,147 @@+//+// detail/win_thread.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_THREAD_HPP+#define ASIO_DETAIL_WIN_THREAD_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_WINDOWS) \+  && !defined(ASIO_WINDOWS_APP) \+  && !defined(UNDER_CE)++#include <cstddef>+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++ASIO_DECL unsigned int __stdcall win_thread_function(void* arg);++#if defined(WINVER) && (WINVER < 0x0500)+ASIO_DECL void __stdcall apc_function(ULONG data);+#else+ASIO_DECL void __stdcall apc_function(ULONG_PTR data);+#endif++template <typename T>+class win_thread_base+{+public:+  static bool terminate_threads()+  {+    return ::InterlockedExchangeAdd(&terminate_threads_, 0) != 0;+  }++  static void set_terminate_threads(bool b)+  {+    ::InterlockedExchange(&terminate_threads_, b ? 1 : 0);+  }++private:+  static long terminate_threads_;+};++template <typename T>+long win_thread_base<T>::terminate_threads_ = 0;++class win_thread+  : private noncopyable,+    public win_thread_base<win_thread>+{+public:+  // Constructor.+  template <typename Function>+  win_thread(Function f, unsigned int stack_size = 0)+    : thread_(0),+      exit_event_(0)+  {+    start_thread(new func<Function>(f), stack_size);+  }++  // Destructor.+  ASIO_DECL ~win_thread();++  // Wait for the thread to exit.+  ASIO_DECL void join();++  // Get number of CPUs.+  ASIO_DECL static std::size_t hardware_concurrency();++private:+  friend ASIO_DECL unsigned int __stdcall win_thread_function(void* arg);++#if defined(WINVER) && (WINVER < 0x0500)+  friend ASIO_DECL void __stdcall apc_function(ULONG);+#else+  friend ASIO_DECL void __stdcall apc_function(ULONG_PTR);+#endif++  class func_base+  {+  public:+    virtual ~func_base() {}+    virtual void run() = 0;+    ::HANDLE entry_event_;+    ::HANDLE exit_event_;+  };++  struct auto_func_base_ptr+  {+    func_base* ptr;+    ~auto_func_base_ptr() { delete ptr; }+  };++  template <typename Function>+  class func+    : public func_base+  {+  public:+    func(Function f)+      : f_(f)+    {+    }++    virtual void run()+    {+      f_();+    }++  private:+    Function f_;+  };++  ASIO_DECL void start_thread(func_base* arg, unsigned int stack_size);++  ::HANDLE thread_;+  ::HANDLE exit_event_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_thread.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_WINDOWS)+       // && !defined(ASIO_WINDOWS_APP)+       // && !defined(UNDER_CE)++#endif // ASIO_DETAIL_WIN_THREAD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/win_tss_ptr.hpp view
@@ -0,0 +1,79 @@+//+// detail/win_tss_ptr.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WIN_TSS_PTR_HPP+#define ASIO_DETAIL_WIN_TSS_PTR_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_WINDOWS)++#include "asio/detail/noncopyable.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper function to create thread-specific storage.+ASIO_DECL DWORD win_tss_ptr_create();++template <typename T>+class win_tss_ptr+  : private noncopyable+{+public:+  // Constructor.+  win_tss_ptr()+    : tss_key_(win_tss_ptr_create())+  {+  }++  // Destructor.+  ~win_tss_ptr()+  {+    ::TlsFree(tss_key_);+  }++  // Get the value.+  operator T*() const+  {+    return static_cast<T*>(::TlsGetValue(tss_key_));+  }++  // Set the value.+  void operator=(T* value)+  {+    ::TlsSetValue(tss_key_, value);+  }++private:+  // Thread-specific storage to allow unlocked access to determine whether a+  // thread is a member of the pool.+  DWORD tss_key_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_tss_ptr.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_WINDOWS)++#endif // ASIO_DETAIL_WIN_TSS_PTR_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winapp_thread.hpp view
@@ -0,0 +1,124 @@+//+// detail/winapp_thread.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINAPP_THREAD_HPP+#define ASIO_DETAIL_WINAPP_THREAD_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_WINDOWS) && defined(ASIO_WINDOWS_APP)++#include "asio/detail/noncopyable.hpp"+#include "asio/detail/scoped_ptr.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++DWORD WINAPI winapp_thread_function(LPVOID arg);++class winapp_thread+  : private noncopyable+{+public:+  // Constructor.+  template <typename Function>+  winapp_thread(Function f, unsigned int = 0)+  {+    scoped_ptr<func_base> arg(new func<Function>(f));+    DWORD thread_id = 0;+    thread_ = ::CreateThread(0, 0, winapp_thread_function,+        arg.get(), 0, &thread_id);+    if (!thread_)+    {+      DWORD last_error = ::GetLastError();+      asio::error_code ec(last_error,+          asio::error::get_system_category());+      asio::detail::throw_error(ec, "thread");+    }+    arg.release();+  }++  // Destructor.+  ~winapp_thread()+  {+    ::CloseHandle(thread_);+  }++  // Wait for the thread to exit.+  void join()+  {+    ::WaitForSingleObjectEx(thread_, INFINITE, false);+  }++  // Get number of CPUs.+  static std::size_t hardware_concurrency()+  {+    SYSTEM_INFO system_info;+    ::GetNativeSystemInfo(&system_info);+    return system_info.dwNumberOfProcessors;+  }++private:+  friend DWORD WINAPI winapp_thread_function(LPVOID arg);++  class func_base+  {+  public:+    virtual ~func_base() {}+    virtual void run() = 0;+  };++  template <typename Function>+  class func+    : public func_base+  {+  public:+    func(Function f)+      : f_(f)+    {+    }++    virtual void run()+    {+      f_();+    }++  private:+    Function f_;+  };++  ::HANDLE thread_;+};++inline DWORD WINAPI winapp_thread_function(LPVOID arg)+{+  scoped_ptr<winapp_thread::func_base> func(+      static_cast<winapp_thread::func_base*>(arg));+  func->run();+  return 0;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS) && defined(ASIO_WINDOWS_APP)++#endif // ASIO_DETAIL_WINAPP_THREAD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/wince_thread.hpp view
@@ -0,0 +1,124 @@+//+// detail/wince_thread.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINCE_THREAD_HPP+#define ASIO_DETAIL_WINCE_THREAD_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_WINDOWS) && defined(UNDER_CE)++#include "asio/detail/noncopyable.hpp"+#include "asio/detail/scoped_ptr.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++DWORD WINAPI wince_thread_function(LPVOID arg);++class wince_thread+  : private noncopyable+{+public:+  // Constructor.+  template <typename Function>+  wince_thread(Function f, unsigned int = 0)+  {+    scoped_ptr<func_base> arg(new func<Function>(f));+    DWORD thread_id = 0;+    thread_ = ::CreateThread(0, 0, wince_thread_function,+        arg.get(), 0, &thread_id);+    if (!thread_)+    {+      DWORD last_error = ::GetLastError();+      asio::error_code ec(last_error,+          asio::error::get_system_category());+      asio::detail::throw_error(ec, "thread");+    }+    arg.release();+  }++  // Destructor.+  ~wince_thread()+  {+    ::CloseHandle(thread_);+  }++  // Wait for the thread to exit.+  void join()+  {+    ::WaitForSingleObject(thread_, INFINITE);+  }++  // Get number of CPUs.+  static std::size_t hardware_concurrency()+  {+    SYSTEM_INFO system_info;+    ::GetSystemInfo(&system_info);+    return system_info.dwNumberOfProcessors;+  }++private:+  friend DWORD WINAPI wince_thread_function(LPVOID arg);++  class func_base+  {+  public:+    virtual ~func_base() {}+    virtual void run() = 0;+  };++  template <typename Function>+  class func+    : public func_base+  {+  public:+    func(Function f)+      : f_(f)+    {+    }++    virtual void run()+    {+      f_();+    }++  private:+    Function f_;+  };++  ::HANDLE thread_;+};++inline DWORD WINAPI wince_thread_function(LPVOID arg)+{+  scoped_ptr<wince_thread::func_base> func(+      static_cast<wince_thread::func_base*>(arg));+  func->run();+  return 0;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS) && defined(UNDER_CE)++#endif // ASIO_DETAIL_WINCE_THREAD_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_async_manager.hpp view
@@ -0,0 +1,305 @@+//+// detail/winrt_async_manager.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP+#define ASIO_DETAIL_WINRT_ASYNC_MANAGER_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_WINDOWS_RUNTIME)++#include <future>+#include "asio/detail/atomic_count.hpp"+#include "asio/detail/winrt_async_op.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class winrt_async_manager+  : public execution_context_service_base<winrt_async_manager>+{+public:+  // Constructor.+  winrt_async_manager(execution_context& context)+    : execution_context_service_base<winrt_async_manager>(context),+      scheduler_(use_service<scheduler_impl>(context)),+      outstanding_ops_(1)+  {+  }++  // Destructor.+  ~winrt_async_manager()+  {+  }++  // Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+    if (--outstanding_ops_ > 0)+    {+      // Block until last operation is complete.+      std::future<void> f = promise_.get_future();+      f.wait();+    }+  }++  void sync(Windows::Foundation::IAsyncAction^ action,+      asio::error_code& ec)+  {+    using namespace Windows::Foundation;+    using Windows::Foundation::AsyncStatus;++    auto promise = std::make_shared<std::promise<asio::error_code>>();+    auto future = promise->get_future();++    action->Completed = ref new AsyncActionCompletedHandler(+      [promise](IAsyncAction^ action, AsyncStatus status)+      {+        switch (status)+        {+        case AsyncStatus::Canceled:+          promise->set_value(asio::error::operation_aborted);+          break;+        case AsyncStatus::Error:+        case AsyncStatus::Completed:+        default:+          asio::error_code ec(+              action->ErrorCode.Value,+              asio::system_category());+          promise->set_value(ec);+          break;+        }+      });++    ec = future.get();+  }++  template <typename TResult>+  TResult sync(Windows::Foundation::IAsyncOperation<TResult>^ operation,+      asio::error_code& ec)+  {+    using namespace Windows::Foundation;+    using Windows::Foundation::AsyncStatus;++    auto promise = std::make_shared<std::promise<asio::error_code>>();+    auto future = promise->get_future();++    operation->Completed = ref new AsyncOperationCompletedHandler<TResult>(+      [promise](IAsyncOperation<TResult>^ operation, AsyncStatus status)+      {+        switch (status)+        {+        case AsyncStatus::Canceled:+          promise->set_value(asio::error::operation_aborted);+          break;+        case AsyncStatus::Error:+        case AsyncStatus::Completed:+        default:+          asio::error_code ec(+              operation->ErrorCode.Value,+              asio::system_category());+          promise->set_value(ec);+          break;+        }+      });++    ec = future.get();+    return operation->GetResults();+  }++  template <typename TResult, typename TProgress>+  TResult sync(+      Windows::Foundation::IAsyncOperationWithProgress<+        TResult, TProgress>^ operation,+      asio::error_code& ec)+  {+    using namespace Windows::Foundation;+    using Windows::Foundation::AsyncStatus;++    auto promise = std::make_shared<std::promise<asio::error_code>>();+    auto future = promise->get_future();++    operation->Completed+      = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>(+        [promise](IAsyncOperationWithProgress<TResult, TProgress>^ operation,+          AsyncStatus status)+        {+          switch (status)+          {+          case AsyncStatus::Canceled:+            promise->set_value(asio::error::operation_aborted);+            break;+          case AsyncStatus::Started:+            break;+          case AsyncStatus::Error:+          case AsyncStatus::Completed:+          default:+            asio::error_code ec(+                operation->ErrorCode.Value,+                asio::system_category());+            promise->set_value(ec);+            break;+          }+        });++    ec = future.get();+    return operation->GetResults();+  }++  void async(Windows::Foundation::IAsyncAction^ action,+      winrt_async_op<void>* handler)+  {+    using namespace Windows::Foundation;+    using Windows::Foundation::AsyncStatus;++    auto on_completed = ref new AsyncActionCompletedHandler(+      [this, handler](IAsyncAction^ action, AsyncStatus status)+      {+        switch (status)+        {+        case AsyncStatus::Canceled:+          handler->ec_ = asio::error::operation_aborted;+          break;+        case AsyncStatus::Started:+          return;+        case AsyncStatus::Completed:+        case AsyncStatus::Error:+        default:+          handler->ec_ = asio::error_code(+              action->ErrorCode.Value,+              asio::system_category());+          break;+        }+        scheduler_.post_deferred_completion(handler);+        if (--outstanding_ops_ == 0)+          promise_.set_value();+      });++    scheduler_.work_started();+    ++outstanding_ops_;+    action->Completed = on_completed;+  }++  template <typename TResult>+  void async(Windows::Foundation::IAsyncOperation<TResult>^ operation,+      winrt_async_op<TResult>* handler)+  {+    using namespace Windows::Foundation;+    using Windows::Foundation::AsyncStatus;++    auto on_completed = ref new AsyncOperationCompletedHandler<TResult>(+      [this, handler](IAsyncOperation<TResult>^ operation, AsyncStatus status)+      {+        switch (status)+        {+        case AsyncStatus::Canceled:+          handler->ec_ = asio::error::operation_aborted;+          break;+        case AsyncStatus::Started:+          return;+        case AsyncStatus::Completed:+          handler->result_ = operation->GetResults();+          // Fall through.+        case AsyncStatus::Error:+        default:+          handler->ec_ = asio::error_code(+              operation->ErrorCode.Value,+              asio::system_category());+          break;+        }+        scheduler_.post_deferred_completion(handler);+        if (--outstanding_ops_ == 0)+          promise_.set_value();+      });++    scheduler_.work_started();+    ++outstanding_ops_;+    operation->Completed = on_completed;+  }++  template <typename TResult, typename TProgress>+  void async(+      Windows::Foundation::IAsyncOperationWithProgress<+        TResult, TProgress>^ operation,+      winrt_async_op<TResult>* handler)+  {+    using namespace Windows::Foundation;+    using Windows::Foundation::AsyncStatus;++    auto on_completed+      = ref new AsyncOperationWithProgressCompletedHandler<TResult, TProgress>(+        [this, handler](IAsyncOperationWithProgress<+          TResult, TProgress>^ operation, AsyncStatus status)+        {+          switch (status)+          {+          case AsyncStatus::Canceled:+            handler->ec_ = asio::error::operation_aborted;+            break;+          case AsyncStatus::Started:+            return;+          case AsyncStatus::Completed:+            handler->result_ = operation->GetResults();+            // Fall through.+          case AsyncStatus::Error:+          default:+            handler->ec_ = asio::error_code(+                operation->ErrorCode.Value,+                asio::system_category());+            break;+          }+          scheduler_.post_deferred_completion(handler);+          if (--outstanding_ops_ == 0)+            promise_.set_value();+        });++    scheduler_.work_started();+    ++outstanding_ops_;+    operation->Completed = on_completed;+  }++private:+  // The scheduler implementation used to post completed handlers.+#if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_impl;+#else+  typedef class scheduler scheduler_impl;+#endif+  scheduler_impl& scheduler_;++  // Count of outstanding operations.+  atomic_count outstanding_ops_;++  // Used to keep wait for outstanding operations to complete.+  std::promise<void> promise_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_ASYNC_MANAGER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_async_op.hpp view
@@ -0,0 +1,65 @@+//+// detail/winrt_async_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_ASYNC_OP_HPP+#define ASIO_DETAIL_WINRT_ASYNC_OP_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/operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename TResult>+class winrt_async_op+  : public operation+{+public:+  // The error code to be passed to the completion handler.+  asio::error_code ec_;++  // The result of the operation, to be passed to the completion handler.+  TResult result_;++protected:+  winrt_async_op(func_type complete_func)+    : operation(complete_func),+      result_()+  {+  }+};++template <>+class winrt_async_op<void>+  : public operation+{+public:+  // The error code to be passed to the completion handler.+  asio::error_code ec_;++protected:+  winrt_async_op(func_type complete_func)+    : operation(complete_func)+  {+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_WINRT_ASYNC_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_resolve_op.hpp view
@@ -0,0 +1,125 @@+//+// detail/winrt_resolve_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_RESOLVE_OP_HPP+#define ASIO_DETAIL_WINRT_RESOLVE_OP_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_WINDOWS_RUNTIME)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/winrt_async_op.hpp"+#include "asio/ip/basic_resolver_results.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol, typename Handler, typename IoExecutor>+class winrt_resolve_op :+  public winrt_async_op<+    Windows::Foundation::Collections::IVectorView<+      Windows::Networking::EndpointPair^>^>+{+public:+  ASIO_DEFINE_HANDLER_PTR(winrt_resolve_op);++  typedef typename Protocol::endpoint endpoint_type;+  typedef asio::ip::basic_resolver_query<Protocol> query_type;+  typedef asio::ip::basic_resolver_results<Protocol> results_type;++  winrt_resolve_op(const query_type& query,+      Handler& handler, const IoExecutor& io_ex)+    : winrt_async_op<+        Windows::Foundation::Collections::IVectorView<+          Windows::Networking::EndpointPair^>^>(+            &winrt_resolve_op::do_complete),+      query_(query),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code&, std::size_t)+  {+    // Take ownership of the operation object.+    winrt_resolve_op* o(static_cast<winrt_resolve_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    results_type results = results_type();+    if (!o->ec_)+    {+      try+      {+        results = results_type::create(o->result_, o->query_.hints(),+            o->query_.host_name(), o->query_.service_name());+      }+      catch (Platform::Exception^ e)+      {+        o->ec_ = asio::error_code(e->HResult,+            asio::system_category());+      }+    }++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, results_type>+      handler(o->handler_, o->ec_, results);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  query_type query_;+  Handler handler_;+  handler_work<Handler, IoExecutor> executor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_RESOLVE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_resolver_service.hpp view
@@ -0,0 +1,212 @@+//+// detail/winrt_resolver_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_RESOLVER_SERVICE_HPP+#define ASIO_DETAIL_WINRT_RESOLVER_SERVICE_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_WINDOWS_RUNTIME)++#include "asio/ip/basic_resolver_query.hpp"+#include "asio/ip/basic_resolver_results.hpp"+#include "asio/post.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/winrt_async_manager.hpp"+#include "asio/detail/winrt_resolve_op.hpp"+#include "asio/detail/winrt_utils.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol>+class winrt_resolver_service :+  public execution_context_service_base<winrt_resolver_service<Protocol> >+{+public:+  // The implementation type of the resolver. A cancellation token is used to+  // indicate to the asynchronous operation that the operation has been+  // cancelled.+  typedef socket_ops::shared_cancel_token_type implementation_type;++  // The endpoint type.+  typedef typename Protocol::endpoint endpoint_type;++  // The query type.+  typedef asio::ip::basic_resolver_query<Protocol> query_type;++  // The results type.+  typedef asio::ip::basic_resolver_results<Protocol> results_type;++  // Constructor.+  winrt_resolver_service(execution_context& context)+    : execution_context_service_base<+        winrt_resolver_service<Protocol> >(context),+      scheduler_(use_service<scheduler_impl>(context)),+      async_manager_(use_service<winrt_async_manager>(context))+  {+  }++  // Destructor.+  ~winrt_resolver_service()+  {+  }++  // Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+  }++  // Perform any fork-related housekeeping.+  void notify_fork(execution_context::fork_event)+  {+  }++  // Construct a new resolver implementation.+  void construct(implementation_type&)+  {+  }++  // Move-construct a new resolver implementation.+  void move_construct(implementation_type&,+      implementation_type&)+  {+  }++  // Move-assign from another resolver implementation.+  void move_assign(implementation_type&,+      winrt_resolver_service&, implementation_type&)+  {+  }++  // Destroy a resolver implementation.+  void destroy(implementation_type&)+  {+  }++  // Cancel pending asynchronous operations.+  void cancel(implementation_type&)+  {+  }++  // Resolve a query to a list of entries.+  results_type resolve(implementation_type&,+      const query_type& query, asio::error_code& ec)+  {+    try+    {+      using namespace Windows::Networking::Sockets;+      auto endpoint_pairs = async_manager_.sync(+          DatagramSocket::GetEndpointPairsAsync(+            winrt_utils::host_name(query.host_name()),+            winrt_utils::string(query.service_name())), ec);++      if (ec)+        return results_type();++      return results_type::create(+          endpoint_pairs, query.hints(),+          query.host_name(), query.service_name());+    }+    catch (Platform::Exception^ e)+    {+      ec = asio::error_code(e->HResult,+          asio::system_category());+      return results_type();+    }+  }++  // Asynchronously resolve a query to a list of entries.+  template <typename Handler, typename IoExecutor>+  void async_resolve(implementation_type& impl, const query_type& query,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef winrt_resolve_op<Protocol, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(query, handler, io_ex);++    ASIO_HANDLER_CREATION((scheduler_.context(),+          *p.p, "resolver", &impl, 0, "async_resolve"));+    (void)impl;++    try+    {+      using namespace Windows::Networking::Sockets;+      async_manager_.async(DatagramSocket::GetEndpointPairsAsync(+            winrt_utils::host_name(query.host_name()),+            winrt_utils::string(query.service_name())), p.p);+      p.v = p.p = 0;+    }+    catch (Platform::Exception^ e)+    {+      p.p->ec_ = asio::error_code(+          e->HResult, asio::system_category());+      scheduler_.post_immediate_completion(p.p, is_continuation);+      p.v = p.p = 0;+    }+  }++  // Resolve an endpoint to a list of entries.+  results_type resolve(implementation_type&,+      const endpoint_type&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return results_type();+  }++  // Asynchronously resolve an endpoint to a list of entries.+  template <typename Handler, typename IoExecutor>+  void async_resolve(implementation_type&, const endpoint_type&,+      Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const results_type results;+    asio::post(io_ex, detail::bind_handler(handler, ec, results));+  }++private:+  // The scheduler implementation used for delivering completions.+#if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_impl;+#else+  typedef class scheduler scheduler_impl;+#endif+  scheduler_impl& scheduler_;++  winrt_async_manager& async_manager_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_RESOLVER_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_connect_op.hpp view
@@ -0,0 +1,98 @@+//+// detail/winrt_socket_connect_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_SOCKET_CONNECT_OP_HPP+#define ASIO_DETAIL_WINRT_SOCKET_CONNECT_OP_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_WINDOWS_RUNTIME)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/winrt_async_op.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class winrt_socket_connect_op :+  public winrt_async_op<void>+{+public:+  ASIO_DEFINE_HANDLER_PTR(winrt_socket_connect_op);++  winrt_socket_connect_op(Handler& handler, const IoExecutor& io_ex)+    : winrt_async_op<void>(&winrt_socket_connect_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code&, std::size_t)+  {+    // Take ownership of the operation object.+    winrt_socket_connect_op* o(static_cast<winrt_socket_connect_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder1<Handler, asio::error_code>+      handler(o->handler_, o->ec_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> executor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_SOCKET_CONNECT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_recv_op.hpp view
@@ -0,0 +1,119 @@+//+// detail/winrt_socket_recv_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_SOCKET_RECV_OP_HPP+#define ASIO_DETAIL_WINRT_SOCKET_RECV_OP_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_WINDOWS_RUNTIME)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/winrt_async_op.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class winrt_socket_recv_op :+  public winrt_async_op<Windows::Storage::Streams::IBuffer^>+{+public:+  ASIO_DEFINE_HANDLER_PTR(winrt_socket_recv_op);++  winrt_socket_recv_op(const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+    : winrt_async_op<Windows::Storage::Streams::IBuffer^>(+          &winrt_socket_recv_op::do_complete),+      buffers_(buffers),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code&, std::size_t)+  {+    // Take ownership of the operation object.+    winrt_socket_recv_op* o(static_cast<winrt_socket_recv_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    // Check whether buffers are still valid.+    if (owner)+    {+      buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::validate(o->buffers_);+    }+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++    std::size_t bytes_transferred = o->result_ ? o->result_->Length : 0;+    if (bytes_transferred == 0 && !o->ec_ &&+        !buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::all_empty(o->buffers_))+    {+      o->ec_ = asio::error::eof;+    }++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, bytes_transferred);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  MutableBufferSequence buffers_;+  Handler handler_;+  handler_work<Handler, IoExecutor> executor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_SOCKET_RECV_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_send_op.hpp view
@@ -0,0 +1,110 @@+//+// detail/winrt_socket_send_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_SOCKET_SEND_OP_HPP+#define ASIO_DETAIL_WINRT_SOCKET_SEND_OP_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_WINDOWS_RUNTIME)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/winrt_async_op.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class winrt_socket_send_op :+  public winrt_async_op<unsigned int>+{+public:+  ASIO_DEFINE_HANDLER_PTR(winrt_socket_send_op);++  winrt_socket_send_op(const ConstBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+    : winrt_async_op<unsigned int>(&winrt_socket_send_op::do_complete),+      buffers_(buffers),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code&, std::size_t)+  {+    // Take ownership of the operation object.+    winrt_socket_send_op* o(static_cast<winrt_socket_send_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++#if defined(ASIO_ENABLE_BUFFER_DEBUGGING)+    // Check whether buffers are still valid.+    if (owner)+    {+      buffer_sequence_adapter<asio::const_buffer,+          ConstBufferSequence>::validate(o->buffers_);+    }+#endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++    // Make a copy of the handler so that the memory can be deallocated before+    // the upcall is made. Even if we're not about to make an upcall, a+    // sub-object of the handler may be the true owner of the memory associated+    // with the handler. Consequently, a local copy of the handler is required+    // to ensure that any owning sub-object remains valid until after we have+    // deallocated the memory here.+    detail::binder2<Handler, asio::error_code, std::size_t>+      handler(o->handler_, o->ec_, o->result_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Make the upcall if required.+    if (owner)+    {+      fenced_block b(fenced_block::half);+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  ConstBufferSequence buffers_;+  Handler handler_;+  handler_work<Handler, IoExecutor> executor_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_SOCKET_SEND_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service.hpp view
@@ -0,0 +1,250 @@+//+// detail/winrt_ssocket_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_SSOCKET_SERVICE_HPP+#define ASIO_DETAIL_WINRT_SSOCKET_SERVICE_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_WINDOWS_RUNTIME)++#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/winrt_socket_connect_op.hpp"+#include "asio/detail/winrt_ssocket_service_base.hpp"+#include "asio/detail/winrt_utils.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol>+class winrt_ssocket_service :+  public execution_context_service_base<winrt_ssocket_service<Protocol> >,+  public winrt_ssocket_service_base+{+public:+  // The protocol type.+  typedef Protocol protocol_type;++  // The endpoint type.+  typedef typename Protocol::endpoint endpoint_type;++  // The native type of a socket.+  typedef Windows::Networking::Sockets::StreamSocket^ native_handle_type;++  // The implementation type of the socket.+  struct implementation_type : base_implementation_type+  {+    // Default constructor.+    implementation_type()+      : base_implementation_type(),+        protocol_(endpoint_type().protocol())+    {+    }++    // The protocol associated with the socket.+    protocol_type protocol_;+  };++  // Constructor.+  winrt_ssocket_service(execution_context& context)+    : execution_context_service_base<winrt_ssocket_service<Protocol> >(context),+      winrt_ssocket_service_base(context)+  {+  }++  // Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+    this->base_shutdown();+  }++  // Move-construct a new socket implementation.+  void move_construct(implementation_type& impl,+      implementation_type& other_impl) ASIO_NOEXCEPT+  {+    this->base_move_construct(impl, other_impl);++    impl.protocol_ = other_impl.protocol_;+    other_impl.protocol_ = endpoint_type().protocol();+  }++  // Move-assign from another socket implementation.+  void move_assign(implementation_type& impl,+      winrt_ssocket_service& other_service,+      implementation_type& other_impl)+  {+    this->base_move_assign(impl, other_service, other_impl);++    impl.protocol_ = other_impl.protocol_;+    other_impl.protocol_ = endpoint_type().protocol();+  }++  // Move-construct a new socket implementation from another protocol type.+  template <typename Protocol1>+  void converting_move_construct(implementation_type& impl,+      winrt_ssocket_service<Protocol1>&,+      typename winrt_ssocket_service<+        Protocol1>::implementation_type& other_impl)+  {+    this->base_move_construct(impl, other_impl);++    impl.protocol_ = protocol_type(other_impl.protocol_);+    other_impl.protocol_ = typename Protocol1::endpoint().protocol();+  }++  // Open a new socket implementation.+  asio::error_code open(implementation_type& impl,+      const protocol_type& protocol, asio::error_code& ec)+  {+    if (is_open(impl))+    {+      ec = asio::error::already_open;+      return ec;+    }++    try+    {+      impl.socket_ = ref new Windows::Networking::Sockets::StreamSocket;+      impl.protocol_ = protocol;+      ec = asio::error_code();+    }+    catch (Platform::Exception^ e)+    {+      ec = asio::error_code(e->HResult,+            asio::system_category());+    }++    return ec;+  }++  // Assign a native socket to a socket implementation.+  asio::error_code assign(implementation_type& impl,+      const protocol_type& protocol, const native_handle_type& native_socket,+      asio::error_code& ec)+  {+    if (is_open(impl))+    {+      ec = asio::error::already_open;+      return ec;+    }++    impl.socket_ = native_socket;+    impl.protocol_ = protocol;+    ec = asio::error_code();++    return ec;+  }++  // Bind the socket to the specified local endpoint.+  asio::error_code bind(implementation_type&,+      const endpoint_type&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Get the local endpoint.+  endpoint_type local_endpoint(const implementation_type& impl,+      asio::error_code& ec) const+  {+    endpoint_type endpoint;+    endpoint.resize(do_get_endpoint(impl, true,+          endpoint.data(), endpoint.size(), ec));+    return endpoint;+  }++  // Get the remote endpoint.+  endpoint_type remote_endpoint(const implementation_type& impl,+      asio::error_code& ec) const+  {+    endpoint_type endpoint;+    endpoint.resize(do_get_endpoint(impl, false,+          endpoint.data(), endpoint.size(), ec));+    return endpoint;+  }++  // Disable sends or receives on the socket.+  asio::error_code shutdown(implementation_type&,+      socket_base::shutdown_type, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Set a socket option.+  template <typename Option>+  asio::error_code set_option(implementation_type& impl,+      const Option& option, asio::error_code& ec)+  {+    return do_set_option(impl, option.level(impl.protocol_),+        option.name(impl.protocol_), option.data(impl.protocol_),+        option.size(impl.protocol_), ec);+  }++  // Get a socket option.+  template <typename Option>+  asio::error_code get_option(const implementation_type& impl,+      Option& option, asio::error_code& ec) const+  {+    std::size_t size = option.size(impl.protocol_);+    do_get_option(impl, option.level(impl.protocol_),+        option.name(impl.protocol_),+        option.data(impl.protocol_), &size, ec);+    if (!ec)+      option.resize(impl.protocol_, size);+    return ec;+  }++  // Connect the socket to the specified endpoint.+  asio::error_code connect(implementation_type& impl,+      const endpoint_type& peer_endpoint, asio::error_code& ec)+  {+    return do_connect(impl, peer_endpoint.data(), ec);+  }++  // Start an asynchronous connect.+  template <typename Handler, typename IoExecutor>+  void async_connect(implementation_type& impl,+      const endpoint_type& peer_endpoint,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef winrt_socket_connect_op<Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(handler, io_ex);++    ASIO_HANDLER_CREATION((scheduler_.context(),+          *p.p, "socket", &impl, 0, "async_connect"));++    start_connect_op(impl, peer_endpoint.data(), p.p, is_continuation);+    p.v = p.p = 0;+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_SSOCKET_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service_base.hpp view
@@ -0,0 +1,362 @@+//+// detail/winrt_ssocket_service_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_SSOCKET_SERVICE_BASE_HPP+#define ASIO_DETAIL_WINRT_SSOCKET_SERVICE_BASE_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_WINDOWS_RUNTIME)++#include "asio/buffer.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/socket_base.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/winrt_async_manager.hpp"+#include "asio/detail/winrt_socket_recv_op.hpp"+#include "asio/detail/winrt_socket_send_op.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class winrt_ssocket_service_base+{+public:+  // The native type of a socket.+  typedef Windows::Networking::Sockets::StreamSocket^ native_handle_type;++  // The implementation type of the socket.+  struct base_implementation_type+  {+    // Default constructor.+    base_implementation_type()+      : socket_(nullptr),+        next_(0),+        prev_(0)+    {+    }++    // The underlying native socket.+    native_handle_type socket_;++    // Pointers to adjacent socket implementations in linked list.+    base_implementation_type* next_;+    base_implementation_type* prev_;+  };++  // Constructor.+  ASIO_DECL winrt_ssocket_service_base(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void base_shutdown();++  // Construct a new socket implementation.+  ASIO_DECL void construct(base_implementation_type&);++  // Move-construct a new socket implementation.+  ASIO_DECL void base_move_construct(base_implementation_type& impl,+      base_implementation_type& other_impl) ASIO_NOEXCEPT;++  // Move-assign from another socket implementation.+  ASIO_DECL void base_move_assign(base_implementation_type& impl,+      winrt_ssocket_service_base& other_service,+      base_implementation_type& other_impl);++  // Destroy a socket implementation.+  ASIO_DECL void destroy(base_implementation_type& impl);++  // Determine whether the socket is open.+  bool is_open(const base_implementation_type& impl) const+  {+    return impl.socket_ != nullptr;+  }++  // Destroy a socket implementation.+  ASIO_DECL asio::error_code close(+      base_implementation_type& impl, asio::error_code& ec);++  // Release ownership of the socket.+  ASIO_DECL native_handle_type release(+      base_implementation_type& impl, asio::error_code& ec);++  // Get the native socket representation.+  native_handle_type native_handle(base_implementation_type& impl)+  {+    return impl.socket_;+  }++  // Cancel all operations associated with the socket.+  asio::error_code cancel(base_implementation_type&,+      asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Determine whether the socket is at the out-of-band data mark.+  bool at_mark(const base_implementation_type&,+      asio::error_code& ec) const+  {+    ec = asio::error::operation_not_supported;+    return false;+  }++  // Determine the number of bytes available for reading.+  std::size_t available(const base_implementation_type&,+      asio::error_code& ec) const+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Perform an IO control command on the socket.+  template <typename IO_Control_Command>+  asio::error_code io_control(base_implementation_type&,+      IO_Control_Command&, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Gets the non-blocking mode of the socket.+  bool non_blocking(const base_implementation_type&) const+  {+    return false;+  }++  // Sets the non-blocking mode of the socket.+  asio::error_code non_blocking(base_implementation_type&,+      bool, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Gets the non-blocking mode of the native socket implementation.+  bool native_non_blocking(const base_implementation_type&) const+  {+    return false;+  }++  // Sets the non-blocking mode of the native socket implementation.+  asio::error_code native_non_blocking(base_implementation_type&,+      bool, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }++  // Send the given data to the peer.+  template <typename ConstBufferSequence>+  std::size_t send(base_implementation_type& impl,+      const ConstBufferSequence& buffers,+      socket_base::message_flags flags, asio::error_code& ec)+  {+    return do_send(impl,+        buffer_sequence_adapter<asio::const_buffer,+          ConstBufferSequence>::first(buffers), flags, ec);+  }++  // Wait until data can be sent without blocking.+  std::size_t send(base_implementation_type&, const null_buffers&,+      socket_base::message_flags, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Start an asynchronous send. The data being sent must be valid for the+  // lifetime of the asynchronous operation.+  template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+  void async_send(base_implementation_type& impl,+      const ConstBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef winrt_socket_send_op<ConstBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((scheduler_.context(),+          *p.p, "socket", &impl, 0, "async_send"));++    start_send_op(impl,+        buffer_sequence_adapter<asio::const_buffer,+          ConstBufferSequence>::first(buffers),+        flags, p.p, is_continuation);+    p.v = p.p = 0;+  }++  // Start an asynchronous wait until data can be sent without blocking.+  template <typename Handler, typename IoExecutor>+  void async_send(base_implementation_type&, const null_buffers&,+      socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex,+        detail::bind_handler(handler, ec, bytes_transferred));+  }++  // Receive some data from the peer. Returns the number of bytes received.+  template <typename MutableBufferSequence>+  std::size_t receive(base_implementation_type& impl,+      const MutableBufferSequence& buffers,+      socket_base::message_flags flags, asio::error_code& ec)+  {+    return do_receive(impl,+        buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::first(buffers), flags, ec);+  }++  // Wait until data can be received without blocking.+  std::size_t receive(base_implementation_type&, const null_buffers&,+      socket_base::message_flags, asio::error_code& ec)+  {+    ec = asio::error::operation_not_supported;+    return 0;+  }++  // Start an asynchronous receive. The buffer for the data being received+  // must be valid for the lifetime of the asynchronous operation.+  template <typename MutableBufferSequence,+      typename Handler, typename IoExecutor>+  void async_receive(base_implementation_type& impl,+      const MutableBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef winrt_socket_recv_op<MutableBufferSequence, Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(buffers, handler, io_ex);++    ASIO_HANDLER_CREATION((scheduler_.context(),+          *p.p, "socket", &impl, 0, "async_receive"));++    start_receive_op(impl,+        buffer_sequence_adapter<asio::mutable_buffer,+          MutableBufferSequence>::first(buffers),+        flags, p.p, is_continuation);+    p.v = p.p = 0;+  }++  // Wait until data can be received without blocking.+  template <typename Handler, typename IoExecutor>+  void async_receive(base_implementation_type&, const null_buffers&,+      socket_base::message_flags, Handler& handler, const IoExecutor& io_ex)+  {+    asio::error_code ec = asio::error::operation_not_supported;+    const std::size_t bytes_transferred = 0;+    asio::post(io_ex,+        detail::bind_handler(handler, ec, bytes_transferred));+  }++protected:+  // Helper function to obtain endpoints associated with the connection.+  ASIO_DECL std::size_t do_get_endpoint(+      const base_implementation_type& impl, bool local,+      void* addr, std::size_t addr_len, asio::error_code& ec) const;++  // Helper function to set a socket option.+  ASIO_DECL asio::error_code do_set_option(+      base_implementation_type& impl,+      int level, int optname, const void* optval,+      std::size_t optlen, asio::error_code& ec);++  // Helper function to get a socket option.+  ASIO_DECL void do_get_option(+      const base_implementation_type& impl,+      int level, int optname, void* optval,+      std::size_t* optlen, asio::error_code& ec) const;++  // Helper function to perform a synchronous connect.+  ASIO_DECL asio::error_code do_connect(+      base_implementation_type& impl,+      const void* addr, asio::error_code& ec);++  // Helper function to start an asynchronous connect.+  ASIO_DECL void start_connect_op(+      base_implementation_type& impl, const void* addr,+      winrt_async_op<void>* op, bool is_continuation);++  // Helper function to perform a synchronous send.+  ASIO_DECL std::size_t do_send(+      base_implementation_type& impl, const asio::const_buffer& data,+      socket_base::message_flags flags, asio::error_code& ec);++  // Helper function to start an asynchronous send.+  ASIO_DECL void start_send_op(base_implementation_type& impl,+      const asio::const_buffer& data, socket_base::message_flags flags,+      winrt_async_op<unsigned int>* op, bool is_continuation);++  // Helper function to perform a synchronous receive.+  ASIO_DECL std::size_t do_receive(+      base_implementation_type& impl, const asio::mutable_buffer& data,+      socket_base::message_flags flags, asio::error_code& ec);++  // Helper function to start an asynchronous receive.+  ASIO_DECL void start_receive_op(base_implementation_type& impl,+      const asio::mutable_buffer& data, socket_base::message_flags flags,+      winrt_async_op<Windows::Storage::Streams::IBuffer^>* op,+      bool is_continuation);++  // The scheduler implementation used for delivering completions.+#if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_impl;+#else+  typedef class scheduler scheduler_impl;+#endif+  scheduler_impl& scheduler_;++  // The manager that keeps track of outstanding operations.+  winrt_async_manager& async_manager_;++  // Mutex to protect access to the linked list of implementations. +  asio::detail::mutex mutex_;++  // The head of a linked list of all implementations.+  base_implementation_type* impl_list_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/winrt_ssocket_service_base.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_SSOCKET_SERVICE_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_timer_scheduler.hpp view
@@ -0,0 +1,147 @@+//+// detail/winrt_timer_scheduler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_TIMER_SCHEDULER_HPP+#define ASIO_DETAIL_WINRT_TIMER_SCHEDULER_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_WINDOWS_RUNTIME)++#include <cstddef>+#include "asio/detail/event.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/thread.hpp"+#include "asio/detail/timer_queue_base.hpp"+#include "asio/detail/timer_queue_set.hpp"+#include "asio/detail/wait_op.hpp"+#include "asio/execution_context.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/scheduler.hpp"+#endif // defined(ASIO_HAS_IOCP)++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/thread.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class winrt_timer_scheduler+  : public execution_context_service_base<winrt_timer_scheduler>+{+public:+  // Constructor.+  ASIO_DECL winrt_timer_scheduler(execution_context& context);++  // Destructor.+  ASIO_DECL ~winrt_timer_scheduler();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Recreate internal descriptors following a fork.+  ASIO_DECL void notify_fork(execution_context::fork_event fork_ev);++  // Initialise the task. No effect as this class uses its own thread.+  ASIO_DECL void init_task();++  // Add a new timer queue to the reactor.+  template <typename Time_Traits>+  void add_timer_queue(timer_queue<Time_Traits>& queue);++  // Remove a timer queue from the reactor.+  template <typename Time_Traits>+  void remove_timer_queue(timer_queue<Time_Traits>& queue);++  // Schedule a new operation in the given timer queue to expire at the+  // specified absolute time.+  template <typename Time_Traits>+  void schedule_timer(timer_queue<Time_Traits>& queue,+      const typename Time_Traits::time_type& time,+      typename timer_queue<Time_Traits>::per_timer_data& timer, wait_op* op);++  // Cancel the timer operations associated with the given token. Returns the+  // number of operations that have been posted or dispatched.+  template <typename Time_Traits>+  std::size_t cancel_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& timer,+      std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)());++  // Move the timer operations associated with the given timer.+  template <typename Time_Traits>+  void move_timer(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data& to,+      typename timer_queue<Time_Traits>::per_timer_data& from);++private:+  // Run the select loop in the thread.+  ASIO_DECL void run_thread();++  // Entry point for the select loop thread.+  ASIO_DECL static void call_run_thread(winrt_timer_scheduler* reactor);++  // Helper function to add a new timer queue.+  ASIO_DECL void do_add_timer_queue(timer_queue_base& queue);++  // Helper function to remove a timer queue.+  ASIO_DECL void do_remove_timer_queue(timer_queue_base& queue);++  // The scheduler implementation used to post completions.+#if defined(ASIO_HAS_IOCP)+  typedef class win_iocp_io_context scheduler_impl;+#else+  typedef class scheduler scheduler_impl;+#endif+  scheduler_impl& scheduler_;++  // Mutex used to protect internal variables.+  asio::detail::mutex mutex_;++  // Event used to wake up background thread.+  asio::detail::event event_;++  // The timer queues.+  timer_queue_set timer_queues_;++  // The background thread that is waiting for timers to expire.+  asio::detail::thread* thread_;++  // Does the background thread need to stop.+  bool stop_thread_;++  // Whether the service has been shut down.+  bool shutdown_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/winrt_timer_scheduler.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/winrt_timer_scheduler.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_TIMER_SCHEDULER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winrt_utils.hpp view
@@ -0,0 +1,106 @@+//+// detail/winrt_utils.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINRT_UTILS_HPP+#define ASIO_DETAIL_WINRT_UTILS_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_WINDOWS_RUNTIME)++#include <codecvt>+#include <cstdlib>+#include <future>+#include <locale>+#include <robuffer.h>+#include <windows.storage.streams.h>+#include <wrl/implements.h>+#include "asio/buffer.hpp"+#include "asio/error_code.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {+namespace winrt_utils {++inline Platform::String^ string(const char* from)+{+  std::wstring tmp(from, from + std::strlen(from));+  return ref new Platform::String(tmp.c_str());+}++inline Platform::String^ string(const std::string& from)+{+  std::wstring tmp(from.begin(), from.end());+  return ref new Platform::String(tmp.c_str());+}++inline std::string string(Platform::String^ from)+{+  std::wstring_convert<std::codecvt_utf8<wchar_t>> converter;+  return converter.to_bytes(from->Data());+}++inline Platform::String^ string(unsigned short from)+{+  return string(std::to_string(from));+}++template <typename T>+inline Platform::String^ string(const T& from)+{+  return string(from.to_string());+}++inline int integer(Platform::String^ from)+{+  return _wtoi(from->Data());+}++template <typename T>+inline Windows::Networking::HostName^ host_name(const T& from)+{+  return ref new Windows::Networking::HostName((string)(from));+}++template <typename ConstBufferSequence>+inline Windows::Storage::Streams::IBuffer^ buffer_dup(+    const ConstBufferSequence& buffers)+{+  using Microsoft::WRL::ComPtr;+  using asio::buffer_size;+  std::size_t size = buffer_size(buffers);+  auto b = ref new Windows::Storage::Streams::Buffer(size);+  ComPtr<IInspectable> insp = reinterpret_cast<IInspectable*>(b);+  ComPtr<Windows::Storage::Streams::IBufferByteAccess> bacc;+  insp.As(&bacc);+  byte* bytes = nullptr;+  bacc->Buffer(&bytes);+  asio::buffer_copy(asio::buffer(bytes, size), buffers);+  b->Length = size;+  return b;+}++} // namespace winrt_utils+} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_WINDOWS_RUNTIME)++#endif // ASIO_DETAIL_WINRT_UTILS_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/winsock_init.hpp view
@@ -0,0 +1,128 @@+//+// detail/winsock_init.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WINSOCK_INIT_HPP+#define ASIO_DETAIL_WINSOCK_INIT_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_WINDOWS) || defined(__CYGWIN__)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class winsock_init_base+{+protected:+  // Structure to track result of initialisation and number of uses. POD is used+  // to ensure that the values are zero-initialised prior to any code being run.+  struct data+  {+    long init_count_;+    long result_;+  };++  ASIO_DECL static void startup(data& d,+      unsigned char major, unsigned char minor);++  ASIO_DECL static void manual_startup(data& d);++  ASIO_DECL static void cleanup(data& d);++  ASIO_DECL static void manual_cleanup(data& d);++  ASIO_DECL static void throw_on_error(data& d);+};++template <int Major = 2, int Minor = 0>+class winsock_init : private winsock_init_base+{+public:+  winsock_init(bool allow_throw = true)+  {+    startup(data_, Major, Minor);+    if (allow_throw)+      throw_on_error(data_);+  }++  winsock_init(const winsock_init&)+  {+    startup(data_, Major, Minor);+    throw_on_error(data_);+  }++  ~winsock_init()+  {+    cleanup(data_);+  }++  // This class may be used to indicate that user code will manage Winsock+  // initialisation and cleanup. This may be required in the case of a DLL, for+  // example, where it is not safe to initialise Winsock from global object+  // constructors.+  //+  // To prevent asio from initialising Winsock, the object must be constructed+  // before any Asio's own global objects. With MSVC, this may be accomplished+  // by adding the following code to the DLL:+  //+  //   #pragma warning(push)+  //   #pragma warning(disable:4073)+  //   #pragma init_seg(lib)+  //   asio::detail::winsock_init<>::manual manual_winsock_init;+  //   #pragma warning(pop)+  class manual+  {+  public:+    manual()+    {+      manual_startup(data_);+    }++    manual(const manual&)+    {+      manual_startup(data_);+    }++    ~manual()+    {+      manual_cleanup(data_);+    }+  };++private:+  friend class manual;+  static data data_;+};++template <int Major, int Minor>+winsock_init_base::data winsock_init<Major, Minor>::data_;++// Static variable to ensure that winsock is initialised before main, and+// therefore before any other threads can get started.+static const winsock_init<>& winsock_init_instance = winsock_init<>(false);++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/winsock_init.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)++#endif // ASIO_DETAIL_WINSOCK_INIT_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/work_dispatcher.hpp view
@@ -0,0 +1,148 @@+//+// detail/work_dispatcher.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WORK_DISPATCHER_HPP+#define ASIO_DETAIL_WORK_DISPATCHER_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/associated_executor.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/executor_work_guard.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/allocator.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/execution/outstanding_work.hpp"+#include "asio/prefer.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename Executor, typename = void>+struct is_work_dispatcher_required : true_type+{+};++template <typename Handler, typename Executor>+struct is_work_dispatcher_required<Handler, Executor,+    typename enable_if<+      is_same<+        typename associated_executor<Handler,+          Executor>::asio_associated_executor_is_unspecialised,+        void+      >::value+    >::type> : false_type+{+};++template <typename Handler, typename Executor, typename = void>+class work_dispatcher+{+public:+  template <typename CompletionHandler>+  work_dispatcher(ASIO_MOVE_ARG(CompletionHandler) handler,+      const Executor& handler_ex)+    : handler_(ASIO_MOVE_CAST(CompletionHandler)(handler)),+      executor_(asio::prefer(handler_ex,+          execution::outstanding_work.tracked))+  {+  }++#if defined(ASIO_HAS_MOVE)+  work_dispatcher(const work_dispatcher& other)+    : handler_(other.handler_),+      executor_(other.executor_)+  {+  }++  work_dispatcher(work_dispatcher&& other)+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+      executor_(ASIO_MOVE_CAST(work_executor_type)(other.executor_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    execution::execute(+        asio::prefer(executor_,+          execution::blocking.possibly,+          execution::allocator((get_associated_allocator)(handler_))),+        ASIO_MOVE_CAST(Handler)(handler_));+  }++private:+  typedef typename decay<+      typename prefer_result<const Executor&,+        execution::outstanding_work_t::tracked_t+      >::type+    >::type work_executor_type;++  Handler handler_;+  work_executor_type executor_;+};++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Handler, typename Executor>+class work_dispatcher<Handler, Executor,+    typename enable_if<!execution::is_executor<Executor>::value>::type>+{+public:+  template <typename CompletionHandler>+  work_dispatcher(ASIO_MOVE_ARG(CompletionHandler) handler,+      const Executor& handler_ex)+    : work_(handler_ex),+      handler_(ASIO_MOVE_CAST(CompletionHandler)(handler))+  {+  }++#if defined(ASIO_HAS_MOVE)+  work_dispatcher(const work_dispatcher& other)+    : work_(other.work_),+      handler_(other.handler_)+  {+  }++  work_dispatcher(work_dispatcher&& other)+    : work_(ASIO_MOVE_CAST(executor_work_guard<Executor>)(other.work_)),+      handler_(ASIO_MOVE_CAST(Handler)(other.handler_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    typename associated_allocator<Handler>::type alloc(+        (get_associated_allocator)(handler_));+    work_.get_executor().dispatch(+        ASIO_MOVE_CAST(Handler)(handler_), alloc);+    work_.reset();+  }++private:+  executor_work_guard<Executor> work_;+  Handler handler_;+};++#endif // !defined(ASIO_NO_TS_EXECUTORS)++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_WORK_DISPATCHER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/wrapped_handler.hpp view
@@ -0,0 +1,327 @@+//+// detail/wrapped_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DETAIL_WRAPPED_HANDLER_HPP+#define ASIO_DETAIL_WRAPPED_HANDLER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++struct is_continuation_delegated+{+  template <typename Dispatcher, typename Handler>+  bool operator()(Dispatcher&, Handler& handler) const+  {+    return asio_handler_cont_helpers::is_continuation(handler);+  }+};++struct is_continuation_if_running+{+  template <typename Dispatcher, typename Handler>+  bool operator()(Dispatcher& dispatcher, Handler&) const+  {+    return dispatcher.running_in_this_thread();+  }+};++template <typename Dispatcher, typename Handler,+    typename IsContinuation = is_continuation_delegated>+class wrapped_handler+{+public:+  typedef void result_type;++  wrapped_handler(Dispatcher dispatcher, Handler& handler)+    : dispatcher_(dispatcher),+      handler_(ASIO_MOVE_CAST(Handler)(handler))+  {+  }++#if defined(ASIO_HAS_MOVE)+  wrapped_handler(const wrapped_handler& other)+    : dispatcher_(other.dispatcher_),+      handler_(other.handler_)+  {+  }++  wrapped_handler(wrapped_handler&& other)+    : dispatcher_(other.dispatcher_),+      handler_(ASIO_MOVE_CAST(Handler)(other.handler_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    dispatcher_.dispatch(ASIO_MOVE_CAST(Handler)(handler_));+  }++  void operator()() const+  {+    dispatcher_.dispatch(handler_);+  }++  template <typename Arg1>+  void operator()(const Arg1& arg1)+  {+    dispatcher_.dispatch(detail::bind_handler(handler_, arg1));+  }++  template <typename Arg1>+  void operator()(const Arg1& arg1) const+  {+    dispatcher_.dispatch(detail::bind_handler(handler_, arg1));+  }++  template <typename Arg1, typename Arg2>+  void operator()(const Arg1& arg1, const Arg2& arg2)+  {+    dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2));+  }++  template <typename Arg1, typename Arg2>+  void operator()(const Arg1& arg1, const Arg2& arg2) const+  {+    dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2));+  }++  template <typename Arg1, typename Arg2, typename Arg3>+  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3)+  {+    dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3));+  }++  template <typename Arg1, typename Arg2, typename Arg3>+  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3) const+  {+    dispatcher_.dispatch(detail::bind_handler(handler_, arg1, arg2, arg3));+  }++  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>+  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,+      const Arg4& arg4)+  {+    dispatcher_.dispatch(+        detail::bind_handler(handler_, arg1, arg2, arg3, arg4));+  }++  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4>+  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,+      const Arg4& arg4) const+  {+    dispatcher_.dispatch(+        detail::bind_handler(handler_, arg1, arg2, arg3, arg4));+  }++  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,+      typename Arg5>+  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,+      const Arg4& arg4, const Arg5& arg5)+  {+    dispatcher_.dispatch(+        detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5));+  }++  template <typename Arg1, typename Arg2, typename Arg3, typename Arg4,+      typename Arg5>+  void operator()(const Arg1& arg1, const Arg2& arg2, const Arg3& arg3,+      const Arg4& arg4, const Arg5& arg5) const+  {+    dispatcher_.dispatch(+        detail::bind_handler(handler_, arg1, arg2, arg3, arg4, arg5));+  }++//private:+  Dispatcher dispatcher_;+  Handler handler_;+};++template <typename Handler, typename Context>+class rewrapped_handler+{+public:+  explicit rewrapped_handler(Handler& handler, const Context& context)+    : context_(context),+      handler_(ASIO_MOVE_CAST(Handler)(handler))+  {+  }++  explicit rewrapped_handler(const Handler& handler, const Context& context)+    : context_(context),+      handler_(handler)+  {+  }++#if defined(ASIO_HAS_MOVE)+  rewrapped_handler(const rewrapped_handler& other)+    : context_(other.context_),+      handler_(other.handler_)+  {+  }++  rewrapped_handler(rewrapped_handler&& other)+    : context_(ASIO_MOVE_CAST(Context)(other.context_)),+      handler_(ASIO_MOVE_CAST(Handler)(other.handler_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    handler_();+  }++  void operator()() const+  {+    handler_();+  }++//private:+  Context context_;+  Handler handler_;+};++template <typename Dispatcher, typename Handler, typename IsContinuation>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Dispatcher, typename Handler, typename IsContinuation>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Dispatcher, typename Handler, typename IsContinuation>+inline bool asio_handler_is_continuation(+    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)+{+  return IsContinuation()(this_handler->dispatcher_, this_handler->handler_);+}++template <typename Function, typename Dispatcher,+    typename Handler, typename IsContinuation>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)+{+  this_handler->dispatcher_.dispatch(+      rewrapped_handler<Function, Handler>(+        function, this_handler->handler_));+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Dispatcher,+    typename Handler, typename IsContinuation>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+    wrapped_handler<Dispatcher, Handler, IsContinuation>* this_handler)+{+  this_handler->dispatcher_.dispatch(+      rewrapped_handler<Function, Handler>(+        function, this_handler->handler_));+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Context>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    rewrapped_handler<Handler, Context>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler, typename Context>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    rewrapped_handler<Handler, Context>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->context_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Dispatcher, typename Context>+inline bool asio_handler_is_continuation(+    rewrapped_handler<Dispatcher, Context>* this_handler)+{+  return asio_handler_cont_helpers::is_continuation(+      this_handler->context_);+}++template <typename Function, typename Handler, typename Context>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+    rewrapped_handler<Handler, Context>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->context_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler, typename Context>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+    rewrapped_handler<Handler, Context>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->context_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_WRAPPED_HANDLER_HPP
+ link/modules/asio-standalone/asio/include/asio/dispatch.hpp view
@@ -0,0 +1,121 @@+//+// dispatch.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_DISPATCH_HPP+#define ASIO_DISPATCH_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 may be called from the current thread prior to+ * returning from <tt>dispatch()</tt>. Otherwise, it is queued for execution.+ *+ * This function has the following effects:+ *+ * @li Constructs a function object handler of type @c Handler, initialized+ * with <tt>handler(forward<CompletionToken>(token))</tt>.+ *+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,+ * initializing the object as <tt>result(handler)</tt>.+ *+ * @li Obtains the handler's associated executor object @c ex by performing+ * <tt>get_associated_executor(handler)</tt>.+ *+ * @li Obtains the handler's associated allocator object @c alloc by performing+ * <tt>get_associated_allocator(handler)</tt>.+ *+ * @li Performs <tt>ex.dispatch(std::move(handler), alloc)</tt>.+ *+ * @li Returns <tt>result.get()</tt>.+ */+template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+    ASIO_MOVE_ARG(CompletionToken) token);++/// Submits a completion token or function object for execution.+/**+ * This function submits an object for execution using the specified executor.+ * The function object may be called from the current thread prior to returning+ * from <tt>dispatch()</tt>. Otherwise, it is queued for execution.+ *+ * This function has the following effects:+ *+ * @li Constructs a function object handler of type @c Handler, initialized+ * with <tt>handler(forward<CompletionToken>(token))</tt>.+ *+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,+ * initializing the object as <tt>result(handler)</tt>.+ *+ * @li Obtains the handler's associated executor object @c ex1 by performing+ * <tt>get_associated_executor(handler)</tt>.+ *+ * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.+ *+ * @li Obtains the handler's associated allocator object @c alloc by performing+ * <tt>get_associated_allocator(handler)</tt>.+ *+ * @li Constructs a function object @c f with a function call operator that+ * performs <tt>ex1.dispatch(std::move(handler), alloc)</tt> followed by+ * <tt>w.reset()</tt>.+ *+ * @li Performs <tt>Executor(ex).dispatch(std::move(f), alloc)</tt>.+ *+ * @li Returns <tt>result.get()</tt>.+ */+template <typename Executor,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+      ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+    const Executor& ex,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+    typename enable_if<+      execution::is_executor<Executor>::value || is_executor<Executor>::value+    >::type* = 0);++/// Submits a completion token or function object for execution.+/**+ * @returns <tt>dispatch(ctx.get_executor(),+ * forward<CompletionToken>(token))</tt>.+ */+template <typename ExecutionContext,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+      ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+        typename ExecutionContext::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+    ExecutionContext& ctx,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename ExecutionContext::executor_type),+    typename enable_if<is_convertible<+      ExecutionContext&, execution_context&>::value>::type* = 0);++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/dispatch.hpp"++#endif // ASIO_DISPATCH_HPP
+ link/modules/asio-standalone/asio/include/asio/error.hpp view
@@ -0,0 +1,356 @@+//+// error.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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_ERROR_HPP+#define ASIO_ERROR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/error_code.hpp"+#include "asio/system_error.hpp"+#if defined(ASIO_WINDOWS) \+  || defined(__CYGWIN__) \+  || defined(ASIO_WINDOWS_RUNTIME)+# include <winerror.h>+#else+# include <cerrno>+# include <netdb.h>+#endif++#if defined(GENERATING_DOCUMENTATION)+/// INTERNAL ONLY.+# define ASIO_NATIVE_ERROR(e) implementation_defined+/// INTERNAL ONLY.+# define ASIO_SOCKET_ERROR(e) implementation_defined+/// INTERNAL ONLY.+# define ASIO_NETDB_ERROR(e) implementation_defined+/// INTERNAL ONLY.+# define ASIO_GETADDRINFO_ERROR(e) implementation_defined+/// INTERNAL ONLY.+# define ASIO_WIN_OR_POSIX(e_win, e_posix) implementation_defined+#elif defined(ASIO_WINDOWS_RUNTIME)+# define ASIO_NATIVE_ERROR(e) __HRESULT_FROM_WIN32(e)+# define ASIO_SOCKET_ERROR(e) __HRESULT_FROM_WIN32(WSA ## e)+# define ASIO_NETDB_ERROR(e) __HRESULT_FROM_WIN32(WSA ## e)+# define ASIO_GETADDRINFO_ERROR(e) __HRESULT_FROM_WIN32(WSA ## e)+# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_win+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# define ASIO_NATIVE_ERROR(e) e+# define ASIO_SOCKET_ERROR(e) WSA ## e+# define ASIO_NETDB_ERROR(e) WSA ## e+# define ASIO_GETADDRINFO_ERROR(e) WSA ## e+# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_win+#else+# define ASIO_NATIVE_ERROR(e) e+# define ASIO_SOCKET_ERROR(e) e+# define ASIO_NETDB_ERROR(e) e+# define ASIO_GETADDRINFO_ERROR(e) e+# define ASIO_WIN_OR_POSIX(e_win, e_posix) e_posix+#endif++#include "asio/detail/push_options.hpp"++namespace asio {+namespace error {++enum basic_errors+{+  /// Permission denied.+  access_denied = ASIO_SOCKET_ERROR(EACCES),++  /// Address family not supported by protocol.+  address_family_not_supported = ASIO_SOCKET_ERROR(EAFNOSUPPORT),++  /// Address already in use.+  address_in_use = ASIO_SOCKET_ERROR(EADDRINUSE),++  /// Transport endpoint is already connected.+  already_connected = ASIO_SOCKET_ERROR(EISCONN),++  /// Operation already in progress.+  already_started = ASIO_SOCKET_ERROR(EALREADY),++  /// Broken pipe.+  broken_pipe = ASIO_WIN_OR_POSIX(+      ASIO_NATIVE_ERROR(ERROR_BROKEN_PIPE),+      ASIO_NATIVE_ERROR(EPIPE)),++  /// A connection has been aborted.+  connection_aborted = ASIO_SOCKET_ERROR(ECONNABORTED),++  /// Connection refused.+  connection_refused = ASIO_SOCKET_ERROR(ECONNREFUSED),++  /// Connection reset by peer.+  connection_reset = ASIO_SOCKET_ERROR(ECONNRESET),++  /// Bad file descriptor.+  bad_descriptor = ASIO_SOCKET_ERROR(EBADF),++  /// Bad address.+  fault = ASIO_SOCKET_ERROR(EFAULT),++  /// No route to host.+  host_unreachable = ASIO_SOCKET_ERROR(EHOSTUNREACH),++  /// Operation now in progress.+  in_progress = ASIO_SOCKET_ERROR(EINPROGRESS),++  /// Interrupted system call.+  interrupted = ASIO_SOCKET_ERROR(EINTR),++  /// Invalid argument.+  invalid_argument = ASIO_SOCKET_ERROR(EINVAL),++  /// Message too long.+  message_size = ASIO_SOCKET_ERROR(EMSGSIZE),++  /// The name was too long.+  name_too_long = ASIO_SOCKET_ERROR(ENAMETOOLONG),++  /// Network is down.+  network_down = ASIO_SOCKET_ERROR(ENETDOWN),++  /// Network dropped connection on reset.+  network_reset = ASIO_SOCKET_ERROR(ENETRESET),++  /// Network is unreachable.+  network_unreachable = ASIO_SOCKET_ERROR(ENETUNREACH),++  /// Too many open files.+  no_descriptors = ASIO_SOCKET_ERROR(EMFILE),++  /// No buffer space available.+  no_buffer_space = ASIO_SOCKET_ERROR(ENOBUFS),++  /// Cannot allocate memory.+  no_memory = ASIO_WIN_OR_POSIX(+      ASIO_NATIVE_ERROR(ERROR_OUTOFMEMORY),+      ASIO_NATIVE_ERROR(ENOMEM)),++  /// Operation not permitted.+  no_permission = ASIO_WIN_OR_POSIX(+      ASIO_NATIVE_ERROR(ERROR_ACCESS_DENIED),+      ASIO_NATIVE_ERROR(EPERM)),++  /// Protocol not available.+  no_protocol_option = ASIO_SOCKET_ERROR(ENOPROTOOPT),++  /// No such device.+  no_such_device = ASIO_WIN_OR_POSIX(+      ASIO_NATIVE_ERROR(ERROR_BAD_UNIT),+      ASIO_NATIVE_ERROR(ENODEV)),++  /// Transport endpoint is not connected.+  not_connected = ASIO_SOCKET_ERROR(ENOTCONN),++  /// Socket operation on non-socket.+  not_socket = ASIO_SOCKET_ERROR(ENOTSOCK),++  /// Operation cancelled.+  operation_aborted = ASIO_WIN_OR_POSIX(+      ASIO_NATIVE_ERROR(ERROR_OPERATION_ABORTED),+      ASIO_NATIVE_ERROR(ECANCELED)),++  /// Operation not supported.+  operation_not_supported = ASIO_SOCKET_ERROR(EOPNOTSUPP),++  /// Cannot send after transport endpoint shutdown.+  shut_down = ASIO_SOCKET_ERROR(ESHUTDOWN),++  /// Connection timed out.+  timed_out = ASIO_SOCKET_ERROR(ETIMEDOUT),++  /// Resource temporarily unavailable.+  try_again = ASIO_WIN_OR_POSIX(+      ASIO_NATIVE_ERROR(ERROR_RETRY),+      ASIO_NATIVE_ERROR(EAGAIN)),++  /// The socket is marked non-blocking and the requested operation would block.+  would_block = ASIO_SOCKET_ERROR(EWOULDBLOCK)+};++enum netdb_errors+{+  /// Host not found (authoritative).+  host_not_found = ASIO_NETDB_ERROR(HOST_NOT_FOUND),++  /// Host not found (non-authoritative).+  host_not_found_try_again = ASIO_NETDB_ERROR(TRY_AGAIN),++  /// The query is valid but does not have associated address data.+  no_data = ASIO_NETDB_ERROR(NO_DATA),++  /// A non-recoverable error occurred.+  no_recovery = ASIO_NETDB_ERROR(NO_RECOVERY)+};++enum addrinfo_errors+{+  /// The service is not supported for the given socket type.+  service_not_found = ASIO_WIN_OR_POSIX(+      ASIO_NATIVE_ERROR(WSATYPE_NOT_FOUND),+      ASIO_GETADDRINFO_ERROR(EAI_SERVICE)),++  /// The socket type is not supported.+  socket_type_not_supported = ASIO_WIN_OR_POSIX(+      ASIO_NATIVE_ERROR(WSAESOCKTNOSUPPORT),+      ASIO_GETADDRINFO_ERROR(EAI_SOCKTYPE))+};++enum misc_errors+{+  /// Already open.+  already_open = 1,++  /// End of file or stream.+  eof,++  /// Element not found.+  not_found,++  /// The descriptor cannot fit into the select system call's fd_set.+  fd_set_failure+};++inline const asio::error_category& get_system_category()+{+  return asio::system_category();+}++#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++extern ASIO_DECL+const asio::error_category& get_netdb_category();++extern ASIO_DECL+const asio::error_category& get_addrinfo_category();++#else // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++inline const asio::error_category& get_netdb_category()+{+  return get_system_category();+}++inline const asio::error_category& get_addrinfo_category()+{+  return get_system_category();+}++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++extern ASIO_DECL+const asio::error_category& get_misc_category();++static const asio::error_category&+  system_category ASIO_UNUSED_VARIABLE+  = asio::error::get_system_category();+static const asio::error_category&+  netdb_category ASIO_UNUSED_VARIABLE+  = asio::error::get_netdb_category();+static const asio::error_category&+  addrinfo_category ASIO_UNUSED_VARIABLE+  = asio::error::get_addrinfo_category();+static const asio::error_category&+  misc_category ASIO_UNUSED_VARIABLE+  = asio::error::get_misc_category();++} // namespace error+} // namespace asio++#if defined(ASIO_HAS_STD_SYSTEM_ERROR)+namespace std {++template<> struct is_error_code_enum<asio::error::basic_errors>+{+  static const bool value = true;+};++template<> struct is_error_code_enum<asio::error::netdb_errors>+{+  static const bool value = true;+};++template<> struct is_error_code_enum<asio::error::addrinfo_errors>+{+  static const bool value = true;+};++template<> struct is_error_code_enum<asio::error::misc_errors>+{+  static const bool value = true;+};++} // namespace std+#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)++namespace asio {+namespace error {++inline asio::error_code make_error_code(basic_errors e)+{+  return asio::error_code(+      static_cast<int>(e), get_system_category());+}++inline asio::error_code make_error_code(netdb_errors e)+{+  return asio::error_code(+      static_cast<int>(e), get_netdb_category());+}++inline asio::error_code make_error_code(addrinfo_errors e)+{+  return asio::error_code(+      static_cast<int>(e), get_addrinfo_category());+}++inline asio::error_code make_error_code(misc_errors e)+{+  return asio::error_code(+      static_cast<int>(e), get_misc_category());+}++} // namespace error+namespace stream_errc {+  // Simulates the proposed stream_errc scoped enum.+  using error::eof;+  using error::not_found;+} // namespace stream_errc+namespace socket_errc {+  // Simulates the proposed socket_errc scoped enum.+  using error::already_open;+  using error::not_found;+} // namespace socket_errc+namespace resolver_errc {+  // Simulates the proposed resolver_errc scoped enum.+  using error::host_not_found;+  const error::netdb_errors try_again = error::host_not_found_try_again;+  using error::service_not_found;+} // namespace resolver_errc+} // namespace asio++#include "asio/detail/pop_options.hpp"++#undef ASIO_NATIVE_ERROR+#undef ASIO_SOCKET_ERROR+#undef ASIO_NETDB_ERROR+#undef ASIO_GETADDRINFO_ERROR+#undef ASIO_WIN_OR_POSIX++#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/error.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/error_code.hpp view
@@ -0,0 +1,202 @@+//+// error_code.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_ERROR_CODE_HPP+#define ASIO_ERROR_CODE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_SYSTEM_ERROR)+# include <system_error>+#else // defined(ASIO_HAS_STD_SYSTEM_ERROR)+# include <string>+# include "asio/detail/noncopyable.hpp"+# if !defined(ASIO_NO_IOSTREAM)+#  include <iosfwd>+# endif // !defined(ASIO_NO_IOSTREAM)+#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(ASIO_HAS_STD_SYSTEM_ERROR)++typedef std::error_category error_category;++#else // defined(ASIO_HAS_STD_SYSTEM_ERROR)++/// Base class for all error categories.+class error_category : private noncopyable+{+public:+  /// Destructor.+  virtual ~error_category()+  {+  }++  /// Returns a string naming the error gategory.+  virtual const char* name() const = 0;++  /// Returns a string describing the error denoted by @c value.+  virtual std::string message(int value) const = 0;++  /// Equality operator to compare two error categories.+  bool operator==(const error_category& rhs) const+  {+    return this == &rhs;+  }++  /// Inequality operator to compare two error categories.+  bool operator!=(const error_category& rhs) const+  {+    return !(*this == rhs);+  }+};++#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)++/// Returns the error category used for the system errors produced by asio.+extern ASIO_DECL const error_category& system_category();++#if defined(ASIO_HAS_STD_SYSTEM_ERROR)++typedef std::error_code error_code;++#else // defined(ASIO_HAS_STD_SYSTEM_ERROR)++/// Class to represent an error code value.+class error_code+{+public:+  /// Default constructor.+  error_code()+    : value_(0),+      category_(&system_category())+  {+  }++  /// Construct with specific error code and category.+  error_code(int v, const error_category& c)+    : value_(v),+      category_(&c)+  {+  }++  /// Construct from an error code enum.+  template <typename ErrorEnum>+  error_code(ErrorEnum e)+  {+    *this = make_error_code(e);+  }++  /// Clear the error value to the default.+  void clear()+  {+    value_ = 0;+    category_ = &system_category();+  }++  /// Assign a new error value.+  void assign(int v, const error_category& c)+  {+    value_ = v;+    category_ = &c;+  }++  /// Get the error value.+  int value() const+  {+    return value_;+  }++  /// Get the error category.+  const error_category& category() const+  {+    return *category_;+  }++  /// Get the message associated with the error.+  std::string message() const+  {+    return category_->message(value_);+  }++  struct unspecified_bool_type_t+  {+  };++  typedef void (*unspecified_bool_type)(unspecified_bool_type_t);++  static void unspecified_bool_true(unspecified_bool_type_t) {}++  /// Operator returns non-null if there is a non-success error code.+  operator unspecified_bool_type() const+  {+    if (value_ == 0)+      return 0;+    else+      return &error_code::unspecified_bool_true;+  }++  /// Operator to test if the error represents success.+  bool operator!() const+  {+    return value_ == 0;+  }++  /// Equality operator to compare two error objects.+  friend bool operator==(const error_code& e1, const error_code& e2)+  {+    return e1.value_ == e2.value_ && e1.category_ == e2.category_;+  }++  /// Inequality operator to compare two error objects.+  friend bool operator!=(const error_code& e1, const error_code& e2)+  {+    return e1.value_ != e2.value_ || e1.category_ != e2.category_;+  }++private:+  // The value associated with the error code.+  int value_;++  // The category associated with the error code.+  const error_category* category_;+};++# if !defined(ASIO_NO_IOSTREAM)++/// Output an error code.+template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const error_code& ec)+{+  os << ec.category().name() << ':' << ec.value();+  return os;+}++# endif // !defined(ASIO_NO_IOSTREAM)++#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/error_code.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_ERROR_CODE_HPP
+ link/modules/asio-standalone/asio/include/asio/execution.hpp view
@@ -0,0 +1,48 @@+//+// execution.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_HPP+#define ASIO_EXECUTION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/execution/allocator.hpp"+#include "asio/execution/any_executor.hpp"+#include "asio/execution/bad_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/submit.hpp"++#endif // ASIO_EXECUTION_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/allocator.hpp view
@@ -0,0 +1,249 @@+//+// execution/allocator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_ALLOCATOR_HPP+#define ASIO_EXECUTION_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/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/static_query.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property to describe which allocator an executor will use to allocate the+/// memory required to store a submitted function object.+template <typename ProtoAllocator>+struct allocator_t+{+  /// The allocator_t property applies to executors, senders, and schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The allocator_t property can be required.+  static constexpr bool is_requirable = true;++  /// The allocator_t property can be preferred.+  static constexpr bool is_preferable = true;++  /// Default constructor.+  constexpr allocator_t();++  /// Obtain the allocator stored in the allocator_t property object.+  /**+   * Present only if @c ProtoAllocator is non-void.+   */+  constexpr ProtoAllocator value() const;++  /// Create an allocator_t object with a different allocator.+  /**+   * Present only if @c ProtoAllocator is void.+   */+  template <typename OtherAllocator>+  allocator_t<OtherAllocator operator()(const OtherAllocator& a);+};++/// A special value used for accessing the allocator_t property.+constexpr allocator_t<void> allocator;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {++template <typename ProtoAllocator>+struct allocator_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, allocator_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, allocator_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, allocator_t>::value();+  }++  template <typename E, typename T = decltype(allocator_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = allocator_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  ASIO_CONSTEXPR ProtoAllocator value() const+  {+    return a_;+  }++private:+  friend struct allocator_t<void>;++  explicit ASIO_CONSTEXPR allocator_t(const ProtoAllocator& a)+    : a_(a)+  {+  }++  ProtoAllocator a_;+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <typename ProtoAllocator> template <typename E, typename T>+const T allocator_t<ProtoAllocator>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <>+struct allocator_t<void>+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);++  ASIO_CONSTEXPR allocator_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, allocator_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, allocator_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, allocator_t>::value();+  }++  template <typename E, typename T = decltype(allocator_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = allocator_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  template <typename OtherProtoAllocator>+  ASIO_CONSTEXPR allocator_t<OtherProtoAllocator> operator()(+      const OtherProtoAllocator& a) const+  {+    return allocator_t<OtherProtoAllocator>(a);+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <typename E, typename T>+const T allocator_t<void>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr allocator_t<void> allocator;+#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+template <typename T>+struct allocator_instance+{+  static allocator_t<T> instance;+};++template <typename T>+allocator_t<T> allocator_instance<T>::instance;++namespace {+static const allocator_t<void>& allocator = allocator_instance<void>::instance;+} // namespace+#endif++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename ProtoAllocator>+struct is_applicable_property<T, execution::allocator_t<ProtoAllocator> >+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T, typename ProtoAllocator>+struct static_query<T, execution::allocator_t<ProtoAllocator>,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::allocator_t<ProtoAllocator> >::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::allocator_t<ProtoAllocator> >::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::allocator_t<ProtoAllocator> >::value();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_ALLOCATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/any_executor.hpp view
@@ -0,0 +1,2264 @@+//+// execution/any_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_ANY_EXECUTOR_HPP+#define ASIO_EXECUTION_ANY_EXECUTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <new>+#include <typeinfo>+#include "asio/detail/assert.hpp"+#include "asio/detail/cstddef.hpp"+#include "asio/detail/executor_function.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/scoped_ptr.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/execution/bad_executor.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/execution/execute.hpp"+#include "asio/execution/executor.hpp"+#include "asio/prefer.hpp"+#include "asio/query.hpp"+#include "asio/require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// Polymorphic executor wrapper.+template <typename... SupportableProperties>+class any_executor+{+public:+  /// Default constructor.+  any_executor() noexcept;++  /// Construct in an empty state. Equivalent effects to default constructor.+  any_executor(nullptr_t) noexcept;++  /// Copy constructor.+  any_executor(const any_executor& e) noexcept;++  /// Move constructor.+  any_executor(any_executor&& e) noexcept;++  /// Construct to point to the same target as another any_executor.+  template <class... OtherSupportableProperties>+    any_executor(any_executor<OtherSupportableProperties...> e);++  /// Construct a polymorphic wrapper for the specified executor.+  template <typename Executor>+  any_executor(Executor e);++  /// Assignment operator.+  any_executor& operator=(const any_executor& e) noexcept;++  /// Move assignment operator.+  any_executor& operator=(any_executor&& e) noexcept;++  /// Assignment operator that sets the polymorphic wrapper to the empty state.+  any_executor& operator=(nullptr_t);++  /// Assignment operator to create a polymorphic wrapper for the specified+  /// executor.+  template <typename Executor>+  any_executor& operator=(Executor e);++  /// Destructor.+  ~any_executor();++  /// Swap targets with another polymorphic wrapper.+  void swap(any_executor& other) 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 execution::any_executor<execution::blocking_t::possibly_t> ex = ...;+   * auto ex2 = asio::requre(ex, execution::blocking.possibly); @endcode+   */+  template <typename Property>+  any_executor require(Property) const;++  /// 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 execution::any_executor<execution::blocking_t::possibly_t> ex = ...;+   * auto ex2 = asio::prefer(ex, execution::blocking.possibly); @endcode+   */+  template <typename Property>+  any_executor prefer(Property) const;++  /// Obtain the value associated with the specified property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code execution::any_executor<execution::occupancy_t> ex = ...;+   * size_t n = asio::query(ex, execution::occupancy); @endcode+   */+  template <typename Property>+  typename Property::polymorphic_query_result_type query(Property) const;++  /// Execute the function on the target executor.+  /**+   * Do not call this function directly. It is intended for use with the+   * execution::execute customisation point.+   *+   * For example:+   * @code execution::any_executor<> ex = ...;+   * execution::execute(ex, my_function_object); @endcode+   *+   * Throws asio::bad_executor if the polymorphic wrapper has no target.+   */+  template <typename Function>+  void execute(Function&& f) const;++  /// Obtain the underlying execution context.+  /**+   * This function is provided for backward compatibility. It is automatically+   * defined when the @c SupportableProperties... list includes a property of+   * type <tt>execution::context_as<U></tt>, for some type <tt>U</tt>.+   */+  automatically_determined context() const;++  /// Determine whether the wrapper has a target executor.+  /**+   * @returns @c true if the polymorphic wrapper has a target executor,+   * otherwise false.+   */+  explicit operator bool() const noexcept;++  /// Get the type of the target executor.+  const type_info& target_type() const noexcept;++  /// Get a pointer to the target executor.+  template <typename Executor> Executor* target() noexcept;++  /// Get a pointer to the target executor.+  template <typename Executor> const Executor* target() const noexcept;+};++/// Equality operator.+/**+ * @relates any_executor+ */+template <typename... SupportableProperties>+bool operator==(const any_executor<SupportableProperties...>& a,+    const any_executor<SupportableProperties...>& b) noexcept;++/// Equality operator.+/**+ * @relates any_executor+ */+template <typename... SupportableProperties>+bool operator==(const any_executor<SupportableProperties...>& a,+    nullptr_t) noexcept;++/// Equality operator.+/**+ * @relates any_executor+ */+template <typename... SupportableProperties>+bool operator==(nullptr_t,+    const any_executor<SupportableProperties...>& b) noexcept;++/// Inequality operator.+/**+ * @relates any_executor+ */+template <typename... SupportableProperties>+bool operator!=(const any_executor<SupportableProperties...>& a,+    const any_executor<SupportableProperties...>& b) noexcept;++/// Inequality operator.+/**+ * @relates any_executor+ */+template <typename... SupportableProperties>+bool operator!=(const any_executor<SupportableProperties...>& a,+    nullptr_t) noexcept;++/// Inequality operator.+/**+ * @relates any_executor+ */+template <typename... SupportableProperties>+bool operator!=(nullptr_t,+    const any_executor<SupportableProperties...>& b) noexcept;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {++#if !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)+#define ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... SupportableProperties>+class any_executor;++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void>+class any_executor;++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#endif // !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)++template <typename U>+struct context_as_t;++namespace detail {++// Traits used to detect whether a property is requirable or preferable, taking+// into account that T::is_requirable or T::is_preferable may not not be well+// formed.++template <typename T, typename = void>+struct is_requirable : false_type {};++template <typename T>+struct is_requirable<T, typename enable_if<T::is_requirable>::type> :+  true_type {};++template <typename T, typename = void>+struct is_preferable : false_type {};++template <typename T>+struct is_preferable<T, typename enable_if<T::is_preferable>::type> :+  true_type {};++// Trait used to detect context_as property, for backward compatibility.++template <typename T>+struct is_context_as : false_type {};++template <typename U>+struct is_context_as<context_as_t<U> > : true_type {};++// Helper template to:+// - Check if a target can supply the supportable properties.+// - Find the first convertible-from-T property in the list.++template <std::size_t I, typename Props>+struct supportable_properties;++template <std::size_t I, typename Prop>+struct supportable_properties<I, void(Prop)>+{+  template <typename T>+  struct is_valid_target : integral_constant<bool,+      (+        is_requirable<Prop>::value+          ? can_require<T, Prop>::value+          : true+      )+      &&+      (+        is_preferable<Prop>::value+          ? can_prefer<T, Prop>::value+          : true+      )+      &&+      (+        !is_requirable<Prop>::value && !is_preferable<Prop>::value+          ? can_query<T, Prop>::value+          : true+      )+    >+  {+  };++  struct found+  {+    ASIO_STATIC_CONSTEXPR(bool, value = true);+    typedef Prop type;+    typedef typename Prop::polymorphic_query_result_type query_result_type;+    ASIO_STATIC_CONSTEXPR(std::size_t, index = I);+  };++  struct not_found+  {+    ASIO_STATIC_CONSTEXPR(bool, value = false);+  };++  template <typename T>+  struct find_convertible_property :+      conditional<+        is_same<T, Prop>::value || is_convertible<T, Prop>::value,+        found,+        not_found+      >::type {};++  template <typename T>+  struct find_convertible_requirable_property :+      conditional<+        is_requirable<Prop>::value+          && (is_same<T, Prop>::value || is_convertible<T, Prop>::value),+        found,+        not_found+      >::type {};++  template <typename T>+  struct find_convertible_preferable_property :+      conditional<+        is_preferable<Prop>::value+          && (is_same<T, Prop>::value || is_convertible<T, Prop>::value),+        found,+        not_found+      >::type {};++  struct find_context_as_property :+      conditional<+        is_context_as<Prop>::value,+        found,+        not_found+      >::type {};+};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <std::size_t I, typename Head, typename... Tail>+struct supportable_properties<I, void(Head, Tail...)>+{+  template <typename T>+  struct is_valid_target : integral_constant<bool,+      (+        supportable_properties<I,+          void(Head)>::template is_valid_target<T>::value+        &&+        supportable_properties<I + 1,+          void(Tail...)>::template is_valid_target<T>::value+      )+    >+  {+  };++  template <typename T>+  struct find_convertible_property :+      conditional<+        is_convertible<T, Head>::value,+        typename supportable_properties<I, void(Head)>::found,+        typename supportable_properties<I + 1,+            void(Tail...)>::template find_convertible_property<T>+      >::type {};++  template <typename T>+  struct find_convertible_requirable_property :+      conditional<+        is_requirable<Head>::value+          && is_convertible<T, Head>::value,+        typename supportable_properties<I, void(Head)>::found,+        typename supportable_properties<I + 1,+            void(Tail...)>::template find_convertible_requirable_property<T>+      >::type {};++  template <typename T>+  struct find_convertible_preferable_property :+      conditional<+        is_preferable<Head>::value+          && is_convertible<T, Head>::value,+        typename supportable_properties<I, void(Head)>::found,+        typename supportable_properties<I + 1,+            void(Tail...)>::template find_convertible_preferable_property<T>+      >::type {};++  struct find_context_as_property :+      conditional<+        is_context_as<Head>::value,+        typename supportable_properties<I, void(Head)>::found,+        typename supportable_properties<I + 1,+            void(Tail...)>::find_context_as_property+      >::type {};+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF(n) \+  template <std::size_t I, \+    typename Head, ASIO_VARIADIC_TPARAMS(n)> \+  struct supportable_properties<I, \+      void(Head, ASIO_VARIADIC_TARGS(n))> \+  { \+    template <typename T> \+    struct is_valid_target : integral_constant<bool, \+        ( \+          supportable_properties<I, \+            void(Head)>::template is_valid_target<T>::value \+          && \+          supportable_properties<I + 1, \+              void(ASIO_VARIADIC_TARGS(n))>::template \+                is_valid_target<T>::value \+        ) \+      > \+    { \+    }; \+  \+    template <typename T> \+    struct find_convertible_property : \+        conditional< \+          is_convertible<T, Head>::value, \+          typename supportable_properties<I, void(Head)>::found, \+          typename supportable_properties<I + 1, \+              void(ASIO_VARIADIC_TARGS(n))>::template \+                find_convertible_property<T> \+        >::type {}; \+  \+    template <typename T> \+    struct find_convertible_requirable_property : \+        conditional< \+          is_requirable<Head>::value \+            && is_convertible<T, Head>::value, \+          typename supportable_properties<I, void(Head)>::found, \+          typename supportable_properties<I + 1, \+              void(ASIO_VARIADIC_TARGS(n))>::template \+                find_convertible_requirable_property<T> \+        >::type {}; \+  \+    template <typename T> \+    struct find_convertible_preferable_property : \+        conditional< \+          is_preferable<Head>::value \+            && is_convertible<T, Head>::value, \+          typename supportable_properties<I, void(Head)>::found, \+          typename supportable_properties<I + 1, \+              void(ASIO_VARIADIC_TARGS(n))>::template \+                find_convertible_preferable_property<T> \+        >::type {}; \+  \+    struct find_context_as_property : \+        conditional< \+          is_context_as<Head>::value, \+          typename supportable_properties<I, void(Head)>::found, \+          typename supportable_properties<I + 1, void( \+            ASIO_VARIADIC_TARGS(n))>::find_context_as_property \+        >::type {}; \+  }; \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF)+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROPS_BASE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename Props>+struct is_valid_target_executor :+  conditional<+    is_executor<T>::value,+    typename supportable_properties<0, Props>::template is_valid_target<T>,+    false_type+  >::type+{+};++class any_executor_base+{+public:+  any_executor_base() ASIO_NOEXCEPT+    : object_fns_(object_fns_table<void>()),+      target_(0),+      target_fns_(target_fns_table<void>())+  {+  }++  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_executor_base(Executor ex, false_type)+    : target_fns_(target_fns_table<Executor>(+          any_executor_base::query_blocking(ex,+            can_query<const Executor&, const execution::blocking_t&>())+          == execution::blocking.always))+  {+    any_executor_base::construct_object(ex,+        integral_constant<bool,+          sizeof(Executor) <= sizeof(object_type)+            && alignment_of<Executor>::value <= alignment_of<object_type>::value+        >());+  }++  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_executor_base(Executor other, true_type)+    : object_fns_(object_fns_table<asio::detail::shared_ptr<void> >()),+      target_fns_(other.target_fns_)+  {+    asio::detail::shared_ptr<Executor> p =+      asio::detail::make_shared<Executor>(+          ASIO_MOVE_CAST(Executor)(other));+    target_ = p->template target<void>();+    new (&object_) asio::detail::shared_ptr<void>(+        ASIO_MOVE_CAST(asio::detail::shared_ptr<Executor>)(p));+  }++  any_executor_base(const any_executor_base& other) ASIO_NOEXCEPT+    : object_fns_(other.object_fns_),+      target_fns_(other.target_fns_)+  {+    object_fns_->copy(*this, other);+  }++  ~any_executor_base() ASIO_NOEXCEPT+  {+    object_fns_->destroy(*this);+  }++  any_executor_base& operator=(+      const any_executor_base& other) ASIO_NOEXCEPT+  {+    if (this != &other)+    {+      object_fns_->destroy(*this);+      object_fns_ = other.object_fns_;+      target_fns_ = other.target_fns_;+      object_fns_->copy(*this, other);+    }+    return *this;+  }++  any_executor_base& operator=(nullptr_t) ASIO_NOEXCEPT+  {+    object_fns_->destroy(*this);+    target_ = 0;+    object_fns_ = object_fns_table<void>();+    target_fns_ = target_fns_table<void>();+    return *this;+  }++#if defined(ASIO_HAS_MOVE)++  any_executor_base(any_executor_base&& other) ASIO_NOEXCEPT+    : object_fns_(other.object_fns_),+      target_fns_(other.target_fns_)+  {+    other.object_fns_ = object_fns_table<void>();+    other.target_fns_ = target_fns_table<void>();+    object_fns_->move(*this, other);+    other.target_ = 0;+  }++  any_executor_base& operator=(+      any_executor_base&& other) ASIO_NOEXCEPT+  {+    if (this != &other)+    {+      object_fns_->destroy(*this);+      object_fns_ = other.object_fns_;+      other.object_fns_ = object_fns_table<void>();+      target_fns_ = other.target_fns_;+      other.target_fns_ = target_fns_table<void>();+      object_fns_->move(*this, other);+      other.target_ = 0;+    }+    return *this;+  }++#endif // defined(ASIO_HAS_MOVE)++  void swap(any_executor_base& other) ASIO_NOEXCEPT+  {+    if (this != &other)+    {+      any_executor_base tmp(ASIO_MOVE_CAST(any_executor_base)(other));+      other = ASIO_MOVE_CAST(any_executor_base)(*this);+      *this = ASIO_MOVE_CAST(any_executor_base)(tmp);+    }+  }++  template <typename F>+  void execute(ASIO_MOVE_ARG(F) f) const+  {+    if (target_fns_->blocking_execute != 0)+    {+      asio::detail::non_const_lvalue<F> f2(f);+      target_fns_->blocking_execute(*this, function_view(f2.value));+    }+    else+    {+      target_fns_->execute(*this,+          function(ASIO_MOVE_CAST(F)(f), std::allocator<void>()));+    }+  }++  template <typename Executor>+  Executor* target()+  {+    return static_cast<Executor*>(target_);+  }++  template <typename Executor>+  const Executor* target() const+  {+    return static_cast<Executor*>(target_);+  }++  const std::type_info& target_type() const+  {+    return target_fns_->target_type();+  }++  struct unspecified_bool_type_t {};+  typedef void (*unspecified_bool_type)(unspecified_bool_type_t);+  static void unspecified_bool_true(unspecified_bool_type_t) {}++  operator unspecified_bool_type() const ASIO_NOEXCEPT+  {+    return target_ ? &any_executor_base::unspecified_bool_true : 0;+  }++  bool operator!() const ASIO_NOEXCEPT+  {+    return target_ == 0;+  }++protected:+  bool equality_helper(const any_executor_base& other) const ASIO_NOEXCEPT+  {+    if (target_ == other.target_)+      return true;+    if (target_ && !other.target_)+      return false;+    if (!target_ && other.target_)+      return false;+    if (target_fns_ != other.target_fns_)+      return false;+    return target_fns_->equal(*this, other);+  }++  template <typename Ex>+  Ex& object()+  {+    return *static_cast<Ex*>(static_cast<void*>(&object_));+  }++  template <typename Ex>+  const Ex& object() const+  {+    return *static_cast<const Ex*>(static_cast<const void*>(&object_));+  }++  struct object_fns+  {+    void (*destroy)(any_executor_base&);+    void (*copy)(any_executor_base&, const any_executor_base&);+    void (*move)(any_executor_base&, any_executor_base&);+    const void* (*target)(const any_executor_base&);+  };++  static void destroy_void(any_executor_base&)+  {+  }++  static void copy_void(any_executor_base& ex1, const any_executor_base&)+  {+    ex1.target_ = 0;+  }++  static void move_void(any_executor_base& ex1, any_executor_base&)+  {+    ex1.target_ = 0;+  }++  static const void* target_void(const any_executor_base&)+  {+    return 0;+  }++  template <typename Obj>+  static const object_fns* object_fns_table(+      typename enable_if<+        is_same<Obj, void>::value+      >::type* = 0)+  {+    static const object_fns fns =+    {+      &any_executor_base::destroy_void,+      &any_executor_base::copy_void,+      &any_executor_base::move_void,+      &any_executor_base::target_void+    };+    return &fns;+  }++  static void destroy_shared(any_executor_base& ex)+  {+    typedef asio::detail::shared_ptr<void> type;+    ex.object<type>().~type();+  }++  static void copy_shared(any_executor_base& ex1, const any_executor_base& ex2)+  {+    typedef asio::detail::shared_ptr<void> type;+    new (&ex1.object_) type(ex2.object<type>());+    ex1.target_ = ex2.target_;+  }++  static void move_shared(any_executor_base& ex1, any_executor_base& ex2)+  {+    typedef asio::detail::shared_ptr<void> type;+    new (&ex1.object_) type(ASIO_MOVE_CAST(type)(ex2.object<type>()));+    ex1.target_ = ex2.target_;+    ex2.object<type>().~type();+  }++  static const void* target_shared(const any_executor_base& ex)+  {+    typedef asio::detail::shared_ptr<void> type;+    return ex.object<type>().get();+  }++  template <typename Obj>+  static const object_fns* object_fns_table(+      typename enable_if<+        is_same<Obj, asio::detail::shared_ptr<void> >::value+      >::type* = 0)+  {+    static const object_fns fns =+    {+      &any_executor_base::destroy_shared,+      &any_executor_base::copy_shared,+      &any_executor_base::move_shared,+      &any_executor_base::target_shared+    };+    return &fns;+  }++  template <typename Obj>+  static void destroy_object(any_executor_base& ex)+  {+    ex.object<Obj>().~Obj();+  }++  template <typename Obj>+  static void copy_object(any_executor_base& ex1, const any_executor_base& ex2)+  {+    new (&ex1.object_) Obj(ex2.object<Obj>());+    ex1.target_ = &ex1.object<Obj>();+  }++  template <typename Obj>+  static void move_object(any_executor_base& ex1, any_executor_base& ex2)+  {+    new (&ex1.object_) Obj(ASIO_MOVE_CAST(Obj)(ex2.object<Obj>()));+    ex1.target_ = &ex1.object<Obj>();+    ex2.object<Obj>().~Obj();+  }++  template <typename Obj>+  static const void* target_object(const any_executor_base& ex)+  {+    return &ex.object<Obj>();+  }++  template <typename Obj>+  static const object_fns* object_fns_table(+      typename enable_if<+        !is_same<Obj, void>::value+          && !is_same<Obj, asio::detail::shared_ptr<void> >::value+      >::type* = 0)+  {+    static const object_fns fns =+    {+      &any_executor_base::destroy_object<Obj>,+      &any_executor_base::copy_object<Obj>,+      &any_executor_base::move_object<Obj>,+      &any_executor_base::target_object<Obj>+    };+    return &fns;+  }++  typedef asio::detail::executor_function function;+  typedef asio::detail::executor_function_view function_view;++  struct target_fns+  {+    const std::type_info& (*target_type)();+    bool (*equal)(const any_executor_base&, const any_executor_base&);+    void (*execute)(const any_executor_base&, ASIO_MOVE_ARG(function));+    void (*blocking_execute)(const any_executor_base&, function_view);+  };++  static const std::type_info& target_type_void()+  {+    return typeid(void);+  }++  static bool equal_void(const any_executor_base&, const any_executor_base&)+  {+    return true;+  }++  static void execute_void(const any_executor_base&,+      ASIO_MOVE_ARG(function))+  {+    bad_executor ex;+    asio::detail::throw_exception(ex);+  }++  static void blocking_execute_void(const any_executor_base&, function_view)+  {+    bad_executor ex;+    asio::detail::throw_exception(ex);+  }++  template <typename Ex>+  static const target_fns* target_fns_table(+      typename enable_if<+        is_same<Ex, void>::value+      >::type* = 0)+  {+    static const target_fns fns =+    {+      &any_executor_base::target_type_void,+      &any_executor_base::equal_void,+      &any_executor_base::execute_void,+      &any_executor_base::blocking_execute_void+    };+    return &fns;+  }++  template <typename Ex>+  static const std::type_info& target_type_ex()+  {+    return typeid(Ex);+  }++  template <typename Ex>+  static bool equal_ex(const any_executor_base& ex1,+      const any_executor_base& ex2)+  {+    return *ex1.target<Ex>() == *ex2.target<Ex>();+  }++  template <typename Ex>+  static void execute_ex(const any_executor_base& ex,+      ASIO_MOVE_ARG(function) f)+  {+    execution::execute(*ex.target<Ex>(), ASIO_MOVE_CAST(function)(f));+  }++  template <typename Ex>+  static void blocking_execute_ex(const any_executor_base& ex, function_view f)+  {+    execution::execute(*ex.target<Ex>(), f);+  }++  template <typename Ex>+  static const target_fns* target_fns_table(bool is_always_blocking,+      typename enable_if<+        !is_same<Ex, void>::value+      >::type* = 0)+  {+    static const target_fns fns_with_execute =+    {+      &any_executor_base::target_type_ex<Ex>,+      &any_executor_base::equal_ex<Ex>,+      &any_executor_base::execute_ex<Ex>,+      0+    };++    static const target_fns fns_with_blocking_execute =+    {+      &any_executor_base::target_type_ex<Ex>,+      &any_executor_base::equal_ex<Ex>,+      0,+      &any_executor_base::blocking_execute_ex<Ex>+    };++    return is_always_blocking ? &fns_with_blocking_execute : &fns_with_execute;+  }++#if defined(ASIO_MSVC)+# pragma warning (push)+# pragma warning (disable:4702)+#endif // defined(ASIO_MSVC)++  static void query_fn_void(void*, const void*, const void*)+  {+    bad_executor ex;+    asio::detail::throw_exception(ex);+  }++  template <typename Ex, class Prop>+  static void query_fn_non_void(void*, const void* ex, const void* prop,+      typename enable_if<+        asio::can_query<const Ex&, const Prop&>::value+          && is_same<typename Prop::polymorphic_query_result_type, void>::value+      >::type*)+  {+    asio::query(*static_cast<const Ex*>(ex),+        *static_cast<const Prop*>(prop));+  }++  template <typename Ex, class Prop>+  static void query_fn_non_void(void*, const void*, const void*,+      typename enable_if<+        !asio::can_query<const Ex&, const Prop&>::value+          && is_same<typename Prop::polymorphic_query_result_type, void>::value+      >::type*)+  {+  }++  template <typename Ex, class Prop>+  static void query_fn_non_void(void* result, const void* ex, const void* prop,+      typename enable_if<+        asio::can_query<const Ex&, const Prop&>::value+          && !is_same<typename Prop::polymorphic_query_result_type, void>::value+          && is_reference<typename Prop::polymorphic_query_result_type>::value+      >::type*)+  {+    *static_cast<typename remove_reference<+      typename Prop::polymorphic_query_result_type>::type**>(result)+        = &static_cast<typename Prop::polymorphic_query_result_type>(+            asio::query(*static_cast<const Ex*>(ex),+              *static_cast<const Prop*>(prop)));+  }++  template <typename Ex, class Prop>+  static void query_fn_non_void(void*, const void*, const void*,+      typename enable_if<+        !asio::can_query<const Ex&, const Prop&>::value+          && !is_same<typename Prop::polymorphic_query_result_type, void>::value+          && is_reference<typename Prop::polymorphic_query_result_type>::value+      >::type*)+  {+    std::terminate(); // Combination should not be possible.+  }++  template <typename Ex, class Prop>+  static void query_fn_non_void(void* result, const void* ex, const void* prop,+      typename enable_if<+        asio::can_query<const Ex&, const Prop&>::value+          && !is_same<typename Prop::polymorphic_query_result_type, void>::value+          && is_scalar<typename Prop::polymorphic_query_result_type>::value+      >::type*)+  {+    *static_cast<typename Prop::polymorphic_query_result_type*>(result)+      = static_cast<typename Prop::polymorphic_query_result_type>(+          asio::query(*static_cast<const Ex*>(ex),+            *static_cast<const Prop*>(prop)));+  }++  template <typename Ex, class Prop>+  static void query_fn_non_void(void* result, const void*, const void*,+      typename enable_if<+        !asio::can_query<const Ex&, const Prop&>::value+          && !is_same<typename Prop::polymorphic_query_result_type, void>::value+          && is_scalar<typename Prop::polymorphic_query_result_type>::value+      >::type*)+  {+    *static_cast<typename Prop::polymorphic_query_result_type*>(result)+      = typename Prop::polymorphic_query_result_type();+  }++  template <typename Ex, class Prop>+  static void query_fn_non_void(void* result, const void* ex, const void* prop,+      typename enable_if<+        asio::can_query<const Ex&, const Prop&>::value+          && !is_same<typename Prop::polymorphic_query_result_type, void>::value+          && !is_reference<typename Prop::polymorphic_query_result_type>::value+          && !is_scalar<typename Prop::polymorphic_query_result_type>::value+      >::type*)+  {+    *static_cast<typename Prop::polymorphic_query_result_type**>(result)+      = new typename Prop::polymorphic_query_result_type(+          asio::query(*static_cast<const Ex*>(ex),+            *static_cast<const Prop*>(prop)));+  }++  template <typename Ex, class Prop>+  static void query_fn_non_void(void* result, const void*, const void*, ...)+  {+    *static_cast<typename Prop::polymorphic_query_result_type**>(result)+      = new typename Prop::polymorphic_query_result_type();+  }++  template <typename Ex, class Prop>+  static void query_fn_impl(void* result, const void* ex, const void* prop,+      typename enable_if<+        is_same<Ex, void>::value+      >::type*)+  {+    query_fn_void(result, ex, prop);+  }++  template <typename Ex, class Prop>+  static void query_fn_impl(void* result, const void* ex, const void* prop,+      typename enable_if<+        !is_same<Ex, void>::value+      >::type*)+  {+    query_fn_non_void<Ex, Prop>(result, ex, prop, 0);+  }++  template <typename Ex, class Prop>+  static void query_fn(void* result, const void* ex, const void* prop)+  {+    query_fn_impl<Ex, Prop>(result, ex, prop, 0);+  }++  template <typename Poly, typename Ex, class Prop>+  static Poly require_fn_impl(const void*, const void*,+      typename enable_if<+        is_same<Ex, void>::value+      >::type*)+  {+    bad_executor ex;+    asio::detail::throw_exception(ex);+    return Poly();+  }++  template <typename Poly, typename Ex, class Prop>+  static Poly require_fn_impl(const void* ex, const void* prop,+      typename enable_if<+        !is_same<Ex, void>::value && Prop::is_requirable+      >::type*)+  {+    return asio::require(*static_cast<const Ex*>(ex),+        *static_cast<const Prop*>(prop));+  }++  template <typename Poly, typename Ex, class Prop>+  static Poly require_fn_impl(const void*, const void*, ...)+  {+    return Poly();+  }++  template <typename Poly, typename Ex, class Prop>+  static Poly require_fn(const void* ex, const void* prop)+  {+    return require_fn_impl<Poly, Ex, Prop>(ex, prop, 0);+  }++  template <typename Poly, typename Ex, class Prop>+  static Poly prefer_fn_impl(const void*, const void*,+      typename enable_if<+        is_same<Ex, void>::value+      >::type*)+  {+    bad_executor ex;+    asio::detail::throw_exception(ex);+    return Poly();+  }++  template <typename Poly, typename Ex, class Prop>+  static Poly prefer_fn_impl(const void* ex, const void* prop,+      typename enable_if<+        !is_same<Ex, void>::value && Prop::is_preferable+      >::type*)+  {+    return asio::prefer(*static_cast<const Ex*>(ex),+        *static_cast<const Prop*>(prop));+  }++  template <typename Poly, typename Ex, class Prop>+  static Poly prefer_fn_impl(const void*, const void*, ...)+  {+    return Poly();+  }++  template <typename Poly, typename Ex, class Prop>+  static Poly prefer_fn(const void* ex, const void* prop)+  {+    return prefer_fn_impl<Poly, Ex, Prop>(ex, prop, 0);+  }++  template <typename Poly>+  struct prop_fns+  {+    void (*query)(void*, const void*, const void*);+    Poly (*require)(const void*, const void*);+    Poly (*prefer)(const void*, const void*);+  };++#if defined(ASIO_MSVC)+# pragma warning (pop)+#endif // defined(ASIO_MSVC)++private:+  template <typename Executor>+  static execution::blocking_t query_blocking(const Executor& ex, true_type)+  {+    return asio::query(ex, execution::blocking);+  }++  template <typename Executor>+  static execution::blocking_t query_blocking(const Executor&, false_type)+  {+    return execution::blocking_t();+  }++  template <typename Executor>+  void construct_object(Executor& ex, true_type)+  {+    object_fns_ = object_fns_table<Executor>();+    target_ = new (&object_) Executor(ASIO_MOVE_CAST(Executor)(ex));+  }++  template <typename Executor>+  void construct_object(Executor& ex, false_type)+  {+    object_fns_ = object_fns_table<asio::detail::shared_ptr<void> >();+    asio::detail::shared_ptr<Executor> p =+      asio::detail::make_shared<Executor>(+          ASIO_MOVE_CAST(Executor)(ex));+    target_ = p.get();+    new (&object_) asio::detail::shared_ptr<void>(+        ASIO_MOVE_CAST(asio::detail::shared_ptr<Executor>)(p));+  }++/*private:*/public:+//  template <typename...> friend class any_executor;++  typedef aligned_storage<+      sizeof(asio::detail::shared_ptr<void>),+      alignment_of<asio::detail::shared_ptr<void> >::value+    >::type object_type;++  object_type object_;+  const object_fns* object_fns_;+  void* target_;+  const target_fns* target_fns_;+};++template <typename Derived, typename Property, typename = void>+struct any_executor_context+{+};++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Derived, typename Property>+struct any_executor_context<Derived, Property,+    typename enable_if<Property::value>::type>+{+  typename Property::query_result_type context() const+  {+    return static_cast<const Derived*>(this)->query(typename Property::type());+  }+};++#endif // !defined(ASIO_NO_TS_EXECUTORS)++} // namespace detail++template <>+class any_executor<> : public detail::any_executor_base+{+public:+  any_executor() ASIO_NOEXCEPT+    : detail::any_executor_base()+  {+  }++  any_executor(nullptr_t) ASIO_NOEXCEPT+    : detail::any_executor_base()+  {+  }++  template <typename Executor>+  any_executor(Executor ex,+      typename enable_if<+        conditional<+          !is_same<Executor, any_executor>::value+            && !is_base_of<detail::any_executor_base, Executor>::value,+          is_executor<Executor>,+          false_type+        >::type::value+      >::type* = 0)+    : detail::any_executor_base(+        ASIO_MOVE_CAST(Executor)(ex), false_type())+  {+  }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename... OtherSupportableProperties>+  any_executor(any_executor<OtherSupportableProperties...> other)+    : detail::any_executor_base(+        static_cast<const detail::any_executor_base&>(other))+  {+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename U0, typename U1, typename U2, typename U3,+      typename U4, typename U5, typename U6, typename U7>+  any_executor(any_executor<U0, U1, U2, U3, U4, U5, U6, U7> other)+    : detail::any_executor_base(+        static_cast<const detail::any_executor_base&>(other))+  {+  }++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  any_executor(const any_executor& other) ASIO_NOEXCEPT+    : detail::any_executor_base(+        static_cast<const detail::any_executor_base&>(other))+  {+  }++  any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT+  {+    if (this != &other)+    {+      detail::any_executor_base::operator=(+          static_cast<const detail::any_executor_base&>(other));+    }+    return *this;+  }++  any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT+  {+    detail::any_executor_base::operator=(p);+    return *this;+  }++#if defined(ASIO_HAS_MOVE)++  any_executor(any_executor&& other) ASIO_NOEXCEPT+    : detail::any_executor_base(+        static_cast<any_executor_base&&>(+          static_cast<any_executor_base&>(other)))+  {+  }++  any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT+  {+    if (this != &other)+    {+      detail::any_executor_base::operator=(+          static_cast<detail::any_executor_base&&>(+            static_cast<detail::any_executor_base&>(other)));+    }+    return *this;+  }++#endif // defined(ASIO_HAS_MOVE)++  void swap(any_executor& other) ASIO_NOEXCEPT+  {+    detail::any_executor_base::swap(+        static_cast<detail::any_executor_base&>(other));+  }++  using detail::any_executor_base::execute;+  using detail::any_executor_base::target;+  using detail::any_executor_base::target_type;+  using detail::any_executor_base::operator unspecified_bool_type;+  using detail::any_executor_base::operator!;++  bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT+  {+    return any_executor_base::equality_helper(other);+  }+};++inline bool operator==(const any_executor<>& a,+    const any_executor<>& b) ASIO_NOEXCEPT+{+  return a.equality_helper(b);+}++inline bool operator==(const any_executor<>& a, nullptr_t) ASIO_NOEXCEPT+{+  return !a;+}++inline bool operator==(nullptr_t, const any_executor<>& b) ASIO_NOEXCEPT+{+  return !b;+}++inline bool operator!=(const any_executor<>& a,+    const any_executor<>& b) ASIO_NOEXCEPT+{+  return !a.equality_helper(b);+}++inline bool operator!=(const any_executor<>& a, nullptr_t) ASIO_NOEXCEPT+{+  return !!a;+}++inline bool operator!=(nullptr_t, const any_executor<>& b) ASIO_NOEXCEPT+{+  return !!b;+}++inline void swap(any_executor<>& a, any_executor<>& b) ASIO_NOEXCEPT+{+  return a.swap(b);+}++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... SupportableProperties>+class any_executor :+  public detail::any_executor_base,+  public detail::any_executor_context<+    any_executor<SupportableProperties...>,+      typename detail::supportable_properties<+        0, void(SupportableProperties...)>::find_context_as_property>+{+public:+  any_executor() ASIO_NOEXCEPT+    : detail::any_executor_base(),+      prop_fns_(prop_fns_table<void>())+  {+  }++  any_executor(nullptr_t) ASIO_NOEXCEPT+    : detail::any_executor_base(),+      prop_fns_(prop_fns_table<void>())+  {+  }++  template <typename Executor>+  any_executor(Executor ex,+      typename enable_if<+        conditional<+          !is_same<Executor, any_executor>::value+            && !is_base_of<detail::any_executor_base, Executor>::value,+          detail::is_valid_target_executor<+            Executor, void(SupportableProperties...)>,+          false_type+        >::type::value+      >::type* = 0)+    : detail::any_executor_base(+        ASIO_MOVE_CAST(Executor)(ex), false_type()),+      prop_fns_(prop_fns_table<Executor>())+  {+  }++  template <typename... OtherSupportableProperties>+  any_executor(any_executor<OtherSupportableProperties...> other,+      typename enable_if<+        conditional<+          !is_same<+            any_executor<OtherSupportableProperties...>,+            any_executor+          >::value,+          typename detail::supportable_properties<+            0, void(SupportableProperties...)>::template is_valid_target<+              any_executor<OtherSupportableProperties...> >,+          false_type+        >::type::value+      >::type* = 0)+    : detail::any_executor_base(ASIO_MOVE_CAST(+          any_executor<OtherSupportableProperties...>)(other), true_type()),+      prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...> >())+  {+  }++  any_executor(const any_executor& other) ASIO_NOEXCEPT+    : detail::any_executor_base(+        static_cast<const detail::any_executor_base&>(other)),+      prop_fns_(other.prop_fns_)+  {+  }++  any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT+  {+    if (this != &other)+    {+      prop_fns_ = other.prop_fns_;+      detail::any_executor_base::operator=(+          static_cast<const detail::any_executor_base&>(other));+    }+    return *this;+  }++  any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT+  {+    prop_fns_ = prop_fns_table<void>();+    detail::any_executor_base::operator=(p);+    return *this;+  }++#if defined(ASIO_HAS_MOVE)++  any_executor(any_executor&& other) ASIO_NOEXCEPT+    : detail::any_executor_base(+        static_cast<any_executor_base&&>(+          static_cast<any_executor_base&>(other))),+      prop_fns_(other.prop_fns_)+  {+    other.prop_fns_ = prop_fns_table<void>();+  }++  any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT+  {+    if (this != &other)+    {+      prop_fns_ = other.prop_fns_;+      detail::any_executor_base::operator=(+          static_cast<detail::any_executor_base&&>(+            static_cast<detail::any_executor_base&>(other)));+    }+    return *this;+  }++#endif // defined(ASIO_HAS_MOVE)++  void swap(any_executor& other) ASIO_NOEXCEPT+  {+    if (this != &other)+    {+      detail::any_executor_base::swap(+          static_cast<detail::any_executor_base&>(other));+      const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_;+      other.prop_fns_ = prop_fns_;+      prop_fns_ = tmp_prop_fns;+    }+  }++  using detail::any_executor_base::execute;+  using detail::any_executor_base::target;+  using detail::any_executor_base::target_type;+  using detail::any_executor_base::operator unspecified_bool_type;+  using detail::any_executor_base::operator!;++  bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT+  {+    return any_executor_base::equality_helper(other);+  }++  template <typename T>+  struct find_convertible_property :+      detail::supportable_properties<+        0, void(SupportableProperties...)>::template+          find_convertible_property<T> {};++  template <typename Property>+  void query(const Property& p,+      typename enable_if<+        is_same<+          typename find_convertible_property<Property>::query_result_type,+          void+        >::value+      >::type* = 0) const+  {+    typedef find_convertible_property<Property> found;+    prop_fns_[found::index].query(0, object_fns_->target(*this),+        &static_cast<const typename found::type&>(p));+  }++  template <typename Property>+  typename find_convertible_property<Property>::query_result_type+  query(const Property& p,+      typename enable_if<+        !is_same<+          typename find_convertible_property<Property>::query_result_type,+          void+        >::value+        &&+        is_reference<+          typename find_convertible_property<Property>::query_result_type+        >::value+      >::type* = 0) const+  {+    typedef find_convertible_property<Property> found;+    typename remove_reference<+      typename found::query_result_type>::type* result = 0;+    prop_fns_[found::index].query(&result, object_fns_->target(*this),+        &static_cast<const typename found::type&>(p));+    return *result;+  }++  template <typename Property>+  typename find_convertible_property<Property>::query_result_type+  query(const Property& p,+      typename enable_if<+        !is_same<+          typename find_convertible_property<Property>::query_result_type,+          void+        >::value+        &&+        is_scalar<+          typename find_convertible_property<Property>::query_result_type+        >::value+      >::type* = 0) const+  {+    typedef find_convertible_property<Property> found;+    typename found::query_result_type result;+    prop_fns_[found::index].query(&result, object_fns_->target(*this),+        &static_cast<const typename found::type&>(p));+    return result;+  }++  template <typename Property>+  typename find_convertible_property<Property>::query_result_type+  query(const Property& p,+      typename enable_if<+        !is_same<+          typename find_convertible_property<Property>::query_result_type,+          void+        >::value+        &&+        !is_reference<+          typename find_convertible_property<Property>::query_result_type+        >::value+        &&+        !is_scalar<+          typename find_convertible_property<Property>::query_result_type+        >::value+      >::type* = 0) const+  {+    typedef find_convertible_property<Property> found;+    typename found::query_result_type* result;+    prop_fns_[found::index].query(&result, object_fns_->target(*this),+        &static_cast<const typename found::type&>(p));+    return *asio::detail::scoped_ptr<+      typename found::query_result_type>(result);+  }++  template <typename T>+  struct find_convertible_requirable_property :+      detail::supportable_properties<+        0, void(SupportableProperties...)>::template+          find_convertible_requirable_property<T> {};++  template <typename Property>+  any_executor require(const Property& p,+      typename enable_if<+        find_convertible_requirable_property<Property>::value+      >::type* = 0) const+  {+    typedef find_convertible_requirable_property<Property> found;+    return prop_fns_[found::index].require(object_fns_->target(*this),+        &static_cast<const typename found::type&>(p));+  }++  template <typename T>+  struct find_convertible_preferable_property :+      detail::supportable_properties<+        0, void(SupportableProperties...)>::template+          find_convertible_preferable_property<T> {};++  template <typename Property>+  any_executor prefer(const Property& p,+      typename enable_if<+        find_convertible_preferable_property<Property>::value+      >::type* = 0) const+  {+    typedef find_convertible_preferable_property<Property> found;+    return prop_fns_[found::index].prefer(object_fns_->target(*this),+        &static_cast<const typename found::type&>(p));+  }++//private:+  template <typename Ex>+  static const prop_fns<any_executor>* prop_fns_table()+  {+    static const prop_fns<any_executor> fns[] =+    {+      {+        &detail::any_executor_base::query_fn<+            Ex, SupportableProperties>,+        &detail::any_executor_base::require_fn<+            any_executor, Ex, SupportableProperties>,+        &detail::any_executor_base::prefer_fn<+            any_executor, Ex, SupportableProperties>+      }...+    };+    return fns;+  }++  const prop_fns<any_executor>* prop_fns_;+};++template <typename... SupportableProperties>+inline bool operator==(const any_executor<SupportableProperties...>& a,+    const any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT+{+  return a.equality_helper(b);+}++template <typename... SupportableProperties>+inline bool operator==(const any_executor<SupportableProperties...>& a,+    nullptr_t) ASIO_NOEXCEPT+{+  return !a;+}++template <typename... SupportableProperties>+inline bool operator==(nullptr_t,+    const any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT+{+  return !b;+}++template <typename... SupportableProperties>+inline bool operator!=(const any_executor<SupportableProperties...>& a,+    const any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT+{+  return !a.equality_helper(b);+}++template <typename... SupportableProperties>+inline bool operator!=(const any_executor<SupportableProperties...>& a,+    nullptr_t) ASIO_NOEXCEPT+{+  return !!a;+}++template <typename... SupportableProperties>+inline bool operator!=(nullptr_t,+    const any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT+{+  return !!b;+}++template <typename... SupportableProperties>+inline void swap(any_executor<SupportableProperties...>& a,+    any_executor<SupportableProperties...>& b) ASIO_NOEXCEPT+{+  return a.swap(b);+}++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \+  ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_##n++#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1 \+  {  \+    &detail::any_executor_base::query_fn<Ex, T1>, \+    &detail::any_executor_base::require_fn<any_executor, Ex, T1>, \+    &detail::any_executor_base::prefer_fn<any_executor, Ex, T1> \+  }+#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2 \+  ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1, \+  { \+    &detail::any_executor_base::query_fn<Ex, T2>, \+    &detail::any_executor_base::require_fn<any_executor, Ex, T2>, \+    &detail::any_executor_base::prefer_fn<any_executor, Ex, T2> \+  }+#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3 \+  ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2, \+  { \+    &detail::any_executor_base::query_fn<Ex, T3>, \+    &detail::any_executor_base::require_fn<any_executor, Ex, T3>, \+    &detail::any_executor_base::prefer_fn<any_executor, Ex, T3> \+  }+#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4 \+  ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3, \+  { \+    &detail::any_executor_base::query_fn<Ex, T4>, \+    &detail::any_executor_base::require_fn<any_executor, Ex, T4>, \+    &detail::any_executor_base::prefer_fn<any_executor, Ex, T4> \+  }+#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5 \+  ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4, \+  { \+    &detail::any_executor_base::query_fn<Ex, T5>, \+    &detail::any_executor_base::require_fn<any_executor, Ex, T5>, \+    &detail::any_executor_base::prefer_fn<any_executor, Ex, T5> \+  }+#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6 \+  ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5, \+  { \+    &detail::any_executor_base::query_fn<Ex, T6>, \+    &detail::any_executor_base::require_fn<any_executor, Ex, T6>, \+    &detail::any_executor_base::prefer_fn<any_executor, Ex, T6> \+  }+#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7 \+  ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6, \+  { \+    &detail::any_executor_base::query_fn<Ex, T7>, \+    &detail::any_executor_base::require_fn<any_executor, Ex, T7>, \+    &detail::any_executor_base::prefer_fn<any_executor, Ex, T7> \+  }+#define ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8 \+  ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7, \+  { \+    &detail::any_executor_base::query_fn<Ex, T8>, \+    &detail::any_executor_base::require_fn<any_executor, Ex, T8>, \+    &detail::any_executor_base::prefer_fn<any_executor, Ex, T8> \+  }++#if defined(ASIO_HAS_MOVE)++# define ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \+  any_executor(any_executor&& other) ASIO_NOEXCEPT \+    : detail::any_executor_base( \+        static_cast<any_executor_base&&>( \+          static_cast<any_executor_base&>(other))), \+      prop_fns_(other.prop_fns_) \+  { \+    other.prop_fns_ = prop_fns_table<void>(); \+  } \+  \+  any_executor& operator=(any_executor&& other) ASIO_NOEXCEPT \+  { \+    if (this != &other) \+    { \+      prop_fns_ = other.prop_fns_; \+      detail::any_executor_base::operator=( \+          static_cast<detail::any_executor_base&&>( \+            static_cast<detail::any_executor_base&>(other))); \+    } \+    return *this; \+  } \+  /**/+#else // defined(ASIO_HAS_MOVE)++# define ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS++#endif // defined(ASIO_HAS_MOVE)++#define ASIO_PRIVATE_ANY_EXECUTOR_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  class any_executor<ASIO_VARIADIC_TARGS(n)> : \+    public detail::any_executor_base, \+    public detail::any_executor_context< \+      any_executor<ASIO_VARIADIC_TARGS(n)>, \+        typename detail::supportable_properties< \+          0, void(ASIO_VARIADIC_TARGS(n))>::find_context_as_property> \+  { \+  public: \+    any_executor() ASIO_NOEXCEPT \+      : detail::any_executor_base(), \+        prop_fns_(prop_fns_table<void>()) \+    { \+    } \+    \+    any_executor(nullptr_t) ASIO_NOEXCEPT \+      : detail::any_executor_base(), \+        prop_fns_(prop_fns_table<void>()) \+    { \+    } \+    \+    template <ASIO_EXECUTION_EXECUTOR Executor> \+    any_executor(Executor ex, \+        typename enable_if< \+          conditional< \+            !is_same<Executor, any_executor>::value \+              && !is_base_of<detail::any_executor_base, Executor>::value, \+            detail::is_valid_target_executor< \+              Executor, void(ASIO_VARIADIC_TARGS(n))>, \+            false_type \+          >::type::value \+        >::type* = 0) \+      : detail::any_executor_base(ASIO_MOVE_CAST( \+            Executor)(ex), false_type()), \+        prop_fns_(prop_fns_table<Executor>()) \+    { \+    } \+    \+    any_executor(const any_executor& other) ASIO_NOEXCEPT \+      : detail::any_executor_base( \+          static_cast<const detail::any_executor_base&>(other)), \+        prop_fns_(other.prop_fns_) \+    { \+    } \+    \+    any_executor(any_executor<> other) \+      : detail::any_executor_base(ASIO_MOVE_CAST( \+            any_executor<>)(other), true_type()), \+        prop_fns_(prop_fns_table<any_executor<> >()) \+    { \+    } \+    \+    template <typename OtherAnyExecutor> \+    any_executor(OtherAnyExecutor other, \+        typename enable_if< \+          conditional< \+            !is_same<OtherAnyExecutor, any_executor>::value \+              && is_base_of<detail::any_executor_base, \+                OtherAnyExecutor>::value, \+            typename detail::supportable_properties< \+              0, void(ASIO_VARIADIC_TARGS(n))>::template \+                is_valid_target<OtherAnyExecutor>, \+            false_type \+          >::type::value \+        >::type* = 0) \+      : detail::any_executor_base(ASIO_MOVE_CAST( \+            OtherAnyExecutor)(other), true_type()), \+        prop_fns_(prop_fns_table<OtherAnyExecutor>()) \+    { \+    } \+    \+    any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT \+    { \+      if (this != &other) \+      { \+        prop_fns_ = other.prop_fns_; \+        detail::any_executor_base::operator=( \+            static_cast<const detail::any_executor_base&>(other)); \+      } \+      return *this; \+    } \+    \+    any_executor& operator=(nullptr_t p) ASIO_NOEXCEPT \+    { \+      prop_fns_ = prop_fns_table<void>(); \+      detail::any_executor_base::operator=(p); \+      return *this; \+    } \+    \+    ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS \+    \+    void swap(any_executor& other) ASIO_NOEXCEPT \+    { \+      if (this != &other) \+      { \+        detail::any_executor_base::swap( \+            static_cast<detail::any_executor_base&>(other)); \+        const prop_fns<any_executor>* tmp_prop_fns = other.prop_fns_; \+        other.prop_fns_ = prop_fns_; \+        prop_fns_ = tmp_prop_fns; \+      } \+    } \+    \+    using detail::any_executor_base::execute; \+    using detail::any_executor_base::target; \+    using detail::any_executor_base::target_type; \+    using detail::any_executor_base::operator unspecified_bool_type; \+    using detail::any_executor_base::operator!; \+    \+    bool equality_helper(const any_executor& other) const ASIO_NOEXCEPT \+    { \+      return any_executor_base::equality_helper(other); \+    } \+    \+    template <typename T> \+    struct find_convertible_property : \+        detail::supportable_properties< \+          0, void(ASIO_VARIADIC_TARGS(n))>::template \+            find_convertible_property<T> {}; \+    \+    template <typename Property> \+    void query(const Property& p, \+        typename enable_if< \+          is_same< \+            typename find_convertible_property<Property>::query_result_type, \+            void \+          >::value \+        >::type* = 0) const \+    { \+      typedef find_convertible_property<Property> found; \+      prop_fns_[found::index].query(0, object_fns_->target(*this), \+          &static_cast<const typename found::type&>(p)); \+    } \+    \+    template <typename Property> \+    typename find_convertible_property<Property>::query_result_type \+    query(const Property& p, \+        typename enable_if< \+          !is_same< \+            typename find_convertible_property<Property>::query_result_type, \+            void \+          >::value \+          && \+          is_reference< \+            typename find_convertible_property<Property>::query_result_type \+          >::value \+        >::type* = 0) const \+    { \+      typedef find_convertible_property<Property> found; \+      typename remove_reference< \+        typename found::query_result_type>::type* result; \+      prop_fns_[found::index].query(&result, object_fns_->target(*this), \+          &static_cast<const typename found::type&>(p)); \+      return *result; \+    } \+    \+    template <typename Property> \+    typename find_convertible_property<Property>::query_result_type \+    query(const Property& p, \+        typename enable_if< \+          !is_same< \+            typename find_convertible_property<Property>::query_result_type, \+            void \+          >::value \+          && \+          is_scalar< \+            typename find_convertible_property<Property>::query_result_type \+          >::value \+        >::type* = 0) const \+    { \+      typedef find_convertible_property<Property> found; \+      typename found::query_result_type result; \+      prop_fns_[found::index].query(&result, object_fns_->target(*this), \+          &static_cast<const typename found::type&>(p)); \+      return result; \+    } \+    \+    template <typename Property> \+    typename find_convertible_property<Property>::query_result_type \+    query(const Property& p, \+        typename enable_if< \+          !is_same< \+            typename find_convertible_property<Property>::query_result_type, \+            void \+          >::value \+          && \+          !is_reference< \+            typename find_convertible_property<Property>::query_result_type \+          >::value \+          && \+          !is_scalar< \+            typename find_convertible_property<Property>::query_result_type \+          >::value \+        >::type* = 0) const \+    { \+      typedef find_convertible_property<Property> found; \+      typename found::query_result_type* result; \+      prop_fns_[found::index].query(&result, object_fns_->target(*this), \+          &static_cast<const typename found::type&>(p)); \+      return *asio::detail::scoped_ptr< \+        typename found::query_result_type>(result); \+    } \+    \+    template <typename T> \+    struct find_convertible_requirable_property : \+        detail::supportable_properties< \+          0, void(ASIO_VARIADIC_TARGS(n))>::template \+            find_convertible_requirable_property<T> {}; \+    \+    template <typename Property> \+    any_executor require(const Property& p, \+        typename enable_if< \+          find_convertible_requirable_property<Property>::value \+        >::type* = 0) const \+    { \+      typedef find_convertible_requirable_property<Property> found; \+      return prop_fns_[found::index].require(object_fns_->target(*this), \+          &static_cast<const typename found::type&>(p)); \+    } \+    \+    template <typename T> \+    struct find_convertible_preferable_property : \+        detail::supportable_properties< \+          0, void(ASIO_VARIADIC_TARGS(n))>::template \+            find_convertible_preferable_property<T> {}; \+    \+    template <typename Property> \+    any_executor prefer(const Property& p, \+        typename enable_if< \+          find_convertible_preferable_property<Property>::value \+        >::type* = 0) const \+    { \+      typedef find_convertible_preferable_property<Property> found; \+      return prop_fns_[found::index].prefer(object_fns_->target(*this), \+          &static_cast<const typename found::type&>(p)); \+    } \+    \+    template <typename Ex> \+    static const prop_fns<any_executor>* prop_fns_table() \+    { \+      static const prop_fns<any_executor> fns[] = \+      { \+        ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS(n) \+      }; \+      return fns; \+    } \+    \+    const prop_fns<any_executor>* prop_fns_; \+    typedef detail::supportable_properties<0, \+        void(ASIO_VARIADIC_TARGS(n))> supportable_properties_type; \+  }; \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  inline bool operator==(const any_executor<ASIO_VARIADIC_TARGS(n)>& a, \+      const any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \+  { \+    return a.equality_helper(b); \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  inline bool operator==(const any_executor<ASIO_VARIADIC_TARGS(n)>& a, \+      nullptr_t) ASIO_NOEXCEPT \+  { \+    return !a; \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  inline bool operator==(nullptr_t, \+      const any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \+  { \+    return !b; \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  inline bool operator!=(const any_executor<ASIO_VARIADIC_TARGS(n)>& a, \+      const any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \+  { \+    return !a.equality_helper(b); \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  inline bool operator!=(const any_executor<ASIO_VARIADIC_TARGS(n)>& a, \+      nullptr_t) ASIO_NOEXCEPT \+  { \+    return !!a; \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  inline bool operator!=(nullptr_t, \+      const any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \+  { \+    return !!b; \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  inline void swap(any_executor<ASIO_VARIADIC_TARGS(n)>& a, \+      any_executor<ASIO_VARIADIC_TARGS(n)>& b) ASIO_NOEXCEPT \+  { \+    return a.swap(b); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_DEF)+#undef ASIO_PRIVATE_ANY_EXECUTOR_DEF+#undef ASIO_PRIVATE_ANY_EXECUTOR_MOVE_OPS+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_1+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_2+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_3+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_4+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_5+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_6+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_7+#undef ASIO_PRIVATE_ANY_EXECUTOR_PROP_FNS_8++#endif // if defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace execution+namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... SupportableProperties>+struct equality_comparable<execution::any_executor<SupportableProperties...> >+{+  static const bool is_valid = true;+  static const bool is_noexcept = true;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <>+struct equality_comparable<execution::any_executor<> >+{+  static const bool is_valid = true;+  static const bool is_noexcept = true;+};++#define ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  struct equality_comparable< \+      execution::any_executor<ASIO_VARIADIC_TARGS(n)> > \+  { \+    static const bool is_valid = true; \+    static const bool is_noexcept = true; \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(+      ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF)+#undef ASIO_PRIVATE_ANY_EXECUTOR_EQUALITY_COMPARABLE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename F, typename... SupportableProperties>+struct execute_member<execution::any_executor<SupportableProperties...>, F>+{+  static const bool is_valid = true;+  static const bool is_noexcept = false;+  typedef void result_type;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename F>+struct execute_member<execution::any_executor<>, F>+{+  static const bool is_valid = true;+  static const bool is_noexcept = false;+  typedef void result_type;+};++#define ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF(n) \+  template <typename F, ASIO_VARIADIC_TPARAMS(n)> \+  struct execute_member< \+      execution::any_executor<ASIO_VARIADIC_TARGS(n)>, F> \+  { \+    static const bool is_valid = true; \+    static const bool is_noexcept = false; \+    typedef void result_type; \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(+      ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF)+#undef ASIO_PRIVATE_ANY_EXECUTOR_EXECUTE_MEMBER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Prop, typename... SupportableProperties>+struct query_member<+    execution::any_executor<SupportableProperties...>, Prop,+    typename enable_if<+      execution::detail::supportable_properties<+        0, void(SupportableProperties...)>::template+          find_convertible_property<Prop>::value+    >::type>+{+  static const bool is_valid = true;+  static const bool is_noexcept = false;+  typedef typename execution::detail::supportable_properties<+      0, void(SupportableProperties...)>::template+        find_convertible_property<Prop>::query_result_type result_type;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF(n) \+  template <typename Prop, ASIO_VARIADIC_TPARAMS(n)> \+  struct query_member< \+      execution::any_executor<ASIO_VARIADIC_TARGS(n)>, Prop, \+      typename enable_if< \+        execution::detail::supportable_properties< \+          0, void(ASIO_VARIADIC_TARGS(n))>::template \+            find_convertible_property<Prop>::value \+    >::type> \+  { \+    static const bool is_valid = true; \+    static const bool is_noexcept = false; \+    typedef typename execution::detail::supportable_properties< \+        0, void(ASIO_VARIADIC_TARGS(n))>::template \+          find_convertible_property<Prop>::query_result_type result_type; \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF)+#undef ASIO_PRIVATE_ANY_EXECUTOR_QUERY_MEMBER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Prop, typename... SupportableProperties>+struct require_member<+    execution::any_executor<SupportableProperties...>, Prop,+    typename enable_if<+      execution::detail::supportable_properties<+        0, void(SupportableProperties...)>::template+          find_convertible_requirable_property<Prop>::value+    >::type>+{+  static const bool is_valid = true;+  static const bool is_noexcept = false;+  typedef execution::any_executor<SupportableProperties...> result_type;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF(n) \+  template <typename Prop, ASIO_VARIADIC_TPARAMS(n)> \+  struct require_member< \+      execution::any_executor<ASIO_VARIADIC_TARGS(n)>, Prop, \+      typename enable_if< \+        execution::detail::supportable_properties< \+          0, void(ASIO_VARIADIC_TARGS(n))>::template \+            find_convertible_requirable_property<Prop>::value \+      >::type> \+  { \+    static const bool is_valid = true; \+    static const bool is_noexcept = false; \+    typedef execution::any_executor<ASIO_VARIADIC_TARGS(n)> result_type; \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(+      ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF)+#undef ASIO_PRIVATE_ANY_EXECUTOR_REQUIRE_MEMBER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Prop, typename... SupportableProperties>+struct prefer_member<+    execution::any_executor<SupportableProperties...>, Prop,+    typename enable_if<+      execution::detail::supportable_properties<+        0, void(SupportableProperties...)>::template+          find_convertible_preferable_property<Prop>::value+    >::type>+{+  static const bool is_valid = true;+  static const bool is_noexcept = false;+  typedef execution::any_executor<SupportableProperties...> result_type;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF(n) \+  template <typename Prop, ASIO_VARIADIC_TPARAMS(n)> \+  struct prefer_member< \+      execution::any_executor<ASIO_VARIADIC_TARGS(n)>, Prop, \+      typename enable_if< \+        execution::detail::supportable_properties< \+          0, void(ASIO_VARIADIC_TARGS(n))>::template \+            find_convertible_preferable_property<Prop>::value \+      >::type> \+  { \+    static const bool is_valid = true; \+    static const bool is_noexcept = false; \+    typedef execution::any_executor<ASIO_VARIADIC_TARGS(n)> result_type; \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF)+#undef ASIO_PRIVATE_ANY_EXECUTOR_PREFER_FREE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_ANY_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/bad_executor.hpp view
@@ -0,0 +1,47 @@+//+// execution/bad_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_BAD_EXECUTOR_HPP+#define ASIO_EXECUTION_BAD_EXECUTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <exception>+#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {++/// Exception thrown when trying to access an empty polymorphic executor.+class bad_executor+  : public std::exception+{+public:+  /// Constructor.+  ASIO_DECL bad_executor() ASIO_NOEXCEPT;++  /// Obtain message associated with exception.+  ASIO_DECL virtual const char* what() const+    ASIO_NOEXCEPT_OR_NOTHROW;+};++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/execution/impl/bad_executor.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_EXECUTION_BAD_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/blocking.hpp view
@@ -0,0 +1,1351 @@+//+// execution/blocking.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_BLOCKING_HPP+#define ASIO_EXECUTION_BLOCKING_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/execution/execute.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/prefer.hpp"+#include "asio/query.hpp"+#include "asio/require.hpp"+#include "asio/traits/query_free.hpp"+#include "asio/traits/query_member.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/static_query.hpp"+#include "asio/traits/static_require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property to describe what guarantees an executor makes about the blocking+/// behaviour of their execution functions.+struct blocking_t+{+  /// The blocking_t property applies to executors, senders, and schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The top-level blocking_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The top-level blocking_t property cannot be preferred.+  static constexpr bool is_preferable = false;++  /// The type returned by queries against an @c any_executor.+  typedef blocking_t polymorphic_query_result_type;++  /// A sub-property that indicates that invocation of an executor's execution+  /// function may block pending completion of one or more invocations of the+  /// submitted function object.+  struct possibly_t+  {+    /// The blocking_t::possibly_t property applies to executors, senders, and+    /// schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The blocking_t::possibly_t property can be required.+    static constexpr bool is_requirable = true;++    /// The blocking_t::possibly_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef blocking_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr possibly_t();++    /// Get the value associated with a property object.+    /**+     * @returns possibly_t();+     */+    static constexpr blocking_t value();+  };++  /// A sub-property that indicates that invocation of an executor's execution+  /// function shall block until completion of all invocations of the submitted+  /// function object.+  struct always_t+  {+    /// The blocking_t::always_t property applies to executors, senders, and+    /// schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The blocking_t::always_t property can be required.+    static constexpr bool is_requirable = true;++    /// The blocking_t::always_t property can be preferred.+    static constexpr bool is_preferable = false;++    /// The type returned by queries against an @c any_executor.+    typedef blocking_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr always_t();++    /// Get the value associated with a property object.+    /**+     * @returns always_t();+     */+    static constexpr blocking_t value();+  };++  /// A sub-property that indicates that invocation of an executor's execution+  /// function shall not block pending completion of the invocations of the+  /// submitted function object.+  struct never_t+  {+    /// The blocking_t::never_t property applies to executors, senders, and+    /// schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The blocking_t::never_t property can be required.+    static constexpr bool is_requirable = true;++    /// The blocking_t::never_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef blocking_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr never_t();++    /// Get the value associated with a property object.+    /**+     * @returns never_t();+     */+    static constexpr blocking_t value();+  };++  /// A special value used for accessing the blocking_t::possibly_t property.+  static constexpr possibly_t possibly;++  /// A special value used for accessing the blocking_t::always_t property.+  static constexpr always_t always;++  /// A special value used for accessing the blocking_t::never_t property.+  static constexpr never_t never;++  /// Default constructor.+  constexpr blocking_t();++  /// Construct from a sub-property value.+  constexpr blocking_t(possibly_t);++  /// Construct from a sub-property value.+  constexpr blocking_t(always_t);++  /// Construct from a sub-property value.+  constexpr blocking_t(never_t);++  /// Compare property values for equality.+  friend constexpr bool operator==(+      const blocking_t& a, const blocking_t& b) noexcept;++  /// Compare property values for inequality.+  friend constexpr bool operator!=(+      const blocking_t& a, const blocking_t& b) noexcept;+};++/// A special value used for accessing the blocking_t property.+constexpr blocking_t blocking;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {+namespace detail {+namespace blocking {++template <int I> struct possibly_t;+template <int I> struct always_t;+template <int I> struct never_t;++} // namespace blocking+namespace blocking_adaptation {++template <int I> struct allowed_t;++template <typename Executor, typename Function>+void blocking_execute(+    ASIO_MOVE_ARG(Executor) ex,+    ASIO_MOVE_ARG(Function) func);++} // namespace blocking_adaptation++template <int I = 0>+struct blocking_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+  typedef blocking_t polymorphic_query_result_type;++  typedef detail::blocking::possibly_t<I> possibly_t;+  typedef detail::blocking::always_t<I> always_t;+  typedef detail::blocking::never_t<I> never_t;++  ASIO_CONSTEXPR blocking_t()+    : value_(-1)+  {+  }++  ASIO_CONSTEXPR blocking_t(possibly_t)+    : value_(0)+  {+  }++  ASIO_CONSTEXPR blocking_t(always_t)+    : value_(1)+  {+  }++  ASIO_CONSTEXPR blocking_t(never_t)+    : value_(2)+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, blocking_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, blocking_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, blocking_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, possibly_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, blocking_t>::is_valid+          && !traits::query_member<T, blocking_t>::is_valid+          && traits::static_query<T, possibly_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, possibly_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, always_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, blocking_t>::is_valid+          && !traits::query_member<T, blocking_t>::is_valid+          && !traits::static_query<T, possibly_t>::is_valid+          && traits::static_query<T, always_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, always_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, never_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, blocking_t>::is_valid+          && !traits::query_member<T, blocking_t>::is_valid+          && !traits::static_query<T, possibly_t>::is_valid+          && !traits::static_query<T, always_t>::is_valid+          && traits::static_query<T, never_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, never_t>::value();+  }++  template <typename E, typename T = decltype(blocking_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = blocking_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  friend ASIO_CONSTEXPR bool operator==(+      const blocking_t& a, const blocking_t& b)+  {+    return a.value_ == b.value_;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const blocking_t& a, const blocking_t& b)+  {+    return a.value_ != b.value_;+  }++  struct convertible_from_blocking_t+  {+    ASIO_CONSTEXPR convertible_from_blocking_t(blocking_t) {}+  };++  template <typename Executor>+  friend ASIO_CONSTEXPR blocking_t query(+      const Executor& ex, convertible_from_blocking_t,+      typename enable_if<+        can_query<const Executor&, possibly_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, blocking_t<>::possibly_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, possibly_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, possibly_t());+  }++  template <typename Executor>+  friend ASIO_CONSTEXPR blocking_t query(+      const Executor& ex, convertible_from_blocking_t,+      typename enable_if<+        !can_query<const Executor&, possibly_t>::value+          && can_query<const Executor&, always_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, blocking_t<>::always_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, always_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, always_t());+  }++  template <typename Executor>+  friend ASIO_CONSTEXPR blocking_t query(+      const Executor& ex, convertible_from_blocking_t,+      typename enable_if<+        !can_query<const Executor&, possibly_t>::value+          && !can_query<const Executor&, always_t>::value+          && can_query<const Executor&, never_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, blocking_t<>::never_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, never_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, never_t());+  }++  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(possibly_t, possibly);+  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(always_t, always);+  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(never_t, never);++#if !defined(ASIO_HAS_CONSTEXPR)+  static const blocking_t instance;+#endif // !defined(ASIO_HAS_CONSTEXPR)++private:+  int value_;+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T blocking_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+template <int I>+const blocking_t<I> blocking_t<I>::instance;+#endif++template <int I>+const typename blocking_t<I>::possibly_t blocking_t<I>::possibly;++template <int I>+const typename blocking_t<I>::always_t blocking_t<I>::always;++template <int I>+const typename blocking_t<I>::never_t blocking_t<I>::never;++namespace blocking {++template <int I = 0>+struct possibly_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef blocking_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR possibly_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, possibly_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, possibly_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, possibly_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR possibly_t static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, possibly_t>::is_valid+          && !traits::query_member<T, possibly_t>::is_valid+          && !traits::query_free<T, possibly_t>::is_valid+          && !can_query<T, always_t<I> >::value+          && !can_query<T, never_t<I> >::value+      >::type* = 0) ASIO_NOEXCEPT+  {+    return possibly_t();+  }++  template <typename E, typename T = decltype(possibly_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = possibly_t::static_query<E>();+#endif // defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR blocking_t<I> value()+  {+    return possibly_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const possibly_t&, const possibly_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const possibly_t&, const possibly_t&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const possibly_t&, const always_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const possibly_t&, const always_t<I>&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const possibly_t&, const never_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const possibly_t&, const never_t<I>&)+  {+    return true;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T possibly_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename Executor>+class adapter+{+public:+  adapter(int, const Executor& e) ASIO_NOEXCEPT+    : executor_(e)+  {+  }++  adapter(const adapter& other) ASIO_NOEXCEPT+    : executor_(other.executor_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  adapter(adapter&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(Executor)(other.executor_))+  {+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  template <int I>+  static ASIO_CONSTEXPR always_t<I> query(+      blocking_t<I>) ASIO_NOEXCEPT+  {+    return always_t<I>();+  }++  template <int I>+  static ASIO_CONSTEXPR always_t<I> query(+      possibly_t<I>) ASIO_NOEXCEPT+  {+    return always_t<I>();+  }++  template <int I>+  static ASIO_CONSTEXPR always_t<I> query(+      always_t<I>) ASIO_NOEXCEPT+  {+    return always_t<I>();+  }++  template <int I>+  static ASIO_CONSTEXPR always_t<I> query(+      never_t<I>) ASIO_NOEXCEPT+  {+    return always_t<I>();+  }++  template <typename Property>+  typename enable_if<+    can_query<const Executor&, Property>::value,+    typename query_result<const Executor&, Property>::type+  >::type query(const Property& p) const+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, Property>::value))+  {+    return asio::query(executor_, p);+  }++  template <int I>+  typename enable_if<+    can_require<const Executor&, possibly_t<I> >::value,+    typename require_result<const Executor&, possibly_t<I> >::type+  >::type require(possibly_t<I>) const ASIO_NOEXCEPT+  {+    return asio::require(executor_, possibly_t<I>());+  }++  template <int I>+  typename enable_if<+    can_require<const Executor&, never_t<I> >::value,+    typename require_result<const Executor&, never_t<I> >::type+  >::type require(never_t<I>) const ASIO_NOEXCEPT+  {+    return asio::require(executor_, never_t<I>());+  }++  template <typename Property>+  typename enable_if<+    can_require<const Executor&, Property>::value,+    adapter<typename decay<+      typename require_result<const Executor&, Property>::type+    >::type>+  >::type require(const Property& p) const+    ASIO_NOEXCEPT_IF((+      is_nothrow_require<const Executor&, Property>::value))+  {+    return adapter<typename decay<+      typename require_result<const Executor&, Property>::type+        >::type>(0, asio::require(executor_, p));+  }++  template <typename Property>+  typename enable_if<+    can_prefer<const Executor&, Property>::value,+    adapter<typename decay<+      typename prefer_result<const Executor&, Property>::type+    >::type>+  >::type prefer(const Property& p) const+    ASIO_NOEXCEPT_IF((+      is_nothrow_prefer<const Executor&, Property>::value))+  {+    return adapter<typename decay<+      typename prefer_result<const Executor&, Property>::type+        >::type>(0, asio::prefer(executor_, p));+  }++  template <typename Function>+  typename enable_if<+    execution::can_execute<const Executor&, Function>::value+  >::type execute(ASIO_MOVE_ARG(Function) f) const+  {+    blocking_adaptation::blocking_execute(+        executor_, ASIO_MOVE_CAST(Function)(f));+  }++  friend bool operator==(const adapter& a, const adapter& b) ASIO_NOEXCEPT+  {+    return a.executor_ == b.executor_;+  }++  friend bool operator!=(const adapter& a, const adapter& b) ASIO_NOEXCEPT+  {+    return a.executor_ != b.executor_;+  }++private:+  Executor executor_;+};++template <int I = 0>+struct always_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+  typedef blocking_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR always_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, always_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, always_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, always_t>::value();+  }++  template <typename E, typename T = decltype(always_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = always_t::static_query<E>();+#endif // defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR blocking_t<I> value()+  {+    return always_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const always_t&, const always_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const always_t&, const always_t&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const always_t&, const possibly_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const always_t&, const possibly_t<I>&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const always_t&, const never_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const always_t&, const never_t<I>&)+  {+    return true;+  }++  template <typename Executor>+  friend adapter<Executor> require(+      const Executor& e, const always_t&,+      typename enable_if<+        is_executor<Executor>::value+        && traits::static_require<+          const Executor&,+          blocking_adaptation::allowed_t<0>+        >::is_valid+      >::type* = 0)+  {+    return adapter<Executor>(0, e);+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T always_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <int I>+struct never_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef blocking_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR never_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, never_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, never_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, never_t>::value();+  }++  template <typename E, typename T = decltype(never_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = never_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR blocking_t<I> value()+  {+    return never_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const never_t&, const never_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const never_t&, const never_t&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const never_t&, const possibly_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const never_t&, const possibly_t<I>&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const never_t&, const always_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const never_t&, const always_t<I>&)+  {+    return true;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T never_t<I>::static_query_v;+#endif // defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++} // namespace blocking+} // namespace detail++typedef detail::blocking_t<> blocking_t;++#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr blocking_t blocking;+#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+namespace { static const blocking_t& blocking = blocking_t::instance; }+#endif++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+struct is_applicable_property<T, execution::blocking_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::blocking_t::possibly_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::blocking_t::always_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::blocking_t::never_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T>+struct query_free_default<T, execution::blocking_t,+  typename enable_if<+    can_query<T, execution::blocking_t::possibly_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::blocking_t::possibly_t>::value));++  typedef execution::blocking_t result_type;+};++template <typename T>+struct query_free_default<T, execution::blocking_t,+  typename enable_if<+    !can_query<T, execution::blocking_t::possibly_t>::value+      && can_query<T, execution::blocking_t::always_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::blocking_t::always_t>::value));++  typedef execution::blocking_t result_type;+};++template <typename T>+struct query_free_default<T, execution::blocking_t,+  typename enable_if<+    !can_query<T, execution::blocking_t::possibly_t>::value+      && !can_query<T, execution::blocking_t::always_t>::value+      && can_query<T, execution::blocking_t::never_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::blocking_t::never_t>::value));++  typedef execution::blocking_t result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T>+struct static_query<T, execution::blocking_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::blocking_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::blocking_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::blocking_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T, execution::blocking_t>::is_valid+      && !traits::query_member<T, execution::blocking_t>::is_valid+      && traits::static_query<T, execution::blocking_t::possibly_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::blocking_t::possibly_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T, execution::blocking_t::possibly_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T, execution::blocking_t>::is_valid+      && !traits::query_member<T, execution::blocking_t>::is_valid+      && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid+      && traits::static_query<T, execution::blocking_t::always_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::blocking_t::always_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T, execution::blocking_t::always_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T, execution::blocking_t>::is_valid+      && !traits::query_member<T, execution::blocking_t>::is_valid+      && !traits::static_query<T, execution::blocking_t::possibly_t>::is_valid+      && !traits::static_query<T, execution::blocking_t::always_t>::is_valid+      && traits::static_query<T, execution::blocking_t::never_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::blocking_t::never_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T, execution::blocking_t::never_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_t::possibly_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::blocking_t::possibly_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::blocking_t::possibly_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::blocking_t::possibly_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_t::possibly_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+      execution::blocking_t::possibly_t>::is_valid+      && !traits::query_member<T, execution::blocking_t::possibly_t>::is_valid+      && !traits::query_free<T, execution::blocking_t::possibly_t>::is_valid+      && !can_query<T, execution::blocking_t::always_t>::value+      && !can_query<T, execution::blocking_t::never_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef execution::blocking_t::possibly_t result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return result_type();+  }+};++template <typename T>+struct static_query<T, execution::blocking_t::always_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::blocking_t::always_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::blocking_t::always_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::blocking_t::always_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_t::never_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::blocking_t::never_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::blocking_t::never_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::blocking_t::never_t>::value();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++template <typename T>+struct static_require<T, execution::blocking_t::possibly_t,+  typename enable_if<+    static_query<T, execution::blocking_t::possibly_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::blocking_t::possibly_t>::result_type,+        execution::blocking_t::possibly_t>::value));+};++template <typename T>+struct static_require<T, execution::blocking_t::always_t,+  typename enable_if<+    static_query<T, execution::blocking_t::always_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::blocking_t::always_t>::result_type,+        execution::blocking_t::always_t>::value));+};++template <typename T>+struct static_require<T, execution::blocking_t::never_t,+  typename enable_if<+    static_query<T, execution::blocking_t::never_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::blocking_t::never_t>::result_type,+        execution::blocking_t::never_t>::value));+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)++template <typename T>+struct require_free_default<T, execution::blocking_t::always_t,+  typename enable_if<+    is_same<T, typename decay<T>::type>::value+      && execution::is_executor<T>::value+      && traits::static_require<+          const T&,+          execution::detail::blocking_adaptation::allowed_t<0>+        >::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef execution::detail::blocking::adapter<T> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <typename Executor>+struct equality_comparable<+  execution::detail::blocking::adapter<Executor> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename Executor, typename Function>+struct execute_member<+  execution::detail::blocking::adapter<Executor>, Function>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++template <typename Executor, int I>+struct query_static_constexpr_member<+  execution::detail::blocking::adapter<Executor>,+  execution::detail::blocking_t<I> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef execution::blocking_t::always_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++template <typename Executor, int I>+struct query_static_constexpr_member<+  execution::detail::blocking::adapter<Executor>,+  execution::detail::blocking::always_t<I> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef execution::blocking_t::always_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++template <typename Executor, int I>+struct query_static_constexpr_member<+  execution::detail::blocking::adapter<Executor>,+  execution::detail::blocking::possibly_t<I> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef execution::blocking_t::always_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++template <typename Executor, int I>+struct query_static_constexpr_member<+  execution::detail::blocking::adapter<Executor>,+  execution::detail::blocking::never_t<I> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef execution::blocking_t::always_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename Executor, typename Property>+struct query_member<+  execution::detail::blocking::adapter<Executor>, Property,+  typename enable_if<+    can_query<const Executor&, Property>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_query<Executor, Property>::value));+  typedef typename query_result<Executor, Property>::type result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Executor, int I>+struct require_member<+  execution::detail::blocking::adapter<Executor>,+  execution::detail::blocking::possibly_t<I>,+  typename enable_if<+    can_require<+      const Executor&,+      execution::detail::blocking::possibly_t<I>+    >::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_require<const Executor&,+        execution::detail::blocking::possibly_t<I> >::value));+  typedef typename require_result<const Executor&,+    execution::detail::blocking::possibly_t<I> >::type result_type;+};++template <typename Executor, int I>+struct require_member<+  execution::detail::blocking::adapter<Executor>,+  execution::detail::blocking::never_t<I>,+  typename enable_if<+    can_require<+      const Executor&,+      execution::detail::blocking::never_t<I>+    >::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_require<const Executor&,+        execution::detail::blocking::never_t<I> >::value));+  typedef typename require_result<const Executor&,+    execution::detail::blocking::never_t<I> >::type result_type;+};++template <typename Executor, typename Property>+struct require_member<+  execution::detail::blocking::adapter<Executor>, Property,+  typename enable_if<+    can_require<const Executor&, Property>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_require<Executor, Property>::value));+  typedef execution::detail::blocking::adapter<typename decay<+    typename require_result<Executor, Property>::type+      >::type> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++template <typename Executor, typename Property>+struct prefer_member<+  execution::detail::blocking::adapter<Executor>, Property,+  typename enable_if<+    can_prefer<const Executor&, Property>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_prefer<Executor, Property>::value));+  typedef execution::detail::blocking::adapter<typename decay<+    typename prefer_result<Executor, Property>::type+      >::type> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_BLOCKING_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/blocking_adaptation.hpp view
@@ -0,0 +1,1064 @@+//+// execution/blocking_adaptation.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_BLOCKING_ADAPTATION_HPP+#define ASIO_EXECUTION_BLOCKING_ADAPTATION_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/event.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/execute.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/prefer.hpp"+#include "asio/query.hpp"+#include "asio/require.hpp"+#include "asio/traits/prefer_member.hpp"+#include "asio/traits/query_free.hpp"+#include "asio/traits/query_member.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/require_member.hpp"+#include "asio/traits/static_query.hpp"+#include "asio/traits/static_require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property to describe whether automatic adaptation of an executor is+/// allowed in order to apply the blocking_adaptation_t::allowed_t property.+struct blocking_adaptation_t+{+  /// The blocking_adaptation_t property applies to executors, senders, and+  /// schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The top-level blocking_adaptation_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The top-level blocking_adaptation_t property cannot be preferred.+  static constexpr bool is_preferable = false;++  /// The type returned by queries against an @c any_executor.+  typedef blocking_adaptation_t polymorphic_query_result_type;++  /// A sub-property that indicates that automatic adaptation is not allowed.+  struct disallowed_t+  {+    /// The blocking_adaptation_t::disallowed_t property applies to executors,+    /// senders, and schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The blocking_adaptation_t::disallowed_t property can be required.+    static constexpr bool is_requirable = true;++    /// The blocking_adaptation_t::disallowed_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef blocking_adaptation_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr disallowed_t();++    /// Get the value associated with a property object.+    /**+     * @returns disallowed_t();+     */+    static constexpr blocking_adaptation_t value();+  };++  /// A sub-property that indicates that automatic adaptation is allowed.+  struct allowed_t+  {+    /// The blocking_adaptation_t::allowed_t property applies to executors,+    /// senders, and schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The blocking_adaptation_t::allowed_t property can be required.+    static constexpr bool is_requirable = true;++    /// The blocking_adaptation_t::allowed_t property can be preferred.+    static constexpr bool is_preferable = false;++    /// The type returned by queries against an @c any_executor.+    typedef blocking_adaptation_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr allowed_t();++    /// Get the value associated with a property object.+    /**+     * @returns allowed_t();+     */+    static constexpr blocking_adaptation_t value();+  };++  /// A special value used for accessing the blocking_adaptation_t::disallowed_t+  /// property.+  static constexpr disallowed_t disallowed;++  /// A special value used for accessing the blocking_adaptation_t::allowed_t+  /// property.+  static constexpr allowed_t allowed;++  /// Default constructor.+  constexpr blocking_adaptation_t();++  /// Construct from a sub-property value.+  constexpr blocking_adaptation_t(disallowed_t);++  /// Construct from a sub-property value.+  constexpr blocking_adaptation_t(allowed_t);++  /// Compare property values for equality.+  friend constexpr bool operator==(+      const blocking_adaptation_t& a, const blocking_adaptation_t& b) noexcept;++  /// Compare property values for inequality.+  friend constexpr bool operator!=(+      const blocking_adaptation_t& a, const blocking_adaptation_t& b) noexcept;+};++/// A special value used for accessing the blocking_adaptation_t property.+constexpr blocking_adaptation_t blocking_adaptation;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {+namespace detail {+namespace blocking_adaptation {++template <int I> struct disallowed_t;+template <int I> struct allowed_t;++} // namespace blocking_adaptation++template <int I = 0>+struct blocking_adaptation_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+  typedef blocking_adaptation_t polymorphic_query_result_type;++  typedef detail::blocking_adaptation::disallowed_t<I> disallowed_t;+  typedef detail::blocking_adaptation::allowed_t<I> allowed_t;++  ASIO_CONSTEXPR blocking_adaptation_t()+    : value_(-1)+  {+  }++  ASIO_CONSTEXPR blocking_adaptation_t(disallowed_t)+    : value_(0)+  {+  }++  ASIO_CONSTEXPR blocking_adaptation_t(allowed_t)+    : value_(1)+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<+      T, blocking_adaptation_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<+        T, blocking_adaptation_t+      >::is_noexcept))+  {+    return traits::query_static_constexpr_member<+        T, blocking_adaptation_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, disallowed_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<+            T, blocking_adaptation_t>::is_valid+          && !traits::query_member<T, blocking_adaptation_t>::is_valid+          && traits::static_query<T, disallowed_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, disallowed_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, allowed_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<+            T, blocking_adaptation_t>::is_valid+          && !traits::query_member<T, blocking_adaptation_t>::is_valid+          && !traits::static_query<T, disallowed_t>::is_valid+          && traits::static_query<T, allowed_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, allowed_t>::value();+  }++  template <typename E,+      typename T = decltype(blocking_adaptation_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = blocking_adaptation_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  friend ASIO_CONSTEXPR bool operator==(+      const blocking_adaptation_t& a, const blocking_adaptation_t& b)+  {+    return a.value_ == b.value_;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const blocking_adaptation_t& a, const blocking_adaptation_t& b)+  {+    return a.value_ != b.value_;+  }++  struct convertible_from_blocking_adaptation_t+  {+    ASIO_CONSTEXPR convertible_from_blocking_adaptation_t(+        blocking_adaptation_t)+    {+    }+  };++  template <typename Executor>+  friend ASIO_CONSTEXPR blocking_adaptation_t query(+      const Executor& ex, convertible_from_blocking_adaptation_t,+      typename enable_if<+        can_query<const Executor&, disallowed_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&,+        blocking_adaptation_t<>::disallowed_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, disallowed_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, disallowed_t());+  }++  template <typename Executor>+  friend ASIO_CONSTEXPR blocking_adaptation_t query(+      const Executor& ex, convertible_from_blocking_adaptation_t,+      typename enable_if<+        !can_query<const Executor&, disallowed_t>::value+          && can_query<const Executor&, allowed_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&,+        blocking_adaptation_t<>::allowed_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, allowed_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, allowed_t());+  }++  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(disallowed_t, disallowed);+  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(allowed_t, allowed);++#if !defined(ASIO_HAS_CONSTEXPR)+  static const blocking_adaptation_t instance;+#endif // !defined(ASIO_HAS_CONSTEXPR)++private:+  int value_;+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T blocking_adaptation_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+template <int I>+const blocking_adaptation_t<I> blocking_adaptation_t<I>::instance;+#endif++template <int I>+const typename blocking_adaptation_t<I>::disallowed_t+blocking_adaptation_t<I>::disallowed;++template <int I>+const typename blocking_adaptation_t<I>::allowed_t+blocking_adaptation_t<I>::allowed;++namespace blocking_adaptation {++template <int I = 0>+struct disallowed_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef blocking_adaptation_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR disallowed_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, disallowed_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, disallowed_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, disallowed_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR disallowed_t static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, disallowed_t>::is_valid+          && !traits::query_member<T, disallowed_t>::is_valid+          && !traits::query_free<T, disallowed_t>::is_valid+          && !can_query<T, allowed_t<I> >::value+      >::type* = 0) ASIO_NOEXCEPT+  {+    return disallowed_t();+  }++  template <typename E, typename T = decltype(disallowed_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = disallowed_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR blocking_adaptation_t<I> value()+  {+    return disallowed_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const disallowed_t&, const disallowed_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const disallowed_t&, const disallowed_t&)+  {+    return false;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T disallowed_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename Executor>+class adapter+{+public:+  adapter(int, const Executor& e) ASIO_NOEXCEPT+    : executor_(e)+  {+  }++  adapter(const adapter& other) ASIO_NOEXCEPT+    : executor_(other.executor_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  adapter(adapter&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(Executor)(other.executor_))+  {+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  template <int I>+  static ASIO_CONSTEXPR allowed_t<I> query(+      blocking_adaptation_t<I>) ASIO_NOEXCEPT+  {+    return allowed_t<I>();+  }++  template <int I>+  static ASIO_CONSTEXPR allowed_t<I> query(+      allowed_t<I>) ASIO_NOEXCEPT+  {+    return allowed_t<I>();+  }++  template <int I>+  static ASIO_CONSTEXPR allowed_t<I> query(+      disallowed_t<I>) ASIO_NOEXCEPT+  {+    return allowed_t<I>();+  }++  template <typename Property>+  typename enable_if<+    can_query<const Executor&, Property>::value,+    typename query_result<const Executor&, Property>::type+  >::type query(const Property& p) const+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, Property>::value))+  {+    return asio::query(executor_, p);+  }++  template <int I>+  Executor require(disallowed_t<I>) const ASIO_NOEXCEPT+  {+    return executor_;+  }++  template <typename Property>+  typename enable_if<+    can_require<const Executor&, Property>::value,+    adapter<typename decay<+      typename require_result<const Executor&, Property>::type+    >::type>+  >::type require(const Property& p) const+    ASIO_NOEXCEPT_IF((+      is_nothrow_require<const Executor&, Property>::value))+  {+    return adapter<typename decay<+      typename require_result<const Executor&, Property>::type+        >::type>(0, asio::require(executor_, p));+  }++  template <typename Property>+  typename enable_if<+    can_prefer<const Executor&, Property>::value,+    adapter<typename decay<+      typename prefer_result<const Executor&, Property>::type+    >::type>+  >::type prefer(const Property& p) const+    ASIO_NOEXCEPT_IF((+      is_nothrow_prefer<const Executor&, Property>::value))+  {+    return adapter<typename decay<+      typename prefer_result<const Executor&, Property>::type+        >::type>(0, asio::prefer(executor_, p));+  }++  template <typename Function>+  typename enable_if<+    execution::can_execute<const Executor&, Function>::value+  >::type execute(ASIO_MOVE_ARG(Function) f) const+  {+    execution::execute(executor_, ASIO_MOVE_CAST(Function)(f));+  }++  friend bool operator==(const adapter& a, const adapter& b) ASIO_NOEXCEPT+  {+    return a.executor_ == b.executor_;+  }++  friend bool operator!=(const adapter& a, const adapter& b) ASIO_NOEXCEPT+  {+    return a.executor_ != b.executor_;+  }++private:+  Executor executor_;+};++template <int I = 0>+struct allowed_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+  typedef blocking_adaptation_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR allowed_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, allowed_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, allowed_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, allowed_t>::value();+  }++  template <typename E, typename T = decltype(allowed_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = allowed_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR blocking_adaptation_t<I> value()+  {+    return allowed_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const allowed_t&, const allowed_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const allowed_t&, const allowed_t&)+  {+    return false;+  }++  template <typename Executor>+  friend adapter<Executor> require(+      const Executor& e, const allowed_t&,+      typename enable_if<+        is_executor<Executor>::value+      >::type* = 0)+  {+    return adapter<Executor>(0, e);+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T allowed_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename Function>+class blocking_execute_state+{+public:+  template <typename F>+  blocking_execute_state(ASIO_MOVE_ARG(F) f)+    : func_(ASIO_MOVE_CAST(F)(f)),+      is_complete_(false)+  {+  }++  template <typename Executor>+  void execute_and_wait(ASIO_MOVE_ARG(Executor) ex)+  {+    handler h = { this };+    execution::execute(ASIO_MOVE_CAST(Executor)(ex), h);+    asio::detail::mutex::scoped_lock lock(mutex_);+    while (!is_complete_)+      event_.wait(lock);+  }++  struct cleanup+  {+    ~cleanup()+    {+      asio::detail::mutex::scoped_lock lock(state_->mutex_);+      state_->is_complete_ = true;+      state_->event_.unlock_and_signal_one_for_destruction(lock);+    }++    blocking_execute_state* state_;+  };++  struct handler+  {+    void operator()()+    {+      cleanup c = { state_ };+      state_->func_();+    }++    blocking_execute_state* state_;+  };++  Function func_;+  asio::detail::mutex mutex_;+  asio::detail::event event_;+  bool is_complete_;+};++template <typename Executor, typename Function>+void blocking_execute(+    ASIO_MOVE_ARG(Executor) ex,+    ASIO_MOVE_ARG(Function) func)+{+  typedef typename decay<Function>::type func_t;+  blocking_execute_state<func_t> state(ASIO_MOVE_CAST(Function)(func));+  state.execute_and_wait(ex);+}++} // namespace blocking_adaptation+} // namespace detail++typedef detail::blocking_adaptation_t<> blocking_adaptation_t;++#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr blocking_adaptation_t blocking_adaptation;+#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+namespace { static const blocking_adaptation_t&+  blocking_adaptation = blocking_adaptation_t::instance; }+#endif++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+struct is_applicable_property<T, execution::blocking_adaptation_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::blocking_adaptation_t::disallowed_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::blocking_adaptation_t::allowed_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T>+struct query_free_default<T, execution::blocking_adaptation_t,+  typename enable_if<+    can_query<T, execution::blocking_adaptation_t::disallowed_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = (is_nothrow_query<T,+      execution::blocking_adaptation_t::disallowed_t>::value));++  typedef execution::blocking_adaptation_t result_type;+};++template <typename T>+struct query_free_default<T, execution::blocking_adaptation_t,+  typename enable_if<+    !can_query<T, execution::blocking_adaptation_t::disallowed_t>::value+      && can_query<T, execution::blocking_adaptation_t::allowed_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::blocking_adaptation_t::allowed_t>::value));++  typedef execution::blocking_adaptation_t result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T>+struct static_query<T, execution::blocking_adaptation_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::blocking_adaptation_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::blocking_adaptation_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::blocking_adaptation_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_adaptation_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::blocking_adaptation_t>::is_valid+      && !traits::query_member<T,+        execution::blocking_adaptation_t>::is_valid+      && traits::static_query<T,+        execution::blocking_adaptation_t::disallowed_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::blocking_adaptation_t::disallowed_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T,+        execution::blocking_adaptation_t::disallowed_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_adaptation_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::blocking_adaptation_t>::is_valid+      && !traits::query_member<T,+        execution::blocking_adaptation_t>::is_valid+      && !traits::static_query<T,+        execution::blocking_adaptation_t::disallowed_t>::is_valid+      && traits::static_query<T,+        execution::blocking_adaptation_t::allowed_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::blocking_adaptation_t::allowed_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T,+        execution::blocking_adaptation_t::allowed_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_adaptation_t::disallowed_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::blocking_adaptation_t::disallowed_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::blocking_adaptation_t::disallowed_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::blocking_adaptation_t::disallowed_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::blocking_adaptation_t::disallowed_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::blocking_adaptation_t::disallowed_t>::is_valid+      && !traits::query_member<T,+        execution::blocking_adaptation_t::disallowed_t>::is_valid+      && !traits::query_free<T,+        execution::blocking_adaptation_t::disallowed_t>::is_valid+      && !can_query<T, execution::blocking_adaptation_t::allowed_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef execution::blocking_adaptation_t::disallowed_t result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return result_type();+  }+};++template <typename T>+struct static_query<T, execution::blocking_adaptation_t::allowed_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::blocking_adaptation_t::allowed_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::blocking_adaptation_t::allowed_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::blocking_adaptation_t::allowed_t>::value();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++template <typename T>+struct static_require<T, execution::blocking_adaptation_t::disallowed_t,+  typename enable_if<+    static_query<T, execution::blocking_adaptation_t::disallowed_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::blocking_adaptation_t::disallowed_t>::result_type,+        execution::blocking_adaptation_t::disallowed_t>::value));+};++template <typename T>+struct static_require<T, execution::blocking_adaptation_t::allowed_t,+  typename enable_if<+    static_query<T, execution::blocking_adaptation_t::allowed_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::blocking_adaptation_t::allowed_t>::result_type,+        execution::blocking_adaptation_t::allowed_t>::value));+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)++template <typename T>+struct require_free_default<T, execution::blocking_adaptation_t::allowed_t,+  typename enable_if<+    is_same<T, typename decay<T>::type>::value+      && execution::is_executor<T>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef execution::detail::blocking_adaptation::adapter<T> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <typename Executor>+struct equality_comparable<+  execution::detail::blocking_adaptation::adapter<Executor> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename Executor, typename Function>+struct execute_member<+  execution::detail::blocking_adaptation::adapter<Executor>, Function>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++template <typename Executor, int I>+struct query_static_constexpr_member<+  execution::detail::blocking_adaptation::adapter<Executor>,+  execution::detail::blocking_adaptation_t<I> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef execution::blocking_adaptation_t::allowed_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++template <typename Executor, int I>+struct query_static_constexpr_member<+  execution::detail::blocking_adaptation::adapter<Executor>,+  execution::detail::blocking_adaptation::allowed_t<I> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef execution::blocking_adaptation_t::allowed_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++template <typename Executor, int I>+struct query_static_constexpr_member<+  execution::detail::blocking_adaptation::adapter<Executor>,+  execution::detail::blocking_adaptation::disallowed_t<I> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef execution::blocking_adaptation_t::allowed_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename Executor, typename Property>+struct query_member<+  execution::detail::blocking_adaptation::adapter<Executor>, Property,+  typename enable_if<+    can_query<const Executor&, Property>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_query<Executor, Property>::value));+  typedef typename query_result<Executor, Property>::type result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Executor, int I>+struct require_member<+  execution::detail::blocking_adaptation::adapter<Executor>,+  execution::detail::blocking_adaptation::disallowed_t<I> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef Executor result_type;+};++template <typename Executor, typename Property>+struct require_member<+  execution::detail::blocking_adaptation::adapter<Executor>, Property,+  typename enable_if<+    can_require<const Executor&, Property>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_require<Executor, Property>::value));+  typedef execution::detail::blocking_adaptation::adapter<typename decay<+    typename require_result<Executor, Property>::type+      >::type> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++template <typename Executor, typename Property>+struct prefer_member<+  execution::detail::blocking_adaptation::adapter<Executor>, Property,+  typename enable_if<+    can_prefer<const Executor&, Property>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_prefer<Executor, Property>::value));+  typedef execution::detail::blocking_adaptation::adapter<typename decay<+    typename prefer_result<Executor, Property>::type+      >::type> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_BLOCKING_ADAPTATION_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/bulk_execute.hpp view
@@ -0,0 +1,390 @@+//+// execution/bulk_execute.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_BULK_EXECUTE_HPP+#define ASIO_EXECUTION_BULK_EXECUTE_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/execution/bulk_guarantee.hpp"+#include "asio/execution/detail/bulk_sender.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/sender.hpp"+#include "asio/traits/bulk_execute_member.hpp"+#include "asio/traits/bulk_execute_free.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++/// A customisation point that creates a bulk sender.+/**+ * The name <tt>execution::bulk_execute</tt> denotes a customisation point+ * object. If <tt>is_convertible_v<N, size_t></tt> is true, then the expression+ * <tt>execution::bulk_execute(S, F, N)</tt> for some subexpressions+ * <tt>S</tt>, <tt>F</tt>, and <tt>N</tt> is expression-equivalent to:+ *+ * @li <tt>S.bulk_execute(F, N)</tt>, if that expression is valid. If the+ *   function selected does not execute <tt>N</tt> invocations of the function+ *   object <tt>F</tt> on the executor <tt>S</tt> in bulk with forward progress+ *   guarantee <tt>asio::query(S, execution::bulk_guarantee)</tt>, and+ *   the result of that function does not model <tt>sender<void></tt>, the+ *   program is ill-formed with no diagnostic required.+ *+ * @li Otherwise, <tt>bulk_execute(S, F, N)</tt>, if that expression is valid,+ *   with overload resolution performed in a context that includes the+ *   declaration <tt>void bulk_execute();</tt> and that does not include a+ *   declaration of <tt>execution::bulk_execute</tt>. If the function selected+ *   by overload resolution does not execute <tt>N</tt> invocations of the+ *   function object <tt>F</tt> on the executor <tt>S</tt> in bulk with forward+ *   progress guarantee <tt>asio::query(E,+ *   execution::bulk_guarantee)</tt>, and the result of that function does not+ *   model <tt>sender<void></tt>, the program is ill-formed with no diagnostic+ *   required.+ *+ * @li Otherwise, if the types <tt>F</tt> and+ *   <tt>executor_index_t<remove_cvref_t<S>></tt> model <tt>invocable</tt> and+ *   if <tt>asio::query(S, execution::bulk_guarantee)</tt> equals+ *   <tt>execution::bulk_guarantee.unsequenced</tt>, then+ *+ *    - Evaluates <tt>DECAY_COPY(std::forward<decltype(F)>(F))</tt> on the+ *      calling thread to create a function object <tt>cf</tt>. [Note:+ *      Additional copies of <tt>cf</tt> may subsequently be created. --end+ *      note.]+ *+ *    - For each value of <tt>i</tt> in <tt>N</tt>, <tt>cf(i)</tt> (or copy of+ *      <tt>cf</tt>)) will be invoked at most once by an execution agent that is+ *      unique for each value of <tt>i</tt>.+ *+ *    - May block pending completion of one or more invocations of <tt>cf</tt>.+ *+ *    - Synchronizes with (C++Std [intro.multithread]) the invocations of+ *      <tt>cf</tt>.+ *+ * @li Otherwise, <tt>execution::bulk_execute(S, F, N)</tt> is ill-formed.+ */+inline constexpr unspecified bulk_execute = unspecified;++/// A type trait that determines whether a @c bulk_execute expression is+/// well-formed.+/**+ * Class template @c can_bulk_execute is a trait that is derived from @c+ * true_type if the expression <tt>execution::bulk_execute(std::declval<S>(),+ * std::declval<F>(), std::declval<N>)</tt> is well formed; otherwise @c+ * false_type.+ */+template <typename S, typename F, typename N>+struct can_bulk_execute :+  integral_constant<bool, automatically_determined>+{+};++} // namespace execution+} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_execution_bulk_execute_fn {++using asio::declval;+using asio::enable_if;+using asio::execution::bulk_guarantee_t;+using asio::execution::detail::bulk_sender;+using asio::execution::executor_index;+using asio::execution::is_sender;+using asio::is_convertible;+using asio::is_same;+using asio::remove_cvref;+using asio::result_of;+using asio::traits::bulk_execute_free;+using asio::traits::bulk_execute_member;+using asio::traits::static_require;++void bulk_execute();++enum overload_type+{+  call_member,+  call_free,+  adapter,+  ill_formed+};++template <typename S, typename Args, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename S, typename F, typename N>+struct call_traits<S, void(F, N),+  typename enable_if<+    (+      is_convertible<N, std::size_t>::value+      &&+      bulk_execute_member<S, F, N>::is_valid+      &&+      is_sender<+        typename bulk_execute_member<S, F, N>::result_type+      >::value+    )+  >::type> :+  bulk_execute_member<S, F, N>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename S, typename F, typename N>+struct call_traits<S, void(F, N),+  typename enable_if<+    (+      is_convertible<N, std::size_t>::value+      &&+      !bulk_execute_member<S, F, N>::is_valid+      &&+      bulk_execute_free<S, F, N>::is_valid+      &&+      is_sender<+        typename bulk_execute_free<S, F, N>::result_type+      >::value+    )+  >::type> :+  bulk_execute_free<S, F, N>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++template <typename S, typename F, typename N>+struct call_traits<S, void(F, N),+  typename enable_if<+    (+      is_convertible<N, std::size_t>::value+      &&+      !bulk_execute_member<S, F, N>::is_valid+      &&+      !bulk_execute_free<S, F, N>::is_valid+      &&+      is_sender<S>::value+      &&+      is_same<+        typename result_of<+          F(typename executor_index<typename remove_cvref<S>::type>::type)+        >::type,+        typename result_of<+          F(typename executor_index<typename remove_cvref<S>::type>::type)+        >::type+      >::value+      &&+      static_require<S, bulk_guarantee_t::unsequenced_t>::is_valid+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef bulk_sender<S, F, N> result_type;+};++struct impl+{+#if defined(ASIO_HAS_MOVE)+  template <typename S, typename F, typename N>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(F, N)>::overload == call_member,+    typename call_traits<S, void(F, N)>::result_type+  >::type+  operator()(S&& s, F&& f, N&& n) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(F, N)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(S)(s).bulk_execute(+        ASIO_MOVE_CAST(F)(f), ASIO_MOVE_CAST(N)(n));+  }++  template <typename S, typename F, typename N>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(F, N)>::overload == call_free,+    typename call_traits<S, void(F, N)>::result_type+  >::type+  operator()(S&& s, F&& f, N&& n) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(F, N)>::is_noexcept))+  {+    return bulk_execute(ASIO_MOVE_CAST(S)(s),+        ASIO_MOVE_CAST(F)(f), ASIO_MOVE_CAST(N)(n));+  }++  template <typename S, typename F, typename N>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(F, N)>::overload == adapter,+    typename call_traits<S, void(F, N)>::result_type+  >::type+  operator()(S&& s, F&& f, N&& n) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(F, N)>::is_noexcept))+  {+    return typename call_traits<S, void(F, N)>::result_type(+        ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(F)(f),+        ASIO_MOVE_CAST(N)(n));+  }+#else // defined(ASIO_HAS_MOVE)+  template <typename S, typename F, typename N>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(const F&, const N&)>::overload == call_member,+    typename call_traits<S, void(const F&, const N&)>::result_type+  >::type+  operator()(S& s, const F& f, const N& n) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(const F&, const N&)>::is_noexcept))+  {+    return s.bulk_execute(ASIO_MOVE_CAST(F)(f),+        ASIO_MOVE_CAST(N)(n));+  }++  template <typename S, typename F, typename N>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(const F&, const N&)>::overload == call_member,+    typename call_traits<S, void(const F&, const N&)>::result_type+  >::type+  operator()(const S& s, const F& f, const N& n) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(const F&, const N&)>::is_noexcept))+  {+    return s.bulk_execute(ASIO_MOVE_CAST(F)(f),+        ASIO_MOVE_CAST(N)(n));+  }++  template <typename S, typename F, typename N>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(const F&, const N&)>::overload == call_free,+    typename call_traits<S, void(const F&, const N&)>::result_type+  >::type+  operator()(S& s, const F& f, const N& n) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(const F&, const N&)>::is_noexcept))+  {+    return bulk_execute(s, ASIO_MOVE_CAST(F)(f),+        ASIO_MOVE_CAST(N)(n));+  }++  template <typename S, typename F, typename N>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(const F&, const N&)>::overload == call_free,+    typename call_traits<S, void(const F&, const N&)>::result_type+  >::type+  operator()(const S& s, const F& f, const N& n) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(const F&, const N&)>::is_noexcept))+  {+    return bulk_execute(s, ASIO_MOVE_CAST(F)(f),+        ASIO_MOVE_CAST(N)(n));+  }++  template <typename S, typename F, typename N>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(const F&, const N&)>::overload == adapter,+    typename call_traits<S, void(const F&, const N&)>::result_type+  >::type+  operator()(S& s, const F& f, const N& n) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(const F&, const N&)>::is_noexcept))+  {+    return typename call_traits<S, void(const F&, const N&)>::result_type(+        s, ASIO_MOVE_CAST(F)(f), ASIO_MOVE_CAST(N)(n));+  }++  template <typename S, typename F, typename N>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(const F&, const N&)>::overload == adapter,+    typename call_traits<S, void(const F&, const N&)>::result_type+  >::type+  operator()(const S& s, const F& f, const N& n) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(const F&, const N&)>::is_noexcept))+  {+    return typename call_traits<S, void(const F&, const N&)>::result_type(+        s, ASIO_MOVE_CAST(F)(f), ASIO_MOVE_CAST(N)(n));+  }+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_execution_bulk_execute_fn+namespace asio {+namespace execution {+namespace {++static ASIO_CONSTEXPR+  const asio_execution_bulk_execute_fn::impl& bulk_execute =+    asio_execution_bulk_execute_fn::static_instance<>::instance;++} // namespace++template <typename S, typename F, typename N>+struct can_bulk_execute :+  integral_constant<bool,+    asio_execution_bulk_execute_fn::call_traits<S, void(F, N)>::overload !=+      asio_execution_bulk_execute_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename F, typename N>+constexpr bool can_bulk_execute_v = can_bulk_execute<S, F, N>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename F, typename N>+struct is_nothrow_bulk_execute :+  integral_constant<bool,+    asio_execution_bulk_execute_fn::call_traits<S, void(F, N)>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename F, typename N>+constexpr bool is_nothrow_bulk_execute_v+  = is_nothrow_bulk_execute<S, F, N>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename F, typename N>+struct bulk_execute_result+{+  typedef typename asio_execution_bulk_execute_fn::call_traits<+      S, void(F, N)>::result_type type;+};++} // namespace execution+} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_BULK_EXECUTE_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/bulk_guarantee.hpp view
@@ -0,0 +1,1018 @@+//+// execution/bulk_guarantee.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_BULK_GUARANTEE_HPP+#define ASIO_EXECUTION_BULK_GUARANTEE_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/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/query.hpp"+#include "asio/traits/query_free.hpp"+#include "asio/traits/query_member.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/static_query.hpp"+#include "asio/traits/static_require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property to communicate the forward progress and ordering guarantees of+/// execution agents associated with the bulk execution.+struct bulk_guarantee_t+{+  /// The bulk_guarantee_t property applies to executors, senders, and+  /// schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The top-level bulk_guarantee_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The top-level bulk_guarantee_t property cannot be preferred.+  static constexpr bool is_preferable = false;++  /// The type returned by queries against an @c any_executor.+  typedef bulk_guarantee_t polymorphic_query_result_type;++  /// A sub-property that indicates that execution agents within the same bulk+  /// execution may be parallelised and vectorised.+  struct unsequenced_t+  {+    /// The bulk_guarantee_t::unsequenced_t property applies to executors,+    /// senders, and schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The bulk_guarantee_t::unsequenced_t property can be required.+    static constexpr bool is_requirable = true;++    /// The bulk_guarantee_t::unsequenced_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef bulk_guarantee_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr unsequenced_t();++    /// Get the value associated with a property object.+    /**+     * @returns unsequenced_t();+     */+    static constexpr bulk_guarantee_t value();+  };++  /// A sub-property that indicates that execution agents within the same bulk+  /// execution may not be parallelised and vectorised.+  struct sequenced_t+  {+    /// The bulk_guarantee_t::sequenced_t property applies to executors,+    /// senders, and schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The bulk_guarantee_t::sequenced_t property can be required.+    static constexpr bool is_requirable = true;++    /// The bulk_guarantee_t::sequenced_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef bulk_guarantee_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr sequenced_t();++    /// Get the value associated with a property object.+    /**+     * @returns sequenced_t();+     */+    static constexpr bulk_guarantee_t value();+  };++  /// A sub-property that indicates that execution agents within the same bulk+  /// execution may be parallelised.+  struct parallel_t+  {+    /// The bulk_guarantee_t::parallel_t property applies to executors,+    /// senders, and schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The bulk_guarantee_t::parallel_t property can be required.+    static constexpr bool is_requirable = true;++    /// The bulk_guarantee_t::parallel_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef bulk_guarantee_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr parallel_t();++    /// Get the value associated with a property object.+    /**+     * @returns parallel_t();+     */+    static constexpr bulk_guarantee_t value();+  };++  /// A special value used for accessing the bulk_guarantee_t::unsequenced_t+  /// property.+  static constexpr unsequenced_t unsequenced;++  /// A special value used for accessing the bulk_guarantee_t::sequenced_t+  /// property.+  static constexpr sequenced_t sequenced;++  /// A special value used for accessing the bulk_guarantee_t::parallel_t+  /// property.+  static constexpr parallel_t parallel;++  /// Default constructor.+  constexpr bulk_guarantee_t();++  /// Construct from a sub-property value.+  constexpr bulk_guarantee_t(unsequenced_t);++  /// Construct from a sub-property value.+  constexpr bulk_guarantee_t(sequenced_t);++  /// Construct from a sub-property value.+  constexpr bulk_guarantee_t(parallel_t);++  /// Compare property values for equality.+  friend constexpr bool operator==(+      const bulk_guarantee_t& a, const bulk_guarantee_t& b) noexcept;++  /// Compare property values for inequality.+  friend constexpr bool operator!=(+      const bulk_guarantee_t& a, const bulk_guarantee_t& b) noexcept;+};++/// A special value used for accessing the bulk_guarantee_t property.+constexpr bulk_guarantee_t bulk_guarantee;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {+namespace detail {+namespace bulk_guarantee {++template <int I> struct unsequenced_t;+template <int I> struct sequenced_t;+template <int I> struct parallel_t;++} // namespace bulk_guarantee++template <int I = 0>+struct bulk_guarantee_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+  typedef bulk_guarantee_t polymorphic_query_result_type;++  typedef detail::bulk_guarantee::unsequenced_t<I> unsequenced_t;+  typedef detail::bulk_guarantee::sequenced_t<I> sequenced_t;+  typedef detail::bulk_guarantee::parallel_t<I> parallel_t;++  ASIO_CONSTEXPR bulk_guarantee_t()+    : value_(-1)+  {+  }++  ASIO_CONSTEXPR bulk_guarantee_t(unsequenced_t)+    : value_(0)+  {+  }++  ASIO_CONSTEXPR bulk_guarantee_t(sequenced_t)+    : value_(1)+  {+  }++  ASIO_CONSTEXPR bulk_guarantee_t(parallel_t)+    : value_(2)+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<+      T, bulk_guarantee_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, bulk_guarantee_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, bulk_guarantee_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, unsequenced_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, bulk_guarantee_t>::is_valid+          && !traits::query_member<T, bulk_guarantee_t>::is_valid+          && traits::static_query<T, unsequenced_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, unsequenced_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, sequenced_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, bulk_guarantee_t>::is_valid+          && !traits::query_member<T, bulk_guarantee_t>::is_valid+          && !traits::static_query<T, unsequenced_t>::is_valid+          && traits::static_query<T, sequenced_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, sequenced_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, parallel_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, bulk_guarantee_t>::is_valid+          && !traits::query_member<T, bulk_guarantee_t>::is_valid+          && !traits::static_query<T, unsequenced_t>::is_valid+          && !traits::static_query<T, sequenced_t>::is_valid+          && traits::static_query<T, parallel_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, parallel_t>::value();+  }++  template <typename E,+      typename T = decltype(bulk_guarantee_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = bulk_guarantee_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  friend ASIO_CONSTEXPR bool operator==(+      const bulk_guarantee_t& a, const bulk_guarantee_t& b)+  {+    return a.value_ == b.value_;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const bulk_guarantee_t& a, const bulk_guarantee_t& b)+  {+    return a.value_ != b.value_;+  }++  struct convertible_from_bulk_guarantee_t+  {+    ASIO_CONSTEXPR convertible_from_bulk_guarantee_t(bulk_guarantee_t) {}+  };++  template <typename Executor>+  friend ASIO_CONSTEXPR bulk_guarantee_t query(+      const Executor& ex, convertible_from_bulk_guarantee_t,+      typename enable_if<+        can_query<const Executor&, unsequenced_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&,+        bulk_guarantee_t<>::unsequenced_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, unsequenced_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, unsequenced_t());+  }++  template <typename Executor>+  friend ASIO_CONSTEXPR bulk_guarantee_t query(+      const Executor& ex, convertible_from_bulk_guarantee_t,+      typename enable_if<+        !can_query<const Executor&, unsequenced_t>::value+          && can_query<const Executor&, sequenced_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&,+        bulk_guarantee_t<>::sequenced_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, sequenced_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, sequenced_t());+  }++  template <typename Executor>+  friend ASIO_CONSTEXPR bulk_guarantee_t query(+      const Executor& ex, convertible_from_bulk_guarantee_t,+      typename enable_if<+        !can_query<const Executor&, unsequenced_t>::value+          && !can_query<const Executor&, sequenced_t>::value+          && can_query<const Executor&, parallel_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, bulk_guarantee_t<>::parallel_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, parallel_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, parallel_t());+  }++  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(unsequenced_t, unsequenced);+  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(sequenced_t, sequenced);+  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(parallel_t, parallel);++#if !defined(ASIO_HAS_CONSTEXPR)+  static const bulk_guarantee_t instance;+#endif // !defined(ASIO_HAS_CONSTEXPR)++private:+  int value_;+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T bulk_guarantee_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+template <int I>+const bulk_guarantee_t<I> bulk_guarantee_t<I>::instance;+#endif++template <int I>+const typename bulk_guarantee_t<I>::unsequenced_t+bulk_guarantee_t<I>::unsequenced;++template <int I>+const typename bulk_guarantee_t<I>::sequenced_t+bulk_guarantee_t<I>::sequenced;++template <int I>+const typename bulk_guarantee_t<I>::parallel_t+bulk_guarantee_t<I>::parallel;++namespace bulk_guarantee {++template <int I = 0>+struct unsequenced_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef bulk_guarantee_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR unsequenced_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, unsequenced_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, unsequenced_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, unsequenced_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR unsequenced_t static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, unsequenced_t>::is_valid+          && !traits::query_member<T, unsequenced_t>::is_valid+          && !traits::query_free<T, unsequenced_t>::is_valid+          && !can_query<T, sequenced_t<I> >::value+          && !can_query<T, parallel_t<I> >::value+      >::type* = 0) ASIO_NOEXCEPT+  {+    return unsequenced_t();+  }++  template <typename E, typename T = decltype(unsequenced_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = unsequenced_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR bulk_guarantee_t<I> value()+  {+    return unsequenced_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const unsequenced_t&, const unsequenced_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const unsequenced_t&, const unsequenced_t&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const unsequenced_t&, const sequenced_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const unsequenced_t&, const sequenced_t<I>&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const unsequenced_t&, const parallel_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const unsequenced_t&, const parallel_t<I>&)+  {+    return true;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T unsequenced_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <int I = 0>+struct sequenced_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef bulk_guarantee_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR sequenced_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, sequenced_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, sequenced_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, sequenced_t>::value();+  }++  template <typename E, typename T = decltype(sequenced_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = sequenced_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR bulk_guarantee_t<I> value()+  {+    return sequenced_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const sequenced_t&, const sequenced_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const sequenced_t&, const sequenced_t&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const sequenced_t&, const unsequenced_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const sequenced_t&, const unsequenced_t<I>&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const sequenced_t&, const parallel_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const sequenced_t&, const parallel_t<I>&)+  {+    return true;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T sequenced_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <int I>+struct parallel_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef bulk_guarantee_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR parallel_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, parallel_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, parallel_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, parallel_t>::value();+  }++  template <typename E, typename T = decltype(parallel_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = parallel_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR bulk_guarantee_t<I> value()+  {+    return parallel_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const parallel_t&, const parallel_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const parallel_t&, const parallel_t&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const parallel_t&, const unsequenced_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const parallel_t&, const unsequenced_t<I>&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator==(+      const parallel_t&, const sequenced_t<I>&)+  {+    return false;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const parallel_t&, const sequenced_t<I>&)+  {+    return true;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T parallel_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++} // namespace bulk_guarantee+} // namespace detail++typedef detail::bulk_guarantee_t<> bulk_guarantee_t;++#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr bulk_guarantee_t bulk_guarantee;+#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+namespace { static const bulk_guarantee_t&+  bulk_guarantee = bulk_guarantee_t::instance; }+#endif++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+struct is_applicable_property<T, execution::bulk_guarantee_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::bulk_guarantee_t::unsequenced_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::bulk_guarantee_t::sequenced_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::bulk_guarantee_t::parallel_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T>+struct query_free_default<T, execution::bulk_guarantee_t,+  typename enable_if<+    can_query<T, execution::bulk_guarantee_t::unsequenced_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::bulk_guarantee_t::unsequenced_t>::value));++  typedef execution::bulk_guarantee_t result_type;+};++template <typename T>+struct query_free_default<T, execution::bulk_guarantee_t,+  typename enable_if<+    !can_query<T, execution::bulk_guarantee_t::unsequenced_t>::value+      && can_query<T, execution::bulk_guarantee_t::sequenced_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::bulk_guarantee_t::sequenced_t>::value));++  typedef execution::bulk_guarantee_t result_type;+};++template <typename T>+struct query_free_default<T, execution::bulk_guarantee_t,+  typename enable_if<+    !can_query<T, execution::bulk_guarantee_t::unsequenced_t>::value+      && !can_query<T, execution::bulk_guarantee_t::sequenced_t>::value+      && can_query<T, execution::bulk_guarantee_t::parallel_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::bulk_guarantee_t::parallel_t>::value));++  typedef execution::bulk_guarantee_t result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T>+struct static_query<T, execution::bulk_guarantee_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::bulk_guarantee_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::bulk_guarantee_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::bulk_guarantee_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::bulk_guarantee_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::bulk_guarantee_t>::is_valid+      && !traits::query_member<T,+        execution::bulk_guarantee_t>::is_valid+      && traits::static_query<T,+        execution::bulk_guarantee_t::unsequenced_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::bulk_guarantee_t::unsequenced_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T,+        execution::bulk_guarantee_t::unsequenced_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::bulk_guarantee_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::bulk_guarantee_t>::is_valid+      && !traits::query_member<T,+        execution::bulk_guarantee_t>::is_valid+      && !traits::static_query<T,+        execution::bulk_guarantee_t::unsequenced_t>::is_valid+      && traits::static_query<T,+        execution::bulk_guarantee_t::sequenced_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::bulk_guarantee_t::sequenced_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T,+        execution::bulk_guarantee_t::sequenced_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::bulk_guarantee_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::bulk_guarantee_t>::is_valid+      && !traits::query_member<T,+        execution::bulk_guarantee_t>::is_valid+      && !traits::static_query<T,+        execution::bulk_guarantee_t::unsequenced_t>::is_valid+      && !traits::static_query<T,+        execution::bulk_guarantee_t::sequenced_t>::is_valid+      && traits::static_query<T,+        execution::bulk_guarantee_t::parallel_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::bulk_guarantee_t::parallel_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T,+        execution::bulk_guarantee_t::parallel_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::bulk_guarantee_t::unsequenced_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::bulk_guarantee_t::unsequenced_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::bulk_guarantee_t::unsequenced_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::bulk_guarantee_t::unsequenced_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::bulk_guarantee_t::unsequenced_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+      execution::bulk_guarantee_t::unsequenced_t>::is_valid+      && !traits::query_member<T,+        execution::bulk_guarantee_t::unsequenced_t>::is_valid+      && !traits::query_free<T,+        execution::bulk_guarantee_t::unsequenced_t>::is_valid+      && !can_query<T, execution::bulk_guarantee_t::sequenced_t>::value+      && !can_query<T, execution::bulk_guarantee_t::parallel_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef execution::bulk_guarantee_t::unsequenced_t result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return result_type();+  }+};++template <typename T>+struct static_query<T, execution::bulk_guarantee_t::sequenced_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::bulk_guarantee_t::sequenced_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::bulk_guarantee_t::sequenced_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::bulk_guarantee_t::sequenced_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::bulk_guarantee_t::parallel_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::bulk_guarantee_t::parallel_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::bulk_guarantee_t::parallel_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::bulk_guarantee_t::parallel_t>::value();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++template <typename T>+struct static_require<T, execution::bulk_guarantee_t::unsequenced_t,+  typename enable_if<+    static_query<T, execution::bulk_guarantee_t::unsequenced_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::bulk_guarantee_t::unsequenced_t>::result_type,+        execution::bulk_guarantee_t::unsequenced_t>::value));+};++template <typename T>+struct static_require<T, execution::bulk_guarantee_t::sequenced_t,+  typename enable_if<+    static_query<T, execution::bulk_guarantee_t::sequenced_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::bulk_guarantee_t::sequenced_t>::result_type,+        execution::bulk_guarantee_t::sequenced_t>::value));+};++template <typename T>+struct static_require<T, execution::bulk_guarantee_t::parallel_t,+  typename enable_if<+    static_query<T, execution::bulk_guarantee_t::parallel_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::bulk_guarantee_t::parallel_t>::result_type,+        execution::bulk_guarantee_t::parallel_t>::value));+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_BULK_GUARANTEE_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/connect.hpp view
@@ -0,0 +1,486 @@+//+// execution/connect.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_CONNECT_HPP+#define ASIO_EXECUTION_CONNECT_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/execution/detail/as_invocable.hpp"+#include "asio/execution/detail/as_operation.hpp"+#include "asio/execution/detail/as_receiver.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/operation_state.hpp"+#include "asio/execution/receiver.hpp"+#include "asio/execution/sender.hpp"+#include "asio/traits/connect_member.hpp"+#include "asio/traits/connect_free.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++/// A customisation point that connects a sender to a receiver.+/**+ * The name <tt>execution::connect</tt> denotes a customisation point object.+ * For some subexpressions <tt>s</tt> and <tt>r</tt>, let <tt>S</tt> be a type+ * such that <tt>decltype((s))</tt> is <tt>S</tt> and let <tt>R</tt> be a type+ * such that <tt>decltype((r))</tt> is <tt>R</tt>. The expression+ * <tt>execution::connect(s, r)</tt> is expression-equivalent to:+ *+ * @li <tt>s.connect(r)</tt>, if that expression is valid, if its type+ *   satisfies <tt>operation_state</tt>, and if <tt>S</tt> satisfies+ *   <tt>sender</tt>.+ *+ * @li Otherwise, <tt>connect(s, r)</tt>, if that expression is valid, if its+ *   type satisfies <tt>operation_state</tt>, and if <tt>S</tt> satisfies+ *   <tt>sender</tt>, with overload resolution performed in a context that+ *   includes the declaration <tt>void connect();</tt> and that does not include+ *   a declaration of <tt>execution::connect</tt>.+ *+ * @li Otherwise, <tt>as_operation{s, r}</tt>, if <tt>r</tt> is not an instance+ *  of <tt>as_receiver<F, S></tt> for some type <tt>F</tt>, and if+ *  <tt>receiver_of<R> && executor_of<remove_cvref_t<S>,+ *  as_invocable<remove_cvref_t<R>, S>></tt> is <tt>true</tt>, where+ *  <tt>as_operation</tt> is an implementation-defined class equivalent to+ *  @code template <class S, class R>+ *  struct as_operation+ *  {+ *    remove_cvref_t<S> e_;+ *    remove_cvref_t<R> r_;+ *    void start() noexcept try {+ *      execution::execute(std::move(e_),+ *          as_invocable<remove_cvref_t<R>, S>{r_});+ *    } catch(...) {+ *      execution::set_error(std::move(r_), current_exception());+ *    }+ *  }; @endcode+ *  and <tt>as_invocable</tt> is a class template equivalent to the following:+ *  @code template<class R>+ *  struct as_invocable+ *  {+ *    R* r_;+ *    explicit as_invocable(R& r) noexcept+ *      : r_(std::addressof(r)) {}+ *    as_invocable(as_invocable && other) noexcept+ *      : r_(std::exchange(other.r_, nullptr)) {}+ *    ~as_invocable() {+ *      if(r_)+ *        execution::set_done(std::move(*r_));+ *    }+ *    void operator()() & noexcept try {+ *      execution::set_value(std::move(*r_));+ *      r_ = nullptr;+ *    } catch(...) {+ *      execution::set_error(std::move(*r_), current_exception());+ *      r_ = nullptr;+ *    }+ *  };+ *  @endcode+ *+ * @li Otherwise, <tt>execution::connect(s, r)</tt> is ill-formed.+ */+inline constexpr unspecified connect = unspecified;++/// A type trait that determines whether a @c connect expression is+/// well-formed.+/**+ * Class template @c can_connect is a trait that is derived from+ * @c true_type if the expression <tt>execution::connect(std::declval<S>(),+ * std::declval<R>())</tt> is well formed; otherwise @c false_type.+ */+template <typename S, typename R>+struct can_connect :+  integral_constant<bool, automatically_determined>+{+};++/// A type trait to determine the result of a @c connect expression.+template <typename S, typename R>+struct connect_result+{+  /// The type of the connect expression.+  /**+   * The type of the expression <tt>execution::connect(std::declval<S>(),+   * std::declval<R>())</tt>.+   */+  typedef automatically_determined type;+};++/// A type alis to determine the result of a @c connect expression.+template <typename S, typename R>+using connect_result_t = typename connect_result<S, R>::type;++} // namespace execution+} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_execution_connect_fn {++using asio::conditional;+using asio::declval;+using asio::enable_if;+using asio::execution::detail::as_invocable;+using asio::execution::detail::as_operation;+using asio::execution::detail::is_as_receiver;+using asio::execution::is_executor_of;+using asio::execution::is_operation_state;+using asio::execution::is_receiver;+using asio::execution::is_sender;+using asio::false_type;+using asio::remove_cvref;+using asio::traits::connect_free;+using asio::traits::connect_member;++void connect();++enum overload_type+{+  call_member,+  call_free,+  adapter,+  ill_formed+};++template <typename S, typename R, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename S, typename R>+struct call_traits<S, void(R),+  typename enable_if<+    (+      connect_member<S, R>::is_valid+      &&+      is_operation_state<typename connect_member<S, R>::result_type>::value+      &&+      is_sender<typename remove_cvref<S>::type>::value+    )+  >::type> :+  connect_member<S, R>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename S, typename R>+struct call_traits<S, void(R),+  typename enable_if<+    (+      !connect_member<S, R>::is_valid+      &&+      connect_free<S, R>::is_valid+      &&+      is_operation_state<typename connect_free<S, R>::result_type>::value+      &&+      is_sender<typename remove_cvref<S>::type>::value+    )+  >::type> :+  connect_free<S, R>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++template <typename S, typename R>+struct call_traits<S, void(R),+  typename enable_if<+    (+      !connect_member<S, R>::is_valid+      &&+      !connect_free<S, R>::is_valid+      &&+      is_receiver<R>::value+      &&+      conditional<+        !is_as_receiver<+          typename remove_cvref<R>::type+        >::value,+        is_executor_of<+          typename remove_cvref<S>::type,+          as_invocable<typename remove_cvref<R>::type, S>+        >,+        false_type+      >::type::value+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef as_operation<S, R> result_type;+};++struct impl+{+#if defined(ASIO_HAS_MOVE)+  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(R)>::overload == call_member,+    typename call_traits<S, void(R)>::result_type+  >::type+  operator()(S&& s, R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(R)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(S)(s).connect(ASIO_MOVE_CAST(R)(r));+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(R)>::overload == call_free,+    typename call_traits<S, void(R)>::result_type+  >::type+  operator()(S&& s, R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(R)>::is_noexcept))+  {+    return connect(ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r));+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(R)>::overload == adapter,+    typename call_traits<S, void(R)>::result_type+  >::type+  operator()(S&& s, R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(R)>::is_noexcept))+  {+    return typename call_traits<S, void(R)>::result_type(+        ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r));+  }+#else // defined(ASIO_HAS_MOVE)+  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(R&)>::overload == call_member,+    typename call_traits<S&, void(R&)>::result_type+  >::type+  operator()(S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(R&)>::is_noexcept))+  {+    return s.connect(r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(R&)>::overload == call_member,+    typename call_traits<const S&, void(R&)>::result_type+  >::type+  operator()(const S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(R&)>::is_noexcept))+  {+    return s.connect(r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(R&)>::overload == call_free,+    typename call_traits<S&, void(R&)>::result_type+  >::type+  operator()(S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(R&)>::is_noexcept))+  {+    return connect(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(R&)>::overload == call_free,+    typename call_traits<const S&, void(R&)>::result_type+  >::type+  operator()(const S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(R&)>::is_noexcept))+  {+    return connect(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(R&)>::overload == adapter,+    typename call_traits<S&, void(R&)>::result_type+  >::type+  operator()(S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(R&)>::is_noexcept))+  {+    return typename call_traits<S&, void(R&)>::result_type(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(R&)>::overload == adapter,+    typename call_traits<const S&, void(R&)>::result_type+  >::type+  operator()(const S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(R&)>::is_noexcept))+  {+    return typename call_traits<const S&, void(R&)>::result_type(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(const R&)>::overload == call_member,+    typename call_traits<S&, void(const R&)>::result_type+  >::type+  operator()(S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(const R&)>::is_noexcept))+  {+    return s.connect(r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(const R&)>::overload == call_member,+    typename call_traits<const S&, void(const R&)>::result_type+  >::type+  operator()(const S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(const R&)>::is_noexcept))+  {+    return s.connect(r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(const R&)>::overload == call_free,+    typename call_traits<S&, void(const R&)>::result_type+  >::type+  operator()(S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(const R&)>::is_noexcept))+  {+    return connect(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(const R&)>::overload == call_free,+    typename call_traits<const S&, void(const R&)>::result_type+  >::type+  operator()(const S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(const R&)>::is_noexcept))+  {+    return connect(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(const R&)>::overload == adapter,+    typename call_traits<S&, void(const R&)>::result_type+  >::type+  operator()(S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(const R&)>::is_noexcept))+  {+    return typename call_traits<S&, void(const R&)>::result_type(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(const R&)>::overload == adapter,+    typename call_traits<const S&, void(const R&)>::result_type+  >::type+  operator()(const S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(const R&)>::is_noexcept))+  {+    return typename call_traits<const S&, void(const R&)>::result_type(s, r);+  }+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_execution_connect_fn+namespace asio {+namespace execution {+namespace {++static ASIO_CONSTEXPR const asio_execution_connect_fn::impl&+  connect = asio_execution_connect_fn::static_instance<>::instance;++} // namespace++template <typename S, typename R>+struct can_connect :+  integral_constant<bool,+    asio_execution_connect_fn::call_traits<S, void(R)>::overload !=+      asio_execution_connect_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename R>+constexpr bool can_connect_v = can_connect<S, R>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename R>+struct is_nothrow_connect :+  integral_constant<bool,+    asio_execution_connect_fn::call_traits<S, void(R)>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename R>+constexpr bool is_nothrow_connect_v+  = is_nothrow_connect<S, R>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename R>+struct connect_result+{+  typedef typename asio_execution_connect_fn::call_traits<+      S, void(R)>::result_type type;+};++#if defined(ASIO_HAS_ALIAS_TEMPLATES)++template <typename S, typename R>+using connect_result_t = typename connect_result<S, R>::type;++#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++} // namespace execution+} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_CONNECT_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/context.hpp view
@@ -0,0 +1,185 @@+//+// execution/context.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_CONTEXT2_HPP+#define ASIO_EXECUTION_CONTEXT2_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/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/static_query.hpp"++#if defined(ASIO_HAS_STD_ANY)+# include <any>+#endif // defined(ASIO_HAS_STD_ANY)++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property that is used to obtain the execution context that is associated+/// with an executor.+struct context_t+{+  /// The context_t property applies to executors, senders, and schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The context_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The context_t property cannot be preferred.+  static constexpr bool is_preferable = false;++  /// The type returned by queries against an @c any_executor.+  typedef std::any polymorphic_query_result_type;+};++/// A special value used for accessing the context_t property.+constexpr context_t context;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {+namespace detail {++template <int I = 0>+struct context_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);++#if defined(ASIO_HAS_STD_ANY)+  typedef std::any polymorphic_query_result_type;+#endif // defined(ASIO_HAS_STD_ANY)++  ASIO_CONSTEXPR context_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, context_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, context_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, context_t>::value();+  }++  template <typename E, typename T = decltype(context_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = context_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+  static const context_t instance;+#endif // !defined(ASIO_HAS_CONSTEXPR)+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T context_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+template <int I>+const context_t<I> context_t<I>::instance;+#endif++} // namespace detail++typedef detail::context_t<> context_t;++#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr context_t context;+#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+namespace { static const context_t& context = context_t::instance; }+#endif++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+struct is_applicable_property<T, execution::context_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T>+struct static_query<T, execution::context_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::context_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::context_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::context_t>::value();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_CONTEXT2_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/context_as.hpp view
@@ -0,0 +1,201 @@+//+// execution/context_as.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_CONTEXT_AS_HPP+#define ASIO_EXECUTION_CONTEXT_AS_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/execution/context.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/query.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/static_query.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property that is used to obtain the execution context that is associated+/// with an executor.+template <typename U>+struct context_as_t+{+  /// The context_as_t property applies to executors, senders, and schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The context_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The context_t property cannot be preferred.+  static constexpr bool is_preferable = false;++  /// The type returned by queries against an @c any_executor.+  typedef T polymorphic_query_result_type;+};++/// A special value used for accessing the context_as_t property.+template <typename U>+constexpr context_as_t context_as;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {++template <typename T>+struct context_as_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename U>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<U>::value+      || is_sender<U>::value || is_scheduler<U>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);++  typedef T polymorphic_query_result_type;++  ASIO_CONSTEXPR context_as_t()+  {+  }++  ASIO_CONSTEXPR context_as_t(context_t)+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename E>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<E, context_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<E, context_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<E, context_t>::value();+  }++  template <typename E, typename U = decltype(context_as_t::static_query<E>())>+  static ASIO_CONSTEXPR const U static_query_v+    = context_as_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  template <typename Executor, typename U>+  friend ASIO_CONSTEXPR U query(+      const Executor& ex, const context_as_t<U>&,+      typename enable_if<+        is_same<T, U>::value+          && can_query<const Executor&, const context_t&>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, const context_t&>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, const context_t&>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, context);+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <typename T> template <typename E, typename U>+const U context_as_t<T>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if (defined(ASIO_HAS_VARIABLE_TEMPLATES) \+    && defined(ASIO_HAS_CONSTEXPR)) \+  || defined(GENERATING_DOCUMENTATION)+template <typename T>+constexpr context_as_t<T> context_as{};+#endif // (defined(ASIO_HAS_VARIABLE_TEMPLATES)+       //     && defined(ASIO_HAS_CONSTEXPR))+       //   || defined(GENERATING_DOCUMENTATION)++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename U>+struct is_applicable_property<T, execution::context_as_t<U> >+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T, typename U>+struct static_query<T, execution::context_as_t<U>,+  typename enable_if<+    static_query<T, execution::context_t>::is_valid+  >::type> : static_query<T, execution::context_t>+{+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T, typename U>+struct query_free<T, execution::context_as_t<U>,+    typename enable_if<+      can_query<const T&, const execution::context_t&>::value+    >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<const T&, const execution::context_t&>::value));++  typedef U result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_CONTEXT_AS_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/detail/as_invocable.hpp view
@@ -0,0 +1,152 @@+//+// execution/detail/as_invocable.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_DETAIL_AS_INVOCABLE_HPP+#define ASIO_EXECUTION_DETAIL_AS_INVOCABLE_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/atomic_count.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/receiver_invocation_error.hpp"+#include "asio/execution/set_done.hpp"+#include "asio/execution/set_error.hpp"+#include "asio/execution/set_value.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++#if defined(ASIO_HAS_MOVE)++template <typename Receiver, typename>+struct as_invocable+{+  Receiver* receiver_;++  explicit as_invocable(Receiver& r) ASIO_NOEXCEPT+    : receiver_(asio::detail::addressof(r))+  {+  }++  as_invocable(as_invocable&& other) ASIO_NOEXCEPT+    : receiver_(other.receiver_)+  {+    other.receiver_ = 0;+  }++  ~as_invocable()+  {+    if (receiver_)+      execution::set_done(ASIO_MOVE_OR_LVALUE(Receiver)(*receiver_));+  }++  void operator()() ASIO_LVALUE_REF_QUAL ASIO_NOEXCEPT+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+    {+#endif // !defined(ASIO_NO_EXCEPTIONS)+      execution::set_value(ASIO_MOVE_CAST(Receiver)(*receiver_));+      receiver_ = 0;+#if !defined(ASIO_NO_EXCEPTIONS)+    }+    catch (...)+    {+#if defined(ASIO_HAS_STD_EXCEPTION_PTR)+      execution::set_error(ASIO_MOVE_CAST(Receiver)(*receiver_),+          std::make_exception_ptr(receiver_invocation_error()));+      receiver_ = 0;+#else // defined(ASIO_HAS_STD_EXCEPTION_PTR)+      std::terminate();+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+    }+#endif // !defined(ASIO_NO_EXCEPTIONS)+  }+};++#else // defined(ASIO_HAS_MOVE)++template <typename Receiver, typename>+struct as_invocable+{+  Receiver* receiver_;+  asio::detail::shared_ptr<asio::detail::atomic_count> ref_count_;++  explicit as_invocable(Receiver& r,+      const asio::detail::shared_ptr<+        asio::detail::atomic_count>& c) ASIO_NOEXCEPT+    : receiver_(asio::detail::addressof(r)),+      ref_count_(c)+  {+  }++  as_invocable(const as_invocable& other) ASIO_NOEXCEPT+    : receiver_(other.receiver_),+      ref_count_(other.ref_count_)+  {+    ++(*ref_count_);+  }++  ~as_invocable()+  {+    if (--(*ref_count_) == 0)+      execution::set_done(*receiver_);+  }++  void operator()() ASIO_LVALUE_REF_QUAL ASIO_NOEXCEPT+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+    {+#endif // !defined(ASIO_NO_EXCEPTIONS)+      execution::set_value(*receiver_);+      ++(*ref_count_);+    }+#if !defined(ASIO_NO_EXCEPTIONS)+    catch (...)+    {+#if defined(ASIO_HAS_STD_EXCEPTION_PTR)+      execution::set_error(*receiver_,+          std::make_exception_ptr(receiver_invocation_error()));+      ++(*ref_count_);+#else // defined(ASIO_HAS_STD_EXCEPTION_PTR)+      std::terminate();+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+    }+#endif // !defined(ASIO_NO_EXCEPTIONS)+  }+};++#endif // defined(ASIO_HAS_MOVE)++template <typename T>+struct is_as_invocable : false_type+{+};++template <typename Function, typename T>+struct is_as_invocable<as_invocable<Function, T> > : true_type+{+};++} // namespace detail+} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_DETAIL_AS_INVOCABLE_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/detail/as_operation.hpp view
@@ -0,0 +1,105 @@+//+// execution/detail/as_operation.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_DETAIL_AS_OPERATION_HPP+#define ASIO_EXECUTION_DETAIL_AS_OPERATION_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/memory.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/detail/as_invocable.hpp"+#include "asio/execution/execute.hpp"+#include "asio/execution/set_error.hpp"+#include "asio/traits/start_member.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++template <typename Executor, typename Receiver>+struct as_operation+{+  typename remove_cvref<Executor>::type ex_;+  typename remove_cvref<Receiver>::type receiver_;+#if !defined(ASIO_HAS_MOVE)+  asio::detail::shared_ptr<asio::detail::atomic_count> ref_count_;+#endif // !defined(ASIO_HAS_MOVE)++  template <typename E, typename R>+  explicit as_operation(ASIO_MOVE_ARG(E) e, ASIO_MOVE_ARG(R) r)+    : ex_(ASIO_MOVE_CAST(E)(e)),+      receiver_(ASIO_MOVE_CAST(R)(r))+#if !defined(ASIO_HAS_MOVE)+      , ref_count_(new asio::detail::atomic_count(1))+#endif // !defined(ASIO_HAS_MOVE)+  {+  }++  void start() ASIO_NOEXCEPT+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+    {+#endif // !defined(ASIO_NO_EXCEPTIONS)+      execution::execute(+          ASIO_MOVE_CAST(typename remove_cvref<Executor>::type)(ex_),+          as_invocable<typename remove_cvref<Receiver>::type,+              Executor>(receiver_+#if !defined(ASIO_HAS_MOVE)+                , ref_count_+#endif // !defined(ASIO_HAS_MOVE)+              ));+#if !defined(ASIO_NO_EXCEPTIONS)+    }+    catch (...)+    {+#if defined(ASIO_HAS_STD_EXCEPTION_PTR)+      execution::set_error(+          ASIO_MOVE_OR_LVALUE(+            typename remove_cvref<Receiver>::type)(+              receiver_),+          std::current_exception());+#else // defined(ASIO_HAS_STD_EXCEPTION_PTR)+      std::terminate();+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+    }+#endif // !defined(ASIO_NO_EXCEPTIONS)+  }+};++} // namespace detail+} // namespace execution+namespace traits {++#if !defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT)++template <typename Executor, typename Receiver>+struct start_member<+    asio::execution::detail::as_operation<Executor, Receiver> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT)++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_DETAIL_AS_OPERATION_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/detail/as_receiver.hpp view
@@ -0,0 +1,128 @@+//+// execution/detail/as_receiver.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_DETAIL_AS_RECEIVER_HPP+#define ASIO_EXECUTION_DETAIL_AS_RECEIVER_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/traits/set_done_member.hpp"+#include "asio/traits/set_error_member.hpp"+#include "asio/traits/set_value_member.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++template <typename Function, typename>+struct as_receiver+{+  Function f_;++  template <typename F>+  explicit as_receiver(ASIO_MOVE_ARG(F) f, int)+    : f_(ASIO_MOVE_CAST(F)(f))+  {+  }++#if defined(ASIO_MSVC) && defined(ASIO_HAS_MOVE)+  as_receiver(as_receiver&& other)+    : f_(ASIO_MOVE_CAST(Function)(other.f_))+  {+  }+#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_MOVE)++  void set_value()+    ASIO_NOEXCEPT_IF(noexcept(declval<Function&>()()))+  {+    f_();+  }++  template <typename E>+  void set_error(E) ASIO_NOEXCEPT+  {+    std::terminate();+  }++  void set_done() ASIO_NOEXCEPT+  {+  }+};++template <typename T>+struct is_as_receiver : false_type+{+};++template <typename Function, typename T>+struct is_as_receiver<as_receiver<Function, T> > : true_type+{+};++} // namespace detail+} // namespace execution+namespace traits {++#if !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++template <typename Function, typename T>+struct set_value_member<+    asio::execution::detail::as_receiver<Function, T>, void()>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+#if defined(ASIO_HAS_NOEXCEPT)+  ASIO_STATIC_CONSTEXPR(bool,+      is_noexcept = noexcept(declval<Function&>()()));+#else // defined(ASIO_HAS_NOEXCEPT)+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+#endif // defined(ASIO_HAS_NOEXCEPT)+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++template <typename Function, typename T, typename E>+struct set_error_member<+    asio::execution::detail::as_receiver<Function, T>, E>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++template <typename Function, typename T>+struct set_done_member<+    asio::execution::detail::as_receiver<Function, T> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_DETAIL_AS_RECEIVER_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/detail/bulk_sender.hpp view
@@ -0,0 +1,261 @@+//+// execution/detail/bulk_sender.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_DETAIL_BULK_SENDER_HPP+#define ASIO_EXECUTION_DETAIL_BULK_SENDER_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/execution/connect.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/set_done.hpp"+#include "asio/execution/set_error.hpp"+#include "asio/traits/connect_member.hpp"+#include "asio/traits/set_done_member.hpp"+#include "asio/traits/set_error_member.hpp"+#include "asio/traits/set_value_member.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++template <typename Receiver, typename Function, typename Number, typename Index>+struct bulk_receiver+{+  typename remove_cvref<Receiver>::type receiver_;+  typename decay<Function>::type f_;+  typename decay<Number>::type n_;++  template <typename R, typename F, typename N>+  explicit bulk_receiver(ASIO_MOVE_ARG(R) r,+      ASIO_MOVE_ARG(F) f, ASIO_MOVE_ARG(N) n)+    : receiver_(ASIO_MOVE_CAST(R)(r)),+      f_(ASIO_MOVE_CAST(F)(f)),+      n_(ASIO_MOVE_CAST(N)(n))+  {+  }++  void set_value()+  {+    for (Index i = 0; i < n_; ++i)+      f_(i);++    execution::set_value(+        ASIO_MOVE_OR_LVALUE(+          typename remove_cvref<Receiver>::type)(receiver_));+  }++  template <typename Error>+  void set_error(ASIO_MOVE_ARG(Error) e) ASIO_NOEXCEPT+  {+    execution::set_error(+        ASIO_MOVE_OR_LVALUE(+          typename remove_cvref<Receiver>::type)(receiver_),+        ASIO_MOVE_CAST(Error)(e));+  }++  void set_done() ASIO_NOEXCEPT+  {+    execution::set_done(+        ASIO_MOVE_OR_LVALUE(+          typename remove_cvref<Receiver>::type)(receiver_));+  }+};++template <typename Sender, typename Receiver,+  typename Function, typename Number>+struct bulk_receiver_traits+{+  typedef bulk_receiver<+      Receiver, Function, Number,+      typename execution::executor_index<+        typename remove_cvref<Sender>::type+      >::type+    > type;++#if defined(ASIO_HAS_MOVE)+  typedef type arg_type;+#else // defined(ASIO_HAS_MOVE)+  typedef const type& arg_type;+#endif // defined(ASIO_HAS_MOVE)+};++template <typename Sender, typename Function, typename Number>+struct bulk_sender : sender_base+{+  typename remove_cvref<Sender>::type sender_;+  typename decay<Function>::type f_;+  typename decay<Number>::type n_;++  template <typename S, typename F, typename N>+  explicit bulk_sender(ASIO_MOVE_ARG(S) s,+      ASIO_MOVE_ARG(F) f, ASIO_MOVE_ARG(N) n)+    : sender_(ASIO_MOVE_CAST(S)(s)),+      f_(ASIO_MOVE_CAST(F)(f)),+      n_(ASIO_MOVE_CAST(N)(n))+  {+  }++  template <typename Receiver>+  typename connect_result<+      ASIO_MOVE_OR_LVALUE_TYPE(typename remove_cvref<Sender>::type),+      typename bulk_receiver_traits<+        Sender, Receiver, Function, Number+      >::arg_type+  >::type connect(ASIO_MOVE_ARG(Receiver) r,+      typename enable_if<+        can_connect<+          typename remove_cvref<Sender>::type,+          typename bulk_receiver_traits<+            Sender, Receiver, Function, Number+          >::arg_type+        >::value+      >::type* = 0) ASIO_RVALUE_REF_QUAL ASIO_NOEXCEPT+  {+    return execution::connect(+        ASIO_MOVE_OR_LVALUE(typename remove_cvref<Sender>::type)(sender_),+        typename bulk_receiver_traits<Sender, Receiver, Function, Number>::type(+          ASIO_MOVE_CAST(Receiver)(r),+          ASIO_MOVE_CAST(typename decay<Function>::type)(f_),+          ASIO_MOVE_CAST(typename decay<Number>::type)(n_)));+  }++  template <typename Receiver>+  typename connect_result<+      const typename remove_cvref<Sender>::type&,+      typename bulk_receiver_traits<+        Sender, Receiver, Function, Number+      >::arg_type+  >::type connect(ASIO_MOVE_ARG(Receiver) r,+      typename enable_if<+        can_connect<+          const typename remove_cvref<Sender>::type&,+          typename bulk_receiver_traits<+            Sender, Receiver, Function, Number+          >::arg_type+        >::value+      >::type* = 0) const ASIO_LVALUE_REF_QUAL ASIO_NOEXCEPT+  {+    return execution::connect(sender_,+        typename bulk_receiver_traits<Sender, Receiver, Function, Number>::type(+          ASIO_MOVE_CAST(Receiver)(r), f_, n_));+  }+};++} // namespace detail+} // namespace execution+namespace traits {++#if !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++template <typename Receiver, typename Function, typename Number, typename Index>+struct set_value_member<+    execution::detail::bulk_receiver<Receiver, Function, Number, Index>,+    void()>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++template <typename Receiver, typename Function,+    typename Number, typename Index, typename Error>+struct set_error_member<+    execution::detail::bulk_receiver<Receiver, Function, Number, Index>,+    Error>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++template <typename Receiver, typename Function, typename Number, typename Index>+struct set_done_member<+    execution::detail::bulk_receiver<Receiver, Function, Number, Index> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)++template <typename Sender, typename Function,+    typename Number, typename Receiver>+struct connect_member<+    execution::detail::bulk_sender<Sender, Function, Number>,+    Receiver,+    typename enable_if<+      execution::can_connect<+        ASIO_MOVE_OR_LVALUE_TYPE(typename remove_cvref<Sender>::type),+        typename execution::detail::bulk_receiver_traits<+          Sender, Receiver, Function, Number+        >::arg_type+      >::value+    >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef typename execution::connect_result<+      ASIO_MOVE_OR_LVALUE_TYPE(typename remove_cvref<Sender>::type),+      typename execution::detail::bulk_receiver_traits<+        Sender, Receiver, Function, Number+      >::arg_type+    >::type result_type;+};++template <typename Sender, typename Function,+    typename Number, typename Receiver>+struct connect_member<+    const execution::detail::bulk_sender<Sender, Function, Number>,+    Receiver,+    typename enable_if<+      execution::can_connect<+        const typename remove_cvref<Sender>::type&,+        typename execution::detail::bulk_receiver_traits<+          Sender, Receiver, Function, Number+        >::arg_type+      >::value+    >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef typename execution::connect_result<+      const typename remove_cvref<Sender>::type&,+      typename execution::detail::bulk_receiver_traits<+        Sender, Receiver, Function, Number+      >::arg_type+    >::type result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_DETAIL_BULK_SENDER_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/detail/submit_receiver.hpp view
@@ -0,0 +1,233 @@+//+// execution/detail/submit_receiver.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_DETAIL_SUBMIT_RECEIVER_HPP+#define ASIO_EXECUTION_DETAIL_SUBMIT_RECEIVER_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/execution/connect.hpp"+#include "asio/execution/receiver.hpp"+#include "asio/execution/set_done.hpp"+#include "asio/execution/set_error.hpp"+#include "asio/execution/set_value.hpp"+#include "asio/traits/set_done_member.hpp"+#include "asio/traits/set_error_member.hpp"+#include "asio/traits/set_value_member.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++template <typename Sender, typename Receiver>+struct submit_receiver;++template <typename Sender, typename Receiver>+struct submit_receiver_wrapper+{+  submit_receiver<Sender, Receiver>* p_;++  explicit submit_receiver_wrapper(submit_receiver<Sender, Receiver>* p)+    : p_(p)+  {+  }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename... Args>+  typename enable_if<is_receiver_of<Receiver, Args...>::value>::type+  set_value(ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL+    ASIO_NOEXCEPT_IF((is_nothrow_receiver_of<Receiver, Args...>::value))+  {+    execution::set_value(+        ASIO_MOVE_OR_LVALUE(+          typename remove_cvref<Receiver>::type)(p_->r_),+        ASIO_MOVE_CAST(Args)(args)...);+    delete p_;+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  void set_value() ASIO_RVALUE_REF_QUAL+    ASIO_NOEXCEPT_IF((is_nothrow_receiver_of<Receiver>::value))+  {+    execution::set_value(+        ASIO_MOVE_OR_LVALUE(+          typename remove_cvref<Receiver>::type)(p_->r_));+    delete p_;+  }++#define ASIO_PRIVATE_SUBMIT_RECEIVER_SET_VALUE_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  typename enable_if<is_receiver_of<Receiver, \+    ASIO_VARIADIC_TARGS(n)>::value>::type \+  set_value(ASIO_VARIADIC_MOVE_PARAMS(n)) ASIO_RVALUE_REF_QUAL \+    ASIO_NOEXCEPT_IF((is_nothrow_receiver_of< \+      Receiver, ASIO_VARIADIC_TARGS(n)>::value)) \+  { \+    execution::set_value( \+        ASIO_MOVE_OR_LVALUE( \+          typename remove_cvref<Receiver>::type)(p_->r_), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+    delete p_; \+  } \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SUBMIT_RECEIVER_SET_VALUE_DEF)+#undef ASIO_PRIVATE_SUBMIT_RECEIVER_SET_VALUE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename E>+  void set_error(ASIO_MOVE_ARG(E) e)+    ASIO_RVALUE_REF_QUAL ASIO_NOEXCEPT+  {+    execution::set_error(+        ASIO_MOVE_OR_LVALUE(+          typename remove_cvref<Receiver>::type)(p_->r_),+        ASIO_MOVE_CAST(E)(e));+    delete p_;+  }++  void set_done() ASIO_RVALUE_REF_QUAL ASIO_NOEXCEPT+  {+    execution::set_done(+        ASIO_MOVE_OR_LVALUE(+          typename remove_cvref<Receiver>::type)(p_->r_));+    delete p_;+  }+};++template <typename Sender, typename Receiver>+struct submit_receiver+{+  typename remove_cvref<Receiver>::type r_;+#if defined(ASIO_HAS_MOVE)+  typename connect_result<Sender,+      submit_receiver_wrapper<Sender, Receiver> >::type state_;+#else // defined(ASIO_HAS_MOVE)+  typename connect_result<Sender,+      const submit_receiver_wrapper<Sender, Receiver>& >::type state_;+#endif // defined(ASIO_HAS_MOVE)++#if defined(ASIO_HAS_MOVE)+  template <typename S, typename R>+  explicit submit_receiver(ASIO_MOVE_ARG(S) s, ASIO_MOVE_ARG(R) r)+    : r_(ASIO_MOVE_CAST(R)(r)),+      state_(execution::connect(ASIO_MOVE_CAST(S)(s),+            submit_receiver_wrapper<Sender, Receiver>(this)))+  {+  }+#else // defined(ASIO_HAS_MOVE)+  explicit submit_receiver(Sender s, Receiver r)+    : r_(r),+      state_(execution::connect(s,+            submit_receiver_wrapper<Sender, Receiver>(this)))+  {+  }+#endif // defined(ASIO_HAS_MOVE)+};++} // namespace detail+} // namespace execution+namespace traits {++#if !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Sender, typename Receiver, typename... Args>+struct set_value_member<+    asio::execution::detail::submit_receiver_wrapper<+      Sender, Receiver>,+    void(Args...)>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (asio::execution::is_nothrow_receiver_of<Receiver, Args...>::value));+  typedef void result_type;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Sender, typename Receiver>+struct set_value_member<+    asio::execution::detail::submit_receiver_wrapper<+      Sender, Receiver>,+    void()>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    asio::execution::is_nothrow_receiver_of<Receiver>::value);+  typedef void result_type;+};++#define ASIO_PRIVATE_SUBMIT_RECEIVER_TRAIT_DEF(n) \+  template <typename Sender, typename Receiver, \+      ASIO_VARIADIC_TPARAMS(n)> \+  struct set_value_member< \+      asio::execution::detail::submit_receiver_wrapper< \+        Sender, Receiver>, \+      void(ASIO_VARIADIC_TARGS(n))> \+  { \+    ASIO_STATIC_CONSTEXPR(bool, is_valid = true); \+    ASIO_STATIC_CONSTEXPR(bool, is_noexcept = \+      (asio::execution::is_nothrow_receiver_of<Receiver, \+        ASIO_VARIADIC_TARGS(n)>::value)); \+    typedef void result_type; \+  }; \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SUBMIT_RECEIVER_TRAIT_DEF)+#undef ASIO_PRIVATE_SUBMIT_RECEIVER_TRAIT_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#endif // !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++template <typename Sender, typename Receiver, typename E>+struct set_error_member<+    asio::execution::detail::submit_receiver_wrapper<+      Sender, Receiver>, E>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++template <typename Sender, typename Receiver>+struct set_done_member<+    asio::execution::detail::submit_receiver_wrapper<+      Sender, Receiver> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_DETAIL_SUBMIT_RECEIVER_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/detail/void_receiver.hpp view
@@ -0,0 +1,90 @@+//+// execution/detail/void_receiver.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_DETAIL_VOID_RECEIVER_HPP+#define ASIO_EXECUTION_DETAIL_VOID_RECEIVER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/traits/set_done_member.hpp"+#include "asio/traits/set_error_member.hpp"+#include "asio/traits/set_value_member.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++struct void_receiver+{+  void set_value() ASIO_NOEXCEPT+  {+  }++  template <typename E>+  void set_error(ASIO_MOVE_ARG(E)) ASIO_NOEXCEPT+  {+  }++  void set_done() ASIO_NOEXCEPT+  {+  }+};++} // namespace detail+} // namespace execution+namespace traits {++#if !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++template <>+struct set_value_member<asio::execution::detail::void_receiver, void()>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++template <typename E>+struct set_error_member<asio::execution::detail::void_receiver, E>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++template <>+struct set_done_member<asio::execution::detail::void_receiver>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_DETAIL_VOID_RECEIVER_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/execute.hpp view
@@ -0,0 +1,264 @@+//+// execution/execute.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_EXECUTE_HPP+#define ASIO_EXECUTION_EXECUTE_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/execution/detail/as_invocable.hpp"+#include "asio/execution/detail/as_receiver.hpp"+#include "asio/traits/execute_member.hpp"+#include "asio/traits/execute_free.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++/// A customisation point that executes a function on an executor.+/**+ * The name <tt>execution::execute</tt> denotes a customisation point object.+ *+ * For some subexpressions <tt>e</tt> and <tt>f</tt>, let <tt>E</tt> be a type+ * such that <tt>decltype((e))</tt> is <tt>E</tt> and let <tt>F</tt> be a type+ * such that <tt>decltype((f))</tt> is <tt>F</tt>. The expression+ * <tt>execution::execute(e, f)</tt> is ill-formed if <tt>F</tt> does not model+ * <tt>invocable</tt>, or if <tt>E</tt> does not model either <tt>executor</tt>+ * or <tt>sender</tt>. Otherwise, it is expression-equivalent to:+ *+ * @li <tt>e.execute(f)</tt>, if that expression is valid. If the function+ *   selected does not execute the function object <tt>f</tt> on the executor+ *   <tt>e</tt>, the program is ill-formed with no diagnostic required.+ *+ * @li Otherwise, <tt>execute(e, f)</tt>, if that expression is valid, with+ *   overload resolution performed in a context that includes the declaration+ *   <tt>void execute();</tt> and that does not include a declaration of+ *   <tt>execution::execute</tt>. If the function selected by overload+ *   resolution does not execute the function object <tt>f</tt> on the executor+ *   <tt>e</tt>, the program is ill-formed with no diagnostic required.+ */+inline constexpr unspecified execute = unspecified;++/// A type trait that determines whether a @c execute expression is well-formed.+/**+ * Class template @c can_execute is a trait that is derived from+ * @c true_type if the expression <tt>execution::execute(std::declval<T>(),+ * std::declval<F>())</tt> is well formed; otherwise @c false_type.+ */+template <typename T, typename F>+struct can_execute :+  integral_constant<bool, automatically_determined>+{+};++} // namespace execution+} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++template <typename T, typename R>+struct is_sender_to;++namespace detail {++template <typename S, typename R>+void submit_helper(ASIO_MOVE_ARG(S) s, ASIO_MOVE_ARG(R) r);++} // namespace detail+} // namespace execution+} // namespace asio+namespace asio_execution_execute_fn {++using asio::conditional;+using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::execution::detail::as_receiver;+using asio::execution::detail::is_as_invocable;+using asio::execution::is_sender_to;+using asio::false_type;+using asio::result_of;+using asio::traits::execute_free;+using asio::traits::execute_member;+using asio::true_type;++void execute();++enum overload_type+{+  call_member,+  call_free,+  adapter,+  ill_formed+};++template <typename T, typename F, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+};++template <typename T, typename F>+struct call_traits<T, void(F),+  typename enable_if<+    (+      execute_member<T, F>::is_valid+    )+  >::type> :+  execute_member<T, F>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename T, typename F>+struct call_traits<T, void(F),+  typename enable_if<+    (+      !execute_member<T, F>::is_valid+      &&+      execute_free<T, F>::is_valid+    )+  >::type> :+  execute_free<T, F>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++template <typename T, typename F>+struct call_traits<T, void(F),+  typename enable_if<+    (+      !execute_member<T, F>::is_valid+      &&+      !execute_free<T, F>::is_valid+      &&+      conditional<true, true_type,+       typename result_of<typename decay<F>::type&()>::type+      >::type::value+      &&+      conditional<+        !is_as_invocable<+          typename decay<F>::type+        >::value,+        is_sender_to<+          T,+          as_receiver<typename decay<F>::type, T>+        >,+        false_type+      >::type::value+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++struct impl+{+  template <typename T, typename F>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(F)>::overload == call_member,+    typename call_traits<T, void(F)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(F) f) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(F)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(T)(t).execute(ASIO_MOVE_CAST(F)(f));+  }++  template <typename T, typename F>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(F)>::overload == call_free,+    typename call_traits<T, void(F)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(F) f) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(F)>::is_noexcept))+  {+    return execute(ASIO_MOVE_CAST(T)(t), ASIO_MOVE_CAST(F)(f));+  }++  template <typename T, typename F>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(F)>::overload == adapter,+    typename call_traits<T, void(F)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(F) f) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(F)>::is_noexcept))+  {+    return asio::execution::detail::submit_helper(+        ASIO_MOVE_CAST(T)(t),+        as_receiver<typename decay<F>::type, T>(+          ASIO_MOVE_CAST(F)(f), 0));+  }+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_execution_execute_fn+namespace asio {+namespace execution {+namespace {++static ASIO_CONSTEXPR const asio_execution_execute_fn::impl&+  execute = asio_execution_execute_fn::static_instance<>::instance;++} // namespace++template <typename T, typename F>+struct can_execute :+  integral_constant<bool,+    asio_execution_execute_fn::call_traits<T, void(F)>::overload !=+      asio_execution_execute_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename F>+constexpr bool can_execute_v = can_execute<T, F>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++} // namespace execution+} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_EXECUTE_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/executor.hpp view
@@ -0,0 +1,238 @@+//+// execution/executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_EXECUTOR_HPP+#define ASIO_EXECUTION_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/execution/execute.hpp"+#include "asio/execution/invocable_archetype.hpp"+#include "asio/traits/equality_comparable.hpp"++#if defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)+# define ASIO_HAS_DEDUCED_EXECUTION_IS_EXECUTOR_TRAIT 1+#endif // defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++template <typename T, typename F>+struct is_executor_of_impl_base :+  integral_constant<bool,+    conditional<true, true_type,+        typename result_of<typename decay<F>::type&()>::type+      >::type::value+      && is_constructible<typename decay<F>::type, F>::value+      && is_move_constructible<typename decay<F>::type>::value+#if defined(ASIO_HAS_NOEXCEPT)+      && is_nothrow_copy_constructible<T>::value+      && is_nothrow_destructible<T>::value+#else // defined(ASIO_HAS_NOEXCEPT)+      && is_copy_constructible<T>::value+      && is_destructible<T>::value+#endif // defined(ASIO_HAS_NOEXCEPT)+      && traits::equality_comparable<T>::is_valid+      && traits::equality_comparable<T>::is_noexcept+  >+{+};++template <typename T, typename F>+struct is_executor_of_impl :+  conditional<+    can_execute<T, F>::value,+    is_executor_of_impl_base<T, F>,+    false_type+  >::type+{+};++template <typename T, typename = void>+struct executor_shape+{+  typedef std::size_t type;+};++template <typename T>+struct executor_shape<T,+    typename void_type<+      typename T::shape_type+    >::type>+{+  typedef typename T::shape_type type;+};++template <typename T, typename Default, typename = void>+struct executor_index+{+  typedef Default type;+};++template <typename T, typename Default>+struct executor_index<T, Default,+    typename void_type<+      typename T::index_type+    >::type>+{+  typedef typename T::index_type type;+};++} // namespace detail++/// The is_executor trait detects whether a type T satisfies the+/// execution::executor concept.+/**+ * Class template @c is_executor is a UnaryTypeTrait that is derived from @c+ * true_type if the type @c T meets the concept definition for an executor,+ * otherwise @c false_type.+ */+template <typename T>+struct is_executor :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  detail::is_executor_of_impl<T, invocable_archetype>+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+ASIO_CONSTEXPR const bool is_executor_v = is_executor<T>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS)++template <typename T>+ASIO_CONCEPT executor = is_executor<T>::value;++#define ASIO_EXECUTION_EXECUTOR ::asio::execution::executor++#else // defined(ASIO_HAS_CONCEPTS)++#define ASIO_EXECUTION_EXECUTOR typename++#endif // defined(ASIO_HAS_CONCEPTS)++/// The is_executor_of trait detects whether a type T satisfies the+/// execution::executor_of concept for some set of value arguments.+/**+ * Class template @c is_executor_of is a type trait that is derived from @c+ * true_type if the type @c T meets the concept definition for an executor+ * that is invocable with a function object of type @c F, otherwise @c+ * false_type.+ */+template <typename T, typename F>+struct is_executor_of :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  integral_constant<bool,+    is_executor<T>::value && detail::is_executor_of_impl<T, F>::value+  >+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename F>+ASIO_CONSTEXPR const bool is_executor_of_v =+  is_executor_of<T, F>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS)++template <typename T, typename F>+ASIO_CONCEPT executor_of = is_executor_of<T, F>::value;++#define ASIO_EXECUTION_EXECUTOR_OF(f) \+  ::asio::execution::executor_of<f>++#else // defined(ASIO_HAS_CONCEPTS)++#define ASIO_EXECUTION_EXECUTOR_OF typename++#endif // defined(ASIO_HAS_CONCEPTS)++/// The executor_shape trait detects the type used by an executor to represent+/// the shape of a bulk operation.+/**+ * Class template @c executor_shape is a type trait with a nested type alias+ * @c type whose type is @c T::shape_type if @c T::shape_type is valid,+ * otherwise @c std::size_t.+ */+template <typename T>+struct executor_shape+#if !defined(GENERATING_DOCUMENTATION)+  : detail::executor_shape<T>+#endif // !defined(GENERATING_DOCUMENTATION)+{+#if defined(GENERATING_DOCUMENTATION)+ /// @c T::shape_type if @c T::shape_type is valid, otherwise @c std::size_t.+ typedef automatically_determined type;+#endif // defined(GENERATING_DOCUMENTATION)+};++#if defined(ASIO_HAS_ALIAS_TEMPLATES)++template <typename T>+using executor_shape_t = typename executor_shape<T>::type;++#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++/// The executor_index trait detects the type used by an executor to represent+/// an index within a bulk operation.+/**+ * Class template @c executor_index is a type trait with a nested type alias+ * @c type whose type is @c T::index_type if @c T::index_type is valid,+ * otherwise @c executor_shape_t<T>.+ */+template <typename T>+struct executor_index+#if !defined(GENERATING_DOCUMENTATION)+  : detail::executor_index<T, typename executor_shape<T>::type>+#endif // !defined(GENERATING_DOCUMENTATION)+{+#if defined(GENERATING_DOCUMENTATION)+ /// @c T::index_type if @c T::index_type is valid, otherwise+ /// @c executor_shape_t<T>.+ typedef automatically_determined type;+#endif // defined(GENERATING_DOCUMENTATION)+};++#if defined(ASIO_HAS_ALIAS_TEMPLATES)++template <typename T>+using executor_index_t = typename executor_index<T>::type;++#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/impl/bad_executor.ipp view
@@ -0,0 +1,40 @@+//+// exection/impl/bad_executor.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_IMPL_BAD_EXECUTOR_IPP+#define ASIO_EXECUTION_IMPL_BAD_EXECUTOR_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/execution/bad_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {++bad_executor::bad_executor() ASIO_NOEXCEPT+{+}++const char* bad_executor::what() const ASIO_NOEXCEPT_OR_NOTHROW+{+  return "bad executor";+}++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_IMPL_BAD_EXECUTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/execution/impl/receiver_invocation_error.ipp view
@@ -0,0 +1,36 @@+//+// exection/impl/receiver_invocation_error.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_IMPL_RECEIVER_INVOCATION_ERROR_IPP+#define ASIO_EXECUTION_IMPL_RECEIVER_INVOCATION_ERROR_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/execution/receiver_invocation_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {++receiver_invocation_error::receiver_invocation_error()+  : std::runtime_error("receiver invocation error")+{+}++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_IMPL_RECEIVER_INVOCATION_ERROR_IPP
+ link/modules/asio-standalone/asio/include/asio/execution/invocable_archetype.hpp view
@@ -0,0 +1,71 @@+//+// execution/invocable_archetype.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_INVOCABLE_ARCHETYPE_HPP+#define ASIO_EXECUTION_INVOCABLE_ARCHETYPE_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/detail/push_options.hpp"++namespace asio {+namespace execution {++/// An archetypal function object used for determining adherence to the+/// execution::executor concept.+struct invocable_archetype+{+#if !defined(GENERATING_DOCUMENTATION)+  // Necessary for compatibility with a C++03 implementation of result_of.+  typedef void result_type;+#endif // !defined(GENERATING_DOCUMENTATION)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  || defined(GENERATING_DOCUMENTATION)++  /// Function call operator.+  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)...)+  {+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   || defined(GENERATING_DOCUMENTATION)++  void operator()()+  {+  }++#define ASIO_PRIVATE_INVOCABLE_ARCHETYPE_CALL_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  void operator()(ASIO_VARIADIC_UNNAMED_MOVE_PARAMS(n)) \+  { \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INVOCABLE_ARCHETYPE_CALL_DEF)+#undef ASIO_PRIVATE_INVOCABLE_ARCHETYPE_CALL_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   || defined(GENERATING_DOCUMENTATION)+};++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_INVOCABLE_ARCHETYPE_HPP+
+ link/modules/asio-standalone/asio/include/asio/execution/mapping.hpp view
@@ -0,0 +1,917 @@+//+// execution/mapping.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_MAPPING_HPP+#define ASIO_EXECUTION_MAPPING_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/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/query.hpp"+#include "asio/traits/query_free.hpp"+#include "asio/traits/query_member.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/static_query.hpp"+#include "asio/traits/static_require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property to describe what guarantees an executor makes about the mapping+/// of execution agents on to threads of execution.+struct mapping_t+{+  /// The mapping_t property applies to executors, senders, and schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The top-level mapping_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The top-level mapping_t property cannot be preferred.+  static constexpr bool is_preferable = false;++  /// The type returned by queries against an @c any_executor.+  typedef mapping_t polymorphic_query_result_type;++  /// A sub-property that indicates that execution agents are mapped on to+  /// threads of execution.+  struct thread_t+  {+    /// The mapping_t::thread_t property applies to executors, senders, and+    /// schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The mapping_t::thread_t property can be required.+    static constexpr bool is_requirable = true;++    /// The mapping_t::thread_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef mapping_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr thread_t();++    /// Get the value associated with a property object.+    /**+     * @returns thread_t();+     */+    static constexpr mapping_t value();+  };++  /// A sub-property that indicates that execution agents are mapped on to+  /// new threads of execution.+  struct new_thread_t+  {+    /// The mapping_t::new_thread_t property applies to executors, senders, and+    /// schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The mapping_t::new_thread_t property can be required.+    static constexpr bool is_requirable = true;++    /// The mapping_t::new_thread_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef mapping_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr new_thread_t();++    /// Get the value associated with a property object.+    /**+     * @returns new_thread_t();+     */+    static constexpr mapping_t value();+  };++  /// A sub-property that indicates that the mapping of execution agents is+  /// implementation-defined.+  struct other_t+  {+    /// The mapping_t::other_t property applies to executors, senders, and+    /// schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The mapping_t::other_t property can be required.+    static constexpr bool is_requirable = true;++    /// The mapping_t::other_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef mapping_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr other_t();++    /// Get the value associated with a property object.+    /**+     * @returns other_t();+     */+    static constexpr mapping_t value();+  };++  /// A special value used for accessing the mapping_t::thread_t property.+  static constexpr thread_t thread;++  /// A special value used for accessing the mapping_t::new_thread_t property.+  static constexpr new_thread_t new_thread;++  /// A special value used for accessing the mapping_t::other_t property.+  static constexpr other_t other;++  /// Default constructor.+  constexpr mapping_t();++  /// Construct from a sub-property value.+  constexpr mapping_t(thread_t);++  /// Construct from a sub-property value.+  constexpr mapping_t(new_thread_t);++  /// Construct from a sub-property value.+  constexpr mapping_t(other_t);++  /// Compare property values for equality.+  friend constexpr bool operator==(+      const mapping_t& a, const mapping_t& b) noexcept;++  /// Compare property values for inequality.+  friend constexpr bool operator!=(+      const mapping_t& a, const mapping_t& b) noexcept;+};++/// A special value used for accessing the mapping_t property.+constexpr mapping_t mapping;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {+namespace detail {+namespace mapping {++template <int I> struct thread_t;+template <int I> struct new_thread_t;+template <int I> struct other_t;++} // namespace mapping++template <int I = 0>+struct mapping_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+  typedef mapping_t polymorphic_query_result_type;++  typedef detail::mapping::thread_t<I> thread_t;+  typedef detail::mapping::new_thread_t<I> new_thread_t;+  typedef detail::mapping::other_t<I> other_t;++  ASIO_CONSTEXPR mapping_t()+    : value_(-1)+  {+  }++  ASIO_CONSTEXPR mapping_t(thread_t)+    : value_(0)+  {+  }++  ASIO_CONSTEXPR mapping_t(new_thread_t)+    : value_(1)+  {+  }++  ASIO_CONSTEXPR mapping_t(other_t)+    : value_(2)+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, mapping_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, mapping_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, mapping_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, thread_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, mapping_t>::is_valid+          && !traits::query_member<T, mapping_t>::is_valid+          && traits::static_query<T, thread_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, thread_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, new_thread_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, mapping_t>::is_valid+          && !traits::query_member<T, mapping_t>::is_valid+          && !traits::static_query<T, thread_t>::is_valid+          && traits::static_query<T, new_thread_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, new_thread_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, other_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, mapping_t>::is_valid+          && !traits::query_member<T, mapping_t>::is_valid+          && !traits::static_query<T, thread_t>::is_valid+          && !traits::static_query<T, new_thread_t>::is_valid+          && traits::static_query<T, other_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, other_t>::value();+  }++  template <typename E, typename T = decltype(mapping_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = mapping_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  friend ASIO_CONSTEXPR bool operator==(+      const mapping_t& a, const mapping_t& b)+  {+    return a.value_ == b.value_;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const mapping_t& a, const mapping_t& b)+  {+    return a.value_ != b.value_;+  }++  struct convertible_from_mapping_t+  {+    ASIO_CONSTEXPR convertible_from_mapping_t(mapping_t) {}+  };++  template <typename Executor>+  friend ASIO_CONSTEXPR mapping_t query(+      const Executor& ex, convertible_from_mapping_t,+      typename enable_if<+        can_query<const Executor&, thread_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, mapping_t<>::thread_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, thread_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, thread_t());+  }++  template <typename Executor>+  friend ASIO_CONSTEXPR mapping_t query(+      const Executor& ex, convertible_from_mapping_t,+      typename enable_if<+        !can_query<const Executor&, thread_t>::value+          && can_query<const Executor&, new_thread_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, mapping_t<>::new_thread_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, new_thread_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, new_thread_t());+  }++  template <typename Executor>+  friend ASIO_CONSTEXPR mapping_t query(+      const Executor& ex, convertible_from_mapping_t,+      typename enable_if<+        !can_query<const Executor&, thread_t>::value+          && !can_query<const Executor&, new_thread_t>::value+          && can_query<const Executor&, other_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, mapping_t<>::other_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, other_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, other_t());+  }++  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(thread_t, thread);+  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(new_thread_t, new_thread);+  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(other_t, other);++#if !defined(ASIO_HAS_CONSTEXPR)+  static const mapping_t instance;+#endif // !defined(ASIO_HAS_CONSTEXPR)++private:+  int value_;+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T mapping_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+template <int I>+const mapping_t<I> mapping_t<I>::instance;+#endif++template <int I>+const typename mapping_t<I>::thread_t mapping_t<I>::thread;++template <int I>+const typename mapping_t<I>::new_thread_t mapping_t<I>::new_thread;++template <int I>+const typename mapping_t<I>::other_t mapping_t<I>::other;++namespace mapping {++template <int I = 0>+struct thread_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef mapping_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR thread_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, thread_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, thread_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, thread_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR thread_t static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, thread_t>::is_valid+          && !traits::query_member<T, thread_t>::is_valid+          && !traits::query_free<T, thread_t>::is_valid+          && !can_query<T, new_thread_t<I> >::value+          && !can_query<T, other_t<I> >::value+      >::type* = 0) ASIO_NOEXCEPT+  {+    return thread_t();+  }++  template <typename E, typename T = decltype(thread_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = thread_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR mapping_t<I> value()+  {+    return thread_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const thread_t&, const thread_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const thread_t&, const thread_t&)+  {+    return false;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T thread_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <int I = 0>+struct new_thread_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef mapping_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR new_thread_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, new_thread_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, new_thread_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, new_thread_t>::value();+  }++  template <typename E, typename T = decltype(new_thread_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = new_thread_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR mapping_t<I> value()+  {+    return new_thread_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const new_thread_t&, const new_thread_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const new_thread_t&, const new_thread_t&)+  {+    return false;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T new_thread_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <int I>+struct other_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef mapping_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR other_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, other_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, other_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, other_t>::value();+  }++  template <typename E, typename T = decltype(other_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = other_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR mapping_t<I> value()+  {+    return other_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const other_t&, const other_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const other_t&, const other_t&)+  {+    return false;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T other_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++} // namespace mapping+} // namespace detail++typedef detail::mapping_t<> mapping_t;++#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr mapping_t mapping;+#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+namespace { static const mapping_t& mapping = mapping_t::instance; }+#endif++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+struct is_applicable_property<T, execution::mapping_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::mapping_t::thread_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::mapping_t::new_thread_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::mapping_t::other_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T>+struct query_free_default<T, execution::mapping_t,+  typename enable_if<+    can_query<T, execution::mapping_t::thread_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::mapping_t::thread_t>::value));++  typedef execution::mapping_t result_type;+};++template <typename T>+struct query_free_default<T, execution::mapping_t,+  typename enable_if<+    !can_query<T, execution::mapping_t::thread_t>::value+      && can_query<T, execution::mapping_t::new_thread_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::mapping_t::new_thread_t>::value));++  typedef execution::mapping_t result_type;+};++template <typename T>+struct query_free_default<T, execution::mapping_t,+  typename enable_if<+    !can_query<T, execution::mapping_t::thread_t>::value+      && !can_query<T, execution::mapping_t::new_thread_t>::value+      && can_query<T, execution::mapping_t::other_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::mapping_t::other_t>::value));++  typedef execution::mapping_t result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T>+struct static_query<T, execution::mapping_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::mapping_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::mapping_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::mapping_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::mapping_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T, execution::mapping_t>::is_valid+      && !traits::query_member<T, execution::mapping_t>::is_valid+      && traits::static_query<T, execution::mapping_t::thread_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::mapping_t::thread_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T, execution::mapping_t::thread_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::mapping_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T, execution::mapping_t>::is_valid+      && !traits::query_member<T, execution::mapping_t>::is_valid+      && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid+      && traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::mapping_t::new_thread_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T, execution::mapping_t::new_thread_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::mapping_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T, execution::mapping_t>::is_valid+      && !traits::query_member<T, execution::mapping_t>::is_valid+      && !traits::static_query<T, execution::mapping_t::thread_t>::is_valid+      && !traits::static_query<T, execution::mapping_t::new_thread_t>::is_valid+      && traits::static_query<T, execution::mapping_t::other_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::mapping_t::other_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T, execution::mapping_t::other_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::mapping_t::thread_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::mapping_t::thread_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::mapping_t::thread_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::mapping_t::thread_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::mapping_t::thread_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+      execution::mapping_t::thread_t>::is_valid+      && !traits::query_member<T, execution::mapping_t::thread_t>::is_valid+      && !traits::query_free<T, execution::mapping_t::thread_t>::is_valid+      && !can_query<T, execution::mapping_t::new_thread_t>::value+      && !can_query<T, execution::mapping_t::other_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef execution::mapping_t::thread_t result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return result_type();+  }+};++template <typename T>+struct static_query<T, execution::mapping_t::new_thread_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::mapping_t::new_thread_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::mapping_t::new_thread_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::mapping_t::new_thread_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::mapping_t::other_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::mapping_t::other_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::mapping_t::other_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::mapping_t::other_t>::value();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++template <typename T>+struct static_require<T, execution::mapping_t::thread_t,+  typename enable_if<+    static_query<T, execution::mapping_t::thread_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::mapping_t::thread_t>::result_type,+        execution::mapping_t::thread_t>::value));+};++template <typename T>+struct static_require<T, execution::mapping_t::new_thread_t,+  typename enable_if<+    static_query<T, execution::mapping_t::new_thread_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::mapping_t::new_thread_t>::result_type,+        execution::mapping_t::new_thread_t>::value));+};++template <typename T>+struct static_require<T, execution::mapping_t::other_t,+  typename enable_if<+    static_query<T, execution::mapping_t::other_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::mapping_t::other_t>::result_type,+        execution::mapping_t::other_t>::value));+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_MAPPING_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/occupancy.hpp view
@@ -0,0 +1,178 @@+//+// execution/occupancy.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_OCCUPANCY_HPP+#define ASIO_EXECUTION_OCCUPANCY_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/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/static_query.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property that gives an estimate of the number of execution agents that+/// should occupy the associated execution context.+struct occupancy_t+{+  /// The occupancy_t property applies to executors, senders, and schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The occupancy_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The occupancy_t property cannot be preferred.+  static constexpr bool is_preferable = false;++  /// The type returned by queries against an @c any_executor.+  typedef std::size_t polymorphic_query_result_type;+};++/// A special value used for accessing the occupancy_t property.+constexpr occupancy_t occupancy;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {+namespace detail {++template <int I = 0>+struct occupancy_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+  typedef std::size_t polymorphic_query_result_type;++  ASIO_CONSTEXPR occupancy_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, occupancy_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, occupancy_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, occupancy_t>::value();+  }++  template <typename E, typename T = decltype(occupancy_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = occupancy_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+  static const occupancy_t instance;+#endif // !defined(ASIO_HAS_CONSTEXPR)+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T occupancy_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+template <int I>+const occupancy_t<I> occupancy_t<I>::instance;+#endif++} // namespace detail++typedef detail::occupancy_t<> occupancy_t;++#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr occupancy_t occupancy;+#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+namespace { static const occupancy_t& occupancy = occupancy_t::instance; }+#endif++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+struct is_applicable_property<T, execution::occupancy_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T>+struct static_query<T, execution::occupancy_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::occupancy_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::occupancy_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::occupancy_t>::value();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_OCCUPANCY_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/operation_state.hpp view
@@ -0,0 +1,94 @@+//+// execution/operation_state.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_OPERATION_STATE_HPP+#define ASIO_EXECUTION_OPERATION_STATE_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/execution/start.hpp"++#if defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT)+# define ASIO_HAS_DEDUCED_EXECUTION_IS_OPERATION_STATE_TRAIT 1+#endif // defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++template <typename T>+struct is_operation_state_base :+  integral_constant<bool,+    is_destructible<T>::value+      && is_object<T>::value+  >+{+};++} // namespace detail++/// The is_operation_state trait detects whether a type T satisfies the+/// execution::operation_state concept.+/**+ * Class template @c is_operation_state is a type trait that is derived from+ * @c true_type if the type @c T meets the concept definition for an+ * @c operation_state, otherwise @c false_type.+ */+template <typename T>+struct is_operation_state :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  conditional<+    can_start<typename add_lvalue_reference<T>::type>::value+      && is_nothrow_start<typename add_lvalue_reference<T>::type>::value,+    detail::is_operation_state_base<T>,+    false_type+  >::type+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+ASIO_CONSTEXPR const bool is_operation_state_v =+  is_operation_state<T>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS)++template <typename T>+ASIO_CONCEPT operation_state = is_operation_state<T>::value;++#define ASIO_EXECUTION_OPERATION_STATE \+  ::asio::execution::operation_state++#else // defined(ASIO_HAS_CONCEPTS)++#define ASIO_EXECUTION_OPERATION_STATE typename++#endif // defined(ASIO_HAS_CONCEPTS)++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_OPERATION_STATE_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/outstanding_work.hpp view
@@ -0,0 +1,721 @@+//+// execution/outstanding_work.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_OUTSTANDING_WORK_HPP+#define ASIO_EXECUTION_OUTSTANDING_WORK_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/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/query.hpp"+#include "asio/traits/query_free.hpp"+#include "asio/traits/query_member.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/static_query.hpp"+#include "asio/traits/static_require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property to describe whether task submission is likely in the future.+struct outstanding_work_t+{+  /// The outstanding_work_t property applies to executors, senders, and+  /// schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The top-level outstanding_work_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The top-level outstanding_work_t property cannot be preferred.+  static constexpr bool is_preferable = false;++  /// The type returned by queries against an @c any_executor.+  typedef outstanding_work_t polymorphic_query_result_type;++  /// A sub-property that indicates that the executor does not represent likely+  /// future submission of a function object.+  struct untracked_t+  {+    /// The outstanding_work_t::untracked_t property applies to executors,+    /// senders, and schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The outstanding_work_t::untracked_t property can be required.+    static constexpr bool is_requirable = true;++    /// The outstanding_work_t::untracked_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef outstanding_work_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr untracked_t();++    /// Get the value associated with a property object.+    /**+     * @returns untracked_t();+     */+    static constexpr outstanding_work_t value();+  };++  /// A sub-property that indicates that the executor represents likely+  /// future submission of a function object.+  struct tracked_t+  {+    /// The outstanding_work_t::untracked_t property applies to executors,+    /// senders, and schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The outstanding_work_t::tracked_t property can be required.+    static constexpr bool is_requirable = true;++    /// The outstanding_work_t::tracked_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef outstanding_work_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr tracked_t();++    /// Get the value associated with a property object.+    /**+     * @returns tracked_t();+     */+    static constexpr outstanding_work_t value();+  };++  /// A special value used for accessing the outstanding_work_t::untracked_t+  /// property.+  static constexpr untracked_t untracked;++  /// A special value used for accessing the outstanding_work_t::tracked_t+  /// property.+  static constexpr tracked_t tracked;++  /// Default constructor.+  constexpr outstanding_work_t();++  /// Construct from a sub-property value.+  constexpr outstanding_work_t(untracked_t);++  /// Construct from a sub-property value.+  constexpr outstanding_work_t(tracked_t);++  /// Compare property values for equality.+  friend constexpr bool operator==(+      const outstanding_work_t& a, const outstanding_work_t& b) noexcept;++  /// Compare property values for inequality.+  friend constexpr bool operator!=(+      const outstanding_work_t& a, const outstanding_work_t& b) noexcept;+};++/// A special value used for accessing the outstanding_work_t property.+constexpr outstanding_work_t outstanding_work;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {+namespace detail {+namespace outstanding_work {++template <int I> struct untracked_t;+template <int I> struct tracked_t;++} // namespace outstanding_work++template <int I = 0>+struct outstanding_work_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+  typedef outstanding_work_t polymorphic_query_result_type;++  typedef detail::outstanding_work::untracked_t<I> untracked_t;+  typedef detail::outstanding_work::tracked_t<I> tracked_t;++  ASIO_CONSTEXPR outstanding_work_t()+    : value_(-1)+  {+  }++  ASIO_CONSTEXPR outstanding_work_t(untracked_t)+    : value_(0)+  {+  }++  ASIO_CONSTEXPR outstanding_work_t(tracked_t)+    : value_(1)+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<+      T, outstanding_work_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<+        T, outstanding_work_t+      >::is_noexcept))+  {+    return traits::query_static_constexpr_member<+        T, outstanding_work_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, untracked_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<+            T, outstanding_work_t>::is_valid+          && !traits::query_member<T, outstanding_work_t>::is_valid+          && traits::static_query<T, untracked_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, untracked_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, tracked_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<+            T, outstanding_work_t>::is_valid+          && !traits::query_member<T, outstanding_work_t>::is_valid+          && !traits::static_query<T, untracked_t>::is_valid+          && traits::static_query<T, tracked_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, tracked_t>::value();+  }++  template <typename E,+      typename T = decltype(outstanding_work_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = outstanding_work_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  friend ASIO_CONSTEXPR bool operator==(+      const outstanding_work_t& a, const outstanding_work_t& b)+  {+    return a.value_ == b.value_;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const outstanding_work_t& a, const outstanding_work_t& b)+  {+    return a.value_ != b.value_;+  }++  struct convertible_from_outstanding_work_t+  {+    ASIO_CONSTEXPR convertible_from_outstanding_work_t(outstanding_work_t)+    {+    }+  };++  template <typename Executor>+  friend ASIO_CONSTEXPR outstanding_work_t query(+      const Executor& ex, convertible_from_outstanding_work_t,+      typename enable_if<+        can_query<const Executor&, untracked_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&,+        outstanding_work_t<>::untracked_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, untracked_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, untracked_t());+  }++  template <typename Executor>+  friend ASIO_CONSTEXPR outstanding_work_t query(+      const Executor& ex, convertible_from_outstanding_work_t,+      typename enable_if<+        !can_query<const Executor&, untracked_t>::value+          && can_query<const Executor&, tracked_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&,+        outstanding_work_t<>::tracked_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, tracked_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, tracked_t());+  }++  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(untracked_t, untracked);+  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(tracked_t, tracked);++#if !defined(ASIO_HAS_CONSTEXPR)+  static const outstanding_work_t instance;+#endif // !defined(ASIO_HAS_CONSTEXPR)++private:+  int value_;+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T outstanding_work_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+template <int I>+const outstanding_work_t<I> outstanding_work_t<I>::instance;+#endif++template <int I>+const typename outstanding_work_t<I>::untracked_t+outstanding_work_t<I>::untracked;++template <int I>+const typename outstanding_work_t<I>::tracked_t+outstanding_work_t<I>::tracked;++namespace outstanding_work {++template <int I = 0>+struct untracked_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef outstanding_work_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR untracked_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, untracked_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, untracked_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, untracked_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR untracked_t static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, untracked_t>::is_valid+          && !traits::query_member<T, untracked_t>::is_valid+          && !traits::query_free<T, untracked_t>::is_valid+          && !can_query<T, tracked_t<I> >::value+      >::type* = 0) ASIO_NOEXCEPT+  {+    return untracked_t();+  }++  template <typename E, typename T = decltype(untracked_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = untracked_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR outstanding_work_t<I> value()+  {+    return untracked_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const untracked_t&, const untracked_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const untracked_t&, const untracked_t&)+  {+    return false;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T untracked_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <int I = 0>+struct tracked_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef outstanding_work_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR tracked_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, tracked_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, tracked_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, tracked_t>::value();+  }++  template <typename E, typename T = decltype(tracked_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = tracked_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR outstanding_work_t<I> value()+  {+    return tracked_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const tracked_t&, const tracked_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const tracked_t&, const tracked_t&)+  {+    return false;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T tracked_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++} // namespace outstanding_work+} // namespace detail++typedef detail::outstanding_work_t<> outstanding_work_t;++#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr outstanding_work_t outstanding_work;+#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+namespace { static const outstanding_work_t&+  outstanding_work = outstanding_work_t::instance; }+#endif++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+struct is_applicable_property<T, execution::outstanding_work_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::outstanding_work_t::untracked_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::outstanding_work_t::tracked_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T>+struct query_free_default<T, execution::outstanding_work_t,+  typename enable_if<+    can_query<T, execution::outstanding_work_t::untracked_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::outstanding_work_t::untracked_t>::value));++  typedef execution::outstanding_work_t result_type;+};++template <typename T>+struct query_free_default<T, execution::outstanding_work_t,+  typename enable_if<+    !can_query<T, execution::outstanding_work_t::untracked_t>::value+      && can_query<T, execution::outstanding_work_t::tracked_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::outstanding_work_t::tracked_t>::value));++  typedef execution::outstanding_work_t result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T>+struct static_query<T, execution::outstanding_work_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::outstanding_work_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::outstanding_work_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::outstanding_work_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::outstanding_work_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::outstanding_work_t>::is_valid+      && !traits::query_member<T,+        execution::outstanding_work_t>::is_valid+      && traits::static_query<T,+        execution::outstanding_work_t::untracked_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::outstanding_work_t::untracked_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T,+        execution::outstanding_work_t::untracked_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::outstanding_work_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::outstanding_work_t>::is_valid+      && !traits::query_member<T,+        execution::outstanding_work_t>::is_valid+      && !traits::static_query<T,+        execution::outstanding_work_t::untracked_t>::is_valid+      && traits::static_query<T,+        execution::outstanding_work_t::tracked_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::outstanding_work_t::tracked_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T,+        execution::outstanding_work_t::tracked_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::outstanding_work_t::untracked_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::outstanding_work_t::untracked_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::outstanding_work_t::untracked_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::outstanding_work_t::untracked_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::outstanding_work_t::untracked_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::outstanding_work_t::untracked_t>::is_valid+      && !traits::query_member<T,+        execution::outstanding_work_t::untracked_t>::is_valid+      && !traits::query_free<T,+        execution::outstanding_work_t::untracked_t>::is_valid+      && !can_query<T, execution::outstanding_work_t::tracked_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef execution::outstanding_work_t::untracked_t result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return result_type();+  }+};++template <typename T>+struct static_query<T, execution::outstanding_work_t::tracked_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::outstanding_work_t::tracked_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::outstanding_work_t::tracked_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::outstanding_work_t::tracked_t>::value();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++template <typename T>+struct static_require<T, execution::outstanding_work_t::untracked_t,+  typename enable_if<+    static_query<T, execution::outstanding_work_t::untracked_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::outstanding_work_t::untracked_t>::result_type,+        execution::outstanding_work_t::untracked_t>::value));+};++template <typename T>+struct static_require<T, execution::outstanding_work_t::tracked_t,+  typename enable_if<+    static_query<T, execution::outstanding_work_t::tracked_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::outstanding_work_t::tracked_t>::result_type,+        execution::outstanding_work_t::tracked_t>::value));+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_OUTSTANDING_WORK_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/prefer_only.hpp view
@@ -0,0 +1,327 @@+//+// execution/prefer_only.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_PREFER_ONLY_HPP+#define ASIO_EXECUTION_PREFER_ONLY_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/is_applicable_property.hpp"+#include "asio/prefer.hpp"+#include "asio/query.hpp"+#include "asio/traits/static_query.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property adapter that is used with the polymorphic executor wrapper+/// to mark properties as preferable, but not requirable.+template <typename Property>+struct prefer_only+{+  /// The prefer_only adapter applies to the same types as the nested property.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_applicable_property<T, Property>::value;++  /// The context_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The context_t property can be preferred, it the underlying property can+  /// be preferred.+  /**+   * @c true if @c Property::is_preferable is @c true, otherwise @c false.+   */+  static constexpr bool is_preferable = automatically_determined;++  /// The type returned by queries against an @c any_executor.+  typedef typename Property::polymorphic_query_result_type+    polymorphic_query_result_type;+};++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {+namespace detail {++template <typename InnerProperty, typename = void>+struct prefer_only_is_preferable+{+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+};++template <typename InnerProperty>+struct prefer_only_is_preferable<InnerProperty,+    typename enable_if<+      InnerProperty::is_preferable+    >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+};++template <typename InnerProperty, typename = void>+struct prefer_only_polymorphic_query_result_type+{+};++template <typename InnerProperty>+struct prefer_only_polymorphic_query_result_type<InnerProperty,+    typename void_type<+      typename InnerProperty::polymorphic_query_result_type+    >::type>+{+  typedef typename InnerProperty::polymorphic_query_result_type+    polymorphic_query_result_type;+};++template <typename InnerProperty, typename = void>+struct prefer_only_property+{+  InnerProperty property;++  prefer_only_property(const InnerProperty& p)+    : property(p)+  {+  }+};++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++template <typename InnerProperty>+struct prefer_only_property<InnerProperty,+    typename void_type<+      decltype(asio::declval<const InnerProperty>().value())+    >::type>+{+  InnerProperty property;++  prefer_only_property(const InnerProperty& p)+    : property(p)+  {+  }++  ASIO_CONSTEXPR auto value() const+    ASIO_NOEXCEPT_IF((+      noexcept(asio::declval<const InnerProperty>().value())))+    -> decltype(asio::declval<const InnerProperty>().value())+  {+    return property.value();+  }+};++#else // defined(ASIO_HAS_DECLTYPE)+      //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++struct prefer_only_memfns_base+{+  void value();+};++template <typename T>+struct prefer_only_memfns_derived+  : T, prefer_only_memfns_base+{+};++template <typename T, T>+struct prefer_only_memfns_check+{+};++template <typename>+char (&prefer_only_value_memfn_helper(...))[2];++template <typename T>+char prefer_only_value_memfn_helper(+    prefer_only_memfns_check<+      void (prefer_only_memfns_base::*)(),+      &prefer_only_memfns_derived<T>::value>*);++template <typename InnerProperty>+struct prefer_only_property<InnerProperty,+    typename enable_if<+      sizeof(prefer_only_value_memfn_helper<InnerProperty>(0)) != 1+        && !is_same<typename InnerProperty::polymorphic_query_result_type,+          void>::value+    >::type>+{+  InnerProperty property;++  prefer_only_property(const InnerProperty& p)+    : property(p)+  {+  }++  ASIO_CONSTEXPR typename InnerProperty::polymorphic_query_result_type+  value() const+  {+    return property.value();+  }+};++#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++} // namespace detail++template <typename InnerProperty>+struct prefer_only :+  detail::prefer_only_is_preferable<InnerProperty>,+  detail::prefer_only_polymorphic_query_result_type<InnerProperty>,+  detail::prefer_only_property<InnerProperty>+{+  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);++  ASIO_CONSTEXPR prefer_only(const InnerProperty& p)+    : detail::prefer_only_property<InnerProperty>(p)+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, InnerProperty>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::static_query<T, InnerProperty>::is_noexcept))+  {+    return traits::static_query<T, InnerProperty>::value();+  }++  template <typename E, typename T = decltype(prefer_only::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = prefer_only::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  template <typename Executor, typename Property>+  friend ASIO_CONSTEXPR+  typename prefer_result<const Executor&, const InnerProperty&>::type+  prefer(const Executor& ex, const prefer_only<Property>& p,+      typename enable_if<+        is_same<Property, InnerProperty>::value+          && can_prefer<const Executor&, const InnerProperty&>::value+      >::type* = 0)+#if !defined(ASIO_MSVC) \+  && !defined(__clang__) // Clang crashes if noexcept is used here.+    ASIO_NOEXCEPT_IF((+      is_nothrow_prefer<const Executor&, const InnerProperty&>::value))+#endif // !defined(ASIO_MSVC)+       //   && !defined(__clang__)+  {+    return asio::prefer(ex, p.property);+  }++  template <typename Executor, typename Property>+  friend ASIO_CONSTEXPR+  typename query_result<const Executor&, const InnerProperty&>::type+  query(const Executor& ex, const prefer_only<Property>& p,+      typename enable_if<+        is_same<Property, InnerProperty>::value+          && can_query<const Executor&, const InnerProperty&>::value+      >::type* = 0)+#if !defined(ASIO_MSVC) \+  && !defined(__clang__) // Clang crashes if noexcept is used here.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, const InnerProperty&>::value))+#endif // !defined(ASIO_MSVC)+       //   && !defined(__clang__)+  {+    return asio::query(ex, p.property);+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <typename InnerProperty> template <typename E, typename T>+const T prefer_only<InnerProperty>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++} // namespace execution++template <typename T, typename InnerProperty>+struct is_applicable_property<T, execution::prefer_only<InnerProperty> >+  : is_applicable_property<T, InnerProperty>+{+};++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T, typename InnerProperty>+struct static_query<T, execution::prefer_only<InnerProperty> > :+  static_query<T, const InnerProperty&>+{+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)++template <typename T, typename InnerProperty>+struct prefer_free_default<T, execution::prefer_only<InnerProperty>,+    typename enable_if<+      can_prefer<const T&, const InnerProperty&>::value+    >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_prefer<const T&, const InnerProperty&>::value));++  typedef typename prefer_result<const T&,+      const InnerProperty&>::type result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T, typename InnerProperty>+struct query_free<T, execution::prefer_only<InnerProperty>,+    typename enable_if<+      can_query<const T&, const InnerProperty&>::value+    >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<const T&, const InnerProperty&>::value));++  typedef typename query_result<const T&,+      const InnerProperty&>::type result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_PREFER_ONLY_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/receiver.hpp view
@@ -0,0 +1,280 @@+//+// execution/receiver.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_RECEIVER_HPP+#define ASIO_EXECUTION_RECEIVER_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/execution/set_done.hpp"+#include "asio/execution/set_error.hpp"+#include "asio/execution/set_value.hpp"++#if defined(ASIO_HAS_STD_EXCEPTION_PTR)+# include <exception>+#else // defined(ASIO_HAS_STD_EXCEPTION_PTR)+# include "asio/error_code.hpp"+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)++#if defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_RECEIVER_OF_FREE_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_RECEIVER_OF_MEMBER_TRAIT)+# define ASIO_HAS_DEDUCED_EXECUTION_IS_RECEIVER_TRAIT 1+#endif // defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_RECEIVER_OF_FREE_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_RECEIVER_OF_MEMBER_TRAIT)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++template <typename T, typename E>+struct is_receiver_base :+  integral_constant<bool,+    is_move_constructible<typename remove_cvref<T>::type>::value+      && is_constructible<typename remove_cvref<T>::type, T>::value+  >+{+};++} // namespace detail++#if defined(ASIO_HAS_STD_EXCEPTION_PTR)+# define ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT = std::exception_ptr+#else // defined(ASIO_HAS_STD_EXCEPTION_PTR)+# define ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT \+  = ::asio::error_code+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)++/// The is_receiver trait detects whether a type T satisfies the+/// execution::receiver concept.+/**+ * Class template @c is_receiver is a type trait that is derived from @c+ * true_type if the type @c T meets the concept definition for a receiver for+ * error type @c E, otherwise @c false_type.+ */+template <typename T, typename E ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT>+struct is_receiver :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  conditional<+    can_set_done<typename remove_cvref<T>::type>::value+      && is_nothrow_set_done<typename remove_cvref<T>::type>::value+      && can_set_error<typename remove_cvref<T>::type, E>::value+      && is_nothrow_set_error<typename remove_cvref<T>::type, E>::value,+    detail::is_receiver_base<T, E>,+    false_type+  >::type+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename E ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT>+ASIO_CONSTEXPR const bool is_receiver_v = is_receiver<T, E>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS)++template <typename T, typename E ASIO_EXECUTION_RECEIVER_ERROR_DEFAULT>+ASIO_CONCEPT receiver = is_receiver<T, E>::value;++#define ASIO_EXECUTION_RECEIVER ::asio::execution::receiver++#else // defined(ASIO_HAS_CONCEPTS)++#define ASIO_EXECUTION_RECEIVER typename++#endif // defined(ASIO_HAS_CONCEPTS)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  || defined(GENERATING_DOCUMENTATION)++/// The is_receiver_of trait detects whether a type T satisfies the+/// execution::receiver_of concept for some set of value arguments.+/**+ * Class template @c is_receiver_of is a type trait that is derived from @c+ * true_type if the type @c T meets the concept definition for a receiver for+ * value arguments @c Vs, otherwise @c false_type.+ */+template <typename T, typename... Vs>+struct is_receiver_of :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  conditional<+    is_receiver<T>::value,+    can_set_value<typename remove_cvref<T>::type, Vs...>,+    false_type+  >::type+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename... Vs>+ASIO_CONSTEXPR const bool is_receiver_of_v =+  is_receiver_of<T, Vs...>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS)++template <typename T, typename... Vs>+ASIO_CONCEPT receiver_of = is_receiver_of<T, Vs...>::value;++#define ASIO_EXECUTION_RECEIVER_OF_0 \+  ::asio::execution::receiver_of++#define ASIO_EXECUTION_RECEIVER_OF_1(v) \+  ::asio::execution::receiver_of<v>++#else // defined(ASIO_HAS_CONCEPTS)++#define ASIO_EXECUTION_RECEIVER_OF_0 typename+#define ASIO_EXECUTION_RECEIVER_OF_1(v) typename++#endif // defined(ASIO_HAS_CONCEPTS)++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   || defined(GENERATING_DOCUMENTATION)++template <typename T, typename = void,+    typename = void, typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void, typename = void>+struct is_receiver_of;++template <typename T>+struct is_receiver_of<T> :+  conditional<+    is_receiver<T>::value,+    can_set_value<typename remove_cvref<T>::type>,+    false_type+  >::type+{+};++#define ASIO_PRIVATE_RECEIVER_OF_TRAITS_DEF(n) \+  template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+  struct is_receiver_of<T, ASIO_VARIADIC_TARGS(n)> : \+    conditional< \+      conditional<true, is_receiver<T>, void>::type::value, \+      can_set_value< \+        typename remove_cvref<T>::type, \+        ASIO_VARIADIC_TARGS(n)>, \+      false_type \+    >::type \+  { \+  }; \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_RECEIVER_OF_TRAITS_DEF)+#undef ASIO_PRIVATE_RECEIVER_OF_TRAITS_DEF++#define ASIO_EXECUTION_RECEIVER_OF_0 typename+#define ASIO_EXECUTION_RECEIVER_OF_1(v) typename++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   || defined(GENERATING_DOCUMENTATION)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  || defined(GENERATING_DOCUMENTATION)++/// The is_nothrow_receiver_of trait detects whether a type T satisfies the+/// execution::receiver_of concept for some set of value arguments, with a+/// noexcept @c set_value operation.+/**+ * Class template @c is_nothrow_receiver_of is a type trait that is derived+ * from @c true_type if the type @c T meets the concept definition for a+ * receiver for value arguments @c Vs, and the expression+ * <tt>execution::set_value(declval<T>(), declval<Ts>()...)</tt> is noexcept,+ * otherwise @c false_type.+ */+template <typename T, typename... Vs>+struct is_nothrow_receiver_of :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  integral_constant<bool,+    is_receiver_of<T, Vs...>::value+      && is_nothrow_set_value<typename remove_cvref<T>::type, Vs...>::value+  >+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename... Vs>+ASIO_CONSTEXPR const bool is_nothrow_receiver_of_v =+  is_nothrow_receiver_of<T, Vs...>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   || defined(GENERATING_DOCUMENTATION)++template <typename T, typename = void,+    typename = void, typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void, typename = void>+struct is_nothrow_receiver_of;++template <typename T>+struct is_nothrow_receiver_of<T> :+  integral_constant<bool,+    is_receiver_of<T>::value+      && is_nothrow_set_value<typename remove_cvref<T>::type>::value+  >+{+};++#define ASIO_PRIVATE_NOTHROW_RECEIVER_OF_TRAITS_DEF(n) \+  template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+  struct is_nothrow_receiver_of<T, ASIO_VARIADIC_TARGS(n)> : \+    integral_constant<bool, \+      is_receiver_of<T, ASIO_VARIADIC_TARGS(n)>::value \+        && is_nothrow_set_value<typename remove_cvref<T>::type, \+          ASIO_VARIADIC_TARGS(n)>::value \+    > \+  { \+  }; \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_NOTHROW_RECEIVER_OF_TRAITS_DEF)+#undef ASIO_PRIVATE_NOTHROW_RECEIVER_OF_TRAITS_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   || defined(GENERATING_DOCUMENTATION)++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_RECEIVER_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/receiver_invocation_error.hpp view
@@ -0,0 +1,48 @@+//+// execution/receiver_invocation_error.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_RECEIVER_INVOCATION_ERROR_HPP+#define ASIO_EXECUTION_RECEIVER_INVOCATION_ERROR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <stdexcept>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {++/// Exception reported via @c set_error when an exception escapes from+/// @c set_value.+class receiver_invocation_error+  : public std::runtime_error+#if defined(ASIO_HAS_STD_NESTED_EXCEPTION)+  , public std::nested_exception+#endif // defined(ASIO_HAS_STD_NESTED_EXCEPTION)+{+public:+  /// Constructor.+  ASIO_DECL receiver_invocation_error();+};++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/execution/impl/receiver_invocation_error.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_EXECUTION_RECEIVER_INVOCATION_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/relationship.hpp view
@@ -0,0 +1,720 @@+//+// execution/relationship.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_RELATIONSHIP_HPP+#define ASIO_EXECUTION_RELATIONSHIP_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/execution/executor.hpp"+#include "asio/execution/scheduler.hpp"+#include "asio/execution/sender.hpp"+#include "asio/is_applicable_property.hpp"+#include "asio/query.hpp"+#include "asio/traits/query_free.hpp"+#include "asio/traits/query_member.hpp"+#include "asio/traits/query_static_constexpr_member.hpp"+#include "asio/traits/static_query.hpp"+#include "asio/traits/static_require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(GENERATING_DOCUMENTATION)++namespace execution {++/// A property to describe whether submitted tasks represent continuations of+/// the calling context.+struct relationship_t+{+  /// The relationship_t property applies to executors, senders, and schedulers.+  template <typename T>+  static constexpr bool is_applicable_property_v =+    is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++  /// The top-level relationship_t property cannot be required.+  static constexpr bool is_requirable = false;++  /// The top-level relationship_t property cannot be preferred.+  static constexpr bool is_preferable = false;++  /// The type returned by queries against an @c any_executor.+  typedef relationship_t polymorphic_query_result_type;++  /// A sub-property that indicates that the executor does not represent a+  /// continuation of the calling context.+  struct fork_t+  {+    /// The relationship_t::fork_t property applies to executors, senders, and+    /// schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The relationship_t::fork_t property can be required.+    static constexpr bool is_requirable = true;++    /// The relationship_t::fork_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef relationship_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr fork_t();++    /// Get the value associated with a property object.+    /**+     * @returns fork_t();+     */+    static constexpr relationship_t value();+  };++  /// A sub-property that indicates that the executor represents a continuation+  /// of the calling context.+  struct continuation_t+  {+    /// The relationship_t::continuation_t property applies to executors,+    /// senders, and schedulers.+    template <typename T>+    static constexpr bool is_applicable_property_v =+      is_executor_v<T> || is_sender_v<T> || is_scheduler_v<T>;++    /// The relationship_t::continuation_t property can be required.+    static constexpr bool is_requirable = true;++    /// The relationship_t::continuation_t property can be preferred.+    static constexpr bool is_preferable = true;++    /// The type returned by queries against an @c any_executor.+    typedef relationship_t polymorphic_query_result_type;++    /// Default constructor.+    constexpr continuation_t();++    /// Get the value associated with a property object.+    /**+     * @returns continuation_t();+     */+    static constexpr relationship_t value();+  };++  /// A special value used for accessing the relationship_t::fork_t property.+  static constexpr fork_t fork;++  /// A special value used for accessing the relationship_t::continuation_t+  /// property.+  static constexpr continuation_t continuation;++  /// Default constructor.+  constexpr relationship_t();++  /// Construct from a sub-property value.+  constexpr relationship_t(fork_t);++  /// Construct from a sub-property value.+  constexpr relationship_t(continuation_t);++  /// Compare property values for equality.+  friend constexpr bool operator==(+      const relationship_t& a, const relationship_t& b) noexcept;++  /// Compare property values for inequality.+  friend constexpr bool operator!=(+      const relationship_t& a, const relationship_t& b) noexcept;+};++/// A special value used for accessing the relationship_t property.+constexpr relationship_t relationship;++} // namespace execution++#else // defined(GENERATING_DOCUMENTATION)++namespace execution {+namespace detail {+namespace relationship {++template <int I> struct fork_t;+template <int I> struct continuation_t;++} // namespace relationship++template <int I = 0>+struct relationship_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = false);+  typedef relationship_t polymorphic_query_result_type;++  typedef detail::relationship::fork_t<I> fork_t;+  typedef detail::relationship::continuation_t<I> continuation_t;++  ASIO_CONSTEXPR relationship_t()+    : value_(-1)+  {+  }++  ASIO_CONSTEXPR relationship_t(fork_t)+    : value_(0)+  {+  }++  ASIO_CONSTEXPR relationship_t(continuation_t)+    : value_(1)+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<+      T, relationship_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<+        T, relationship_t+      >::is_noexcept))+  {+    return traits::query_static_constexpr_member<+        T, relationship_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, fork_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<+            T, relationship_t>::is_valid+          && !traits::query_member<T, relationship_t>::is_valid+          && traits::static_query<T, fork_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, fork_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::static_query<T, continuation_t>::result_type+  static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<+            T, relationship_t>::is_valid+          && !traits::query_member<T, relationship_t>::is_valid+          && !traits::static_query<T, fork_t>::is_valid+          && traits::static_query<T, continuation_t>::is_valid+      >::type* = 0) ASIO_NOEXCEPT+  {+    return traits::static_query<T, continuation_t>::value();+  }++  template <typename E,+      typename T = decltype(relationship_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = relationship_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  friend ASIO_CONSTEXPR bool operator==(+      const relationship_t& a, const relationship_t& b)+  {+    return a.value_ == b.value_;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const relationship_t& a, const relationship_t& b)+  {+    return a.value_ != b.value_;+  }++  struct convertible_from_relationship_t+  {+    ASIO_CONSTEXPR convertible_from_relationship_t(relationship_t)+    {+    }+  };++  template <typename Executor>+  friend ASIO_CONSTEXPR relationship_t query(+      const Executor& ex, convertible_from_relationship_t,+      typename enable_if<+        can_query<const Executor&, fork_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, relationship_t<>::fork_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, fork_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, fork_t());+  }++  template <typename Executor>+  friend ASIO_CONSTEXPR relationship_t query(+      const Executor& ex, convertible_from_relationship_t,+      typename enable_if<+        !can_query<const Executor&, fork_t>::value+          && can_query<const Executor&, continuation_t>::value+      >::type* = 0)+#if !defined(__clang__) // Clang crashes if noexcept is used here.+#if defined(ASIO_MSVC) // Visual C++ wants the type to be qualified.+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&,+        relationship_t<>::continuation_t>::value))+#else // defined(ASIO_MSVC)+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, continuation_t>::value))+#endif // defined(ASIO_MSVC)+#endif // !defined(__clang__)+  {+    return asio::query(ex, continuation_t());+  }++  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(fork_t, fork);+  ASIO_STATIC_CONSTEXPR_DEFAULT_INIT(continuation_t, continuation);++#if !defined(ASIO_HAS_CONSTEXPR)+  static const relationship_t instance;+#endif // !defined(ASIO_HAS_CONSTEXPR)++private:+  int value_;+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T relationship_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_CONSTEXPR)+template <int I>+const relationship_t<I> relationship_t<I>::instance;+#endif++template <int I>+const typename relationship_t<I>::fork_t+relationship_t<I>::fork;++template <int I>+const typename relationship_t<I>::continuation_t+relationship_t<I>::continuation;++namespace relationship {++template <int I = 0>+struct fork_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef relationship_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR fork_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, fork_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, fork_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, fork_t>::value();+  }++  template <typename T>+  static ASIO_CONSTEXPR fork_t static_query(+      typename enable_if<+        !traits::query_static_constexpr_member<T, fork_t>::is_valid+          && !traits::query_member<T, fork_t>::is_valid+          && !traits::query_free<T, fork_t>::is_valid+          && !can_query<T, continuation_t<I> >::value+      >::type* = 0) ASIO_NOEXCEPT+  {+    return fork_t();+  }++  template <typename E, typename T = decltype(fork_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = fork_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR relationship_t<I> value()+  {+    return fork_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const fork_t&, const fork_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const fork_t&, const fork_t&)+  {+    return false;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T fork_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <int I = 0>+struct continuation_t+{+#if defined(ASIO_HAS_VARIABLE_TEMPLATES)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = is_executor<T>::value+      || is_sender<T>::value || is_scheduler<T>::value);+#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++  ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);+  ASIO_STATIC_CONSTEXPR(bool, is_preferable = true);+  typedef relationship_t<I> polymorphic_query_result_type;++  ASIO_CONSTEXPR continuation_t()+  {+  }++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+  template <typename T>+  static ASIO_CONSTEXPR+  typename traits::query_static_constexpr_member<T, continuation_t>::result_type+  static_query()+    ASIO_NOEXCEPT_IF((+      traits::query_static_constexpr_member<T, continuation_t>::is_noexcept))+  {+    return traits::query_static_constexpr_member<T, continuation_t>::value();+  }++  template <typename E,+      typename T = decltype(continuation_t::static_query<E>())>+  static ASIO_CONSTEXPR const T static_query_v+    = continuation_t::static_query<E>();+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++  static ASIO_CONSTEXPR relationship_t<I> value()+  {+    return continuation_t();+  }++  friend ASIO_CONSTEXPR bool operator==(+      const continuation_t&, const continuation_t&)+  {+    return true;+  }++  friend ASIO_CONSTEXPR bool operator!=(+      const continuation_t&, const continuation_t&)+  {+    return false;+  }+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)+template <int I> template <typename E, typename T>+const T continuation_t<I>::static_query_v;+#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++} // namespace relationship+} // namespace detail++typedef detail::relationship_t<> relationship_t;++#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr relationship_t relationship;+#else // defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+namespace { static const relationship_t&+  relationship = relationship_t::instance; }+#endif++} // namespace execution++#if !defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+struct is_applicable_property<T, execution::relationship_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::relationship_t::fork_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++template <typename T>+struct is_applicable_property<T, execution::relationship_t::continuation_t>+  : integral_constant<bool,+      execution::is_executor<T>::value+        || execution::is_sender<T>::value+        || execution::is_scheduler<T>::value>+{+};++#endif // !defined(ASIO_HAS_VARIABLE_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T>+struct query_free_default<T, execution::relationship_t,+  typename enable_if<+    can_query<T, execution::relationship_t::fork_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::relationship_t::fork_t>::value));++  typedef execution::relationship_t result_type;+};++template <typename T>+struct query_free_default<T, execution::relationship_t,+  typename enable_if<+    !can_query<T, execution::relationship_t::fork_t>::value+      && can_query<T, execution::relationship_t::continuation_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (is_nothrow_query<T, execution::relationship_t::continuation_t>::value));++  typedef execution::relationship_t result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT) \+  || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++template <typename T>+struct static_query<T, execution::relationship_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::relationship_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::relationship_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::relationship_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::relationship_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::relationship_t>::is_valid+      && !traits::query_member<T,+        execution::relationship_t>::is_valid+      && traits::static_query<T,+        execution::relationship_t::fork_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::relationship_t::fork_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T,+        execution::relationship_t::fork_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::relationship_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::relationship_t>::is_valid+      && !traits::query_member<T,+        execution::relationship_t>::is_valid+      && !traits::static_query<T,+        execution::relationship_t::fork_t>::is_valid+      && traits::static_query<T,+        execution::relationship_t::continuation_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::static_query<T,+    execution::relationship_t::continuation_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::static_query<T,+        execution::relationship_t::continuation_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::relationship_t::fork_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::relationship_t::fork_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::relationship_t::fork_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::relationship_t::fork_t>::value();+  }+};++template <typename T>+struct static_query<T, execution::relationship_t::fork_t,+  typename enable_if<+    !traits::query_static_constexpr_member<T,+        execution::relationship_t::fork_t>::is_valid+      && !traits::query_member<T,+        execution::relationship_t::fork_t>::is_valid+      && !traits::query_free<T,+        execution::relationship_t::fork_t>::is_valid+      && !can_query<T, execution::relationship_t::continuation_t>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef execution::relationship_t::fork_t result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return result_type();+  }+};++template <typename T>+struct static_query<T, execution::relationship_t::continuation_t,+  typename enable_if<+    traits::query_static_constexpr_member<T,+      execution::relationship_t::continuation_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++  typedef typename traits::query_static_constexpr_member<T,+    execution::relationship_t::continuation_t>::result_type result_type;++  static ASIO_CONSTEXPR result_type value()+  {+    return traits::query_static_constexpr_member<T,+      execution::relationship_t::continuation_t>::value();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)+       //   || !defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)++#if !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++template <typename T>+struct static_require<T, execution::relationship_t::fork_t,+  typename enable_if<+    static_query<T, execution::relationship_t::fork_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::relationship_t::fork_t>::result_type,+        execution::relationship_t::fork_t>::value));+};++template <typename T>+struct static_require<T, execution::relationship_t::continuation_t,+  typename enable_if<+    static_query<T, execution::relationship_t::continuation_t>::is_valid+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid =+    (is_same<typename static_query<T,+      execution::relationship_t::continuation_t>::result_type,+        execution::relationship_t::continuation_t>::value));+};++#endif // !defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++} // namespace traits++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_RELATIONSHIP_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/schedule.hpp view
@@ -0,0 +1,290 @@+//+// execution/schedule.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_SCHEDULE_HPP+#define ASIO_EXECUTION_SCHEDULE_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/execution/executor.hpp"+#include "asio/traits/schedule_member.hpp"+#include "asio/traits/schedule_free.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++/// A customisation point that is used to obtain a sender from a scheduler.+/**+ * The name <tt>execution::schedule</tt> denotes a customisation point object.+ * For some subexpression <tt>s</tt>, let <tt>S</tt> be a type such that+ * <tt>decltype((s))</tt> is <tt>S</tt>. The expression+ * <tt>execution::schedule(s)</tt> is expression-equivalent to:+ *+ * @li <tt>s.schedule()</tt>, if that expression is valid and its type models+ *   <tt>sender</tt>.+ *+ * @li Otherwise, <tt>schedule(s)</tt>, if that expression is valid and its+ *   type models <tt>sender</tt> with overload resolution performed in a context+ *   that includes the declaration <tt>void schedule();</tt> and that does not+ *   include a declaration of <tt>execution::schedule</tt>.+ *+ * @li Otherwise, <tt>S</tt> if <tt>S</tt> satisfies <tt>executor</tt>.+ *+ * @li Otherwise, <tt>execution::schedule(s)</tt> is ill-formed.+ */+inline constexpr unspecified schedule = unspecified;++/// A type trait that determines whether a @c schedule expression is+/// well-formed.+/**+ * Class template @c can_schedule is a trait that is derived from @c true_type+ * if the expression <tt>execution::schedule(std::declval<S>())</tt> is well+ * formed; otherwise @c false_type.+ */+template <typename S>+struct can_schedule :+  integral_constant<bool, automatically_determined>+{+};++} // namespace execution+} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_execution_schedule_fn {++using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::execution::is_executor;+using asio::traits::schedule_free;+using asio::traits::schedule_member;++void schedule();++enum overload_type+{+  identity,+  call_member,+  call_free,+  ill_formed+};++template <typename S, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename S>+struct call_traits<S,+  typename enable_if<+    (+      schedule_member<S>::is_valid+    )+  >::type> :+  schedule_member<S>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename S>+struct call_traits<S,+  typename enable_if<+    (+      !schedule_member<S>::is_valid+      &&+      schedule_free<S>::is_valid+    )+  >::type> :+  schedule_free<S>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++template <typename S>+struct call_traits<S,+  typename enable_if<+    (+      !schedule_member<S>::is_valid+      &&+      !schedule_free<S>::is_valid+      &&+      is_executor<typename decay<S>::type>::value+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++#if defined(ASIO_HAS_MOVE)+  typedef ASIO_MOVE_ARG(S) result_type;+#else // defined(ASIO_HAS_MOVE)+  typedef ASIO_MOVE_ARG(typename decay<S>::type) result_type;+#endif // defined(ASIO_HAS_MOVE)+};++struct impl+{+  template <typename S>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S>::overload == identity,+    typename call_traits<S>::result_type+  >::type+  operator()(ASIO_MOVE_ARG(S) s) const+    ASIO_NOEXCEPT_IF((+      call_traits<S>::is_noexcept))+  {+    return ASIO_MOVE_CAST(S)(s);+  }++#if defined(ASIO_HAS_MOVE)+  template <typename S>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S>::overload == call_member,+    typename call_traits<S>::result_type+  >::type+  operator()(S&& s) const+    ASIO_NOEXCEPT_IF((+      call_traits<S>::is_noexcept))+  {+    return ASIO_MOVE_CAST(S)(s).schedule();+  }++  template <typename S>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S>::overload == call_free,+    typename call_traits<S>::result_type+  >::type+  operator()(S&& s) const+    ASIO_NOEXCEPT_IF((+      call_traits<S>::is_noexcept))+  {+    return schedule(ASIO_MOVE_CAST(S)(s));+  }+#else // defined(ASIO_HAS_MOVE)+  template <typename S>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&>::overload == call_member,+    typename call_traits<S&>::result_type+  >::type+  operator()(S& s) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&>::is_noexcept))+  {+    return s.schedule();+  }++  template <typename S>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&>::overload == call_member,+    typename call_traits<const S&>::result_type+  >::type+  operator()(const S& s) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&>::is_noexcept))+  {+    return s.schedule();+  }++  template <typename S>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&>::overload == call_free,+    typename call_traits<S&>::result_type+  >::type+  operator()(S& s) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&>::is_noexcept))+  {+    return schedule(s);+  }++  template <typename S>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&>::overload == call_free,+    typename call_traits<const S&>::result_type+  >::type+  operator()(const S& s) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&>::is_noexcept))+  {+    return schedule(s);+  }+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_execution_schedule_fn+namespace asio {+namespace execution {+namespace {++static ASIO_CONSTEXPR const asio_execution_schedule_fn::impl&+  schedule = asio_execution_schedule_fn::static_instance<>::instance;++} // namespace++template <typename S>+struct can_schedule :+  integral_constant<bool,+    asio_execution_schedule_fn::call_traits<S>::overload !=+      asio_execution_schedule_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S>+constexpr bool can_schedule_v = can_schedule<S>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S>+struct is_nothrow_schedule :+  integral_constant<bool,+    asio_execution_schedule_fn::call_traits<S>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S>+constexpr bool is_nothrow_schedule_v+  = is_nothrow_schedule<S>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++} // namespace execution+} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_SCHEDULE_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/scheduler.hpp view
@@ -0,0 +1,86 @@+//+// execution/scheduler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_SCHEDULER_HPP+#define ASIO_EXECUTION_SCHEDULER_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/execution/schedule.hpp"+#include "asio/traits/equality_comparable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace execution {+namespace detail {++template <typename T>+struct is_scheduler_base :+  integral_constant<bool,+    is_copy_constructible<typename remove_cvref<T>::type>::value+      && traits::equality_comparable<typename remove_cvref<T>::type>::is_valid+  >+{+};++} // namespace detail++/// The is_scheduler trait detects whether a type T satisfies the+/// execution::scheduler concept.+/**+ * Class template @c is_scheduler is a type trait that is derived from @c+ * true_type if the type @c T meets the concept definition for a scheduler for+ * error type @c E, otherwise @c false_type.+ */+template <typename T>+struct is_scheduler :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  conditional<+    can_schedule<T>::value,+    detail::is_scheduler_base<T>,+    false_type+  >::type+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+ASIO_CONSTEXPR const bool is_scheduler_v = is_scheduler<T>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS)++template <typename T>+ASIO_CONCEPT scheduler = is_scheduler<T>::value;++#define ASIO_EXECUTION_SCHEDULER ::asio::execution::scheduler++#else // defined(ASIO_HAS_CONCEPTS)++#define ASIO_EXECUTION_SCHEDULER typename++#endif // defined(ASIO_HAS_CONCEPTS)++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_SCHEDULER_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/sender.hpp view
@@ -0,0 +1,311 @@+//+// execution/sender.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_SENDER_HPP+#define ASIO_EXECUTION_SENDER_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/execution/detail/as_invocable.hpp"+#include "asio/execution/detail/void_receiver.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/receiver.hpp"++#include "asio/detail/push_options.hpp"++#if defined(ASIO_HAS_ALIAS_TEMPLATES) \+  && defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  && defined(ASIO_HAS_DECLTYPE) \+  && !defined(ASIO_MSVC) || (_MSC_VER >= 1910)+# define ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT 1+#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)+       //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   && defined(ASIO_HAS_DECLTYPE)+       //   && !defined(ASIO_MSVC) || (_MSC_VER >= 1910)++namespace asio {+namespace execution {+namespace detail {++namespace sender_base_ns { struct sender_base {}; }++template <typename S, typename = void>+struct sender_traits_base+{+  typedef void asio_execution_sender_traits_base_is_unspecialised;+};++template <typename S>+struct sender_traits_base<S,+    typename enable_if<+      is_base_of<sender_base_ns::sender_base, S>::value+    >::type>+{+};++template <typename S, typename = void, typename = void, typename = void>+struct has_sender_types : false_type+{+};++#if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT)++template <+    template <+      template <typename...> class Tuple,+      template <typename...> class Variant+    > class>+struct has_value_types+{+  typedef void type;+};++template <+  template <+    template <typename...> class Variant+  > class>+struct has_error_types+{+  typedef void type;+};++template <typename S>+struct has_sender_types<S,+    typename has_value_types<S::template value_types>::type,+    typename has_error_types<S::template error_types>::type,+    typename conditional<S::sends_done, void, void>::type> : true_type+{+};++template <typename S>+struct sender_traits_base<S,+    typename enable_if<+      has_sender_types<S>::value+    >::type>+{+  template <+      template <typename...> class Tuple,+      template <typename...> class Variant>+  using value_types = typename S::template value_types<Tuple, Variant>;++  template <template <typename...> class Variant>+  using error_types = typename S::template error_types<Variant>;++  ASIO_STATIC_CONSTEXPR(bool, sends_done = S::sends_done);+};++#endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT)++template <typename S>+struct sender_traits_base<S,+    typename enable_if<+      !has_sender_types<S>::value+        && detail::is_executor_of_impl<S,+          as_invocable<void_receiver, S> >::value+    >::type>+{+#if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) \+  && defined(ASIO_HAS_STD_EXCEPTION_PTR)++  template <+      template <typename...> class Tuple,+      template <typename...> class Variant>+  using value_types = Variant<Tuple<>>;++  template <template <typename...> class Variant>+  using error_types = Variant<std::exception_ptr>;++  ASIO_STATIC_CONSTEXPR(bool, sends_done = true);++#endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT)+       //   && defined(ASIO_HAS_STD_EXCEPTION_PTR)+};++} // namespace detail++/// Base class used for tagging senders.+#if defined(GENERATING_DOCUMENTATION)+typedef unspecified sender_base;+#else // defined(GENERATING_DOCUMENTATION)+typedef detail::sender_base_ns::sender_base sender_base;+#endif // defined(GENERATING_DOCUMENTATION)++/// Traits for senders.+template <typename S>+struct sender_traits+#if !defined(GENERATING_DOCUMENTATION)+  : detail::sender_traits_base<S>+#endif // !defined(GENERATING_DOCUMENTATION)+{+};++namespace detail {++template <typename S, typename = void>+struct has_sender_traits : true_type+{+};++template <typename S>+struct has_sender_traits<S,+    typename enable_if<+      is_same<+        typename asio::execution::sender_traits<+          S>::asio_execution_sender_traits_base_is_unspecialised,+        void+      >::value+    >::type> : false_type+{+};++} // namespace detail++/// The is_sender trait detects whether a type T satisfies the+/// execution::sender concept.++/**+ * Class template @c is_sender is a type trait that is derived from @c+ * true_type if the type @c T meets the concept definition for a sender,+ * otherwise @c false_type.+ */+template <typename T>+struct is_sender :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  conditional<+    detail::has_sender_traits<typename remove_cvref<T>::type>::value,+    is_move_constructible<typename remove_cvref<T>::type>,+    false_type+  >::type+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+ASIO_CONSTEXPR const bool is_sender_v = is_sender<T>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS)++template <typename T>+ASIO_CONCEPT sender = is_sender<T>::value;++#define ASIO_EXECUTION_SENDER ::asio::execution::sender++#else // defined(ASIO_HAS_CONCEPTS)++#define ASIO_EXECUTION_SENDER typename++#endif // defined(ASIO_HAS_CONCEPTS)++template <typename S, typename R>+struct can_connect;++/// The is_sender_to trait detects whether a type T satisfies the+/// execution::sender_to concept for some receiver.+/**+ * Class template @c is_sender_to is a type trait that is derived from @c+ * true_type if the type @c T meets the concept definition for a sender+ * for some receiver type R, otherwise @c false.+ */+template <typename T, typename R>+struct is_sender_to :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  integral_constant<bool,+    is_sender<T>::value+      && is_receiver<R>::value+      && can_connect<T, R>::value+  >+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename R>+ASIO_CONSTEXPR const bool is_sender_to_v =+  is_sender_to<T, R>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS)++template <typename T, typename R>+ASIO_CONCEPT sender_to = is_sender_to<T, R>::value;++#define ASIO_EXECUTION_SENDER_TO(r) \+  ::asio::execution::sender_to<r>++#else // defined(ASIO_HAS_CONCEPTS)++#define ASIO_EXECUTION_SENDER_TO(r) typename++#endif // defined(ASIO_HAS_CONCEPTS)++/// The is_typed_sender trait detects whether a type T satisfies the+/// execution::typed_sender concept.+/**+ * Class template @c is_typed_sender is a type trait that is derived from @c+ * true_type if the type @c T meets the concept definition for a typed sender,+ * otherwise @c false.+ */+template <typename T>+struct is_typed_sender :+#if defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  integral_constant<bool,+    is_sender<T>::value+      && detail::has_sender_types<+        sender_traits<typename remove_cvref<T>::type> >::value+  >+#endif // defined(GENERATING_DOCUMENTATION)+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T>+ASIO_CONSTEXPR const bool is_typed_sender_v = is_typed_sender<T>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS)++template <typename T>+ASIO_CONCEPT typed_sender = is_typed_sender<T>::value;++#define ASIO_EXECUTION_TYPED_SENDER \+  ::asio::execution::typed_sender++#else // defined(ASIO_HAS_CONCEPTS)++#define ASIO_EXECUTION_TYPED_SENDER typename++#endif // defined(ASIO_HAS_CONCEPTS)++} // namespace execution+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/execution/connect.hpp"++#endif // ASIO_EXECUTION_SENDER_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/set_done.hpp view
@@ -0,0 +1,253 @@+//+// execution/set_done.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_SET_DONE_HPP+#define ASIO_EXECUTION_SET_DONE_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/traits/set_done_member.hpp"+#include "asio/traits/set_done_free.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++/// A customisation point that delivers a done notification to a receiver.+/**+ * The name <tt>execution::set_done</tt> denotes a customisation point object.+ * The expression <tt>execution::set_done(R)</tt> for some subexpression+ * <tt>R</tt> is expression-equivalent to:+ *+ * @li <tt>R.set_done()</tt>, if that expression is valid. If the function+ *   selected does not signal the receiver <tt>R</tt>'s done channel, the+ *   program is ill-formed with no diagnostic required.+ *+ * @li Otherwise, <tt>set_done(R)</tt>, if that expression is valid, with+ * overload resolution performed in a context that includes the declaration+ * <tt>void set_done();</tt> and that does not include a declaration of+ * <tt>execution::set_done</tt>. If the function selected by overload+ * resolution does not signal the receiver <tt>R</tt>'s done channel, the+ * program is ill-formed with no diagnostic required.+ *+ * @li Otherwise, <tt>execution::set_done(R)</tt> is ill-formed.+ */+inline constexpr unspecified set_done = unspecified;++/// A type trait that determines whether a @c set_done expression is+/// well-formed.+/**+ * Class template @c can_set_done is a trait that is derived from+ * @c true_type if the expression <tt>execution::set_done(std::declval<R>(),+ * std::declval<E>())</tt> is well formed; otherwise @c false_type.+ */+template <typename R>+struct can_set_done :+  integral_constant<bool, automatically_determined>+{+};++} // namespace execution+} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_execution_set_done_fn {++using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::traits::set_done_free;+using asio::traits::set_done_member;++void set_done();++enum overload_type+{+  call_member,+  call_free,+  ill_formed+};++template <typename R, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename R>+struct call_traits<R,+  typename enable_if<+    (+      set_done_member<R>::is_valid+    )+  >::type> :+  set_done_member<R>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename R>+struct call_traits<R,+  typename enable_if<+    (+      !set_done_member<R>::is_valid+      &&+      set_done_free<R>::is_valid+    )+  >::type> :+  set_done_free<R>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++struct impl+{+#if defined(ASIO_HAS_MOVE)+  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R>::overload == call_member,+    typename call_traits<R>::result_type+  >::type+  operator()(R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R>::is_noexcept))+  {+    return ASIO_MOVE_CAST(R)(r).set_done();+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R>::overload == call_free,+    typename call_traits<R>::result_type+  >::type+  operator()(R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R>::is_noexcept))+  {+    return set_done(ASIO_MOVE_CAST(R)(r));+  }+#else // defined(ASIO_HAS_MOVE)+  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&>::overload == call_member,+    typename call_traits<R&>::result_type+  >::type+  operator()(R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&>::is_noexcept))+  {+    return r.set_done();+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&>::overload == call_member,+    typename call_traits<const R&>::result_type+  >::type+  operator()(const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&>::is_noexcept))+  {+    return r.set_done();+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&>::overload == call_free,+    typename call_traits<R&>::result_type+  >::type+  operator()(R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&>::is_noexcept))+  {+    return set_done(r);+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&>::overload == call_free,+    typename call_traits<const R&>::result_type+  >::type+  operator()(const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&>::is_noexcept))+  {+    return set_done(r);+  }+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_execution_set_done_fn+namespace asio {+namespace execution {+namespace {++static ASIO_CONSTEXPR const asio_execution_set_done_fn::impl&+  set_done = asio_execution_set_done_fn::static_instance<>::instance;++} // namespace++template <typename R>+struct can_set_done :+  integral_constant<bool,+    asio_execution_set_done_fn::call_traits<R>::overload !=+      asio_execution_set_done_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R>+constexpr bool can_set_done_v = can_set_done<R>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R>+struct is_nothrow_set_done :+  integral_constant<bool,+    asio_execution_set_done_fn::call_traits<R>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R>+constexpr bool is_nothrow_set_done_v+  = is_nothrow_set_done<R>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++} // namespace execution+} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_SET_DONE_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/set_error.hpp view
@@ -0,0 +1,253 @@+//+// execution/set_error.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_SET_ERROR_HPP+#define ASIO_EXECUTION_SET_ERROR_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/traits/set_error_member.hpp"+#include "asio/traits/set_error_free.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++/// A customisation point that delivers an error notification to a receiver.+/**+ * The name <tt>execution::set_error</tt> denotes a customisation point object.+ * The expression <tt>execution::set_error(R, E)</tt> for some subexpressions+ * <tt>R</tt> and <tt>E</tt> are expression-equivalent to:+ *+ * @li <tt>R.set_error(E)</tt>, if that expression is valid. If the function+ *   selected does not send the error <tt>E</tt> to the receiver <tt>R</tt>'s+ *   error channel, the program is ill-formed with no diagnostic required.+ *+ * @li Otherwise, <tt>set_error(R, E)</tt>, if that expression is valid, with+ *   overload resolution performed in a context that includes the declaration+ *   <tt>void set_error();</tt> and that does not include a declaration of+ *   <tt>execution::set_error</tt>. If the function selected by overload+ *   resolution does not send the error <tt>E</tt> to the receiver <tt>R</tt>'s+ *   error channel, the program is ill-formed with no diagnostic required.+ *+ * @li Otherwise, <tt>execution::set_error(R, E)</tt> is ill-formed.+ */+inline constexpr unspecified set_error = unspecified;++/// A type trait that determines whether a @c set_error expression is+/// well-formed.+/**+ * Class template @c can_set_error is a trait that is derived from+ * @c true_type if the expression <tt>execution::set_error(std::declval<R>(),+ * std::declval<E>())</tt> is well formed; otherwise @c false_type.+ */+template <typename R, typename E>+struct can_set_error :+  integral_constant<bool, automatically_determined>+{+};++} // namespace execution+} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_execution_set_error_fn {++using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::traits::set_error_free;+using asio::traits::set_error_member;++void set_error();++enum overload_type+{+  call_member,+  call_free,+  ill_formed+};++template <typename R, typename E, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename R, typename E>+struct call_traits<R, void(E),+  typename enable_if<+    (+      set_error_member<R, E>::is_valid+    )+  >::type> :+  set_error_member<R, E>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename R, typename E>+struct call_traits<R, void(E),+  typename enable_if<+    (+      !set_error_member<R, E>::is_valid+      &&+      set_error_free<R, E>::is_valid+    )+  >::type> :+  set_error_free<R, E>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++struct impl+{+#if defined(ASIO_HAS_MOVE)+  template <typename R, typename E>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R, void(E)>::overload == call_member,+    typename call_traits<R, void(E)>::result_type+  >::type+  operator()(R&& r, E&& e) const+    ASIO_NOEXCEPT_IF((+      call_traits<R, void(E)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(R)(r).set_error(ASIO_MOVE_CAST(E)(e));+  }++  template <typename R, typename E>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R, void(E)>::overload == call_free,+    typename call_traits<R, void(E)>::result_type+  >::type+  operator()(R&& r, E&& e) const+    ASIO_NOEXCEPT_IF((+      call_traits<R, void(E)>::is_noexcept))+  {+    return set_error(ASIO_MOVE_CAST(R)(r), ASIO_MOVE_CAST(E)(e));+  }+#else // defined(ASIO_HAS_MOVE)+  template <typename R, typename E>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&, void(const E&)>::overload == call_member,+    typename call_traits<R&, void(const E&)>::result_type+  >::type+  operator()(R& r, const E& e) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&, void(const E&)>::is_noexcept))+  {+    return r.set_error(e);+  }++  template <typename R, typename E>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&, void(const E&)>::overload == call_member,+    typename call_traits<const R&, void(const E&)>::result_type+  >::type+  operator()(const R& r, const E& e) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&, void(const E&)>::is_noexcept))+  {+    return r.set_error(e);+  }++  template <typename R, typename E>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&, void(const E&)>::overload == call_free,+    typename call_traits<R&, void(const E&)>::result_type+  >::type+  operator()(R& r, const E& e) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&, void(const E&)>::is_noexcept))+  {+    return set_error(r, e);+  }++  template <typename R, typename E>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&, void(const E&)>::overload == call_free,+    typename call_traits<const R&, void(const E&)>::result_type+  >::type+  operator()(const R& r, const E& e) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&, void(const E&)>::is_noexcept))+  {+    return set_error(r, e);+  }+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_execution_set_error_fn+namespace asio {+namespace execution {+namespace {++static ASIO_CONSTEXPR const asio_execution_set_error_fn::impl&+  set_error = asio_execution_set_error_fn::static_instance<>::instance;++} // namespace++template <typename R, typename E>+struct can_set_error :+  integral_constant<bool,+    asio_execution_set_error_fn::call_traits<R, void(E)>::overload !=+      asio_execution_set_error_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R, typename E>+constexpr bool can_set_error_v = can_set_error<R, E>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R, typename E>+struct is_nothrow_set_error :+  integral_constant<bool,+    asio_execution_set_error_fn::call_traits<R, void(E)>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R, typename E>+constexpr bool is_nothrow_set_error_v+  = is_nothrow_set_error<R, E>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++} // namespace execution+} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_SET_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/set_value.hpp view
@@ -0,0 +1,486 @@+//+// execution/set_value.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_SET_VALUE_HPP+#define ASIO_EXECUTION_SET_VALUE_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/traits/set_value_member.hpp"+#include "asio/traits/set_value_free.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++/// A customisation point that delivers a value to a receiver.+/**+ * The name <tt>execution::set_value</tt> denotes a customisation point object.+ * The expression <tt>execution::set_value(R, Vs...)</tt> for some+ * subexpressions <tt>R</tt> and <tt>Vs...</tt> is expression-equivalent to:+ *+ * @li <tt>R.set_value(Vs...)</tt>, if that expression is valid. If the+ *   function selected does not send the value(s) <tt>Vs...</tt> to the receiver+ *   <tt>R</tt>'s value channel, the program is ill-formed with no diagnostic+ *   required.+ *+ * @li Otherwise, <tt>set_value(R, Vs...)</tt>, if that expression is valid,+ *   with overload resolution performed in a context that includes the+ *   declaration <tt>void set_value();</tt> and that does not include a+ *   declaration of <tt>execution::set_value</tt>. If the function selected by+ *   overload resolution does not send the value(s) <tt>Vs...</tt> to the+ *   receiver <tt>R</tt>'s value channel, the program is ill-formed with no+ *   diagnostic required.+ *+ * @li Otherwise, <tt>execution::set_value(R, Vs...)</tt> is ill-formed.+ */+inline constexpr unspecified set_value = unspecified;++/// A type trait that determines whether a @c set_value expression is+/// well-formed.+/**+ * Class template @c can_set_value is a trait that is derived from+ * @c true_type if the expression <tt>execution::set_value(std::declval<R>(),+ * std::declval<Vs>()...)</tt> is well formed; otherwise @c false_type.+ */+template <typename R, typename... Vs>+struct can_set_value :+  integral_constant<bool, automatically_determined>+{+};++} // namespace execution+} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_execution_set_value_fn {++using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::traits::set_value_free;+using asio::traits::set_value_member;++void set_value();++enum overload_type+{+  call_member,+  call_free,+  ill_formed+};++template <typename R, typename Vs, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename R, typename Vs>+struct call_traits<R, Vs,+  typename enable_if<+    (+      set_value_member<R, Vs>::is_valid+    )+  >::type> :+  set_value_member<R, Vs>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename R, typename Vs>+struct call_traits<R, Vs,+  typename enable_if<+    (+      !set_value_member<R, Vs>::is_valid+      &&+      set_value_free<R, Vs>::is_valid+    )+  >::type> :+  set_value_free<R, Vs>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++struct impl+{+#if defined(ASIO_HAS_MOVE)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename R, typename... Vs>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R, void(Vs...)>::overload == call_member,+    typename call_traits<R, void(Vs...)>::result_type+  >::type+  operator()(R&& r, Vs&&... v) const+    ASIO_NOEXCEPT_IF((+      call_traits<R, void(Vs...)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(R)(r).set_value(ASIO_MOVE_CAST(Vs)(v)...);+  }++  template <typename R, typename... Vs>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R, void(Vs...)>::overload == call_free,+    typename call_traits<R, void(Vs...)>::result_type+  >::type+  operator()(R&& r, Vs&&... v) const+    ASIO_NOEXCEPT_IF((+      call_traits<R, void(Vs...)>::is_noexcept))+  {+    return set_value(ASIO_MOVE_CAST(R)(r),+        ASIO_MOVE_CAST(Vs)(v)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R, void()>::overload == call_member,+    typename call_traits<R, void()>::result_type+  >::type+  operator()(R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R, void()>::is_noexcept))+  {+    return ASIO_MOVE_CAST(R)(r).set_value();+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R, void()>::overload == call_free,+    typename call_traits<R, void()>::result_type+  >::type+  operator()(R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R, void()>::is_noexcept))+  {+    return set_value(ASIO_MOVE_CAST(R)(r));+  }++#define ASIO_PRIVATE_SET_VALUE_CALL_DEF(n) \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  ASIO_CONSTEXPR typename enable_if< \+    call_traits<R, \+      void(ASIO_VARIADIC_TARGS(n))>::overload == call_member, \+    typename call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::result_type \+  >::type \+  operator()(R&& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    ASIO_NOEXCEPT_IF(( \+      call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \+  { \+    return ASIO_MOVE_CAST(R)(r).set_value( \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  ASIO_CONSTEXPR typename enable_if< \+    call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::overload == call_free, \+    typename call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::result_type \+  >::type \+  operator()(R&& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    ASIO_NOEXCEPT_IF(( \+      call_traits<R, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \+  { \+    return set_value(ASIO_MOVE_CAST(R)(r), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_CALL_DEF)+#undef ASIO_PRIVATE_SET_VALUE_CALL_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#else // defined(ASIO_HAS_MOVE)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename R, typename... Vs>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&, void(const Vs&...)>::overload == call_member,+    typename call_traits<R&, void(const Vs&...)>::result_type+  >::type+  operator()(R& r, const Vs&... v) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&, void(const Vs&...)>::is_noexcept))+  {+    return r.set_value(v...);+  }++  template <typename R, typename... Vs>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&, void(const Vs&...)>::overload == call_member,+    typename call_traits<const R&, void(const Vs&...)>::result_type+  >::type+  operator()(const R& r, const Vs&... v) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&, void(const Vs&...)>::is_noexcept))+  {+    return r.set_value(v...);+  }++  template <typename R, typename... Vs>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&, void(const Vs&...)>::overload == call_free,+    typename call_traits<R&, void(const Vs&...)>::result_type+  >::type+  operator()(R& r, const Vs&... v) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&, void(const Vs&...)>::is_noexcept))+  {+    return set_value(r, v...);+  }++  template <typename R, typename... Vs>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&, void(const Vs&...)>::overload == call_free,+    typename call_traits<const R&, void(const Vs&...)>::result_type+  >::type+  operator()(const R& r, const Vs&... v) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&, void(const Vs&...)>::is_noexcept))+  {+    return set_value(r, v...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&, void()>::overload == call_member,+    typename call_traits<R&, void()>::result_type+  >::type+  operator()(R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&, void()>::is_noexcept))+  {+    return r.set_value();+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&, void()>::overload == call_member,+    typename call_traits<const R&, void()>::result_type+  >::type+  operator()(const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&, void()>::is_noexcept))+  {+    return r.set_value();+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&, void()>::overload == call_free,+    typename call_traits<R&, void()>::result_type+  >::type+  operator()(R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&, void()>::is_noexcept))+  {+    return set_value(r);+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&, void()>::overload == call_free,+    typename call_traits<const R&, void()>::result_type+  >::type+  operator()(const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&, void()>::is_noexcept))+  {+    return set_value(r);+  }++#define ASIO_PRIVATE_SET_VALUE_CALL_DEF(n) \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  ASIO_CONSTEXPR typename enable_if< \+    call_traits<R&, \+      void(ASIO_VARIADIC_TARGS(n))>::overload == call_member, \+    typename call_traits<R&, void(ASIO_VARIADIC_TARGS(n))>::result_type \+  >::type \+  operator()(R& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    ASIO_NOEXCEPT_IF(( \+      call_traits<R&, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \+  { \+    return r.set_value(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  ASIO_CONSTEXPR typename enable_if< \+    call_traits<const R&, \+      void(ASIO_VARIADIC_TARGS(n))>::overload == call_member, \+    typename call_traits<const R&, \+      void(ASIO_VARIADIC_TARGS(n))>::result_type \+  >::type \+  operator()(const R& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    ASIO_NOEXCEPT_IF(( \+      call_traits<const R&, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \+  { \+    return r.set_value(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  ASIO_CONSTEXPR typename enable_if< \+    call_traits<R&, \+      void(ASIO_VARIADIC_TARGS(n))>::overload == call_free, \+    typename call_traits<R&, void(ASIO_VARIADIC_TARGS(n))>::result_type \+  >::type \+  operator()(R& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    ASIO_NOEXCEPT_IF(( \+      call_traits<R&, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \+  { \+    return set_value(r, ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  ASIO_CONSTEXPR typename enable_if< \+    call_traits<const R&, \+      void(ASIO_VARIADIC_TARGS(n))>::overload == call_free, \+    typename call_traits<const R&, \+      void(ASIO_VARIADIC_TARGS(n))>::result_type \+  >::type \+  operator()(const R& r, ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    ASIO_NOEXCEPT_IF(( \+      call_traits<const R&, void(ASIO_VARIADIC_TARGS(n))>::is_noexcept)) \+  { \+    return set_value(r, ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_CALL_DEF)+#undef ASIO_PRIVATE_SET_VALUE_CALL_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#endif // defined(ASIO_HAS_MOVE)+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_execution_set_value_fn+namespace asio {+namespace execution {+namespace {++static ASIO_CONSTEXPR const asio_execution_set_value_fn::impl&+  set_value = asio_execution_set_value_fn::static_instance<>::instance;++} // namespace++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename R, typename... Vs>+struct can_set_value :+  integral_constant<bool,+    asio_execution_set_value_fn::call_traits<R, void(Vs...)>::overload !=+      asio_execution_set_value_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R, typename... Vs>+constexpr bool can_set_value_v = can_set_value<R, Vs...>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R, typename... Vs>+struct is_nothrow_set_value :+  integral_constant<bool,+    asio_execution_set_value_fn::call_traits<R, void(Vs...)>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R, typename... Vs>+constexpr bool is_nothrow_set_value_v+  = is_nothrow_set_value<R, Vs...>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename R, typename = void,+    typename = void, typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void, typename = void>+struct can_set_value;++template <typename R, typename = void,+    typename = void, typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void, typename = void>+struct is_nothrow_set_value;++template <typename R>+struct can_set_value<R> :+  integral_constant<bool,+    asio_execution_set_value_fn::call_traits<R, void()>::overload !=+      asio_execution_set_value_fn::ill_formed>+{+};++template <typename R>+struct is_nothrow_set_value<R> :+  integral_constant<bool,+    asio_execution_set_value_fn::call_traits<R, void()>::is_noexcept>+{+};++#define ASIO_PRIVATE_SET_VALUE_TRAITS_DEF(n) \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct can_set_value<R, ASIO_VARIADIC_TARGS(n)> : \+    integral_constant<bool, \+      asio_execution_set_value_fn::call_traits<R, \+        void(ASIO_VARIADIC_TARGS(n))>::overload != \+          asio_execution_set_value_fn::ill_formed> \+  { \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct is_nothrow_set_value<R, ASIO_VARIADIC_TARGS(n)> : \+    integral_constant<bool, \+      asio_execution_set_value_fn::call_traits<R, \+        void(ASIO_VARIADIC_TARGS(n))>::is_noexcept> \+  { \+  }; \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_TRAITS_DEF)+#undef ASIO_PRIVATE_SET_VALUE_TRAITS_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace execution+} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_SET_VALUE_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/start.hpp view
@@ -0,0 +1,250 @@+//+// execution/start.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_START_HPP+#define ASIO_EXECUTION_START_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/traits/start_member.hpp"+#include "asio/traits/start_free.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++/// A customisation point that notifies an operation state object to start+/// its associated operation.+/**+ * The name <tt>execution::start</tt> denotes a customisation point object.+ * The expression <tt>execution::start(R)</tt> for some subexpression+ * <tt>R</tt> is expression-equivalent to:+ *+ * @li <tt>R.start()</tt>, if that expression is valid.+ *+ * @li Otherwise, <tt>start(R)</tt>, if that expression is valid, with+ * overload resolution performed in a context that includes the declaration+ * <tt>void start();</tt> and that does not include a declaration of+ * <tt>execution::start</tt>.+ *+ * @li Otherwise, <tt>execution::start(R)</tt> is ill-formed.+ */+inline constexpr unspecified start = unspecified;++/// A type trait that determines whether a @c start expression is+/// well-formed.+/**+ * Class template @c can_start is a trait that is derived from+ * @c true_type if the expression <tt>execution::start(std::declval<R>(),+ * std::declval<E>())</tt> is well formed; otherwise @c false_type.+ */+template <typename R>+struct can_start :+  integral_constant<bool, automatically_determined>+{+};++} // namespace execution+} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_execution_start_fn {++using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::traits::start_free;+using asio::traits::start_member;++void start();++enum overload_type+{+  call_member,+  call_free,+  ill_formed+};++template <typename R, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename R>+struct call_traits<R,+  typename enable_if<+    (+      start_member<R>::is_valid+    )+  >::type> :+  start_member<R>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename R>+struct call_traits<R,+  typename enable_if<+    (+      !start_member<R>::is_valid+      &&+      start_free<R>::is_valid+    )+  >::type> :+  start_free<R>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++struct impl+{+#if defined(ASIO_HAS_MOVE)+  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R>::overload == call_member,+    typename call_traits<R>::result_type+  >::type+  operator()(R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R>::is_noexcept))+  {+    return ASIO_MOVE_CAST(R)(r).start();+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R>::overload == call_free,+    typename call_traits<R>::result_type+  >::type+  operator()(R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R>::is_noexcept))+  {+    return start(ASIO_MOVE_CAST(R)(r));+  }+#else // defined(ASIO_HAS_MOVE)+  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&>::overload == call_member,+    typename call_traits<R&>::result_type+  >::type+  operator()(R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&>::is_noexcept))+  {+    return r.start();+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&>::overload == call_member,+    typename call_traits<const R&>::result_type+  >::type+  operator()(const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&>::is_noexcept))+  {+    return r.start();+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<R&>::overload == call_free,+    typename call_traits<R&>::result_type+  >::type+  operator()(R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<R&>::is_noexcept))+  {+    return start(r);+  }++  template <typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const R&>::overload == call_free,+    typename call_traits<const R&>::result_type+  >::type+  operator()(const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const R&>::is_noexcept))+  {+    return start(r);+  }+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_execution_start_fn+namespace asio {+namespace execution {+namespace {++static ASIO_CONSTEXPR const asio_execution_start_fn::impl&+  start = asio_execution_start_fn::static_instance<>::instance;++} // namespace++template <typename R>+struct can_start :+  integral_constant<bool,+    asio_execution_start_fn::call_traits<R>::overload !=+      asio_execution_start_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R>+constexpr bool can_start_v = can_start<R>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R>+struct is_nothrow_start :+  integral_constant<bool,+    asio_execution_start_fn::call_traits<R>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename R>+constexpr bool is_nothrow_start_v+  = is_nothrow_start<R>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++} // namespace execution+} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_START_HPP
+ link/modules/asio-standalone/asio/include/asio/execution/submit.hpp view
@@ -0,0 +1,450 @@+//+// execution/submit.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_SUBMIT_HPP+#define ASIO_EXECUTION_SUBMIT_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/execution/detail/submit_receiver.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/receiver.hpp"+#include "asio/execution/sender.hpp"+#include "asio/execution/start.hpp"+#include "asio/traits/submit_member.hpp"+#include "asio/traits/submit_free.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace execution {++/// A customisation point that submits a sender to a receiver.+/**+ * The name <tt>execution::submit</tt> denotes a customisation point object. For+ * some subexpressions <tt>s</tt> and <tt>r</tt>, let <tt>S</tt> be a type such+ * that <tt>decltype((s))</tt> is <tt>S</tt> and let <tt>R</tt> be a type such+ * that <tt>decltype((r))</tt> is <tt>R</tt>. The expression+ * <tt>execution::submit(s, r)</tt> is ill-formed if <tt>sender_to<S, R></tt> is+ * not <tt>true</tt>. Otherwise, it is expression-equivalent to:+ *+ * @li <tt>s.submit(r)</tt>, if that expression is valid and <tt>S</tt> models+ *   <tt>sender</tt>. If the function selected does not submit the receiver+ *   object <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with+ *   no diagnostic required.+ *+ * @li Otherwise, <tt>submit(s, r)</tt>, if that expression is valid and+ *   <tt>S</tt> models <tt>sender</tt>, with overload resolution performed in a+ *   context that includes the declaration <tt>void submit();</tt> and that does+ *   not include a declaration of <tt>execution::submit</tt>. If the function+ *   selected by overload resolution does not submit the receiver object+ *   <tt>r</tt> via the sender <tt>s</tt>, the program is ill-formed with no+ *   diagnostic required.+ *+ * @li Otherwise, <tt>execution::start((new submit_receiver<S,+ *   R>{s,r})->state_)</tt>, where <tt>submit_receiver</tt> is an+ *   implementation-defined class template equivalent to:+ *   @code template<class S, class R>+ *   struct submit_receiver {+ *     struct wrap {+ *       submit_receiver * p_;+ *       template<class...As>+ *         requires receiver_of<R, As...>+ *       void set_value(As&&... as) &&+ *         noexcept(is_nothrow_receiver_of_v<R, As...>) {+ *         execution::set_value(std::move(p_->r_), (As&&) as...);+ *         delete p_;+ *       }+ *       template<class E>+ *         requires receiver<R, E>+ *       void set_error(E&& e) && noexcept {+ *         execution::set_error(std::move(p_->r_), (E&&) e);+ *         delete p_;+ *       }+ *       void set_done() && noexcept {+ *         execution::set_done(std::move(p_->r_));+ *         delete p_;+ *       }+ *     };+ *     remove_cvref_t<R> r_;+ *     connect_result_t<S, wrap> state_;+ *     submit_receiver(S&& s, R&& r)+ *       : r_((R&&) r)+ *       , state_(execution::connect((S&&) s, wrap{this})) {}+ *   };+ *   @endcode+ */+inline constexpr unspecified submit = unspecified;++/// A type trait that determines whether a @c submit expression is+/// well-formed.+/**+ * Class template @c can_submit is a trait that is derived from+ * @c true_type if the expression <tt>execution::submit(std::declval<R>(),+ * std::declval<E>())</tt> is well formed; otherwise @c false_type.+ */+template <typename S, typename R>+struct can_submit :+  integral_constant<bool, automatically_determined>+{+};++} // namespace execution+} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_execution_submit_fn {++using asio::declval;+using asio::enable_if;+using asio::execution::is_sender_to;+using asio::traits::submit_free;+using asio::traits::submit_member;++void submit();++enum overload_type+{+  call_member,+  call_free,+  adapter,+  ill_formed+};++template <typename S, typename R, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename S, typename R>+struct call_traits<S, void(R),+  typename enable_if<+    (+      submit_member<S, R>::is_valid+      &&+      is_sender_to<S, R>::value+    )+  >::type> :+  submit_member<S, R>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename S, typename R>+struct call_traits<S, void(R),+  typename enable_if<+    (+      !submit_member<S, R>::is_valid+      &&+      submit_free<S, R>::is_valid+      &&+      is_sender_to<S, R>::value+    )+  >::type> :+  submit_free<S, R>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++template <typename S, typename R>+struct call_traits<S, void(R),+  typename enable_if<+    (+      !submit_member<S, R>::is_valid+      &&+      !submit_free<S, R>::is_valid+      &&+      is_sender_to<S, R>::value+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++struct impl+{+#if defined(ASIO_HAS_MOVE)+  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(R)>::overload == call_member,+    typename call_traits<S, void(R)>::result_type+  >::type+  operator()(S&& s, R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(R)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(S)(s).submit(ASIO_MOVE_CAST(R)(r));+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(R)>::overload == call_free,+    typename call_traits<S, void(R)>::result_type+  >::type+  operator()(S&& s, R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(R)>::is_noexcept))+  {+    return submit(ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r));+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S, void(R)>::overload == adapter,+    typename call_traits<S, void(R)>::result_type+  >::type+  operator()(S&& s, R&& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S, void(R)>::is_noexcept))+  {+    return asio::execution::start(+        (new asio::execution::detail::submit_receiver<S, R>(+          ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r)))->state_);+  }+#else // defined(ASIO_HAS_MOVE)+  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(R&)>::overload == call_member,+    typename call_traits<S&, void(R&)>::result_type+  >::type+  operator()(S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(R&)>::is_noexcept))+  {+    return s.submit(r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(R&)>::overload == call_member,+    typename call_traits<const S&, void(R&)>::result_type+  >::type+  operator()(const S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(R&)>::is_noexcept))+  {+    return s.submit(r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(R&)>::overload == call_free,+    typename call_traits<S&, void(R&)>::result_type+  >::type+  operator()(S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(R&)>::is_noexcept))+  {+    return submit(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(R&)>::overload == call_free,+    typename call_traits<const S&, void(R&)>::result_type+  >::type+  operator()(const S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(R&)>::is_noexcept))+  {+    return submit(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(R&)>::overload == adapter,+    typename call_traits<S&, void(R&)>::result_type+  >::type+  operator()(S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(R&)>::is_noexcept))+  {+    return asio::execution::start(+        (new asio::execution::detail::submit_receiver<+          S&, R&>(s, r))->state_);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(R&)>::overload == adapter,+    typename call_traits<const S&, void(R&)>::result_type+  >::type+  operator()(const S& s, R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(R&)>::is_noexcept))+  {+    asio::execution::start(+        (new asio::execution::detail::submit_receiver<+          const S&, R&>(s, r))->state_);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(const R&)>::overload == call_member,+    typename call_traits<S&, void(const R&)>::result_type+  >::type+  operator()(S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(const R&)>::is_noexcept))+  {+    return s.submit(r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(const R&)>::overload == call_member,+    typename call_traits<const S&, void(const R&)>::result_type+  >::type+  operator()(const S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(const R&)>::is_noexcept))+  {+    return s.submit(r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(const R&)>::overload == call_free,+    typename call_traits<S&, void(const R&)>::result_type+  >::type+  operator()(S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(const R&)>::is_noexcept))+  {+    return submit(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(const R&)>::overload == call_free,+    typename call_traits<const S&, void(const R&)>::result_type+  >::type+  operator()(const S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(const R&)>::is_noexcept))+  {+    return submit(s, r);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<S&, void(const R&)>::overload == adapter,+    typename call_traits<S&, void(const R&)>::result_type+  >::type+  operator()(S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<S&, void(const R&)>::is_noexcept))+  {+    asio::execution::start(+        (new asio::execution::detail::submit_receiver<+          S&, const R&>(s, r))->state_);+  }++  template <typename S, typename R>+  ASIO_CONSTEXPR typename enable_if<+    call_traits<const S&, void(const R&)>::overload == adapter,+    typename call_traits<const S&, void(const R&)>::result_type+  >::type+  operator()(const S& s, const R& r) const+    ASIO_NOEXCEPT_IF((+      call_traits<const S&, void(const R&)>::is_noexcept))+  {+    asio::execution::start(+        (new asio::execution::detail::submit_receiver<+          const S&, const R&>(s, r))->state_);+  }+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_execution_submit_fn+namespace asio {+namespace execution {+namespace {++static ASIO_CONSTEXPR const asio_execution_submit_fn::impl&+  submit = asio_execution_submit_fn::static_instance<>::instance;++} // namespace++template <typename S, typename R>+struct can_submit :+  integral_constant<bool,+    asio_execution_submit_fn::call_traits<S, void(R)>::overload !=+      asio_execution_submit_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename R>+constexpr bool can_submit_v = can_submit<S, R>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename R>+struct is_nothrow_submit :+  integral_constant<bool,+    asio_execution_submit_fn::call_traits<S, void(R)>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename R>+constexpr bool is_nothrow_submit_v+  = is_nothrow_submit<S, R>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename S, typename R>+struct submit_result+{+  typedef typename asio_execution_submit_fn::call_traits<+      S, void(R)>::result_type type;+};++namespace detail {++template <typename S, typename R>+void submit_helper(ASIO_MOVE_ARG(S) s, ASIO_MOVE_ARG(R) r)+{+  execution::submit(ASIO_MOVE_CAST(S)(s), ASIO_MOVE_CAST(R)(r));+}++} // namespace detail+} // namespace execution+} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXECUTION_SUBMIT_HPP
+ link/modules/asio-standalone/asio/include/asio/execution_context.hpp view
@@ -0,0 +1,412 @@+//+// execution_context.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTION_CONTEXT_HPP+#define ASIO_EXECUTION_CONTEXT_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 <stdexcept>+#include <typeinfo>+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++class execution_context;+class io_context;++#if !defined(GENERATING_DOCUMENTATION)+template <typename Service> Service& use_service(execution_context&);+template <typename Service> Service& use_service(io_context&);+template <typename Service> void add_service(execution_context&, Service*);+template <typename Service> bool has_service(execution_context&);+#endif // !defined(GENERATING_DOCUMENTATION)++namespace detail { class service_registry; }++/// A context for function object execution.+/**+ * An execution context represents a place where function objects will be+ * executed. An @c io_context is an example of an execution context.+ *+ * @par The execution_context class and services+ *+ * Class execution_context implements an extensible, type-safe, polymorphic set+ * of services, indexed by service type.+ *+ * Services exist to manage the resources that are shared across an execution+ * context. For example, timers may be implemented in terms of a single timer+ * queue, and this queue would be stored in a service.+ *+ * Access to the services of an execution_context is via three function+ * templates, use_service(), add_service() and has_service().+ *+ * In a call to @c use_service<Service>(), the type argument chooses a service,+ * making available all members of the named type. If @c Service is not present+ * in an execution_context, an object of type @c Service is created and added+ * to the execution_context. A C++ program can check if an execution_context+ * implements a particular service with the function template @c+ * has_service<Service>().+ *+ * Service objects may be explicitly added to an execution_context using the+ * function template @c add_service<Service>(). If the @c Service is already+ * present, the service_already_exists exception is thrown. If the owner of the+ * service is not the same object as the execution_context parameter, the+ * invalid_service_owner exception is thrown.+ *+ * Once a service reference is obtained from an execution_context object by+ * calling use_service(), that reference remains usable as long as the owning+ * execution_context object exists.+ *+ * All service implementations have execution_context::service as a public base+ * class. Custom services may be implemented by deriving from this class and+ * then added to an execution_context using the facilities described above.+ *+ * @par The execution_context as a base class+ *+ * Class execution_context may be used only as a base class for concrete+ * execution context types. The @c io_context is an example of such a derived+ * type.+ *+ * On destruction, a class that is derived from execution_context must perform+ * <tt>execution_context::shutdown()</tt> followed by+ * <tt>execution_context::destroy()</tt>.+ *+ * This destruction sequence permits programs to simplify their resource+ * management by using @c shared_ptr<>. Where an object's lifetime is tied to+ * the lifetime of a connection (or some other sequence of asynchronous+ * operations), a @c shared_ptr to the object would be bound into the handlers+ * for all asynchronous operations associated with it. This works as follows:+ *+ * @li When a single connection ends, all associated asynchronous operations+ * complete. The corresponding handler objects are destroyed, and all @c+ * shared_ptr references to the objects are destroyed.+ *+ * @li To shut down the whole program, the io_context function stop() is called+ * to terminate any run() calls as soon as possible. The io_context destructor+ * calls @c shutdown() and @c destroy() to destroy all pending handlers,+ * causing all @c shared_ptr references to all connection objects to be+ * destroyed.+ */+class execution_context+  : private noncopyable+{+public:+  class id;+  class service;++public:+  /// Constructor.+  ASIO_DECL execution_context();++  /// Destructor.+  ASIO_DECL ~execution_context();++protected:+  /// Shuts down all services in the context.+  /**+   * This function is implemented as follows:+   *+   * @li For each service object @c svc in the execution_context set, in+   * reverse order of the beginning of service object lifetime, performs @c+   * svc->shutdown().+   */+  ASIO_DECL void shutdown();++  /// Destroys all services in the context.+  /**+   * This function is implemented as follows:+   *+   * @li For each service object @c svc in the execution_context set, in+   * reverse order * of the beginning of service object lifetime, performs+   * <tt>delete static_cast<execution_context::service*>(svc)</tt>.+   */+  ASIO_DECL void destroy();++public:+  /// Fork-related event notifications.+  enum fork_event+  {+    /// Notify the context that the process is about to fork.+    fork_prepare,++    /// Notify the context that the process has forked and is the parent.+    fork_parent,++    /// Notify the context that the process has forked and is the child.+    fork_child+  };++  /// Notify the execution_context of a fork-related event.+  /**+   * This function is used to inform the execution_context that the process is+   * about to fork, or has just forked. This allows the execution_context, and+   * the services it contains, to perform any necessary housekeeping to ensure+   * correct operation following a fork.+   *+   * This function must not be called while any other execution_context+   * function, or any function associated with the execution_context's derived+   * class, is being called in another thread. It is, however, safe to call+   * this function from within a completion handler, provided no other thread+   * is accessing the execution_context or its derived class.+   *+   * @param event A fork-related event.+   *+   * @throws asio::system_error Thrown on failure. If the notification+   * fails the execution_context object should no longer be used and should be+   * destroyed.+   *+   * @par Example+   * The following code illustrates how to incorporate the notify_fork()+   * function:+   * @code my_execution_context.notify_fork(execution_context::fork_prepare);+   * if (fork() == 0)+   * {+   *   // This is the child process.+   *   my_execution_context.notify_fork(execution_context::fork_child);+   * }+   * else+   * {+   *   // This is the parent process.+   *   my_execution_context.notify_fork(execution_context::fork_parent);+   * } @endcode+   *+   * @note For each service object @c svc in the execution_context set,+   * performs <tt>svc->notify_fork();</tt>. When processing the fork_prepare+   * event, services are visited in reverse order of the beginning of service+   * object lifetime. Otherwise, services are visited in order of the beginning+   * of service object lifetime.+   */+  ASIO_DECL void notify_fork(fork_event event);++  /// Obtain the service object corresponding to the given type.+  /**+   * This function is used to locate a service object that corresponds to the+   * given service type. If there is no existing implementation of the service,+   * then the execution_context will create a new instance of the service.+   *+   * @param e The execution_context object that owns the service.+   *+   * @return The service interface implementing the specified service type.+   * Ownership of the service interface is not transferred to the caller.+   */+  template <typename Service>+  friend Service& use_service(execution_context& e);++  /// Obtain the service object corresponding to the given type.+  /**+   * This function is used to locate a service object that corresponds to the+   * given service type. If there is no existing implementation of the service,+   * then the io_context will create a new instance of the service.+   *+   * @param ioc The io_context object that owns the service.+   *+   * @return The service interface implementing the specified service type.+   * Ownership of the service interface is not transferred to the caller.+   *+   * @note This overload is preserved for backwards compatibility with services+   * that inherit from io_context::service.+   */+  template <typename Service>+  friend Service& use_service(io_context& ioc);++#if defined(GENERATING_DOCUMENTATION)++  /// Creates a service object and adds it to the execution_context.+  /**+   * This function is used to add a service to the execution_context.+   *+   * @param e The execution_context object that owns the service.+   *+   * @param args Zero or more arguments to be passed to the service+   * constructor.+   *+   * @throws asio::service_already_exists Thrown if a service of the+   * given type is already present in the execution_context.+   */+  template <typename Service, typename... Args>+  friend Service& make_service(execution_context& e, Args&&... args);++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Service, typename... Args>+  friend Service& make_service(execution_context& e,+      ASIO_MOVE_ARG(Args)... args);++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Service>+  friend Service& make_service(execution_context& e);++#define ASIO_PRIVATE_MAKE_SERVICE_DEF(n) \+  template <typename Service, ASIO_VARIADIC_TPARAMS(n)> \+  friend Service& make_service(execution_context& e, \+      ASIO_VARIADIC_MOVE_PARAMS(n)); \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_MAKE_SERVICE_DEF)+#undef ASIO_PRIVATE_MAKE_SERVICE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  /// (Deprecated: Use make_service().) Add a service object to the+  /// execution_context.+  /**+   * This function is used to add a service to the execution_context.+   *+   * @param e The execution_context object that owns the service.+   *+   * @param svc The service object. On success, ownership of the service object+   * is transferred to the execution_context. When the execution_context object+   * is destroyed, it will destroy the service object by performing: @code+   * delete static_cast<execution_context::service*>(svc) @endcode+   *+   * @throws asio::service_already_exists Thrown if a service of the+   * given type is already present in the execution_context.+   *+   * @throws asio::invalid_service_owner Thrown if the service's owning+   * execution_context is not the execution_context object specified by the+   * @c e parameter.+   */+  template <typename Service>+  friend void add_service(execution_context& e, Service* svc);++  /// Determine if an execution_context contains a specified service type.+  /**+   * This function is used to determine whether the execution_context contains a+   * service object corresponding to the given service type.+   *+   * @param e The execution_context object that owns the service.+   *+   * @return A boolean indicating whether the execution_context contains the+   * service.+   */+  template <typename Service>+  friend bool has_service(execution_context& e);++private:+  // The service registry.+  asio::detail::service_registry* service_registry_;+};++/// Class used to uniquely identify a service.+class execution_context::id+  : private noncopyable+{+public:+  /// Constructor.+  id() {}+};++/// Base class for all io_context services.+class execution_context::service+  : private noncopyable+{+public:+  /// Get the context object that owns the service.+  execution_context& context();++protected:+  /// Constructor.+  /**+   * @param owner The execution_context object that owns the service.+   */+  ASIO_DECL service(execution_context& owner);++  /// Destructor.+  ASIO_DECL virtual ~service();++private:+  /// Destroy all user-defined handler objects owned by the service.+  virtual void shutdown() = 0;++  /// Handle notification of a fork-related event to perform any necessary+  /// housekeeping.+  /**+   * This function is not a pure virtual so that services only have to+   * implement it if necessary. The default implementation does nothing.+   */+  ASIO_DECL virtual void notify_fork(+      execution_context::fork_event event);++  friend class asio::detail::service_registry;+  struct key+  {+    key() : type_info_(0), id_(0) {}+    const std::type_info* type_info_;+    const execution_context::id* id_;+  } key_;++  execution_context& owner_;+  service* next_;+};++/// Exception thrown when trying to add a duplicate service to an+/// execution_context.+class service_already_exists+  : public std::logic_error+{+public:+  ASIO_DECL service_already_exists();+};++/// Exception thrown when trying to add a service object to an+/// execution_context where the service has a different owner.+class invalid_service_owner+  : public std::logic_error+{+public:+  ASIO_DECL invalid_service_owner();+};++namespace detail {++// Special derived service id type to keep classes header-file only.+template <typename Type>+class service_id+  : public execution_context::id+{+};++// Special service base class to keep classes header-file only.+template <typename Type>+class execution_context_service_base+  : public execution_context::service+{+public:+  static service_id<Type> id;++  // Constructor.+  execution_context_service_base(execution_context& e)+    : execution_context::service(e)+  {+  }+};++template <typename Type>+service_id<Type> execution_context_service_base<Type>::id;++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/execution_context.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/execution_context.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_EXECUTION_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/executor.hpp view
@@ -0,0 +1,347 @@+//+// executor.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTOR_HPP+#define ASIO_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_NO_TS_EXECUTORS)++#include <typeinfo>+#include "asio/detail/cstddef.hpp"+#include "asio/detail/executor_function.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Exception thrown when trying to access an empty polymorphic executor.+class bad_executor+  : public std::exception+{+public:+  /// Constructor.+  ASIO_DECL bad_executor() ASIO_NOEXCEPT;++  /// Obtain message associated with exception.+  ASIO_DECL virtual const char* what() const+    ASIO_NOEXCEPT_OR_NOTHROW;+};++/// Polymorphic wrapper for executors.+class executor+{+public:+  /// Default constructor.+  executor() ASIO_NOEXCEPT+    : impl_(0)+  {+  }++  /// Construct from nullptr.+  executor(nullptr_t) ASIO_NOEXCEPT+    : impl_(0)+  {+  }++  /// Copy constructor.+  executor(const executor& other) ASIO_NOEXCEPT+    : impl_(other.clone())+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  executor(executor&& other) ASIO_NOEXCEPT+    : impl_(other.impl_)+  {+    other.impl_ = 0;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Construct a polymorphic wrapper for the specified executor.+  template <typename Executor>+  executor(Executor e);++  /// Allocator-aware constructor to create a polymorphic wrapper for the+  /// specified executor.+  template <typename Executor, typename Allocator>+  executor(allocator_arg_t, const Allocator& a, Executor e);++  /// Destructor.+  ~executor()+  {+    destroy();+  }++  /// Assignment operator.+  executor& operator=(const executor& other) ASIO_NOEXCEPT+  {+    destroy();+    impl_ = other.clone();+    return *this;+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  // Move assignment operator.+  executor& operator=(executor&& other) ASIO_NOEXCEPT+  {+    destroy();+    impl_ = other.impl_;+    other.impl_ = 0;+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Assignment operator for nullptr_t.+  executor& operator=(nullptr_t) ASIO_NOEXCEPT+  {+    destroy();+    impl_ = 0;+    return *this;+  }++  /// Assignment operator to create a polymorphic wrapper for the specified+  /// executor.+  template <typename Executor>+  executor& operator=(ASIO_MOVE_ARG(Executor) e) ASIO_NOEXCEPT+  {+    executor tmp(ASIO_MOVE_CAST(Executor)(e));+    destroy();+    impl_ = tmp.impl_;+    tmp.impl_ = 0;+    return *this;+  }++  /// Obtain the underlying execution context.+  execution_context& context() const ASIO_NOEXCEPT+  {+    return get_impl()->context();+  }++  /// Inform the executor that it has some outstanding work to do.+  void on_work_started() const ASIO_NOEXCEPT+  {+    get_impl()->on_work_started();+  }++  /// Inform the executor that some work is no longer outstanding.+  void on_work_finished() const ASIO_NOEXCEPT+  {+    get_impl()->on_work_finished();+  }++  /// Request the executor to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object is executed according to the rules of the+   * target executor object.+   *+   * @param f The function object to be called. The executor will make a copy+   * of the handler object as required. The function signature of the function+   * object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename Allocator>+  void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const;++  /// Request the executor to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object is executed according to the rules of the+   * target executor object.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename Allocator>+  void post(ASIO_MOVE_ARG(Function) f, const Allocator& a) const;++  /// Request the executor to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object is executed according to the rules of the+   * target executor object.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename Allocator>+  void defer(ASIO_MOVE_ARG(Function) f, const Allocator& a) const;++  struct unspecified_bool_type_t {};+  typedef void (*unspecified_bool_type)(unspecified_bool_type_t);+  static void unspecified_bool_true(unspecified_bool_type_t) {}++  /// Operator to test if the executor contains a valid target.+  operator unspecified_bool_type() const ASIO_NOEXCEPT+  {+    return impl_ ? &executor::unspecified_bool_true : 0;+  }++  /// Obtain type information for the target executor object.+  /**+   * @returns If @c *this has a target type of type @c T, <tt>typeid(T)</tt>;+   * otherwise, <tt>typeid(void)</tt>.+   */+#if !defined(ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)+  const std::type_info& target_type() const ASIO_NOEXCEPT+  {+    return impl_ ? impl_->target_type() : typeid(void);+  }+#else // !defined(ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)+  const void* target_type() const ASIO_NOEXCEPT+  {+    return impl_ ? impl_->target_type() : 0;+  }+#endif // !defined(ASIO_NO_TYPEID) || defined(GENERATING_DOCUMENTATION)++  /// Obtain a pointer to the target executor object.+  /**+   * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored+   * executor target; otherwise, a null pointer.+   */+  template <typename Executor>+  Executor* target() ASIO_NOEXCEPT;++  /// Obtain a pointer to the target executor object.+  /**+   * @returns If <tt>target_type() == typeid(T)</tt>, a pointer to the stored+   * executor target; otherwise, a null pointer.+   */+  template <typename Executor>+  const Executor* target() const ASIO_NOEXCEPT;++  /// Compare two executors for equality.+  friend bool operator==(const executor& a,+      const executor& b) ASIO_NOEXCEPT+  {+    if (a.impl_ == b.impl_)+      return true;+    if (!a.impl_ || !b.impl_)+      return false;+    return a.impl_->equals(b.impl_);+  }++  /// Compare two executors for inequality.+  friend bool operator!=(const executor& a,+      const executor& b) ASIO_NOEXCEPT+  {+    return !(a == b);+  }++private:+#if !defined(GENERATING_DOCUMENTATION)+  typedef detail::executor_function function;+  template <typename, typename> class impl;++#if !defined(ASIO_NO_TYPEID)+  typedef const std::type_info& type_id_result_type;+#else // !defined(ASIO_NO_TYPEID)+  typedef const void* type_id_result_type;+#endif // !defined(ASIO_NO_TYPEID)++  template <typename T>+  static type_id_result_type type_id()+  {+#if !defined(ASIO_NO_TYPEID)+    return typeid(T);+#else // !defined(ASIO_NO_TYPEID)+    static int unique_id;+    return &unique_id;+#endif // !defined(ASIO_NO_TYPEID)+  }++  // Base class for all polymorphic executor implementations.+  class impl_base+  {+  public:+    virtual impl_base* clone() const ASIO_NOEXCEPT = 0;+    virtual void destroy() ASIO_NOEXCEPT = 0;+    virtual execution_context& context() ASIO_NOEXCEPT = 0;+    virtual void on_work_started() ASIO_NOEXCEPT = 0;+    virtual void on_work_finished() ASIO_NOEXCEPT = 0;+    virtual void dispatch(ASIO_MOVE_ARG(function)) = 0;+    virtual void post(ASIO_MOVE_ARG(function)) = 0;+    virtual void defer(ASIO_MOVE_ARG(function)) = 0;+    virtual type_id_result_type target_type() const ASIO_NOEXCEPT = 0;+    virtual void* target() ASIO_NOEXCEPT = 0;+    virtual const void* target() const ASIO_NOEXCEPT = 0;+    virtual bool equals(const impl_base* e) const ASIO_NOEXCEPT = 0;++  protected:+    impl_base(bool fast_dispatch) : fast_dispatch_(fast_dispatch) {}+    virtual ~impl_base() {}++  private:+    friend class executor;+    const bool fast_dispatch_;+  };++  // Helper function to check and return the implementation pointer.+  impl_base* get_impl() const+  {+    if (!impl_)+    {+      bad_executor ex;+      asio::detail::throw_exception(ex);+    }+    return impl_;+  }++  // Helper function to clone another implementation.+  impl_base* clone() const ASIO_NOEXCEPT+  {+    return impl_ ? impl_->clone() : 0;+  }++  // Helper function to destroy an implementation.+  void destroy() ASIO_NOEXCEPT+  {+    if (impl_)+      impl_->destroy();+  }++  impl_base* impl_;+#endif // !defined(GENERATING_DOCUMENTATION)+};++} // namespace asio++ASIO_USES_ALLOCATOR(asio::executor)++#include "asio/detail/pop_options.hpp"++#include "asio/impl/executor.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/executor.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // !defined(ASIO_NO_TS_EXECUTORS)++#endif // ASIO_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/executor_work_guard.hpp view
@@ -0,0 +1,287 @@+//+// executor_work_guard.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_EXECUTOR_WORK_GUARD_HPP+#define ASIO_EXECUTOR_WORK_GUARD_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_TS_EXECUTORS)++#include "asio/associated_executor.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution.hpp"+#include "asio/is_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_EXECUTOR_WORK_GUARD_DECL)+#define ASIO_EXECUTOR_WORK_GUARD_DECL++template <typename Executor, typename = void>+class executor_work_guard;++#endif // !defined(ASIO_EXECUTOR_WORK_GUARD_DECL)++/// An object of type @c executor_work_guard controls ownership of executor work+/// within a scope.+#if defined(GENERATING_DOCUMENTATION)+template <typename Executor>+#else // defined(GENERATING_DOCUMENTATION)+template <typename Executor, typename>+#endif // defined(GENERATING_DOCUMENTATION)+class executor_work_guard+{+public:+  /// The underlying executor type.+  typedef Executor executor_type;++  /// Constructs a @c executor_work_guard object for the specified executor.+  /**+   * Stores a copy of @c e and calls <tt>on_work_started()</tt> on it.+   */+  explicit executor_work_guard(const executor_type& e) ASIO_NOEXCEPT+    : executor_(e),+      owns_(true)+  {+    executor_.on_work_started();+  }++  /// Copy constructor.+  executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT+    : executor_(other.executor_),+      owns_(other.owns_)+  {+    if (owns_)+      executor_.on_work_started();+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  executor_work_guard(executor_work_guard&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)),+      owns_(other.owns_)+  {+    other.owns_ = false;+  }+#endif //  defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  /**+   * Unless the object has already been reset, or is in a moved-from state,+   * calls <tt>on_work_finished()</tt> on the stored executor.+   */+  ~executor_work_guard()+  {+    if (owns_)+      executor_.on_work_finished();+  }++  /// Obtain the associated executor.+  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return executor_;+  }++  /// Whether the executor_work_guard object owns some outstanding work.+  bool owns_work() const ASIO_NOEXCEPT+  {+    return owns_;+  }++  /// Indicate that the work is no longer outstanding.+  /**+   * Unless the object has already been reset, or is in a moved-from state,+   * calls <tt>on_work_finished()</tt> on the stored executor.+   */+  void reset() ASIO_NOEXCEPT+  {+    if (owns_)+    {+      executor_.on_work_finished();+      owns_ = false;+    }+  }++private:+  // Disallow assignment.+  executor_work_guard& operator=(const executor_work_guard&);++  executor_type executor_;+  bool owns_;+};++#if !defined(GENERATING_DOCUMENTATION)++template <typename Executor>+class executor_work_guard<Executor,+    typename enable_if<+      !is_executor<Executor>::value && execution::is_executor<Executor>::value+    >::type>+{+public:+  typedef Executor executor_type;++  explicit executor_work_guard(const executor_type& e) ASIO_NOEXCEPT+    : executor_(e),+      owns_(true)+  {+    new (&work_) work_type(asio::prefer(executor_,+          execution::outstanding_work.tracked));+  }++  executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT+    : executor_(other.executor_),+      owns_(other.owns_)+  {+    if (owns_)+    {+      new (&work_) work_type(asio::prefer(executor_,+            execution::outstanding_work.tracked));+    }+  }++#if defined(ASIO_HAS_MOVE)+  executor_work_guard(executor_work_guard&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)),+      owns_(other.owns_)+  {+    if (owns_)+    {+      new (&work_) work_type(+          ASIO_MOVE_CAST(work_type)(+            *static_cast<work_type*>(+              static_cast<void*>(&other.work_))));+      other.owns_ = false;+    }+  }+#endif //  defined(ASIO_HAS_MOVE)++  ~executor_work_guard()+  {+    if (owns_)+      static_cast<work_type*>(static_cast<void*>(&work_))->~work_type();+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return executor_;+  }++  bool owns_work() const ASIO_NOEXCEPT+  {+    return owns_;+  }++  void reset() ASIO_NOEXCEPT+  {+    if (owns_)+    {+      static_cast<work_type*>(static_cast<void*>(&work_))->~work_type();+      owns_ = false;+    }+  }++private:+  // Disallow assignment.+  executor_work_guard& operator=(const executor_work_guard&);++  typedef typename decay<+      typename prefer_result<+        const executor_type&,+        execution::outstanding_work_t::tracked_t+      >::type+    >::type work_type;++  executor_type executor_;+  typename aligned_storage<sizeof(work_type),+      alignment_of<work_type>::value>::type work_;+  bool owns_;+};++#endif // !defined(GENERATING_DOCUMENTATION)++/// Create an @ref executor_work_guard object.+template <typename Executor>+inline executor_work_guard<Executor> make_work_guard(const Executor& ex,+    typename enable_if<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type* = 0)+{+  return executor_work_guard<Executor>(ex);+}++/// Create an @ref executor_work_guard object.+template <typename ExecutionContext>+inline executor_work_guard<typename ExecutionContext::executor_type>+make_work_guard(ExecutionContext& ctx,+    typename enable_if<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type* = 0)+{+  return executor_work_guard<typename ExecutionContext::executor_type>(+      ctx.get_executor());+}++/// Create an @ref executor_work_guard object.+template <typename T>+inline executor_work_guard<typename associated_executor<T>::type>+make_work_guard(const T& t,+    typename enable_if<+      !is_executor<T>::value && !execution::is_executor<T>::value+        && !is_convertible<T&, execution_context&+    >::value>::type* = 0)+{+  return executor_work_guard<typename associated_executor<T>::type>(+      associated_executor<T>::get(t));+}++/// Create an @ref executor_work_guard object.+template <typename T, typename Executor>+inline executor_work_guard<typename associated_executor<T, Executor>::type>+make_work_guard(const T& t, const Executor& ex,+    typename enable_if<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type* = 0)+{+  return executor_work_guard<typename associated_executor<T, Executor>::type>(+      associated_executor<T, Executor>::get(t, ex));+}++/// Create an @ref executor_work_guard object.+template <typename T, typename ExecutionContext>+inline executor_work_guard<typename associated_executor<T,+  typename ExecutionContext::executor_type>::type>+make_work_guard(const T& t, ExecutionContext& ctx,+    typename enable_if<+      !is_executor<T>::value && !execution::is_executor<T>::value+        && !is_convertible<T&, execution_context&>::value+        && is_convertible<ExecutionContext&, execution_context&>::value+    >::type* = 0)+{+  return executor_work_guard<typename associated_executor<T,+    typename ExecutionContext::executor_type>::type>(+      associated_executor<T, typename ExecutionContext::executor_type>::get(+        t, ctx.get_executor()));+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_TS_EXECUTORS)++#endif // ASIO_EXECUTOR_WORK_GUARD_HPP
+ link/modules/asio-standalone/asio/include/asio/generic/basic_endpoint.hpp view
@@ -0,0 +1,193 @@+//+// generic/basic_endpoint.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_GENERIC_BASIC_ENDPOINT_HPP+#define ASIO_GENERIC_BASIC_ENDPOINT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/generic/detail/endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace generic {++/// Describes an endpoint for any socket type.+/**+ * The asio::generic::basic_endpoint class template describes an endpoint+ * that may be associated with any socket type.+ *+ * @note The socket types sockaddr type must be able to fit into a+ * @c sockaddr_storage structure.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * @par Concepts:+ * Endpoint.+ */+template <typename Protocol>+class basic_endpoint+{+public:+  /// The protocol type associated with the endpoint.+  typedef Protocol protocol_type;++  /// The type of the endpoint structure. This type is dependent on the+  /// underlying implementation of the socket layer.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined data_type;+#else+  typedef asio::detail::socket_addr_type data_type;+#endif++  /// Default constructor.+  basic_endpoint() ASIO_NOEXCEPT+  {+  }++  /// Construct an endpoint from the specified socket address.+  basic_endpoint(const void* socket_address,+      std::size_t socket_address_size, int socket_protocol = 0)+    : impl_(socket_address, socket_address_size, socket_protocol)+  {+  }++  /// Construct an endpoint from the specific endpoint type.+  template <typename Endpoint>+  basic_endpoint(const Endpoint& endpoint)+    : impl_(endpoint.data(), endpoint.size(), endpoint.protocol().protocol())+  {+  }++  /// Copy constructor.+  basic_endpoint(const basic_endpoint& other)+    : impl_(other.impl_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  basic_endpoint(basic_endpoint&& other)+    : impl_(other.impl_)+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Assign from another endpoint.+  basic_endpoint& operator=(const basic_endpoint& other)+  {+    impl_ = other.impl_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  /// Move-assign from another endpoint.+  basic_endpoint& operator=(basic_endpoint&& other)+  {+    impl_ = other.impl_;+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  /// The protocol associated with the endpoint.+  protocol_type protocol() const+  {+    return protocol_type(impl_.family(), impl_.protocol());+  }++  /// Get the underlying endpoint in the native type.+  data_type* data()+  {+    return impl_.data();+  }++  /// Get the underlying endpoint in the native type.+  const data_type* data() const+  {+    return impl_.data();+  }++  /// Get the underlying size of the endpoint in the native type.+  std::size_t size() const+  {+    return impl_.size();+  }++  /// Set the underlying size of the endpoint in the native type.+  void resize(std::size_t new_size)+  {+    impl_.resize(new_size);+  }++  /// Get the capacity of the endpoint in the native type.+  std::size_t capacity() const+  {+    return impl_.capacity();+  }++  /// Compare two endpoints for equality.+  friend bool operator==(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return e1.impl_ == e2.impl_;+  }++  /// Compare two endpoints for inequality.+  friend bool operator!=(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return !(e1.impl_ == e2.impl_);+  }++  /// Compare endpoints for ordering.+  friend bool operator<(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return e1.impl_ < e2.impl_;+  }++  /// Compare endpoints for ordering.+  friend bool operator>(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return e2.impl_ < e1.impl_;+  }++  /// Compare endpoints for ordering.+  friend bool operator<=(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return !(e2 < e1);+  }++  /// Compare endpoints for ordering.+  friend bool operator>=(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return !(e1 < e2);+  }++private:+  // The underlying generic endpoint.+  asio::generic::detail::endpoint impl_;+};++} // namespace generic+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_GENERIC_BASIC_ENDPOINT_HPP
+ link/modules/asio-standalone/asio/include/asio/generic/datagram_protocol.hpp view
@@ -0,0 +1,123 @@+//+// generic/datagram_protocol.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_GENERIC_DATAGRAM_PROTOCOL_HPP+#define ASIO_GENERIC_DATAGRAM_PROTOCOL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <typeinfo>+#include "asio/basic_datagram_socket.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/generic/basic_endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace generic {++/// Encapsulates the flags needed for a generic datagram-oriented socket.+/**+ * The asio::generic::datagram_protocol class contains flags necessary+ * for datagram-oriented sockets of any address family and protocol.+ *+ * @par Examples+ * Constructing using a native address family and socket protocol:+ * @code datagram_protocol p(AF_INET, IPPROTO_UDP); @endcode+ * Constructing from a specific protocol type:+ * @code datagram_protocol p(asio::ip::udp::v4()); @endcode+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol.+ */+class datagram_protocol+{+public:+  /// Construct a protocol object for a specific address family and protocol.+  datagram_protocol(int address_family, int socket_protocol)+    : family_(address_family),+      protocol_(socket_protocol)+  {+  }++  /// Construct a generic protocol object from a specific protocol.+  /**+   * @throws @c bad_cast Thrown if the source protocol is not datagram-oriented.+   */+  template <typename Protocol>+  datagram_protocol(const Protocol& source_protocol)+    : family_(source_protocol.family()),+      protocol_(source_protocol.protocol())+  {+    if (source_protocol.type() != type())+    {+      std::bad_cast ex;+      asio::detail::throw_exception(ex);+    }+  }++  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return ASIO_OS_DEF(SOCK_DGRAM);+  }++  /// Obtain an identifier for the protocol.+  int protocol() const ASIO_NOEXCEPT+  {+    return protocol_;+  }++  /// Obtain an identifier for the protocol family.+  int family() const ASIO_NOEXCEPT+  {+    return family_;+  }++  /// Compare two protocols for equality.+  friend bool operator==(const datagram_protocol& p1,+      const datagram_protocol& p2)+  {+    return p1.family_ == p2.family_ && p1.protocol_ == p2.protocol_;+  }++  /// Compare two protocols for inequality.+  friend bool operator!=(const datagram_protocol& p1,+      const datagram_protocol& p2)+  {+    return !(p1 == p2);+  }++  /// The type of an endpoint.+  typedef basic_endpoint<datagram_protocol> endpoint;++  /// The generic socket type.+  typedef basic_datagram_socket<datagram_protocol> socket;++private:+  int family_;+  int protocol_;+};++} // namespace generic+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_GENERIC_DATAGRAM_PROTOCOL_HPP
+ link/modules/asio-standalone/asio/include/asio/generic/detail/endpoint.hpp view
@@ -0,0 +1,133 @@+//+// generic/detail/endpoint.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_GENERIC_DETAIL_ENDPOINT_HPP+#define ASIO_GENERIC_DETAIL_ENDPOINT_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/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace generic {+namespace detail {++// Helper class for implementing a generic socket endpoint.+class endpoint+{+public:+  // Default constructor.+  ASIO_DECL endpoint();++  // Construct an endpoint from the specified raw bytes.+  ASIO_DECL endpoint(const void* sock_addr,+      std::size_t sock_addr_size, int sock_protocol);++  // Copy constructor.+  endpoint(const endpoint& other)+    : data_(other.data_),+      size_(other.size_),+      protocol_(other.protocol_)+  {+  }++  // Assign from another endpoint.+  endpoint& operator=(const endpoint& other)+  {+    data_ = other.data_;+    size_ = other.size_;+    protocol_ = other.protocol_;+    return *this;+  }++  // Get the address family associated with the endpoint.+  int family() const+  {+    return data_.base.sa_family;+  }++  // Get the socket protocol associated with the endpoint.+  int protocol() const+  {+    return protocol_;+  }++  // Get the underlying endpoint in the native type.+  asio::detail::socket_addr_type* data()+  {+    return &data_.base;+  }++  // Get the underlying endpoint in the native type.+  const asio::detail::socket_addr_type* data() const+  {+    return &data_.base;+  }++  // Get the underlying size of the endpoint in the native type.+  std::size_t size() const+  {+    return size_;+  }++  // Set the underlying size of the endpoint in the native type.+  ASIO_DECL void resize(std::size_t size);++  // Get the capacity of the endpoint in the native type.+  std::size_t capacity() const+  {+    return sizeof(asio::detail::sockaddr_storage_type);+  }++  // Compare two endpoints for equality.+  ASIO_DECL friend bool operator==(+      const endpoint& e1, const endpoint& e2);++  // Compare endpoints for ordering.+  ASIO_DECL friend bool operator<(+      const endpoint& e1, const endpoint& e2);++private:+  // The underlying socket address.+  union data_union+  {+    asio::detail::socket_addr_type base;+    asio::detail::sockaddr_storage_type generic;+  } data_;++  // The length of the socket address stored in the endpoint.+  std::size_t size_;++  // The socket protocol associated with the endpoint.+  int protocol_;++  // Initialise with a specified memory.+  ASIO_DECL void init(const void* sock_addr,+      std::size_t sock_addr_size, int sock_protocol);+};++} // namespace detail+} // namespace generic+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/generic/detail/impl/endpoint.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_GENERIC_DETAIL_ENDPOINT_HPP
+ link/modules/asio-standalone/asio/include/asio/generic/detail/impl/endpoint.ipp view
@@ -0,0 +1,110 @@+//+// generic/detail/impl/endpoint.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_GENERIC_DETAIL_IMPL_ENDPOINT_IPP+#define ASIO_GENERIC_DETAIL_IMPL_ENDPOINT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <cstring>+#include <typeinfo>+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/error.hpp"+#include "asio/generic/detail/endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace generic {+namespace detail {++endpoint::endpoint()+{+  init(0, 0, 0);+}++endpoint::endpoint(const void* sock_addr,+    std::size_t sock_addr_size, int sock_protocol)+{+  init(sock_addr, sock_addr_size, sock_protocol);+}++void endpoint::resize(std::size_t new_size)+{+  if (new_size > sizeof(asio::detail::sockaddr_storage_type))+  {+    asio::error_code ec(asio::error::invalid_argument);+    asio::detail::throw_error(ec);+  }+  else+  {+    size_ = new_size;+    protocol_ = 0;+  }+}++bool operator==(const endpoint& e1, const endpoint& e2)+{+  using namespace std; // For memcmp.+  return e1.size() == e2.size() && memcmp(e1.data(), e2.data(), e1.size()) == 0;+}++bool operator<(const endpoint& e1, const endpoint& e2)+{+  if (e1.protocol() < e2.protocol())+    return true;++  if (e1.protocol() > e2.protocol())+    return false;++  using namespace std; // For memcmp.+  std::size_t compare_size = e1.size() < e2.size() ? e1.size() : e2.size();+  int compare_result = memcmp(e1.data(), e2.data(), compare_size);++  if (compare_result < 0)+    return true;++  if (compare_result > 0)+    return false;++  return e1.size() < e2.size();+}++void endpoint::init(const void* sock_addr,+    std::size_t sock_addr_size, int sock_protocol)+{+  if (sock_addr_size > sizeof(asio::detail::sockaddr_storage_type))+  {+    asio::error_code ec(asio::error::invalid_argument);+    asio::detail::throw_error(ec);+  }++  using namespace std; // For memset and memcpy.+  memset(&data_.generic, 0, sizeof(asio::detail::sockaddr_storage_type));+  if (sock_addr_size > 0)+    memcpy(&data_.generic, sock_addr, sock_addr_size);++  size_ = sock_addr_size;+  protocol_ = sock_protocol;+}++} // namespace detail+} // namespace generic+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_GENERIC_DETAIL_IMPL_ENDPOINT_IPP
+ link/modules/asio-standalone/asio/include/asio/generic/raw_protocol.hpp view
@@ -0,0 +1,121 @@+//+// generic/raw_protocol.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_GENERIC_RAW_PROTOCOL_HPP+#define ASIO_GENERIC_RAW_PROTOCOL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <typeinfo>+#include "asio/basic_raw_socket.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/generic/basic_endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace generic {++/// Encapsulates the flags needed for a generic raw socket.+/**+ * The asio::generic::raw_protocol class contains flags necessary for+ * raw sockets of any address family and protocol.+ *+ * @par Examples+ * Constructing using a native address family and socket protocol:+ * @code raw_protocol p(AF_INET, IPPROTO_ICMP); @endcode+ * Constructing from a specific protocol type:+ * @code raw_protocol p(asio::ip::icmp::v4()); @endcode+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol.+ */+class raw_protocol+{+public:+  /// Construct a protocol object for a specific address family and protocol.+  raw_protocol(int address_family, int socket_protocol)+    : family_(address_family),+      protocol_(socket_protocol)+  {+  }++  /// Construct a generic protocol object from a specific protocol.+  /**+   * @throws @c bad_cast Thrown if the source protocol is not raw-oriented.+   */+  template <typename Protocol>+  raw_protocol(const Protocol& source_protocol)+    : family_(source_protocol.family()),+      protocol_(source_protocol.protocol())+  {+    if (source_protocol.type() != type())+    {+      std::bad_cast ex;+      asio::detail::throw_exception(ex);+    }+  }++  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return ASIO_OS_DEF(SOCK_RAW);+  }++  /// Obtain an identifier for the protocol.+  int protocol() const ASIO_NOEXCEPT+  {+    return protocol_;+  }++  /// Obtain an identifier for the protocol family.+  int family() const ASIO_NOEXCEPT+  {+    return family_;+  }++  /// Compare two protocols for equality.+  friend bool operator==(const raw_protocol& p1, const raw_protocol& p2)+  {+    return p1.family_ == p2.family_ && p1.protocol_ == p2.protocol_;+  }++  /// Compare two protocols for inequality.+  friend bool operator!=(const raw_protocol& p1, const raw_protocol& p2)+  {+    return !(p1 == p2);+  }++  /// The type of an endpoint.+  typedef basic_endpoint<raw_protocol> endpoint;++  /// The generic socket type.+  typedef basic_raw_socket<raw_protocol> socket;++private:+  int family_;+  int protocol_;+};++} // namespace generic+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_GENERIC_RAW_PROTOCOL_HPP
+ link/modules/asio-standalone/asio/include/asio/generic/seq_packet_protocol.hpp view
@@ -0,0 +1,122 @@+//+// generic/seq_packet_protocol.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_GENERIC_SEQ_PACKET_PROTOCOL_HPP+#define ASIO_GENERIC_SEQ_PACKET_PROTOCOL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <typeinfo>+#include "asio/basic_seq_packet_socket.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/generic/basic_endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace generic {++/// Encapsulates the flags needed for a generic sequenced packet socket.+/**+ * The asio::generic::seq_packet_protocol class contains flags necessary+ * for seq_packet-oriented sockets of any address family and protocol.+ *+ * @par Examples+ * Constructing using a native address family and socket protocol:+ * @code seq_packet_protocol p(AF_INET, IPPROTO_SCTP); @endcode+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol.+ */+class seq_packet_protocol+{+public:+  /// Construct a protocol object for a specific address family and protocol.+  seq_packet_protocol(int address_family, int socket_protocol)+    : family_(address_family),+      protocol_(socket_protocol)+  {+  }++  /// Construct a generic protocol object from a specific protocol.+  /**+   * @throws @c bad_cast Thrown if the source protocol is not based around+   * sequenced packets.+   */+  template <typename Protocol>+  seq_packet_protocol(const Protocol& source_protocol)+    : family_(source_protocol.family()),+      protocol_(source_protocol.protocol())+  {+    if (source_protocol.type() != type())+    {+      std::bad_cast ex;+      asio::detail::throw_exception(ex);+    }+  }++  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return ASIO_OS_DEF(SOCK_SEQPACKET);+  }++  /// Obtain an identifier for the protocol.+  int protocol() const ASIO_NOEXCEPT+  {+    return protocol_;+  }++  /// Obtain an identifier for the protocol family.+  int family() const ASIO_NOEXCEPT+  {+    return family_;+  }++  /// Compare two protocols for equality.+  friend bool operator==(const seq_packet_protocol& p1,+      const seq_packet_protocol& p2)+  {+    return p1.family_ == p2.family_ && p1.protocol_ == p2.protocol_;+  }++  /// Compare two protocols for inequality.+  friend bool operator!=(const seq_packet_protocol& p1,+      const seq_packet_protocol& p2)+  {+    return !(p1 == p2);+  }++  /// The type of an endpoint.+  typedef basic_endpoint<seq_packet_protocol> endpoint;++  /// The generic socket type.+  typedef basic_seq_packet_socket<seq_packet_protocol> socket;++private:+  int family_;+  int protocol_;+};++} // namespace generic+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_GENERIC_SEQ_PACKET_PROTOCOL_HPP
+ link/modules/asio-standalone/asio/include/asio/generic/stream_protocol.hpp view
@@ -0,0 +1,127 @@+//+// generic/stream_protocol.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_GENERIC_STREAM_PROTOCOL_HPP+#define ASIO_GENERIC_STREAM_PROTOCOL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <typeinfo>+#include "asio/basic_socket_iostream.hpp"+#include "asio/basic_stream_socket.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/generic/basic_endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace generic {++/// Encapsulates the flags needed for a generic stream-oriented socket.+/**+ * The asio::generic::stream_protocol class contains flags necessary for+ * stream-oriented sockets of any address family and protocol.+ *+ * @par Examples+ * Constructing using a native address family and socket protocol:+ * @code stream_protocol p(AF_INET, IPPROTO_TCP); @endcode+ * Constructing from a specific protocol type:+ * @code stream_protocol p(asio::ip::tcp::v4()); @endcode+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol.+ */+class stream_protocol+{+public:+  /// Construct a protocol object for a specific address family and protocol.+  stream_protocol(int address_family, int socket_protocol)+    : family_(address_family),+      protocol_(socket_protocol)+  {+  }++  /// Construct a generic protocol object from a specific protocol.+  /**+   * @throws @c bad_cast Thrown if the source protocol is not stream-oriented.+   */+  template <typename Protocol>+  stream_protocol(const Protocol& source_protocol)+    : family_(source_protocol.family()),+      protocol_(source_protocol.protocol())+  {+    if (source_protocol.type() != type())+    {+      std::bad_cast ex;+      asio::detail::throw_exception(ex);+    }+  }++  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return ASIO_OS_DEF(SOCK_STREAM);+  }++  /// Obtain an identifier for the protocol.+  int protocol() const ASIO_NOEXCEPT+  {+    return protocol_;+  }++  /// Obtain an identifier for the protocol family.+  int family() const ASIO_NOEXCEPT+  {+    return family_;+  }++  /// Compare two protocols for equality.+  friend bool operator==(const stream_protocol& p1, const stream_protocol& p2)+  {+    return p1.family_ == p2.family_ && p1.protocol_ == p2.protocol_;+  }++  /// Compare two protocols for inequality.+  friend bool operator!=(const stream_protocol& p1, const stream_protocol& p2)+  {+    return !(p1 == p2);+  }++  /// The type of an endpoint.+  typedef basic_endpoint<stream_protocol> endpoint;++  /// The generic socket type.+  typedef basic_stream_socket<stream_protocol> socket;++#if !defined(ASIO_NO_IOSTREAM)+  /// The generic socket iostream type.+  typedef basic_socket_iostream<stream_protocol> iostream;+#endif // !defined(ASIO_NO_IOSTREAM)++private:+  int family_;+  int protocol_;+};++} // namespace generic+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_GENERIC_STREAM_PROTOCOL_HPP
+ link/modules/asio-standalone/asio/include/asio/handler_alloc_hook.hpp view
@@ -0,0 +1,104 @@+//+// handler_alloc_hook.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_HANDLER_ALLOC_HOOK_HPP+#define ASIO_HANDLER_ALLOC_HOOK_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 {++#if defined(ASIO_NO_DEPRECATED)++// Places in asio that would have previously called the allocate or deallocate+// hooks to manage memory, now call them only to check whether the result types+// are these types. If the result is not the correct type, it indicates that+// the user code still has the old hooks in place, and if so we want to trigger+// a compile error.+enum asio_handler_allocate_is_no_longer_used {};+enum asio_handler_deallocate_is_no_longer_used {};++typedef asio_handler_allocate_is_no_longer_used+  asio_handler_allocate_is_deprecated;+typedef asio_handler_deallocate_is_no_longer_used+  asio_handler_deallocate_is_deprecated;++#else // defined(ASIO_NO_DEPRECATED)++typedef void* asio_handler_allocate_is_deprecated;+typedef void asio_handler_deallocate_is_deprecated;++#endif // defined(ASIO_NO_DEPRECATED)++/// (Deprecated: Use the associated_allocator trait.) Default allocation+/// function for handlers.+/**+ * Asynchronous operations may need to allocate temporary objects. Since+ * asynchronous operations have a handler function object, these temporary+ * objects can be said to be associated with the handler.+ *+ * Implement asio_handler_allocate and asio_handler_deallocate for your own+ * handlers to provide custom allocation for these temporary objects.+ *+ * The default implementation of these allocation hooks uses <tt>::operator+ * new</tt> and <tt>::operator delete</tt>.+ *+ * @note All temporary objects associated with a handler will be deallocated+ * before the upcall to the handler is performed. This allows the same memory to+ * be reused for a subsequent asynchronous operation initiated by the handler.+ *+ * @par Example+ * @code+ * class my_handler;+ *+ * void* asio_handler_allocate(std::size_t size, my_handler* context)+ * {+ *   return ::operator new(size);+ * }+ *+ * void asio_handler_deallocate(void* pointer, std::size_t size,+ *     my_handler* context)+ * {+ *   ::operator delete(pointer);+ * }+ * @endcode+ */+ASIO_DECL asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size, ...);++/// Default deallocation function for handlers.+/**+ * Implement asio_handler_allocate and asio_handler_deallocate for your own+ * handlers to provide custom allocation for the associated temporary objects.+ *+ * The default implementation of these allocation hooks uses <tt>::operator+ * new</tt> and <tt>::operator delete</tt>.+ *+ * @sa asio_handler_allocate.+ */+ASIO_DECL asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size, ...);++} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/handler_alloc_hook.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_HANDLER_ALLOC_HOOK_HPP
+ link/modules/asio-standalone/asio/include/asio/handler_continuation_hook.hpp view
@@ -0,0 +1,54 @@+//+// handler_continuation_hook.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_HANDLER_CONTINUATION_HOOK_HPP+#define ASIO_HANDLER_CONTINUATION_HOOK_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 {++/// Default continuation function for handlers.+/**+ * Asynchronous operations may represent a continuation of the asynchronous+ * control flow associated with the current handler. The implementation can use+ * this knowledge to optimise scheduling of the handler.+ *+ * Implement asio_handler_is_continuation for your own handlers to indicate+ * when a handler represents a continuation.+ *+ * The default implementation of the continuation hook returns <tt>false</tt>.+ *+ * @par Example+ * @code+ * class my_handler;+ *+ * bool asio_handler_is_continuation(my_handler* context)+ * {+ *   return true;+ * }+ * @endcode+ */+inline bool asio_handler_is_continuation(...)+{+  return false;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_HANDLER_CONTINUATION_HOOK_HPP
+ link/modules/asio-standalone/asio/include/asio/handler_invoke_hook.hpp view
@@ -0,0 +1,111 @@+//+// handler_invoke_hook.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_HANDLER_INVOKE_HOOK_HPP+#define ASIO_HANDLER_INVOKE_HOOK_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 {++/** @defgroup asio_handler_invoke asio::asio_handler_invoke+ *+ * @brief (Deprecated: Use the associated_executor trait.) Default invoke+ * function for handlers.+ *+ * Completion handlers for asynchronous operations are invoked by the+ * io_context associated with the corresponding object (e.g. a socket or+ * deadline_timer). Certain guarantees are made on when the handler may be+ * invoked, in particular that a handler can only be invoked from a thread that+ * is currently calling @c run() on the corresponding io_context object.+ * Handlers may subsequently be invoked through other objects (such as+ * io_context::strand objects) that provide additional guarantees.+ *+ * When asynchronous operations are composed from other asynchronous+ * operations, all intermediate handlers should be invoked using the same+ * method as the final handler. This is required to ensure that user-defined+ * objects are not accessed in a way that may violate the guarantees. This+ * hooking function ensures that the invoked method used for the final handler+ * is accessible at each intermediate step.+ *+ * Implement asio_handler_invoke for your own handlers to specify a custom+ * invocation strategy.+ *+ * This default implementation invokes the function object like so:+ * @code function(); @endcode+ * If necessary, the default implementation makes a copy of the function object+ * so that the non-const operator() can be used.+ *+ * @par Example+ * @code+ * class my_handler;+ *+ * template <typename Function>+ * void asio_handler_invoke(Function function, my_handler* context)+ * {+ *   context->strand_.dispatch(function);+ * }+ * @endcode+ */+/*@{*/++#if defined(ASIO_NO_DEPRECATED)++// Places in asio that would have previously called the invocation hook to+// execute a handler, now call it only to check whether the result type is this+// type. If the result is not this type, it indicates that the user code still+// has the old hooks in place, and if so we want to trigger a compile error.+enum asio_handler_invoke_is_no_longer_used {};++typedef asio_handler_invoke_is_no_longer_used+  asio_handler_invoke_is_deprecated;++#else // defined(ASIO_NO_DEPRECATED)++typedef void asio_handler_invoke_is_deprecated;++#endif // defined(ASIO_NO_DEPRECATED)++/// Default handler invocation hook used for non-const function objects.+template <typename Function>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function, ...)+{+  function();+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++/// Default handler invocation hook used for const function objects.+template <typename Function>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function, ...)+{+  Function tmp(function);+  tmp();+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++/*@}*/++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_HANDLER_INVOKE_HOOK_HPP
+ link/modules/asio-standalone/asio/include/asio/high_resolution_timer.hpp view
@@ -0,0 +1,44 @@+//+// high_resolution_timer.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_HIGH_RESOLUTION_TIMER_HPP+#define ASIO_HIGH_RESOLUTION_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_CHRONO) || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_waitable_timer.hpp"+#include "asio/detail/chrono.hpp"++namespace asio {++/// Typedef for a timer based on the high resolution clock.+/**+ * This typedef uses the C++11 @c &lt;chrono&gt; standard library facility, if+ * available. Otherwise, it may use the Boost.Chrono library. To explicitly+ * utilise Boost.Chrono, use the basic_waitable_timer template directly:+ * @code+ * typedef basic_waitable_timer<boost::chrono::high_resolution_clock> timer;+ * @endcode+ */+typedef basic_waitable_timer<+    chrono::high_resolution_clock>+  high_resolution_timer;++} // namespace asio++#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_HIGH_RESOLUTION_TIMER_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/awaitable.hpp view
@@ -0,0 +1,436 @@+//+// impl/awaitable.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_AWAITABLE_HPP+#define ASIO_IMPL_AWAITABLE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <exception>+#include <new>+#include <tuple>+#include <utility>+#include "asio/detail/thread_context.hpp"+#include "asio/detail/thread_info_base.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/post.hpp"+#include "asio/system_error.hpp"+#include "asio/this_coro.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// An awaitable_thread represents a thread-of-execution that is composed of one+// or more "stack frames", with each frame represented by an awaitable_frame.+// All execution occurs in the context of the awaitable_thread's executor. An+// awaitable_thread continues to "pump" the stack frames by repeatedly resuming+// the top stack frame until the stack is empty, or until ownership of the+// stack is transferred to another awaitable_thread object.+//+//                +------------------------------------++//                | top_of_stack_                      |+//                |                                    V+// +--------------+---+                            +-----------------++// |                  |                            |                 |+// | awaitable_thread |<---------------------------+ awaitable_frame |+// |                  |           attached_thread_ |                 |+// +--------------+---+           (Set only when   +---+-------------++//                |               frames are being     |+//                |               actively pumped      | caller_+//                |               by a thread, and     |+//                |               then only for        V+//                |               the top frame.)  +-----------------++//                |                                |                 |+//                |                                | awaitable_frame |+//                |                                |                 |+//                |                                +---+-------------++//                |                                    |+//                |                                    | caller_+//                |                                    :+//                |                                    :+//                |                                    |+//                |                                    V+//                |                                +-----------------++//                | bottom_of_stack_               |                 |+//                +------------------------------->| awaitable_frame |+//                                                 |                 |+//                                                 +-----------------+++template <typename Executor>+class awaitable_frame_base+{+public:+#if !defined(ASIO_DISABLE_AWAITABLE_FRAME_RECYCLING)+  void* operator new(std::size_t size)+  {+    return asio::detail::thread_info_base::allocate(+        asio::detail::thread_info_base::awaitable_frame_tag(),+        asio::detail::thread_context::thread_call_stack::top(),+        size);+  }++  void operator delete(void* pointer, std::size_t size)+  {+    asio::detail::thread_info_base::deallocate(+        asio::detail::thread_info_base::awaitable_frame_tag(),+        asio::detail::thread_context::thread_call_stack::top(),+        pointer, size);+  }+#endif // !defined(ASIO_DISABLE_AWAITABLE_FRAME_RECYCLING)++  // The frame starts in a suspended state until the awaitable_thread object+  // pumps the stack.+  auto initial_suspend() noexcept+  {+    return suspend_always();+  }++  // On final suspension the frame is popped from the top of the stack.+  auto final_suspend() noexcept+  {+    struct result+    {+      awaitable_frame_base* this_;++      bool await_ready() const noexcept+      {+        return false;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+        this_->pop_frame();+      }++      void await_resume() const noexcept+      {+      }+    };++    return result{this};+  }++  void set_except(std::exception_ptr e) noexcept+  {+    pending_exception_ = e;+  }++  void set_error(const asio::error_code& ec)+  {+    this->set_except(std::make_exception_ptr(asio::system_error(ec)));+  }++  void unhandled_exception()+  {+    set_except(std::current_exception());+  }++  void rethrow_exception()+  {+    if (pending_exception_)+    {+      std::exception_ptr ex = std::exchange(pending_exception_, nullptr);+      std::rethrow_exception(ex);+    }+  }++  template <typename T>+  auto await_transform(awaitable<T, Executor> a) const+  {+    return a;+  }++  // This await transformation obtains the associated executor of the thread of+  // execution.+  auto await_transform(this_coro::executor_t) noexcept+  {+    struct result+    {+      awaitable_frame_base* this_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      auto await_resume() const noexcept+      {+        return this_->attached_thread_->get_executor();+      }+    };++    return result{this};+  }++  // This await transformation is used to run an async operation's initiation+  // function object after the coroutine has been suspended. This ensures that+  // immediate resumption of the coroutine in another thread does not cause a+  // race condition.+  template <typename Function>+  auto await_transform(Function f,+      typename enable_if<+        is_convertible<+          typename result_of<Function(awaitable_frame_base*)>::type,+          awaitable_thread<Executor>*+        >::value+      >::type* = 0)+  {+    struct result+    {+      Function function_;+      awaitable_frame_base* this_;++      bool await_ready() const noexcept+      {+        return false;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+        function_(this_);+      }++      void await_resume() const noexcept+      {+      }+    };++    return result{std::move(f), this};+  }++  void attach_thread(awaitable_thread<Executor>* handler) noexcept+  {+    attached_thread_ = handler;+  }++  awaitable_thread<Executor>* detach_thread() noexcept+  {+    return std::exchange(attached_thread_, nullptr);+  }++  void push_frame(awaitable_frame_base<Executor>* caller) noexcept+  {+    caller_ = caller;+    attached_thread_ = caller_->attached_thread_;+    attached_thread_->top_of_stack_ = this;+    caller_->attached_thread_ = nullptr;+  }++  void pop_frame() noexcept+  {+    if (caller_)+      caller_->attached_thread_ = attached_thread_;+    attached_thread_->top_of_stack_ = caller_;+    attached_thread_ = nullptr;+    caller_ = nullptr;+  }++  void resume()+  {+    coro_.resume();+  }++  void destroy()+  {+    coro_.destroy();+  }++protected:+  coroutine_handle<void> coro_ = nullptr;+  awaitable_thread<Executor>* attached_thread_ = nullptr;+  awaitable_frame_base<Executor>* caller_ = nullptr;+  std::exception_ptr pending_exception_ = nullptr;+};++template <typename T, typename Executor>+class awaitable_frame+  : public awaitable_frame_base<Executor>+{+public:+  awaitable_frame() noexcept+  {+  }++  awaitable_frame(awaitable_frame&& other) noexcept+    : awaitable_frame_base<Executor>(std::move(other))+  {+  }++  ~awaitable_frame()+  {+    if (has_result_)+      static_cast<T*>(static_cast<void*>(result_))->~T();+  }++  awaitable<T, Executor> get_return_object() noexcept+  {+    this->coro_ = coroutine_handle<awaitable_frame>::from_promise(*this);+    return awaitable<T, Executor>(this);+  };++  template <typename U>+  void return_value(U&& u)+  {+    new (&result_) T(std::forward<U>(u));+    has_result_ = true;+  }++  template <typename... Us>+  void return_values(Us&&... us)+  {+    this->return_value(std::forward_as_tuple(std::forward<Us>(us)...));+  }++  T get()+  {+    this->caller_ = nullptr;+    this->rethrow_exception();+    return std::move(*static_cast<T*>(static_cast<void*>(result_)));+  }++private:+  alignas(T) unsigned char result_[sizeof(T)];+  bool has_result_ = false;+};++template <typename Executor>+class awaitable_frame<void, Executor>+  : public awaitable_frame_base<Executor>+{+public:+  awaitable<void, Executor> get_return_object()+  {+    this->coro_ = coroutine_handle<awaitable_frame>::from_promise(*this);+    return awaitable<void, Executor>(this);+  };++  void return_void()+  {+  }++  void get()+  {+    this->caller_ = nullptr;+    this->rethrow_exception();+  }+};++template <typename Executor>+class awaitable_thread+{+public:+  typedef Executor executor_type;++  // Construct from the entry point of a new thread of execution.+  awaitable_thread(awaitable<void, Executor> p, const Executor& ex)+    : bottom_of_stack_(std::move(p)),+      top_of_stack_(bottom_of_stack_.frame_),+      executor_(ex)+  {+  }++  // Transfer ownership from another awaitable_thread.+  awaitable_thread(awaitable_thread&& other) noexcept+    : bottom_of_stack_(std::move(other.bottom_of_stack_)),+      top_of_stack_(std::exchange(other.top_of_stack_, nullptr)),+      executor_(std::move(other.executor_))+  {+  }++  // Clean up with a last ditch effort to ensure the thread is unwound within+  // the context of the executor.+  ~awaitable_thread()+  {+    if (bottom_of_stack_.valid())+    {+      // Coroutine "stack unwinding" must be performed through the executor.+      (post)(executor_,+          [a = std::move(bottom_of_stack_)]() mutable+          {+            awaitable<void, Executor>(std::move(a));+          });+    }+  }++  executor_type get_executor() const noexcept+  {+    return executor_;+  }++  // Launch a new thread of execution.+  void launch()+  {+    top_of_stack_->attach_thread(this);+    pump();+  }++protected:+  template <typename> friend class awaitable_frame_base;++  // Repeatedly resume the top stack frame until the stack is empty or until it+  // has been transferred to another resumable_thread object.+  void pump()+  {+    do top_of_stack_->resume(); while (top_of_stack_);+    if (bottom_of_stack_.valid())+    {+      awaitable<void, Executor> a(std::move(bottom_of_stack_));+      a.frame_->rethrow_exception();+    }+  }++  awaitable<void, Executor> bottom_of_stack_;+  awaitable_frame_base<Executor>* top_of_stack_;+  executor_type executor_;+};++} // namespace detail+} // namespace asio++#if !defined(GENERATING_DOCUMENTATION)+# if defined(ASIO_HAS_STD_COROUTINE)++namespace std {++template <typename T, typename Executor, typename... Args>+struct coroutine_traits<asio::awaitable<T, Executor>, Args...>+{+  typedef asio::detail::awaitable_frame<T, Executor> promise_type;+};++} // namespace std++# else // defined(ASIO_HAS_STD_COROUTINE)++namespace std { namespace experimental {++template <typename T, typename Executor, typename... Args>+struct coroutine_traits<asio::awaitable<T, Executor>, Args...>+{+  typedef asio::detail::awaitable_frame<T, Executor> promise_type;+};++}} // namespace std::experimental++# endif // defined(ASIO_HAS_STD_COROUTINE)+#endif // !defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_AWAITABLE_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/buffered_read_stream.hpp view
@@ -0,0 +1,527 @@+//+// impl/buffered_read_stream.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_BUFFERED_READ_STREAM_HPP+#define ASIO_IMPL_BUFFERED_READ_STREAM_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/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename Stream>+std::size_t buffered_read_stream<Stream>::fill()+{+  detail::buffer_resize_guard<detail::buffered_stream_storage>+    resize_guard(storage_);+  std::size_t previous_size = storage_.size();+  storage_.resize(storage_.capacity());+  storage_.resize(previous_size + next_layer_.read_some(buffer(+          storage_.data() + previous_size,+          storage_.size() - previous_size)));+  resize_guard.commit();+  return storage_.size() - previous_size;+}++template <typename Stream>+std::size_t buffered_read_stream<Stream>::fill(asio::error_code& ec)+{+  detail::buffer_resize_guard<detail::buffered_stream_storage>+    resize_guard(storage_);+  std::size_t previous_size = storage_.size();+  storage_.resize(storage_.capacity());+  storage_.resize(previous_size + next_layer_.read_some(buffer(+          storage_.data() + previous_size,+          storage_.size() - previous_size),+        ec));+  resize_guard.commit();+  return storage_.size() - previous_size;+}++namespace detail+{+  template <typename ReadHandler>+  class buffered_fill_handler+  {+  public:+    buffered_fill_handler(detail::buffered_stream_storage& storage,+        std::size_t previous_size, ReadHandler& handler)+      : storage_(storage),+        previous_size_(previous_size),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    buffered_fill_handler(const buffered_fill_handler& other)+      : storage_(other.storage_),+        previous_size_(other.previous_size_),+        handler_(other.handler_)+    {+    }++    buffered_fill_handler(buffered_fill_handler&& other)+      : storage_(other.storage_),+        previous_size_(other.previous_size_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        const std::size_t bytes_transferred)+    {+      storage_.resize(previous_size_ + bytes_transferred);+      handler_(ec, bytes_transferred);+    }++  //private:+    detail::buffered_stream_storage& storage_;+    std::size_t previous_size_;+    ReadHandler handler_;+  };++  template <typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      buffered_fill_handler<ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      buffered_fill_handler<ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename ReadHandler>+  inline bool asio_handler_is_continuation(+      buffered_fill_handler<ReadHandler>* this_handler)+  {+    return asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      buffered_fill_handler<ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      buffered_fill_handler<ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Stream>+  class initiate_async_buffered_fill+  {+  public:+    typedef typename remove_reference<+      Stream>::type::lowest_layer_type::executor_type executor_type;++    explicit initiate_async_buffered_fill(+        typename remove_reference<Stream>::type& next_layer)+      : next_layer_(next_layer)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return next_layer_.lowest_layer().get_executor();+    }++    template <typename ReadHandler>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        buffered_stream_storage* storage) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      std::size_t previous_size = storage->size();+      storage->resize(storage->capacity());+      next_layer_.async_read_some(+          buffer(+            storage->data() + previous_size,+            storage->size() - previous_size),+          buffered_fill_handler<typename decay<ReadHandler>::type>(+            *storage, previous_size, handler2.value));+    }++  private:+    typename remove_reference<Stream>::type& next_layer_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::buffered_fill_handler<ReadHandler>, Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(const detail::buffered_fill_handler<ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename ReadHandler, typename Executor>+struct associated_executor<+    detail::buffered_fill_handler<ReadHandler>, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(const detail::buffered_fill_handler<ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename Stream>+template <+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+buffered_read_stream<Stream>::async_fill(+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_buffered_fill<Stream>(next_layer_),+      handler, &storage_);+}++template <typename Stream>+template <typename MutableBufferSequence>+std::size_t buffered_read_stream<Stream>::read_some(+    const MutableBufferSequence& buffers)+{+  using asio::buffer_size;+  if (buffer_size(buffers) == 0)+    return 0;++  if (storage_.empty())+    this->fill();++  return this->copy(buffers);+}++template <typename Stream>+template <typename MutableBufferSequence>+std::size_t buffered_read_stream<Stream>::read_some(+    const MutableBufferSequence& buffers, asio::error_code& ec)+{+  ec = asio::error_code();++  using asio::buffer_size;+  if (buffer_size(buffers) == 0)+    return 0;++  if (storage_.empty() && !this->fill(ec))+    return 0;++  return this->copy(buffers);+}++namespace detail+{+  template <typename MutableBufferSequence, typename ReadHandler>+  class buffered_read_some_handler+  {+  public:+    buffered_read_some_handler(detail::buffered_stream_storage& storage,+        const MutableBufferSequence& buffers, ReadHandler& handler)+      : storage_(storage),+        buffers_(buffers),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+      buffered_read_some_handler(const buffered_read_some_handler& other)+        : storage_(other.storage_),+          buffers_(other.buffers_),+          handler_(other.handler_)+      {+      }++      buffered_read_some_handler(buffered_read_some_handler&& other)+        : storage_(other.storage_),+          buffers_(other.buffers_),+          handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+      {+      }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec, std::size_t)+    {+      if (ec || storage_.empty())+      {+        const std::size_t length = 0;+        handler_(ec, length);+      }+      else+      {+        const std::size_t bytes_copied = asio::buffer_copy(+            buffers_, storage_.data(), storage_.size());+        storage_.consume(bytes_copied);+        handler_(ec, bytes_copied);+      }+    }++  //private:+    detail::buffered_stream_storage& storage_;+    MutableBufferSequence buffers_;+    ReadHandler handler_;+  };++  template <typename MutableBufferSequence, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      buffered_read_some_handler<+        MutableBufferSequence, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename MutableBufferSequence, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      buffered_read_some_handler<+        MutableBufferSequence, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename MutableBufferSequence, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      buffered_read_some_handler<+        MutableBufferSequence, ReadHandler>* this_handler)+  {+    return asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename MutableBufferSequence,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      buffered_read_some_handler<+        MutableBufferSequence, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename MutableBufferSequence,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      buffered_read_some_handler<+        MutableBufferSequence, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Stream>+  class initiate_async_buffered_read_some+  {+  public:+    typedef typename remove_reference<+      Stream>::type::lowest_layer_type::executor_type executor_type;++    explicit initiate_async_buffered_read_some(+        typename remove_reference<Stream>::type& next_layer)+      : next_layer_(next_layer)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return next_layer_.lowest_layer().get_executor();+    }++    template <typename ReadHandler, typename MutableBufferSequence>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        buffered_stream_storage* storage,+        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;++      using asio::buffer_size;+      non_const_lvalue<ReadHandler> handler2(handler);+      if (buffer_size(buffers) == 0 || !storage->empty())+      {+        next_layer_.async_read_some(ASIO_MUTABLE_BUFFER(0, 0),+            buffered_read_some_handler<MutableBufferSequence,+              typename decay<ReadHandler>::type>(+                *storage, buffers, handler2.value));+      }+      else+      {+        initiate_async_buffered_fill<Stream>(this->next_layer_)(+            buffered_read_some_handler<MutableBufferSequence,+              typename decay<ReadHandler>::type>(+                *storage, buffers, handler2.value),+            storage);+      }+    }++  private:+    typename remove_reference<Stream>::type& next_layer_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename MutableBufferSequence,+    typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::buffered_read_some_handler<+        MutableBufferSequence, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename MutableBufferSequence,+    typename ReadHandler, typename Executor>+struct associated_executor<+    detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,+    Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::buffered_read_some_handler<+        MutableBufferSequence, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename Stream>+template <typename MutableBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+buffered_read_stream<Stream>::async_read_some(+    const MutableBufferSequence& buffers,+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_buffered_read_some<Stream>(next_layer_),+      handler, &storage_, buffers);+}++template <typename Stream>+template <typename MutableBufferSequence>+std::size_t buffered_read_stream<Stream>::peek(+    const MutableBufferSequence& buffers)+{+  if (storage_.empty())+    this->fill();+  return this->peek_copy(buffers);+}++template <typename Stream>+template <typename MutableBufferSequence>+std::size_t buffered_read_stream<Stream>::peek(+    const MutableBufferSequence& buffers, asio::error_code& ec)+{+  ec = asio::error_code();+  if (storage_.empty() && !this->fill(ec))+    return 0;+  return this->peek_copy(buffers);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_BUFFERED_READ_STREAM_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/buffered_write_stream.hpp view
@@ -0,0 +1,507 @@+//+// impl/buffered_write_stream.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_BUFFERED_WRITE_STREAM_HPP+#define ASIO_IMPL_BUFFERED_WRITE_STREAM_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/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename Stream>+std::size_t buffered_write_stream<Stream>::flush()+{+  std::size_t bytes_written = write(next_layer_,+      buffer(storage_.data(), storage_.size()));+  storage_.consume(bytes_written);+  return bytes_written;+}++template <typename Stream>+std::size_t buffered_write_stream<Stream>::flush(asio::error_code& ec)+{+  std::size_t bytes_written = write(next_layer_,+      buffer(storage_.data(), storage_.size()),+      transfer_all(), ec);+  storage_.consume(bytes_written);+  return bytes_written;+}++namespace detail+{+  template <typename WriteHandler>+  class buffered_flush_handler+  {+  public:+    buffered_flush_handler(detail::buffered_stream_storage& storage,+        WriteHandler& handler)+      : storage_(storage),+        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    buffered_flush_handler(const buffered_flush_handler& other)+      : storage_(other.storage_),+        handler_(other.handler_)+    {+    }++    buffered_flush_handler(buffered_flush_handler&& other)+      : storage_(other.storage_),+        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        const std::size_t bytes_written)+    {+      storage_.consume(bytes_written);+      handler_(ec, bytes_written);+    }++  //private:+    detail::buffered_stream_storage& storage_;+    WriteHandler handler_;+  };++  template <typename WriteHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      buffered_flush_handler<WriteHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename WriteHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      buffered_flush_handler<WriteHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename WriteHandler>+  inline bool asio_handler_is_continuation(+      buffered_flush_handler<WriteHandler>* this_handler)+  {+    return asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      buffered_flush_handler<WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      buffered_flush_handler<WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Stream>+  class initiate_async_buffered_flush+  {+  public:+    typedef typename remove_reference<+      Stream>::type::lowest_layer_type::executor_type executor_type;++    explicit initiate_async_buffered_flush(+        typename remove_reference<Stream>::type& next_layer)+      : next_layer_(next_layer)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return next_layer_.lowest_layer().get_executor();+    }++    template <typename WriteHandler>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        buffered_stream_storage* storage) 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;++      non_const_lvalue<WriteHandler> handler2(handler);+      async_write(next_layer_, buffer(storage->data(), storage->size()),+          buffered_flush_handler<typename decay<WriteHandler>::type>(+            *storage, handler2.value));+    }++  private:+    typename remove_reference<Stream>::type& next_layer_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename WriteHandler, typename Allocator>+struct associated_allocator<+    detail::buffered_flush_handler<WriteHandler>, Allocator>+{+  typedef typename associated_allocator<WriteHandler, Allocator>::type type;++  static type get(const detail::buffered_flush_handler<WriteHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename WriteHandler, typename Executor>+struct associated_executor<+    detail::buffered_flush_handler<WriteHandler>, Executor>+{+  typedef typename associated_executor<WriteHandler, Executor>::type type;++  static type get(const detail::buffered_flush_handler<WriteHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename Stream>+template <+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+buffered_write_stream<Stream>::async_flush(+    ASIO_MOVE_ARG(WriteHandler) handler)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_buffered_flush<Stream>(next_layer_),+      handler, &storage_);+}++template <typename Stream>+template <typename ConstBufferSequence>+std::size_t buffered_write_stream<Stream>::write_some(+    const ConstBufferSequence& buffers)+{+  using asio::buffer_size;+  if (buffer_size(buffers) == 0)+    return 0;++  if (storage_.size() == storage_.capacity())+    this->flush();++  return this->copy(buffers);+}++template <typename Stream>+template <typename ConstBufferSequence>+std::size_t buffered_write_stream<Stream>::write_some(+    const ConstBufferSequence& buffers, asio::error_code& ec)+{+  ec = asio::error_code();++  using asio::buffer_size;+  if (buffer_size(buffers) == 0)+    return 0;++  if (storage_.size() == storage_.capacity() && !flush(ec))+    return 0;++  return this->copy(buffers);+}++namespace detail+{+  template <typename ConstBufferSequence, typename WriteHandler>+  class buffered_write_some_handler+  {+  public:+    buffered_write_some_handler(detail::buffered_stream_storage& storage,+        const ConstBufferSequence& buffers, WriteHandler& handler)+      : storage_(storage),+        buffers_(buffers),+        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+      buffered_write_some_handler(const buffered_write_some_handler& other)+        : storage_(other.storage_),+          buffers_(other.buffers_),+          handler_(other.handler_)+      {+      }++      buffered_write_some_handler(buffered_write_some_handler&& other)+        : storage_(other.storage_),+          buffers_(other.buffers_),+          handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))+      {+      }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec, std::size_t)+    {+      if (ec)+      {+        const std::size_t length = 0;+        handler_(ec, length);+      }+      else+      {+        using asio::buffer_size;+        std::size_t orig_size = storage_.size();+        std::size_t space_avail = storage_.capacity() - orig_size;+        std::size_t bytes_avail = buffer_size(buffers_);+        std::size_t length = bytes_avail < space_avail+          ? bytes_avail : space_avail;+        storage_.resize(orig_size + length);+        const std::size_t bytes_copied = asio::buffer_copy(+            storage_.data() + orig_size, buffers_, length);+        handler_(ec, bytes_copied);+      }+    }++  //private:+    detail::buffered_stream_storage& storage_;+    ConstBufferSequence buffers_;+    WriteHandler handler_;+  };++  template <typename ConstBufferSequence, typename WriteHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      buffered_write_some_handler<+        ConstBufferSequence, WriteHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename ConstBufferSequence, typename WriteHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      buffered_write_some_handler<+        ConstBufferSequence, WriteHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename ConstBufferSequence, typename WriteHandler>+  inline bool asio_handler_is_continuation(+      buffered_write_some_handler<+        ConstBufferSequence, WriteHandler>* this_handler)+  {+    return asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename ConstBufferSequence,+      typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      buffered_write_some_handler<+        ConstBufferSequence, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename ConstBufferSequence,+      typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      buffered_write_some_handler<+        ConstBufferSequence, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Stream>+  class initiate_async_buffered_write_some+  {+  public:+    typedef typename remove_reference<+      Stream>::type::lowest_layer_type::executor_type executor_type;++    explicit initiate_async_buffered_write_some(+        typename remove_reference<Stream>::type& next_layer)+      : next_layer_(next_layer)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return next_layer_.lowest_layer().get_executor();+    }++    template <typename WriteHandler, typename ConstBufferSequence>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        buffered_stream_storage* storage,+        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;++      using asio::buffer_size;+      non_const_lvalue<WriteHandler> handler2(handler);+      if (buffer_size(buffers) == 0 || storage->size() < storage->capacity())+      {+        next_layer_.async_write_some(ASIO_CONST_BUFFER(0, 0),+            buffered_write_some_handler<ConstBufferSequence,+              typename decay<WriteHandler>::type>(+                *storage, buffers, handler2.value));+      }+      else+      {+        initiate_async_buffered_flush<Stream>(this->next_layer_)(+            buffered_write_some_handler<ConstBufferSequence,+              typename decay<WriteHandler>::type>(+                *storage, buffers, handler2.value),+            storage);+      }+    }++  private:+    typename remove_reference<Stream>::type& next_layer_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename ConstBufferSequence,+    typename WriteHandler, typename Allocator>+struct associated_allocator<+    detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,+    Allocator>+{+  typedef typename associated_allocator<WriteHandler, Allocator>::type type;++  static type get(+      const detail::buffered_write_some_handler<+        ConstBufferSequence, WriteHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename ConstBufferSequence,+    typename WriteHandler, typename Executor>+struct associated_executor<+    detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,+    Executor>+{+  typedef typename associated_executor<WriteHandler, Executor>::type type;++  static type get(+      const detail::buffered_write_some_handler<+        ConstBufferSequence, WriteHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename Stream>+template <typename ConstBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+buffered_write_stream<Stream>::async_write_some(+    const ConstBufferSequence& buffers,+    ASIO_MOVE_ARG(WriteHandler) handler)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_buffered_write_some<Stream>(next_layer_),+      handler, &storage_, buffers);+}++template <typename Stream>+template <typename ConstBufferSequence>+std::size_t buffered_write_stream<Stream>::copy(+    const ConstBufferSequence& buffers)+{+  using asio::buffer_size;+  std::size_t orig_size = storage_.size();+  std::size_t space_avail = storage_.capacity() - orig_size;+  std::size_t bytes_avail = buffer_size(buffers);+  std::size_t length = bytes_avail < space_avail ? bytes_avail : space_avail;+  storage_.resize(orig_size + length);+  return asio::buffer_copy(+      storage_.data() + orig_size, buffers, length);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_BUFFERED_WRITE_STREAM_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/co_spawn.hpp view
@@ -0,0 +1,298 @@+//+// impl/co_spawn.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_CO_SPAWN_HPP+#define ASIO_IMPL_CO_SPAWN_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/awaitable.hpp"+#include "asio/dispatch.hpp"+#include "asio/execution/outstanding_work.hpp"+#include "asio/post.hpp"+#include "asio/prefer.hpp"+#include "asio/use_awaitable.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Executor, typename = void>+class co_spawn_work_guard+{+public:+  typedef typename decay<+      typename prefer_result<Executor,+        execution::outstanding_work_t::tracked_t+      >::type+    >::type executor_type;++  co_spawn_work_guard(const Executor& ex)+    : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+  {+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return executor_;+  }++private:+  executor_type executor_;+};++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Executor>+struct co_spawn_work_guard<Executor,+    typename enable_if<+      !execution::is_executor<Executor>::value+    >::type> : executor_work_guard<Executor>+{+  co_spawn_work_guard(const Executor& ex)+    : executor_work_guard<Executor>(ex)+  {+  }+};++#endif // !defined(ASIO_NO_TS_EXECUTORS)++template <typename Executor>+inline co_spawn_work_guard<Executor>+make_co_spawn_work_guard(const Executor& ex)+{+  return co_spawn_work_guard<Executor>(ex);+}++template <typename T, typename Executor, typename F, typename Handler>+awaitable<void, Executor> co_spawn_entry_point(+    awaitable<T, Executor>*, Executor ex, F f, Handler handler)+{+  auto spawn_work = make_co_spawn_work_guard(ex);+  auto handler_work = make_co_spawn_work_guard(+      asio::get_associated_executor(handler, ex));++  (void) co_await (post)(spawn_work.get_executor(),+      use_awaitable_t<Executor>{});++  bool done = false;+  try+  {+    T t = co_await f();++    done = true;++    (dispatch)(handler_work.get_executor(),+        [handler = std::move(handler), t = std::move(t)]() mutable+        {+          handler(std::exception_ptr(), std::move(t));+        });+  }+  catch (...)+  {+    if (done)+      throw;++    (dispatch)(handler_work.get_executor(),+        [handler = std::move(handler), e = std::current_exception()]() mutable+        {+          handler(e, T());+        });+  }+}++template <typename Executor, typename F, typename Handler>+awaitable<void, Executor> co_spawn_entry_point(+    awaitable<void, Executor>*, Executor ex, F f, Handler handler)+{+  auto spawn_work = make_co_spawn_work_guard(ex);+  auto handler_work = make_co_spawn_work_guard(+      asio::get_associated_executor(handler, ex));++  (void) co_await (post)(spawn_work.get_executor(),+      use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"});++  std::exception_ptr e = nullptr;+  try+  {+    co_await f();+  }+  catch (...)+  {+    e = std::current_exception();+  }++  (dispatch)(handler_work.get_executor(),+      [handler = std::move(handler), e]() mutable+      {+        handler(e);+      });+}++template <typename T, typename Executor>+class awaitable_as_function+{+public:+  explicit awaitable_as_function(awaitable<T, Executor>&& a)+    : awaitable_(std::move(a))+  {+  }++  awaitable<T, Executor> operator()()+  {+    return std::move(awaitable_);+  }++private:+  awaitable<T, Executor> awaitable_;+};++template <typename Executor>+class initiate_co_spawn+{+public:+  typedef Executor executor_type;++  template <typename OtherExecutor>+  explicit initiate_co_spawn(const OtherExecutor& ex)+    : ex_(ex)+  {+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return ex_;+  }++  template <typename Handler, typename F>+  void operator()(Handler&& handler, F&& f) const+  {+    typedef typename result_of<F()>::type awaitable_type;++    auto a = (co_spawn_entry_point)(static_cast<awaitable_type*>(nullptr),+        ex_, std::forward<F>(f), std::forward<Handler>(handler));+    awaitable_handler<executor_type, void>(std::move(a), ex_).launch();+  }++private:+  Executor ex_;+};++} // namespace detail++template <typename Executor, typename T, typename AwaitableExecutor,+    ASIO_COMPLETION_TOKEN_FOR(+      void(std::exception_ptr, T)) CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE(+    CompletionToken, void(std::exception_ptr, T))+co_spawn(const Executor& ex,+    awaitable<T, AwaitableExecutor> a, CompletionToken&& token,+    typename enable_if<+      (is_executor<Executor>::value || execution::is_executor<Executor>::value)+        && is_convertible<Executor, AwaitableExecutor>::value+    >::type*)+{+  return async_initiate<CompletionToken, void(std::exception_ptr, T)>(+      detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)),+      token, detail::awaitable_as_function<T, AwaitableExecutor>(std::move(a)));+}++template <typename Executor, typename AwaitableExecutor,+    ASIO_COMPLETION_TOKEN_FOR(+      void(std::exception_ptr)) CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE(+    CompletionToken, void(std::exception_ptr))+co_spawn(const Executor& ex,+    awaitable<void, AwaitableExecutor> a, CompletionToken&& token,+    typename enable_if<+      (is_executor<Executor>::value || execution::is_executor<Executor>::value)+        && is_convertible<Executor, AwaitableExecutor>::value+    >::type*)+{+  return async_initiate<CompletionToken, void(std::exception_ptr)>(+      detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)),+      token, detail::awaitable_as_function<+        void, AwaitableExecutor>(std::move(a)));+}++template <typename ExecutionContext, typename T, typename AwaitableExecutor,+    ASIO_COMPLETION_TOKEN_FOR(+      void(std::exception_ptr, T)) CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE(+    CompletionToken, void(std::exception_ptr, T))+co_spawn(ExecutionContext& ctx,+    awaitable<T, AwaitableExecutor> a, CompletionToken&& token,+    typename enable_if<+      is_convertible<ExecutionContext&, execution_context&>::value+        && is_convertible<typename ExecutionContext::executor_type,+          AwaitableExecutor>::value+    >::type*)+{+  return (co_spawn)(ctx.get_executor(), std::move(a),+      std::forward<CompletionToken>(token));+}++template <typename ExecutionContext, typename AwaitableExecutor,+    ASIO_COMPLETION_TOKEN_FOR(+      void(std::exception_ptr)) CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE(+    CompletionToken, void(std::exception_ptr))+co_spawn(ExecutionContext& ctx,+    awaitable<void, AwaitableExecutor> a, CompletionToken&& token,+    typename enable_if<+      is_convertible<ExecutionContext&, execution_context&>::value+        && is_convertible<typename ExecutionContext::executor_type,+          AwaitableExecutor>::value+    >::type*)+{+  return (co_spawn)(ctx.get_executor(), std::move(a),+      std::forward<CompletionToken>(token));+}++template <typename Executor, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<+      typename result_of<F()>::type>::type) CompletionToken>+inline 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,+    typename enable_if<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type*)+{+  return async_initiate<CompletionToken,+    typename detail::awaitable_signature<typename result_of<F()>::type>::type>(+      detail::initiate_co_spawn<+        typename result_of<F()>::type::executor_type>(ex),+      token, std::forward<F>(f));+}++template <typename ExecutionContext, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<+      typename result_of<F()>::type>::type) CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken,+    typename detail::awaitable_signature<typename result_of<F()>::type>::type)+co_spawn(ExecutionContext& ctx, F&& f, CompletionToken&& token,+    typename enable_if<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type*)+{+  return (co_spawn)(ctx.get_executor(), std::forward<F>(f),+      std::forward<CompletionToken>(token));+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_CO_SPAWN_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/compose.hpp view
@@ -0,0 +1,635 @@+//+// impl/compose.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_COMPOSE_HPP+#define ASIO_IMPL_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/associated_executor.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution/outstanding_work.hpp"+#include "asio/executor_work_guard.hpp"+#include "asio/is_executor.hpp"+#include "asio/system_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail+{+  template <typename Executor, typename = void>+  class composed_work_guard+  {+  public:+    typedef typename decay<+        typename prefer_result<Executor,+          execution::outstanding_work_t::tracked_t+        >::type+      >::type executor_type;++    composed_work_guard(const Executor& ex)+      : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+    {+    }++    void reset()+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return executor_;+    }++  private:+    executor_type executor_;+  };++#if !defined(ASIO_NO_TS_EXECUTORS)++  template <typename Executor>+  struct composed_work_guard<Executor,+      typename enable_if<+        !execution::is_executor<Executor>::value+      >::type> : executor_work_guard<Executor>+  {+    composed_work_guard(const Executor& ex)+      : executor_work_guard<Executor>(ex)+    {+    }+  };++#endif // !defined(ASIO_NO_TS_EXECUTORS)++  template <typename>+  struct composed_io_executors;++  template <>+  struct composed_io_executors<void()>+  {+    composed_io_executors() ASIO_NOEXCEPT+      : head_(system_executor())+    {+    }++    typedef system_executor head_type;+    system_executor head_;+  };++  inline composed_io_executors<void()> make_composed_io_executors()+  {+    return composed_io_executors<void()>();+  }++  template <typename Head>+  struct composed_io_executors<void(Head)>+  {+    explicit composed_io_executors(const Head& ex) ASIO_NOEXCEPT+      : head_(ex)+    {+    }++    typedef Head head_type;+    Head head_;+  };++  template <typename Head>+  inline composed_io_executors<void(Head)>+  make_composed_io_executors(const Head& head)+  {+    return composed_io_executors<void(Head)>(head);+  }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Head, typename... Tail>+  struct composed_io_executors<void(Head, Tail...)>+  {+    explicit composed_io_executors(const Head& head,+        const Tail&... tail) ASIO_NOEXCEPT+      : head_(head),+        tail_(tail...)+    {+    }++    void reset()+    {+      head_.reset();+      tail_.reset();+    }++    typedef Head head_type;+    Head head_;+    composed_io_executors<void(Tail...)> tail_;+  };++  template <typename Head, typename... Tail>+  inline composed_io_executors<void(Head, Tail...)>+  make_composed_io_executors(const Head& head, const Tail&... tail)+  {+    return composed_io_executors<void(Head, Tail...)>(head, tail...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF(n) \+  template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \+  struct composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \+  { \+    explicit composed_io_executors(const Head& head, \+        ASIO_VARIADIC_CONSTREF_PARAMS(n)) ASIO_NOEXCEPT \+      : head_(head), \+        tail_(ASIO_VARIADIC_BYVAL_ARGS(n)) \+    { \+    } \+  \+    void reset() \+    { \+      head_.reset(); \+      tail_.reset(); \+    } \+  \+    typedef Head head_type; \+    Head head_; \+    composed_io_executors<void(ASIO_VARIADIC_TARGS(n))> tail_; \+  }; \+  \+  template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \+  inline composed_io_executors<void(Head, ASIO_VARIADIC_TARGS(n))> \+  make_composed_io_executors(const Head& head, \+      ASIO_VARIADIC_CONSTREF_PARAMS(n)) \+  { \+    return composed_io_executors< \+      void(Head, ASIO_VARIADIC_TARGS(n))>( \+        head, ASIO_VARIADIC_BYVAL_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF)+#undef ASIO_PRIVATE_COMPOSED_IO_EXECUTORS_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename>+  struct composed_work;++  template <>+  struct composed_work<void()>+  {+    typedef composed_io_executors<void()> executors_type;++    composed_work(const executors_type&) ASIO_NOEXCEPT+      : head_(system_executor())+    {+    }++    void reset()+    {+      head_.reset();+    }++    typedef system_executor head_type;+    composed_work_guard<system_executor> head_;+  };++  template <typename Head>+  struct composed_work<void(Head)>+  {+    typedef composed_io_executors<void(Head)> executors_type;++    explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT+      : head_(ex.head_)+    {+    }++    void reset()+    {+      head_.reset();+    }++    typedef Head head_type;+    composed_work_guard<Head> head_;+  };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Head, typename... Tail>+  struct composed_work<void(Head, Tail...)>+  {+    typedef composed_io_executors<void(Head, Tail...)> executors_type;++    explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT+      : head_(ex.head_),+        tail_(ex.tail_)+    {+    }++    void reset()+    {+      head_.reset();+      tail_.reset();+    }++    typedef Head head_type;+    composed_work_guard<Head> head_;+    composed_work<void(Tail...)> tail_;+  };++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_COMPOSED_WORK_DEF(n) \+  template <typename Head, ASIO_VARIADIC_TPARAMS(n)> \+  struct composed_work<void(Head, ASIO_VARIADIC_TARGS(n))> \+  { \+    typedef composed_io_executors<void(Head, \+      ASIO_VARIADIC_TARGS(n))> executors_type; \+  \+    explicit composed_work(const executors_type& ex) ASIO_NOEXCEPT \+      : head_(ex.head_), \+        tail_(ex.tail_) \+    { \+    } \+  \+    void reset() \+    { \+      head_.reset(); \+      tail_.reset(); \+    } \+  \+    typedef Head head_type; \+    composed_work_guard<Head> head_; \+    composed_work<void(ASIO_VARIADIC_TARGS(n))> tail_; \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_WORK_DEF)+#undef ASIO_PRIVATE_COMPOSED_WORK_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)+  template <typename Impl, typename Work, typename Handler, typename Signature>+  class composed_op;++  template <typename Impl, typename Work, typename Handler,+      typename R, typename... Args>+  class composed_op<Impl, Work, Handler, R(Args...)>+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+  template <typename Impl, typename Work, typename Handler, typename Signature>+  class composed_op+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+  {+  public:+    template <typename I, typename W, typename H>+    composed_op(ASIO_MOVE_ARG(I) impl,+        ASIO_MOVE_ARG(W) work,+        ASIO_MOVE_ARG(H) handler)+      : impl_(ASIO_MOVE_CAST(I)(impl)),+        work_(ASIO_MOVE_CAST(W)(work)),+        handler_(ASIO_MOVE_CAST(H)(handler)),+        invocations_(0)+    {+    }++#if defined(ASIO_HAS_MOVE)+    composed_op(composed_op&& other)+      : impl_(ASIO_MOVE_CAST(Impl)(other.impl_)),+        work_(ASIO_MOVE_CAST(Work)(other.work_)),+        handler_(ASIO_MOVE_CAST(Handler)(other.handler_)),+        invocations_(other.invocations_)+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    typedef typename associated_executor<Handler,+        typename composed_work_guard<+          typename Work::head_type+        >::executor_type+      >::type executor_type;++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return (get_associated_executor)(handler_, work_.head_.get_executor());+    }++    typedef typename associated_allocator<Handler,+      std::allocator<void> >::type allocator_type;++    allocator_type get_allocator() const ASIO_NOEXCEPT+    {+      return (get_associated_allocator)(handler_, std::allocator<void>());+    }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++    template<typename... T>+    void operator()(ASIO_MOVE_ARG(T)... t)+    {+      if (invocations_ < ~0u)+        ++invocations_;+      impl_(*this, ASIO_MOVE_CAST(T)(t)...);+    }++    void complete(Args... args)+    {+      this->work_.reset();+      this->handler_(ASIO_MOVE_CAST(Args)(args)...);+    }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++    void operator()()+    {+      if (invocations_ < ~0u)+        ++invocations_;+      impl_(*this);+    }++    void complete()+    {+      this->work_.reset();+      this->handler_();+    }++#define ASIO_PRIVATE_COMPOSED_OP_DEF(n) \+    template<ASIO_VARIADIC_TPARAMS(n)> \+    void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \+    { \+      if (invocations_ < ~0u) \+        ++invocations_; \+      impl_(*this, ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    \+    template<ASIO_VARIADIC_TPARAMS(n)> \+    void complete(ASIO_VARIADIC_MOVE_PARAMS(n)) \+    { \+      this->work_.reset(); \+      this->handler_(ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    /**/+    ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPOSED_OP_DEF)+#undef ASIO_PRIVATE_COMPOSED_OP_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  //private:+    Impl impl_;+    Work work_;+    Handler handler_;+    unsigned invocations_;+  };++  template <typename Impl, typename Work, typename Handler, typename Signature>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      composed_op<Impl, Work, Handler, Signature>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Impl, typename Work, typename Handler, typename Signature>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      composed_op<Impl, Work, Handler, Signature>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Impl, typename Work, typename Handler, typename Signature>+  inline bool asio_handler_is_continuation(+      composed_op<Impl, Work, Handler, Signature>* this_handler)+  {+    return this_handler->invocations_ > 1 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename Impl,+      typename Work, typename Handler, typename Signature>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      composed_op<Impl, Work, Handler, Signature>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename Impl,+      typename Work, typename Handler, typename Signature>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      composed_op<Impl, Work, Handler, Signature>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Signature, typename Executors>+  class initiate_composed_op+  {+  public:+    typedef typename composed_io_executors<Executors>::head_type executor_type;++    template <typename T>+    explicit initiate_composed_op(int, ASIO_MOVE_ARG(T) executors)+      : executors_(ASIO_MOVE_CAST(T)(executors))+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return executors_.head_;+    }++    template <typename Handler, typename Impl>+    void operator()(ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Impl) impl) const+    {+      composed_op<typename decay<Impl>::type, composed_work<Executors>,+        typename decay<Handler>::type, Signature>(+          ASIO_MOVE_CAST(Impl)(impl),+          composed_work<Executors>(executors_),+          ASIO_MOVE_CAST(Handler)(handler))();+    }++  private:+    composed_io_executors<Executors> executors_;+  };++  template <typename Signature, typename Executors>+  inline initiate_composed_op<Signature, Executors> make_initiate_composed_op(+      ASIO_MOVE_ARG(composed_io_executors<Executors>) executors)+  {+    return initiate_composed_op<Signature, Executors>(0,+        ASIO_MOVE_CAST(composed_io_executors<Executors>)(executors));+  }++  template <typename IoObject>+  inline typename IoObject::executor_type+  get_composed_io_executor(IoObject& io_object,+      typename enable_if<+        !is_executor<IoObject>::value+          && !execution::is_executor<IoObject>::value+      >::type* = 0)+  {+    return io_object.get_executor();+  }++  template <typename Executor>+  inline const Executor& get_composed_io_executor(const Executor& ex,+      typename enable_if<+        is_executor<Executor>::value+          || execution::is_executor<Executor>::value+      >::type* = 0)+  {+    return ex;+  }+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++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)+{+  return async_initiate<CompletionToken, Signature>(+      detail::make_initiate_composed_op<Signature>(+        detail::make_composed_io_executors(+          detail::get_composed_io_executor(+            ASIO_MOVE_CAST(IoObjectsOrExecutors)(+              io_objects_or_executors))...)),+      token, ASIO_MOVE_CAST(Implementation)(implementation));+}++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++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)+{+  return async_initiate<CompletionToken, Signature>(+      detail::make_initiate_composed_op<Signature>(+        detail::make_composed_io_executors()),+      token, ASIO_MOVE_CAST(Implementation)(implementation));+}++# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n) \+  ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_##n++# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1 \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2 \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3 \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4 \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5 \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6 \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7 \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7))+# define ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8 \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T1)(x1)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T2)(x2)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T3)(x3)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T4)(x4)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T5)(x5)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T6)(x6)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T7)(x7)), \+  detail::get_composed_io_executor(ASIO_MOVE_CAST(T8)(x8))++#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)) \+  { \+    return async_initiate<CompletionToken, Signature>( \+        detail::make_initiate_composed_op<Signature>( \+          detail::make_composed_io_executors( \+            ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR(n))), \+        token, ASIO_MOVE_CAST(Implementation)(implementation)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_COMPOSE_DEF)+#undef ASIO_PRIVATE_ASYNC_COMPOSE_DEF++#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_1+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_2+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_3+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_4+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_5+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_6+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_7+#undef ASIO_PRIVATE_GET_COMPOSED_IO_EXECUTOR_8++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_COMPOSE_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/connect.hpp view
@@ -0,0 +1,916 @@+//+// impl/connect.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_CONNECT_HPP+#define ASIO_IMPL_CONNECT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include <algorithm>+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_tracking.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/post.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail+{+  struct default_connect_condition+  {+    template <typename Endpoint>+    bool operator()(const asio::error_code&, const Endpoint&)+    {+      return true;+    }+  };++  template <typename Protocol, typename Iterator>+  inline typename Protocol::endpoint deref_connect_result(+      Iterator iter, asio::error_code& ec)+  {+    return ec ? typename Protocol::endpoint() : *iter;+  }++  template <typename T, typename Iterator>+  struct legacy_connect_condition_helper : T+  {+    typedef char (*fallback_func_type)(...);+    operator fallback_func_type() const;+  };++  template <typename R, typename Arg1, typename Arg2, typename Iterator>+  struct legacy_connect_condition_helper<R (*)(Arg1, Arg2), Iterator>+  {+    R operator()(Arg1, Arg2) const;+    char operator()(...) const;+  };++  template <typename T, typename Iterator>+  struct is_legacy_connect_condition+  {+    static char asio_connect_condition_check(char);+    static char (&asio_connect_condition_check(Iterator))[2];++    static const bool value =+      sizeof(asio_connect_condition_check(+        (*static_cast<legacy_connect_condition_helper<T, Iterator>*>(0))(+          *static_cast<const asio::error_code*>(0),+          *static_cast<const Iterator*>(0)))) != 1;+  };++  template <typename ConnectCondition, typename Iterator>+  inline Iterator call_connect_condition(ConnectCondition& connect_condition,+      const asio::error_code& ec, Iterator next, Iterator end,+      typename enable_if<is_legacy_connect_condition<+        ConnectCondition, Iterator>::value>::type* = 0)+  {+    if (next != end)+      return connect_condition(ec, next);+    return end;+  }++  template <typename ConnectCondition, typename Iterator>+  inline Iterator call_connect_condition(ConnectCondition& connect_condition,+      const asio::error_code& ec, Iterator next, Iterator end,+      typename enable_if<!is_legacy_connect_condition<+        ConnectCondition, Iterator>::value>::type* = 0)+  {+    for (;next != end; ++next)+      if (connect_condition(ec, *next))+        return next;+    return end;+  }+}++template <typename Protocol, typename Executor, typename EndpointSequence>+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type*)+{+  asio::error_code ec;+  typename Protocol::endpoint result = connect(s, endpoints, ec);+  asio::detail::throw_error(ec, "connect");+  return result;+}++template <typename Protocol, typename Executor, typename EndpointSequence>+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints, asio::error_code& ec,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type*)+{+  return detail::deref_connect_result<Protocol>(+      connect(s, endpoints.begin(), endpoints.end(),+        detail::default_connect_condition(), ec), ec);+}++#if !defined(ASIO_NO_DEPRECATED)+template <typename Protocol, typename Executor, typename Iterator>+Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+{+  asio::error_code ec;+  Iterator result = connect(s, begin, ec);+  asio::detail::throw_error(ec, "connect");+  return result;+}++template <typename Protocol, typename Executor, typename Iterator>+inline Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, asio::error_code& ec,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+{+  return connect(s, begin, Iterator(), detail::default_connect_condition(), ec);+}+#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Protocol, typename Executor, typename Iterator>+Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, Iterator end)+{+  asio::error_code ec;+  Iterator result = connect(s, begin, end, ec);+  asio::detail::throw_error(ec, "connect");+  return result;+}++template <typename Protocol, typename Executor, typename Iterator>+inline Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, Iterator end, asio::error_code& ec)+{+  return connect(s, begin, end, detail::default_connect_condition(), ec);+}++template <typename Protocol, typename Executor,+    typename EndpointSequence, typename ConnectCondition>+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints, ConnectCondition connect_condition,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type*)+{+  asio::error_code ec;+  typename Protocol::endpoint result = connect(+      s, endpoints, connect_condition, ec);+  asio::detail::throw_error(ec, "connect");+  return result;+}++template <typename Protocol, typename Executor,+    typename EndpointSequence, typename ConnectCondition>+typename Protocol::endpoint connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints, ConnectCondition connect_condition,+    asio::error_code& ec,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type*)+{+  return detail::deref_connect_result<Protocol>(+      connect(s, endpoints.begin(), endpoints.end(),+        connect_condition, ec), ec);+}++#if !defined(ASIO_NO_DEPRECATED)+template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition>+Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, ConnectCondition connect_condition,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+{+  asio::error_code ec;+  Iterator result = connect(s, begin, connect_condition, ec);+  asio::detail::throw_error(ec, "connect");+  return result;+}++template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition>+inline Iterator connect(basic_socket<Protocol, Executor>& s,+    Iterator begin, ConnectCondition connect_condition,+    asio::error_code& ec,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+{+  return connect(s, begin, Iterator(), connect_condition, ec);+}+#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition>+Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    Iterator end, ConnectCondition connect_condition)+{+  asio::error_code ec;+  Iterator result = connect(s, begin, end, connect_condition, ec);+  asio::detail::throw_error(ec, "connect");+  return result;+}++template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition>+Iterator connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    Iterator end, ConnectCondition connect_condition,+    asio::error_code& ec)+{+  ec = asio::error_code();++  for (Iterator iter = begin; iter != end; ++iter)+  {+    iter = (detail::call_connect_condition(connect_condition, ec, iter, end));+    if (iter != end)+    {+      s.close(ec);+      s.connect(*iter, ec);+      if (!ec)+        return iter;+    }+    else+      break;+  }++  if (!ec)+    ec = asio::error::not_found;++  return end;+}++namespace detail+{+  // Enable the empty base class optimisation for the connect condition.+  template <typename ConnectCondition>+  class base_from_connect_condition+  {+  protected:+    explicit base_from_connect_condition(+        const ConnectCondition& connect_condition)+      : connect_condition_(connect_condition)+    {+    }++    template <typename Iterator>+    void check_condition(const asio::error_code& ec,+        Iterator& iter, Iterator& end)+    {+      iter = detail::call_connect_condition(connect_condition_, ec, iter, end);+    }++  private:+    ConnectCondition connect_condition_;+  };++  // The default_connect_condition implementation is essentially a no-op. This+  // template specialisation lets us eliminate all costs associated with it.+  template <>+  class base_from_connect_condition<default_connect_condition>+  {+  protected:+    explicit base_from_connect_condition(const default_connect_condition&)+    {+    }++    template <typename Iterator>+    void check_condition(const asio::error_code&, Iterator&, Iterator&)+    {+    }+  };++  template <typename Protocol, typename Executor, typename EndpointSequence,+      typename ConnectCondition, typename RangeConnectHandler>+  class range_connect_op : base_from_connect_condition<ConnectCondition>+  {+  public:+    range_connect_op(basic_socket<Protocol, Executor>& sock,+        const EndpointSequence& endpoints,+        const ConnectCondition& connect_condition,+        RangeConnectHandler& handler)+      : base_from_connect_condition<ConnectCondition>(connect_condition),+        socket_(sock),+        endpoints_(endpoints),+        index_(0),+        start_(0),+        handler_(ASIO_MOVE_CAST(RangeConnectHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    range_connect_op(const range_connect_op& other)+      : base_from_connect_condition<ConnectCondition>(other),+        socket_(other.socket_),+        endpoints_(other.endpoints_),+        index_(other.index_),+        start_(other.start_),+        handler_(other.handler_)+    {+    }++    range_connect_op(range_connect_op&& other)+      : base_from_connect_condition<ConnectCondition>(other),+        socket_(other.socket_),+        endpoints_(other.endpoints_),+        index_(other.index_),+        start_(other.start_),+        handler_(ASIO_MOVE_CAST(RangeConnectHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(asio::error_code ec, int start = 0)+    {+      this->process(ec, start,+          const_cast<const EndpointSequence&>(endpoints_).begin(),+          const_cast<const EndpointSequence&>(endpoints_).end());+    }++  //private:+    template <typename Iterator>+    void process(asio::error_code ec,+        int start, Iterator begin, Iterator end)+    {+      Iterator iter = begin;+      std::advance(iter, index_);++      switch (start_ = start)+      {+        case 1:+        for (;;)+        {+          this->check_condition(ec, iter, end);+          index_ = std::distance(begin, iter);++          if (iter != end)+          {+            socket_.close(ec);+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));+            socket_.async_connect(*iter,+                ASIO_MOVE_CAST(range_connect_op)(*this));+            return;+          }++          if (start)+          {+            ec = asio::error::not_found;+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));+            asio::post(socket_.get_executor(),+                detail::bind_handler(+                  ASIO_MOVE_CAST(range_connect_op)(*this), ec));+            return;+          }++          /* fall-through */ default:++          if (iter == end)+            break;++          if (!socket_.is_open())+          {+            ec = asio::error::operation_aborted;+            break;+          }++          if (!ec)+            break;++          ++iter;+          ++index_;+        }++        handler_(static_cast<const asio::error_code&>(ec),+            static_cast<const typename Protocol::endpoint&>(+              ec || iter == end ? typename Protocol::endpoint() : *iter));+      }+    }++    basic_socket<Protocol, Executor>& socket_;+    EndpointSequence endpoints_;+    std::size_t index_;+    int start_;+    RangeConnectHandler handler_;+  };++  template <typename Protocol, typename Executor, typename EndpointSequence,+      typename ConnectCondition, typename RangeConnectHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      range_connect_op<Protocol, Executor, EndpointSequence,+        ConnectCondition, RangeConnectHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Protocol, typename Executor, typename EndpointSequence,+      typename ConnectCondition, typename RangeConnectHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      range_connect_op<Protocol, Executor, EndpointSequence,+        ConnectCondition, RangeConnectHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Protocol, typename Executor, typename EndpointSequence,+      typename ConnectCondition, typename RangeConnectHandler>+  inline bool asio_handler_is_continuation(+      range_connect_op<Protocol, Executor, EndpointSequence,+        ConnectCondition, RangeConnectHandler>* this_handler)+  {+    return asio_handler_cont_helpers::is_continuation(+        this_handler->handler_);+  }++  template <typename Function, typename Executor, typename Protocol,+      typename EndpointSequence, typename ConnectCondition,+      typename RangeConnectHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      range_connect_op<Protocol, Executor, EndpointSequence,+        ConnectCondition, RangeConnectHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename Executor, typename Protocol,+      typename EndpointSequence, typename ConnectCondition,+      typename RangeConnectHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      range_connect_op<Protocol, Executor, EndpointSequence,+        ConnectCondition, RangeConnectHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Protocol, typename Executor>+  class initiate_async_range_connect+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_range_connect(basic_socket<Protocol, Executor>& s)+      : socket_(s)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return socket_.get_executor();+    }++    template <typename RangeConnectHandler,+        typename EndpointSequence, typename ConnectCondition>+    void operator()(ASIO_MOVE_ARG(RangeConnectHandler) handler,+        const EndpointSequence& endpoints,+        const ConnectCondition& connect_condition) const+    {+      // If you get an error on the following line it means that your+      // handler does not meet the documented type requirements for an+      // RangeConnectHandler.+      ASIO_RANGE_CONNECT_HANDLER_CHECK(RangeConnectHandler,+          handler, typename Protocol::endpoint) type_check;++      non_const_lvalue<RangeConnectHandler> handler2(handler);+      range_connect_op<Protocol, Executor, EndpointSequence, ConnectCondition,+        typename decay<RangeConnectHandler>::type>(socket_, endpoints,+          connect_condition, handler2.value)(asio::error_code(), 1);+    }++  private:+    basic_socket<Protocol, Executor>& socket_;+  };++  template <typename Protocol, typename Executor, typename Iterator,+      typename ConnectCondition, typename IteratorConnectHandler>+  class iterator_connect_op : base_from_connect_condition<ConnectCondition>+  {+  public:+    iterator_connect_op(basic_socket<Protocol, Executor>& sock,+        const Iterator& begin, const Iterator& end,+        const ConnectCondition& connect_condition,+        IteratorConnectHandler& handler)+      : base_from_connect_condition<ConnectCondition>(connect_condition),+        socket_(sock),+        iter_(begin),+        end_(end),+        start_(0),+        handler_(ASIO_MOVE_CAST(IteratorConnectHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    iterator_connect_op(const iterator_connect_op& other)+      : base_from_connect_condition<ConnectCondition>(other),+        socket_(other.socket_),+        iter_(other.iter_),+        end_(other.end_),+        start_(other.start_),+        handler_(other.handler_)+    {+    }++    iterator_connect_op(iterator_connect_op&& other)+      : base_from_connect_condition<ConnectCondition>(other),+        socket_(other.socket_),+        iter_(other.iter_),+        end_(other.end_),+        start_(other.start_),+        handler_(ASIO_MOVE_CAST(IteratorConnectHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(asio::error_code ec, int start = 0)+    {+      switch (start_ = start)+      {+        case 1:+        for (;;)+        {+          this->check_condition(ec, iter_, end_);++          if (iter_ != end_)+          {+            socket_.close(ec);+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));+            socket_.async_connect(*iter_,+                ASIO_MOVE_CAST(iterator_connect_op)(*this));+            return;+          }++          if (start)+          {+            ec = asio::error::not_found;+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_connect"));+            asio::post(socket_.get_executor(),+                detail::bind_handler(+                  ASIO_MOVE_CAST(iterator_connect_op)(*this), ec));+            return;+          }++          /* fall-through */ default:++          if (iter_ == end_)+            break;++          if (!socket_.is_open())+          {+            ec = asio::error::operation_aborted;+            break;+          }++          if (!ec)+            break;++          ++iter_;+        }++        handler_(static_cast<const asio::error_code&>(ec),+            static_cast<const Iterator&>(iter_));+      }+    }++  //private:+    basic_socket<Protocol, Executor>& socket_;+    Iterator iter_;+    Iterator end_;+    int start_;+    IteratorConnectHandler handler_;+  };++  template <typename Protocol, typename Executor, typename Iterator,+      typename ConnectCondition, typename IteratorConnectHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      iterator_connect_op<Protocol, Executor, Iterator,+        ConnectCondition, IteratorConnectHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Protocol, typename Executor, typename Iterator,+      typename ConnectCondition, typename IteratorConnectHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      iterator_connect_op<Protocol, Executor, Iterator,+        ConnectCondition, IteratorConnectHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Protocol, typename Executor, typename Iterator,+      typename ConnectCondition, typename IteratorConnectHandler>+  inline bool asio_handler_is_continuation(+      iterator_connect_op<Protocol, Executor, Iterator,+        ConnectCondition, IteratorConnectHandler>* this_handler)+  {+    return asio_handler_cont_helpers::is_continuation(+        this_handler->handler_);+  }++  template <typename Function, typename Executor, typename Protocol,+      typename Iterator, typename ConnectCondition,+      typename IteratorConnectHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      iterator_connect_op<Protocol, Executor, Iterator,+        ConnectCondition, IteratorConnectHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename Executor, typename Protocol,+      typename Iterator, typename ConnectCondition,+      typename IteratorConnectHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      iterator_connect_op<Protocol, Executor, Iterator,+        ConnectCondition, IteratorConnectHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Protocol, typename Executor>+  class initiate_async_iterator_connect+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_iterator_connect(+        basic_socket<Protocol, Executor>& s)+      : socket_(s)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return socket_.get_executor();+    }++    template <typename IteratorConnectHandler,+        typename Iterator, typename ConnectCondition>+    void operator()(ASIO_MOVE_ARG(IteratorConnectHandler) handler,+        Iterator begin, Iterator end,+        const ConnectCondition& connect_condition) const+    {+      // If you get an error on the following line it means that your+      // handler does not meet the documented type requirements for an+      // IteratorConnectHandler.+      ASIO_ITERATOR_CONNECT_HANDLER_CHECK(+          IteratorConnectHandler, handler, Iterator) type_check;++      non_const_lvalue<IteratorConnectHandler> handler2(handler);+      iterator_connect_op<Protocol, Executor, Iterator, ConnectCondition,+        typename decay<IteratorConnectHandler>::type>(socket_, begin, end,+          connect_condition, handler2.value)(asio::error_code(), 1);+    }++  private:+    basic_socket<Protocol, Executor>& socket_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename Protocol, typename Executor, typename EndpointSequence,+    typename ConnectCondition, typename RangeConnectHandler, typename Allocator>+struct associated_allocator<+    detail::range_connect_op<Protocol, Executor, EndpointSequence,+      ConnectCondition, RangeConnectHandler>, Allocator>+{+  typedef typename associated_allocator<+      RangeConnectHandler, Allocator>::type type;++  static type get(+      const detail::range_connect_op<Protocol, Executor, EndpointSequence,+        ConnectCondition, RangeConnectHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<RangeConnectHandler,+        Allocator>::get(h.handler_, a);+  }+};++template <typename Protocol, typename Executor, typename EndpointSequence,+    typename ConnectCondition, typename RangeConnectHandler, typename Executor1>+struct associated_executor<+    detail::range_connect_op<Protocol, Executor, EndpointSequence,+      ConnectCondition, RangeConnectHandler>, Executor1>+  : detail::associated_executor_forwarding_base<RangeConnectHandler, Executor1>+{+  typedef typename associated_executor<+      RangeConnectHandler, Executor1>::type type;++  static type get(+      const detail::range_connect_op<Protocol, Executor, EndpointSequence,+      ConnectCondition, RangeConnectHandler>& h,+      const Executor1& ex = Executor1()) ASIO_NOEXCEPT+  {+    return associated_executor<RangeConnectHandler,+        Executor1>::get(h.handler_, ex);+  }+};++template <typename Protocol, typename Executor, typename Iterator,+    typename ConnectCondition, typename IteratorConnectHandler,+    typename Allocator>+struct associated_allocator<+    detail::iterator_connect_op<Protocol, Executor,+      Iterator, ConnectCondition, IteratorConnectHandler>,+    Allocator>+{+  typedef typename associated_allocator<+      IteratorConnectHandler, Allocator>::type type;++  static type get(+      const detail::iterator_connect_op<Protocol, Executor,+        Iterator, ConnectCondition, IteratorConnectHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<IteratorConnectHandler,+        Allocator>::get(h.handler_, a);+  }+};++template <typename Protocol, typename Executor, typename Iterator,+    typename ConnectCondition, typename IteratorConnectHandler,+    typename Executor1>+struct associated_executor<+    detail::iterator_connect_op<Protocol, Executor,+      Iterator, ConnectCondition, IteratorConnectHandler>,+    Executor1>+  : detail::associated_executor_forwarding_base<+      IteratorConnectHandler, Executor1>+{+  typedef typename associated_executor<+      IteratorConnectHandler, Executor1>::type type;++  static type get(+      const detail::iterator_connect_op<Protocol, Executor,+        Iterator, ConnectCondition, IteratorConnectHandler>& h,+      const Executor1& ex = Executor1()) ASIO_NOEXCEPT+  {+    return associated_executor<IteratorConnectHandler,+        Executor1>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename Protocol, typename Executor, typename EndpointSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      typename Protocol::endpoint)) RangeConnectHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+    void (asio::error_code, typename Protocol::endpoint))+async_connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints,+    ASIO_MOVE_ARG(RangeConnectHandler) handler,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type*)+{+  return async_initiate<RangeConnectHandler,+    void (asio::error_code, typename Protocol::endpoint)>(+      detail::initiate_async_range_connect<Protocol, Executor>(s),+      handler, endpoints, detail::default_connect_condition());+}++#if !defined(ASIO_NO_DEPRECATED)+template <typename Protocol, typename Executor, typename Iterator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      Iterator)) IteratorConnectHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+    void (asio::error_code, Iterator))+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    ASIO_MOVE_ARG(IteratorConnectHandler) handler,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+{+  return async_initiate<IteratorConnectHandler,+    void (asio::error_code, Iterator)>(+      detail::initiate_async_iterator_connect<Protocol, Executor>(s),+      handler, begin, Iterator(), detail::default_connect_condition());+}+#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Protocol, typename Executor, typename Iterator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      Iterator)) IteratorConnectHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+    void (asio::error_code, Iterator))+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,+    ASIO_MOVE_ARG(IteratorConnectHandler) handler)+{+  return async_initiate<IteratorConnectHandler,+    void (asio::error_code, Iterator)>(+      detail::initiate_async_iterator_connect<Protocol, Executor>(s),+      handler, begin, end, detail::default_connect_condition());+}++template <typename Protocol, typename Executor,+    typename EndpointSequence, typename ConnectCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      typename Protocol::endpoint)) RangeConnectHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+    void (asio::error_code, typename Protocol::endpoint))+async_connect(basic_socket<Protocol, Executor>& s,+    const EndpointSequence& endpoints, ConnectCondition connect_condition,+    ASIO_MOVE_ARG(RangeConnectHandler) handler,+    typename enable_if<is_endpoint_sequence<+        EndpointSequence>::value>::type*)+{+  return async_initiate<RangeConnectHandler,+    void (asio::error_code, typename Protocol::endpoint)>(+      detail::initiate_async_range_connect<Protocol, Executor>(s),+      handler, endpoints, connect_condition);+}++#if !defined(ASIO_NO_DEPRECATED)+template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      Iterator)) IteratorConnectHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+    void (asio::error_code, Iterator))+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    ConnectCondition connect_condition,+    ASIO_MOVE_ARG(IteratorConnectHandler) handler,+    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type*)+{+  return async_initiate<IteratorConnectHandler,+    void (asio::error_code, Iterator)>(+      detail::initiate_async_iterator_connect<Protocol, Executor>(s),+      handler, begin, Iterator(), connect_condition);+}+#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Protocol, typename Executor,+    typename Iterator, typename ConnectCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      Iterator)) IteratorConnectHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+    void (asio::error_code, Iterator))+async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,+    Iterator end, ConnectCondition connect_condition,+    ASIO_MOVE_ARG(IteratorConnectHandler) handler)+{+  return async_initiate<IteratorConnectHandler,+    void (asio::error_code, Iterator)>(+      detail::initiate_async_iterator_connect<Protocol, Executor>(s),+      handler, begin, end, connect_condition);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_CONNECT_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/defer.hpp view
@@ -0,0 +1,248 @@+//+// impl/defer.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_DEFER_HPP+#define ASIO_IMPL_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/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/detail/work_dispatcher.hpp"+#include "asio/execution/allocator.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/execution/relationship.hpp"+#include "asio/prefer.hpp"+#include "asio/require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class initiate_defer+{+public:+  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename associated_executor<+            typename decay<CompletionHandler>::type+          >::type+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_executor<handler_t>::type ex(+        (get_associated_executor)(handler));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    execution::execute(+        asio::prefer(+          asio::require(ex, execution::blocking.never),+          execution::relationship.continuation,+          execution::allocator(alloc)),+        ASIO_MOVE_CAST(CompletionHandler)(handler));+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename associated_executor<+            typename decay<CompletionHandler>::type+          >::type+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_executor<handler_t>::type ex(+        (get_associated_executor)(handler));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    ex.defer(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);+  }+};++template <typename Executor>+class initiate_defer_with_executor+{+public:+  typedef Executor executor_type;++  explicit initiate_defer_with_executor(const Executor& ex)+    : ex_(ex)+  {+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return ex_;+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        !detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    execution::execute(+        asio::prefer(+          asio::require(ex_, execution::blocking.never),+          execution::relationship.continuation,+          execution::allocator(alloc)),+        ASIO_MOVE_CAST(CompletionHandler)(handler));+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typedef typename associated_executor<+      handler_t, Executor>::type handler_ex_t;+    handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    execution::execute(+        asio::prefer(+          asio::require(ex_, execution::blocking.never),+          execution::relationship.continuation,+          execution::allocator(alloc)),+        detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        !detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    ex_.defer(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typedef typename associated_executor<+      handler_t, Executor>::type handler_ex_t;+    handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    ex_.defer(detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler),+          handler_ex), alloc);+  }++private:+  Executor ex_;+};++} // namespace detail++template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+    ASIO_MOVE_ARG(CompletionToken) token)+{+  return async_initiate<CompletionToken, void()>(+      detail::initiate_defer(), token);+}++template <typename Executor,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+    const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token,+    typename enable_if<+      execution::is_executor<Executor>::value || is_executor<Executor>::value+    >::type*)+{+  return async_initiate<CompletionToken, void()>(+      detail::initiate_defer_with_executor<Executor>(ex), token);+}++template <typename ExecutionContext,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+    ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token,+    typename enable_if<is_convertible<+      ExecutionContext&, execution_context&>::value>::type*)+{+  return async_initiate<CompletionToken, void()>(+      detail::initiate_defer_with_executor<+        typename ExecutionContext::executor_type>(+          ctx.get_executor()), token);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_DEFER_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/detached.hpp view
@@ -0,0 +1,130 @@+//+// impl/detached.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_DETACHED_HPP+#define ASIO_IMPL_DETACHED_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/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++  // Class to adapt a detached_t as a completion handler.+  class detached_handler+  {+  public:+    typedef void result_type;++    detached_handler(detached_t)+    {+    }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++    template <typename... Args>+    void operator()(Args...)+    {+    }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++    void operator()()+    {+    }++#define ASIO_PRIVATE_DETACHED_DEF(n) \+    template <ASIO_VARIADIC_TPARAMS(n)> \+    void operator()(ASIO_VARIADIC_TARGS(n)) \+    { \+    } \+    /**/+    ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_DETACHED_DEF)+#undef ASIO_PRIVATE_DETACHED_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+  };++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename Signature>+struct async_result<detached_t, Signature>+{+  typedef asio::detail::detached_handler completion_handler_type;++  typedef void return_type;++  explicit async_result(completion_handler_type&)+  {+  }++  void get()+  {+  }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static return_type initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken),+      ASIO_MOVE_ARG(Args)... args)+  {+    ASIO_MOVE_CAST(Initiation)(initiation)(+        detail::detached_handler(detached_t()),+        ASIO_MOVE_CAST(Args)(args)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken>+  static return_type initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken))+  {+    ASIO_MOVE_CAST(Initiation)(initiation)(+        detail::detached_handler(detached_t()));+  }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, typename RawCompletionToken, \+      ASIO_VARIADIC_TPARAMS(n)> \+  static return_type initiate( \+      ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_MOVE_ARG(RawCompletionToken), \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    ASIO_MOVE_CAST(Initiation)(initiation)( \+        detail::detached_handler(detached_t()), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_DETACHED_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/dispatch.hpp view
@@ -0,0 +1,243 @@+//+// impl/dispatch.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_DISPATCH_HPP+#define ASIO_IMPL_DISPATCH_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/detail/work_dispatcher.hpp"+#include "asio/execution/allocator.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/prefer.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class initiate_dispatch+{+public:+  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename associated_executor<+            typename decay<CompletionHandler>::type+          >::type+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_executor<handler_t>::type ex(+        (get_associated_executor)(handler));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    execution::execute(+        asio::prefer(ex,+          execution::blocking.possibly,+          execution::allocator(alloc)),+        ASIO_MOVE_CAST(CompletionHandler)(handler));+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename associated_executor<+            typename decay<CompletionHandler>::type+          >::type+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_executor<handler_t>::type ex(+        (get_associated_executor)(handler));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    ex.dispatch(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);+  }+};++template <typename Executor>+class initiate_dispatch_with_executor+{+public:+  typedef Executor executor_type;++  explicit initiate_dispatch_with_executor(const Executor& ex)+    : ex_(ex)+  {+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return ex_;+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        !detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    execution::execute(+        asio::prefer(ex_,+          execution::blocking.possibly,+          execution::allocator(alloc)),+        ASIO_MOVE_CAST(CompletionHandler)(handler));+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typedef typename associated_executor<+      handler_t, Executor>::type handler_ex_t;+    handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    execution::execute(+        asio::prefer(ex_,+          execution::blocking.possibly,+          execution::allocator(alloc)),+        detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        !detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    ex_.dispatch(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typedef typename associated_executor<+      handler_t, Executor>::type handler_ex_t;+    handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    ex_.dispatch(detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler),+          handler_ex), alloc);+  }++private:+  Executor ex_;+};++} // namespace detail++template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+    ASIO_MOVE_ARG(CompletionToken) token)+{+  return async_initiate<CompletionToken, void()>(+      detail::initiate_dispatch(), token);+}++template <typename Executor,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+    const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token,+    typename enable_if<+      execution::is_executor<Executor>::value || is_executor<Executor>::value+    >::type*)+{+  return async_initiate<CompletionToken, void()>(+      detail::initiate_dispatch_with_executor<Executor>(ex), token);+}++template <typename ExecutionContext,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+    ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token,+    typename enable_if<is_convertible<+      ExecutionContext&, execution_context&>::value>::type*)+{+  return async_initiate<CompletionToken, void()>(+      detail::initiate_dispatch_with_executor<+        typename ExecutionContext::executor_type>(+          ctx.get_executor()), token);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_DISPATCH_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/error.ipp view
@@ -0,0 +1,128 @@+//+// impl/error.ipp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_ERROR_IPP+#define ASIO_IMPL_ERROR_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace error {++#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++namespace detail {++class netdb_category : public asio::error_category+{+public:+  const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT+  {+    return "asio.netdb";+  }++  std::string message(int value) const+  {+    if (value == error::host_not_found)+      return "Host not found (authoritative)";+    if (value == error::host_not_found_try_again)+      return "Host not found (non-authoritative), try again later";+    if (value == error::no_data)+      return "The query is valid, but it does not have associated data";+    if (value == error::no_recovery)+      return "A non-recoverable error occurred during database lookup";+    return "asio.netdb error";+  }+};++} // namespace detail++const asio::error_category& get_netdb_category()+{+  static detail::netdb_category instance;+  return instance;+}++namespace detail {++class addrinfo_category : public asio::error_category+{+public:+  const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT+  {+    return "asio.addrinfo";+  }++  std::string message(int value) const+  {+    if (value == error::service_not_found)+      return "Service not found";+    if (value == error::socket_type_not_supported)+      return "Socket type not supported";+    return "asio.addrinfo error";+  }+};++} // namespace detail++const asio::error_category& get_addrinfo_category()+{+  static detail::addrinfo_category instance;+  return instance;+}++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++namespace detail {++class misc_category : public asio::error_category+{+public:+  const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT+  {+    return "asio.misc";+  }++  std::string message(int value) const+  {+    if (value == error::already_open)+      return "Already open";+    if (value == error::eof)+      return "End of file";+    if (value == error::not_found)+      return "Element not found";+    if (value == error::fd_set_failure)+      return "The descriptor does not fit into the select call's fd_set";+    return "asio.misc error";+  }+};++} // namespace detail++const asio::error_category& get_misc_category()+{+  static detail::misc_category instance;+  return instance;+}++} // namespace error+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_ERROR_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/error_code.ipp view
@@ -0,0 +1,206 @@+//+// impl/error_code.ipp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_ERROR_CODE_IPP+#define ASIO_IMPL_ERROR_CODE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# include <winerror.h>+#elif defined(ASIO_WINDOWS_RUNTIME)+# include <windows.h>+#else+# include <cerrno>+# include <cstring>+# include <string>+#endif+#include "asio/detail/local_free_on_block_exit.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/error_code.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class system_category : public error_category+{+public:+  const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT+  {+    return "asio.system";+  }++  std::string message(int value) const+  {+#if defined(ASIO_WINDOWS_RUNTIME) || defined(ASIO_WINDOWS_APP)+    std::wstring wmsg(128, wchar_t());+    for (;;)+    {+      DWORD wlength = ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM+          | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value,+          MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),+          &wmsg[0], static_cast<DWORD>(wmsg.size()), 0);+      if (wlength == 0 && ::GetLastError() == ERROR_INSUFFICIENT_BUFFER)+      {+        wmsg.resize(wmsg.size() + wmsg.size() / 2);+        continue;+      }+      if (wlength && wmsg[wlength - 1] == '\n')+        --wlength;+      if (wlength && wmsg[wlength - 1] == '\r')+        --wlength;+      if (wlength)+      {+        std::string msg(wlength * 2, char());+        int length = ::WideCharToMultiByte(CP_ACP, 0,+            wmsg.c_str(), static_cast<int>(wlength),+            &msg[0], static_cast<int>(wlength * 2), 0, 0);+        if (length <= 0)+          return "asio.system error";+        msg.resize(static_cast<std::size_t>(length));+        return msg;+      }+      else+        return "asio.system error";+    }+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+    char* msg = 0;+    DWORD length = ::FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER+        | FORMAT_MESSAGE_FROM_SYSTEM+        | FORMAT_MESSAGE_IGNORE_INSERTS, 0, value,+        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (char*)&msg, 0, 0);+    detail::local_free_on_block_exit local_free_obj(msg);+    if (length && msg[length - 1] == '\n')+      msg[--length] = '\0';+    if (length && msg[length - 1] == '\r')+      msg[--length] = '\0';+    if (length)+      return msg;+    else+      return "asio.system error";+#else // defined(ASIO_WINDOWS_DESKTOP) || defined(__CYGWIN__)+#if !defined(__sun)+    if (value == ECANCELED)+      return "Operation aborted.";+#endif // !defined(__sun)+#if defined(__sun) || defined(__QNX__) || defined(__SYMBIAN32__)+    using namespace std;+    return strerror(value);+#else+    char buf[256] = "";+    using namespace std;+    return strerror_result(strerror_r(value, buf, sizeof(buf)), buf);+#endif+#endif // defined(ASIO_WINDOWS_DESKTOP) || defined(__CYGWIN__)+  }++#if defined(ASIO_HAS_STD_ERROR_CODE)+  std::error_condition default_error_condition(+      int ev) const ASIO_ERROR_CATEGORY_NOEXCEPT+  {+    switch (ev)+    {+    case access_denied:+      return std::errc::permission_denied;+    case address_family_not_supported:+      return std::errc::address_family_not_supported;+    case address_in_use:+      return std::errc::address_in_use;+    case already_connected:+      return std::errc::already_connected;+    case already_started:+      return std::errc::connection_already_in_progress;+    case broken_pipe:+      return std::errc::broken_pipe;+    case connection_aborted:+      return std::errc::connection_aborted;+    case connection_refused:+      return std::errc::connection_refused;+    case connection_reset:+      return std::errc::connection_reset;+    case bad_descriptor:+      return std::errc::bad_file_descriptor;+    case fault:+      return std::errc::bad_address;+    case host_unreachable:+      return std::errc::host_unreachable;+    case in_progress:+      return std::errc::operation_in_progress;+    case interrupted:+      return std::errc::interrupted;+    case invalid_argument:+      return std::errc::invalid_argument;+    case message_size:+      return std::errc::message_size;+    case name_too_long:+      return std::errc::filename_too_long;+    case network_down:+      return std::errc::network_down;+    case network_reset:+      return std::errc::network_reset;+    case network_unreachable:+      return std::errc::network_unreachable;+    case no_descriptors:+      return std::errc::too_many_files_open;+    case no_buffer_space:+      return std::errc::no_buffer_space;+    case no_memory:+      return std::errc::not_enough_memory;+    case no_permission:+      return std::errc::operation_not_permitted;+    case no_protocol_option:+      return std::errc::no_protocol_option;+    case no_such_device:+      return std::errc::no_such_device;+    case not_connected:+      return std::errc::not_connected;+    case not_socket:+      return std::errc::not_a_socket;+    case operation_aborted:+      return std::errc::operation_canceled;+    case operation_not_supported:+      return std::errc::operation_not_supported;+    case shut_down:+      return std::make_error_condition(ev, *this);+    case timed_out:+      return std::errc::timed_out;+    case try_again:+      return std::errc::resource_unavailable_try_again;+    case would_block:+      return std::errc::operation_would_block;+    default:+      return std::make_error_condition(ev, *this);+  }+#endif // defined(ASIO_HAS_STD_ERROR_CODE)++private:+  // Helper function to adapt the result from glibc's variant of strerror_r.+  static const char* strerror_result(int, const char* s) { return s; }+  static const char* strerror_result(const char* s, const char*) { return s; }+};++} // namespace detail++const error_category& system_category()+{+  static detail::system_category instance;+  return instance;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_ERROR_CODE_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/execution_context.hpp view
@@ -0,0 +1,109 @@+//+// impl/execution_context.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_EXECUTION_CONTEXT_HPP+#define ASIO_IMPL_EXECUTION_CONTEXT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/scoped_ptr.hpp"+#include "asio/detail/service_registry.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(GENERATING_DOCUMENTATION)++template <typename Service>+inline Service& use_service(execution_context& e)+{+  // Check that Service meets the necessary type requirements.+  (void)static_cast<execution_context::service*>(static_cast<Service*>(0));++  return e.service_registry_->template use_service<Service>();+}++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Service, typename... Args>+Service& make_service(execution_context& e, ASIO_MOVE_ARG(Args)... args)+{+  detail::scoped_ptr<Service> svc(+      new Service(e, ASIO_MOVE_CAST(Args)(args)...));+  e.service_registry_->template add_service<Service>(svc.get());+  Service& result = *svc;+  svc.release();+  return result;+}++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Service>+Service& make_service(execution_context& e)+{+  detail::scoped_ptr<Service> svc(new Service(e));+  e.service_registry_->template add_service<Service>(svc.get());+  Service& result = *svc;+  svc.release();+  return result;+}++#define ASIO_PRIVATE_MAKE_SERVICE_DEF(n) \+  template <typename Service, ASIO_VARIADIC_TPARAMS(n)> \+  Service& make_service(execution_context& e, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    detail::scoped_ptr<Service> svc( \+        new Service(e, ASIO_VARIADIC_MOVE_ARGS(n))); \+    e.service_registry_->template add_service<Service>(svc.get()); \+    Service& result = *svc; \+    svc.release(); \+    return result; \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_MAKE_SERVICE_DEF)+#undef ASIO_PRIVATE_MAKE_SERVICE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Service>+inline void add_service(execution_context& e, Service* svc)+{+  // Check that Service meets the necessary type requirements.+  (void)static_cast<execution_context::service*>(static_cast<Service*>(0));++  e.service_registry_->template add_service<Service>(svc);+}++template <typename Service>+inline bool has_service(execution_context& e)+{+  // Check that Service meets the necessary type requirements.+  (void)static_cast<execution_context::service*>(static_cast<Service*>(0));++  return e.service_registry_->template has_service<Service>();+}++#endif // !defined(GENERATING_DOCUMENTATION)++inline execution_context& execution_context::service::context()+{+  return owner_;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_EXECUTION_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/execution_context.ipp view
@@ -0,0 +1,82 @@+//+// impl/execution_context.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_EXECUTION_CONTEXT_IPP+#define ASIO_IMPL_EXECUTION_CONTEXT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/service_registry.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++execution_context::execution_context()+  : service_registry_(new asio::detail::service_registry(*this))+{+}++execution_context::~execution_context()+{+  shutdown();+  destroy();+  delete service_registry_;+}++void execution_context::shutdown()+{+  service_registry_->shutdown_services();+}++void execution_context::destroy()+{+  service_registry_->destroy_services();+}++void execution_context::notify_fork(+    asio::execution_context::fork_event event)+{+  service_registry_->notify_fork(event);+}++execution_context::service::service(execution_context& owner)+  : owner_(owner),+    next_(0)+{+}++execution_context::service::~service()+{+}++void execution_context::service::notify_fork(execution_context::fork_event)+{+}++service_already_exists::service_already_exists()+  : std::logic_error("Service already exists.")+{+}++invalid_service_owner::invalid_service_owner()+  : std::logic_error("Invalid service owner.")+{+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_EXECUTION_CONTEXT_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/executor.hpp view
@@ -0,0 +1,301 @@+//+// impl/executor.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_EXECUTOR_HPP+#define ASIO_IMPL_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_NO_TS_EXECUTORS)++#include "asio/detail/atomic_count.hpp"+#include "asio/detail/global.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/executor.hpp"+#include "asio/system_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(GENERATING_DOCUMENTATION)++// Default polymorphic executor implementation.+template <typename Executor, typename Allocator>+class executor::impl+  : public executor::impl_base+{+public:+  typedef ASIO_REBIND_ALLOC(Allocator, impl) allocator_type;++  static impl_base* create(const Executor& e, Allocator a = Allocator())+  {+    raw_mem mem(a);+    impl* p = new (mem.ptr_) impl(e, a);+    mem.ptr_ = 0;+    return p;+  }++  impl(const Executor& e, const Allocator& a) ASIO_NOEXCEPT+    : impl_base(false),+      ref_count_(1),+      executor_(e),+      allocator_(a)+  {+  }++  impl_base* clone() const ASIO_NOEXCEPT+  {+    detail::ref_count_up(ref_count_);+    return const_cast<impl_base*>(static_cast<const impl_base*>(this));+  }++  void destroy() ASIO_NOEXCEPT+  {+    if (detail::ref_count_down(ref_count_))+    {+      allocator_type alloc(allocator_);+      impl* p = this;+      p->~impl();+      alloc.deallocate(p, 1);+    }+  }++  void on_work_started() ASIO_NOEXCEPT+  {+    executor_.on_work_started();+  }++  void on_work_finished() ASIO_NOEXCEPT+  {+    executor_.on_work_finished();+  }++  execution_context& context() ASIO_NOEXCEPT+  {+    return executor_.context();+  }++  void dispatch(ASIO_MOVE_ARG(function) f)+  {+    executor_.dispatch(ASIO_MOVE_CAST(function)(f), allocator_);+  }++  void post(ASIO_MOVE_ARG(function) f)+  {+    executor_.post(ASIO_MOVE_CAST(function)(f), allocator_);+  }++  void defer(ASIO_MOVE_ARG(function) f)+  {+    executor_.defer(ASIO_MOVE_CAST(function)(f), allocator_);+  }++  type_id_result_type target_type() const ASIO_NOEXCEPT+  {+    return type_id<Executor>();+  }++  void* target() ASIO_NOEXCEPT+  {+    return &executor_;+  }++  const void* target() const ASIO_NOEXCEPT+  {+    return &executor_;+  }++  bool equals(const impl_base* e) const ASIO_NOEXCEPT+  {+    if (this == e)+      return true;+    if (target_type() != e->target_type())+      return false;+    return executor_ == *static_cast<const Executor*>(e->target());+  }++private:+  mutable detail::atomic_count ref_count_;+  Executor executor_;+  Allocator allocator_;++  struct raw_mem+  {+    allocator_type allocator_;+    impl* ptr_;++    explicit raw_mem(const Allocator& a)+      : allocator_(a),+        ptr_(allocator_.allocate(1))+    {+    }++    ~raw_mem()+    {+      if (ptr_)+        allocator_.deallocate(ptr_, 1);+    }++  private:+    // Disallow copying and assignment.+    raw_mem(const raw_mem&);+    raw_mem operator=(const raw_mem&);+  };+};++// Polymorphic executor specialisation for system_executor.+template <typename Allocator>+class executor::impl<system_executor, Allocator>+  : public executor::impl_base+{+public:+  static impl_base* create(const system_executor&,+      const Allocator& = Allocator())+  {+    return &detail::global<impl<system_executor, std::allocator<void> > >();+  }++  impl()+    : impl_base(true)+  {+  }++  impl_base* clone() const ASIO_NOEXCEPT+  {+    return const_cast<impl_base*>(static_cast<const impl_base*>(this));+  }++  void destroy() ASIO_NOEXCEPT+  {+  }++  void on_work_started() ASIO_NOEXCEPT+  {+    executor_.on_work_started();+  }++  void on_work_finished() ASIO_NOEXCEPT+  {+    executor_.on_work_finished();+  }++  execution_context& context() ASIO_NOEXCEPT+  {+    return executor_.context();+  }++  void dispatch(ASIO_MOVE_ARG(function) f)+  {+    executor_.dispatch(ASIO_MOVE_CAST(function)(f),+        std::allocator<void>());+  }++  void post(ASIO_MOVE_ARG(function) f)+  {+    executor_.post(ASIO_MOVE_CAST(function)(f),+        std::allocator<void>());+  }++  void defer(ASIO_MOVE_ARG(function) f)+  {+    executor_.defer(ASIO_MOVE_CAST(function)(f),+        std::allocator<void>());+  }++  type_id_result_type target_type() const ASIO_NOEXCEPT+  {+    return type_id<system_executor>();+  }++  void* target() ASIO_NOEXCEPT+  {+    return &executor_;+  }++  const void* target() const ASIO_NOEXCEPT+  {+    return &executor_;+  }++  bool equals(const impl_base* e) const ASIO_NOEXCEPT+  {+    return this == e;+  }++private:+  system_executor executor_;+};++template <typename Executor>+executor::executor(Executor e)+  : impl_(impl<Executor, std::allocator<void> >::create(e))+{+}++template <typename Executor, typename Allocator>+executor::executor(allocator_arg_t, const Allocator& a, Executor e)+  : impl_(impl<Executor, Allocator>::create(e, a))+{+}++template <typename Function, typename Allocator>+void executor::dispatch(ASIO_MOVE_ARG(Function) f,+    const Allocator& a) const+{+  impl_base* i = get_impl();+  if (i->fast_dispatch_)+    system_executor().dispatch(ASIO_MOVE_CAST(Function)(f), a);+  else+    i->dispatch(function(ASIO_MOVE_CAST(Function)(f), a));+}++template <typename Function, typename Allocator>+void executor::post(ASIO_MOVE_ARG(Function) f,+    const Allocator& a) const+{+  get_impl()->post(function(ASIO_MOVE_CAST(Function)(f), a));+}++template <typename Function, typename Allocator>+void executor::defer(ASIO_MOVE_ARG(Function) f,+    const Allocator& a) const+{+  get_impl()->defer(function(ASIO_MOVE_CAST(Function)(f), a));+}++template <typename Executor>+Executor* executor::target() ASIO_NOEXCEPT+{+  return impl_ && impl_->target_type() == type_id<Executor>()+    ? static_cast<Executor*>(impl_->target()) : 0;+}++template <typename Executor>+const Executor* executor::target() const ASIO_NOEXCEPT+{+  return impl_ && impl_->target_type() == type_id<Executor>()+    ? static_cast<Executor*>(impl_->target()) : 0;+}++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_TS_EXECUTORS)++#endif // ASIO_IMPL_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/executor.ipp view
@@ -0,0 +1,43 @@+//+// impl/executor.ipp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_EXECUTOR_IPP+#define ASIO_IMPL_EXECUTOR_IPP++#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_TS_EXECUTORS)++#include "asio/executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++bad_executor::bad_executor() ASIO_NOEXCEPT+{+}++const char* bad_executor::what() const ASIO_NOEXCEPT_OR_NOTHROW+{+  return "bad executor";+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_TS_EXECUTORS)++#endif // ASIO_IMPL_EXECUTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/handler_alloc_hook.ipp view
@@ -0,0 +1,61 @@+//+// impl/handler_alloc_hook.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_HANDLER_ALLOC_HOOK_IPP+#define ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/thread_context.hpp"+#include "asio/detail/thread_info_base.hpp"+#include "asio/handler_alloc_hook.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size, ...)+{+#if defined(ASIO_NO_DEPRECATED)+  (void)size;+  return asio_handler_allocate_is_no_longer_used();+#elif !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+  return detail::thread_info_base::allocate(+      detail::thread_context::thread_call_stack::top(), size);+#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+  return ::operator new(size);+#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+}++asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size, ...)+{+#if defined(ASIO_NO_DEPRECATED)+  (void)pointer;+  (void)size;+  return asio_handler_deallocate_is_no_longer_used();+#elif !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+  detail::thread_info_base::deallocate(+      detail::thread_context::thread_call_stack::top(), pointer, size);+#else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+  (void)size;+  ::operator delete(pointer);+#endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_HANDLER_ALLOC_HOOK_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/io_context.hpp view
@@ -0,0 +1,440 @@+//+// impl/io_context.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_IO_CONTEXT_HPP+#define ASIO_IMPL_IO_CONTEXT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/completion_handler.hpp"+#include "asio/detail/executor_op.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/detail/service_registry.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(GENERATING_DOCUMENTATION)++template <typename Service>+inline Service& use_service(io_context& ioc)+{+  // Check that Service meets the necessary type requirements.+  (void)static_cast<execution_context::service*>(static_cast<Service*>(0));+  (void)static_cast<const execution_context::id*>(&Service::id);++  return ioc.service_registry_->template use_service<Service>(ioc);+}++template <>+inline detail::io_context_impl& use_service<detail::io_context_impl>(+    io_context& ioc)+{+  return ioc.impl_;+}++#endif // !defined(GENERATING_DOCUMENTATION)++inline io_context::executor_type+io_context::get_executor() ASIO_NOEXCEPT+{+  return executor_type(*this);+}++#if defined(ASIO_HAS_CHRONO)++template <typename Rep, typename Period>+std::size_t io_context::run_for(+    const chrono::duration<Rep, Period>& rel_time)+{+  return this->run_until(chrono::steady_clock::now() + rel_time);+}++template <typename Clock, typename Duration>+std::size_t io_context::run_until(+    const chrono::time_point<Clock, Duration>& abs_time)+{+  std::size_t n = 0;+  while (this->run_one_until(abs_time))+    if (n != (std::numeric_limits<std::size_t>::max)())+      ++n;+  return n;+}++template <typename Rep, typename Period>+std::size_t io_context::run_one_for(+    const chrono::duration<Rep, Period>& rel_time)+{+  return this->run_one_until(chrono::steady_clock::now() + rel_time);+}++template <typename Clock, typename Duration>+std::size_t io_context::run_one_until(+    const chrono::time_point<Clock, Duration>& abs_time)+{+  typename Clock::time_point now = Clock::now();+  while (now < abs_time)+  {+    typename Clock::duration rel_time = abs_time - now;+    if (rel_time > chrono::seconds(1))+      rel_time = chrono::seconds(1);++    asio::error_code ec;+    std::size_t s = impl_.wait_one(+        static_cast<long>(chrono::duration_cast<+          chrono::microseconds>(rel_time).count()), ec);+    asio::detail::throw_error(ec);++    if (s || impl_.stopped())+      return s;++    now = Clock::now();+  }++  return 0;+}++#endif // defined(ASIO_HAS_CHRONO)++#if !defined(ASIO_NO_DEPRECATED)++inline void io_context::reset()+{+  restart();+}++struct io_context::initiate_dispatch+{+  template <typename LegacyCompletionHandler>+  void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler,+      io_context* self) const+  {+    // If you get an error on the following line it means that your handler does+    // not meet the documented type requirements for a LegacyCompletionHandler.+    ASIO_LEGACY_COMPLETION_HANDLER_CHECK(+        LegacyCompletionHandler, handler) type_check;++    detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler);+    if (self->impl_.can_dispatch())+    {+      detail::fenced_block b(detail::fenced_block::full);+      asio_handler_invoke_helpers::invoke(+          handler2.value, handler2.value);+    }+    else+    {+      // Allocate and construct an operation to wrap the handler.+      typedef detail::completion_handler<+        typename decay<LegacyCompletionHandler>::type, executor_type> op;+      typename op::ptr p = { detail::addressof(handler2.value),+        op::ptr::allocate(handler2.value), 0 };+      p.p = new (p.v) op(handler2.value, self->get_executor());++      ASIO_HANDLER_CREATION((*self, *p.p,+            "io_context", self, 0, "dispatch"));++      self->impl_.do_dispatch(p.p);+      p.v = p.p = 0;+    }+  }+};++template <typename LegacyCompletionHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+io_context::dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+{+  return async_initiate<LegacyCompletionHandler, void ()>(+      initiate_dispatch(), handler, this);+}++struct io_context::initiate_post+{+  template <typename LegacyCompletionHandler>+  void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler,+      io_context* self) const+  {+    // If you get an error on the following line it means that your handler does+    // not meet the documented type requirements for a LegacyCompletionHandler.+    ASIO_LEGACY_COMPLETION_HANDLER_CHECK(+        LegacyCompletionHandler, handler) type_check;++    detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler);++    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler2.value);++    // Allocate and construct an operation to wrap the handler.+    typedef detail::completion_handler<+      typename decay<LegacyCompletionHandler>::type, executor_type> op;+    typename op::ptr p = { detail::addressof(handler2.value),+        op::ptr::allocate(handler2.value), 0 };+    p.p = new (p.v) op(handler2.value, self->get_executor());++    ASIO_HANDLER_CREATION((*self, *p.p,+          "io_context", self, 0, "post"));++    self->impl_.post_immediate_completion(p.p, is_continuation);+    p.v = p.p = 0;+  }+};++template <typename LegacyCompletionHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+io_context::post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+{+  return async_initiate<LegacyCompletionHandler, void ()>(+      initiate_post(), handler, this);+}++template <typename Handler>+#if defined(GENERATING_DOCUMENTATION)+unspecified+#else+inline detail::wrapped_handler<io_context&, Handler>+#endif+io_context::wrap(Handler handler)+{+  return detail::wrapped_handler<io_context&, Handler>(*this, handler);+}++#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Allocator, unsigned int Bits>+io_context::basic_executor_type<Allocator, Bits>&+io_context::basic_executor_type<Allocator, Bits>::operator=(+    const basic_executor_type& other) ASIO_NOEXCEPT+{+  if (this != &other)+  {+    io_context* old_io_context = io_context_;+    io_context_ = other.io_context_;+    allocator_ = other.allocator_;+    bits_ = other.bits_;+    if (Bits & outstanding_work_tracked)+    {+      if (io_context_)+        io_context_->impl_.work_started();+      if (old_io_context)+        old_io_context->impl_.work_finished();+    }+  }+  return *this;+}++#if defined(ASIO_HAS_MOVE)+template <typename Allocator, unsigned int Bits>+io_context::basic_executor_type<Allocator, Bits>&+io_context::basic_executor_type<Allocator, Bits>::operator=(+    basic_executor_type&& other) ASIO_NOEXCEPT+{+  if (this != &other)+  {+    io_context_ = other.io_context_;+    allocator_ = std::move(other.allocator_);+    bits_ = other.bits_;+    if (Bits & outstanding_work_tracked)+      other.io_context_ = 0;+  }+  return *this;+}+#endif // defined(ASIO_HAS_MOVE)++template <typename Allocator, unsigned int Bits>+inline bool io_context::basic_executor_type<Allocator,+    Bits>::running_in_this_thread() const ASIO_NOEXCEPT+{+  return io_context_->impl_.can_dispatch();+}++template <typename Allocator, unsigned int Bits>+template <typename Function>+void io_context::basic_executor_type<Allocator, Bits>::execute(+    ASIO_MOVE_ARG(Function) f) const+{+  typedef typename decay<Function>::type function_type;++  // Invoke immediately if the blocking.possibly property is enabled and we are+  // already inside the thread pool.+  if ((bits_ & blocking_never) == 0 && io_context_->impl_.can_dispatch())+  {+    // Make a local, non-const copy of the function.+    function_type tmp(ASIO_MOVE_CAST(Function)(f));++#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  && !defined(ASIO_NO_EXCEPTIONS)+    try+    {+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       //   && !defined(ASIO_NO_EXCEPTIONS)+      detail::fenced_block b(detail::fenced_block::full);+      asio_handler_invoke_helpers::invoke(tmp, tmp);+      return;+#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  && !defined(ASIO_NO_EXCEPTIONS)+    }+    catch (...)+    {+      io_context_->impl_.capture_current_exception();+      return;+    }+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       //   && !defined(ASIO_NO_EXCEPTIONS)+  }++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type, Allocator, detail::operation> op;+  typename op::ptr p = { detail::addressof(allocator_),+      op::ptr::allocate(allocator_), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), allocator_);++  ASIO_HANDLER_CREATION((*io_context_, *p.p,+        "io_context", io_context_, 0, "execute"));++  io_context_->impl_.post_immediate_completion(p.p,+      (bits_ & relationship_continuation) != 0);+  p.v = p.p = 0;+}++#if !defined(ASIO_NO_TS_EXECUTORS)+template <typename Allocator, unsigned int Bits>+inline io_context& io_context::basic_executor_type<+    Allocator, Bits>::context() const ASIO_NOEXCEPT+{+  return *io_context_;+}++template <typename Allocator, unsigned int Bits>+inline void io_context::basic_executor_type<Allocator,+    Bits>::on_work_started() const ASIO_NOEXCEPT+{+  io_context_->impl_.work_started();+}++template <typename Allocator, unsigned int Bits>+inline void io_context::basic_executor_type<Allocator,+    Bits>::on_work_finished() const ASIO_NOEXCEPT+{+  io_context_->impl_.work_finished();+}++template <typename Allocator, unsigned int Bits>+template <typename Function, typename OtherAllocator>+void io_context::basic_executor_type<Allocator, Bits>::dispatch(+    ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const+{+  typedef typename decay<Function>::type function_type;++  // Invoke immediately if we are already inside the thread pool.+  if (io_context_->impl_.can_dispatch())+  {+    // Make a local, non-const copy of the function.+    function_type tmp(ASIO_MOVE_CAST(Function)(f));++    detail::fenced_block b(detail::fenced_block::full);+    asio_handler_invoke_helpers::invoke(tmp, tmp);+    return;+  }++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type,+      OtherAllocator, detail::operation> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);++  ASIO_HANDLER_CREATION((*io_context_, *p.p,+        "io_context", io_context_, 0, "dispatch"));++  io_context_->impl_.post_immediate_completion(p.p, false);+  p.v = p.p = 0;+}++template <typename Allocator, unsigned int Bits>+template <typename Function, typename OtherAllocator>+void io_context::basic_executor_type<Allocator, Bits>::post(+    ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const+{+  typedef typename decay<Function>::type function_type;++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type,+      OtherAllocator, detail::operation> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);++  ASIO_HANDLER_CREATION((*io_context_, *p.p,+        "io_context", io_context_, 0, "post"));++  io_context_->impl_.post_immediate_completion(p.p, false);+  p.v = p.p = 0;+}++template <typename Allocator, unsigned int Bits>+template <typename Function, typename OtherAllocator>+void io_context::basic_executor_type<Allocator, Bits>::defer(+    ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const+{+  typedef typename decay<Function>::type function_type;++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type,+      OtherAllocator, detail::operation> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);++  ASIO_HANDLER_CREATION((*io_context_, *p.p,+        "io_context", io_context_, 0, "defer"));++  io_context_->impl_.post_immediate_completion(p.p, true);+  p.v = p.p = 0;+}+#endif // !defined(ASIO_NO_TS_EXECUTORS)++#if !defined(ASIO_NO_DEPRECATED)+inline io_context::work::work(asio::io_context& io_context)+  : io_context_impl_(io_context.impl_)+{+  io_context_impl_.work_started();+}++inline io_context::work::work(const work& other)+  : io_context_impl_(other.io_context_impl_)+{+  io_context_impl_.work_started();+}++inline io_context::work::~work()+{+  io_context_impl_.work_finished();+}++inline asio::io_context& io_context::work::get_io_context()+{+  return static_cast<asio::io_context&>(io_context_impl_.context());+}+#endif // !defined(ASIO_NO_DEPRECATED)++inline asio::io_context& io_context::service::get_io_context()+{+  return static_cast<asio::io_context&>(context());+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_IO_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/io_context.ipp view
@@ -0,0 +1,175 @@+//+// impl/io_context.ipp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_IO_CONTEXT_IPP+#define ASIO_IMPL_IO_CONTEXT_IPP++#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/concurrency_hint.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/scoped_ptr.hpp"+#include "asio/detail/service_registry.hpp"+#include "asio/detail/throw_error.hpp"++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else+# include "asio/detail/scheduler.hpp"+#endif++#include "asio/detail/push_options.hpp"++namespace asio {++io_context::io_context()+  : impl_(add_impl(new impl_type(*this,+          ASIO_CONCURRENCY_HINT_DEFAULT, false)))+{+}++io_context::io_context(int concurrency_hint)+  : impl_(add_impl(new impl_type(*this, concurrency_hint == 1+          ? ASIO_CONCURRENCY_HINT_1 : concurrency_hint, false)))+{+}++io_context::impl_type& io_context::add_impl(io_context::impl_type* impl)+{+  asio::detail::scoped_ptr<impl_type> scoped_impl(impl);+  asio::add_service<impl_type>(*this, scoped_impl.get());+  return *scoped_impl.release();+}++io_context::~io_context()+{+}++io_context::count_type io_context::run()+{+  asio::error_code ec;+  count_type s = impl_.run(ec);+  asio::detail::throw_error(ec);+  return s;+}++#if !defined(ASIO_NO_DEPRECATED)+io_context::count_type io_context::run(asio::error_code& ec)+{+  return impl_.run(ec);+}+#endif // !defined(ASIO_NO_DEPRECATED)++io_context::count_type io_context::run_one()+{+  asio::error_code ec;+  count_type s = impl_.run_one(ec);+  asio::detail::throw_error(ec);+  return s;+}++#if !defined(ASIO_NO_DEPRECATED)+io_context::count_type io_context::run_one(asio::error_code& ec)+{+  return impl_.run_one(ec);+}+#endif // !defined(ASIO_NO_DEPRECATED)++io_context::count_type io_context::poll()+{+  asio::error_code ec;+  count_type s = impl_.poll(ec);+  asio::detail::throw_error(ec);+  return s;+}++#if !defined(ASIO_NO_DEPRECATED)+io_context::count_type io_context::poll(asio::error_code& ec)+{+  return impl_.poll(ec);+}+#endif // !defined(ASIO_NO_DEPRECATED)++io_context::count_type io_context::poll_one()+{+  asio::error_code ec;+  count_type s = impl_.poll_one(ec);+  asio::detail::throw_error(ec);+  return s;+}++#if !defined(ASIO_NO_DEPRECATED)+io_context::count_type io_context::poll_one(asio::error_code& ec)+{+  return impl_.poll_one(ec);+}+#endif // !defined(ASIO_NO_DEPRECATED)++void io_context::stop()+{+  impl_.stop();+}++bool io_context::stopped() const+{+  return impl_.stopped();+}++void io_context::restart()+{+  impl_.restart();+}++io_context::service::service(asio::io_context& owner)+  : execution_context::service(owner)+{+}++io_context::service::~service()+{+}++void io_context::service::shutdown()+{+#if !defined(ASIO_NO_DEPRECATED)+  shutdown_service();+#endif // !defined(ASIO_NO_DEPRECATED)+}++#if !defined(ASIO_NO_DEPRECATED)+void io_context::service::shutdown_service()+{+}+#endif // !defined(ASIO_NO_DEPRECATED)++void io_context::service::notify_fork(io_context::fork_event ev)+{+#if !defined(ASIO_NO_DEPRECATED)+  fork_service(ev);+#else // !defined(ASIO_NO_DEPRECATED)+  (void)ev;+#endif // !defined(ASIO_NO_DEPRECATED)+}++#if !defined(ASIO_NO_DEPRECATED)+void io_context::service::fork_service(io_context::fork_event)+{+}+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_IO_CONTEXT_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/multiple_exceptions.ipp view
@@ -0,0 +1,49 @@+//+// impl/multiple_exceptions.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_MULTIPLE_EXCEPTIONS_IPP+#define ASIO_IMPL_MULTIPLE_EXCEPTIONS_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/multiple_exceptions.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(ASIO_HAS_STD_EXCEPTION_PTR)++multiple_exceptions::multiple_exceptions(+    std::exception_ptr first) ASIO_NOEXCEPT+  : first_(ASIO_MOVE_CAST(std::exception_ptr)(first))+{+}++const char* multiple_exceptions::what() const ASIO_NOEXCEPT_OR_NOTHROW+{+  return "multiple exceptions";+}++std::exception_ptr multiple_exceptions::first_exception() const+{+  return first_;+}++#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_MULTIPLE_EXCEPTIONS_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/post.hpp view
@@ -0,0 +1,248 @@+//+// impl/post.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_POST_HPP+#define ASIO_IMPL_POST_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/detail/work_dispatcher.hpp"+#include "asio/execution/allocator.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/execution/relationship.hpp"+#include "asio/prefer.hpp"+#include "asio/require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class initiate_post+{+public:+  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename associated_executor<+            typename decay<CompletionHandler>::type+          >::type+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_executor<handler_t>::type ex(+        (get_associated_executor)(handler));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    execution::execute(+        asio::prefer(+          asio::require(ex, execution::blocking.never),+          execution::relationship.fork,+          execution::allocator(alloc)),+        ASIO_MOVE_CAST(CompletionHandler)(handler));+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename associated_executor<+            typename decay<CompletionHandler>::type+          >::type+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_executor<handler_t>::type ex(+        (get_associated_executor)(handler));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    ex.post(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);+  }+};++template <typename Executor>+class initiate_post_with_executor+{+public:+  typedef Executor executor_type;++  explicit initiate_post_with_executor(const Executor& ex)+    : ex_(ex)+  {+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return ex_;+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        !detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    execution::execute(+        asio::prefer(+          asio::require(ex_, execution::blocking.never),+          execution::relationship.fork,+          execution::allocator(alloc)),+        ASIO_MOVE_CAST(CompletionHandler)(handler));+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typedef typename associated_executor<+      handler_t, Executor>::type handler_ex_t;+    handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    execution::execute(+        asio::prefer(+          asio::require(ex_, execution::blocking.never),+          execution::relationship.fork,+          execution::allocator(alloc)),+        detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        !detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    ex_.post(ASIO_MOVE_CAST(CompletionHandler)(handler), alloc);+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+        &&+        detail::is_work_dispatcher_required<+          typename decay<CompletionHandler>::type,+          Executor+        >::value+      >::type* = 0) const+  {+    typedef typename decay<CompletionHandler>::type handler_t;++    typedef typename associated_executor<+      handler_t, Executor>::type handler_ex_t;+    handler_ex_t handler_ex((get_associated_executor)(handler, ex_));++    typename associated_allocator<handler_t>::type alloc(+        (get_associated_allocator)(handler));++    ex_.post(detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler),+          handler_ex), alloc);+  }++private:+  Executor ex_;+};++} // namespace detail++template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+    ASIO_MOVE_ARG(CompletionToken) token)+{+  return async_initiate<CompletionToken, void()>(+      detail::initiate_post(), token);+}++template <typename Executor,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+    const Executor& ex, ASIO_MOVE_ARG(CompletionToken) token,+    typename enable_if<+      execution::is_executor<Executor>::value || is_executor<Executor>::value+    >::type*)+{+  return async_initiate<CompletionToken, void()>(+      detail::initiate_post_with_executor<Executor>(ex), token);+}++template <typename ExecutionContext,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+    ExecutionContext& ctx, ASIO_MOVE_ARG(CompletionToken) token,+    typename enable_if<is_convertible<+      ExecutionContext&, execution_context&>::value>::type*)+{+  return async_initiate<CompletionToken, void()>(+      detail::initiate_post_with_executor<+        typename ExecutionContext::executor_type>(+          ctx.get_executor()), token);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_POST_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/read.hpp view
@@ -0,0 +1,1202 @@+//+// impl/read.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_READ_HPP+#define ASIO_IMPL_READ_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include <algorithm>+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/buffer.hpp"+#include "asio/completion_condition.hpp"+#include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_completion_cond.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/consuming_buffers.hpp"+#include "asio/detail/dependent_type.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_tracking.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 {++namespace detail+{+  template <typename SyncReadStream, typename MutableBufferSequence,+      typename MutableBufferIterator, typename CompletionCondition>+  std::size_t read_buffer_sequence(SyncReadStream& s,+      const MutableBufferSequence& buffers, const MutableBufferIterator&,+      CompletionCondition completion_condition, asio::error_code& ec)+  {+    ec = asio::error_code();+    asio::detail::consuming_buffers<mutable_buffer,+        MutableBufferSequence, MutableBufferIterator> tmp(buffers);+    while (!tmp.empty())+    {+      if (std::size_t max_size = detail::adapt_completion_condition_result(+            completion_condition(ec, tmp.total_consumed())))+        tmp.consume(s.read_some(tmp.prepare(max_size), ec));+      else+        break;+    }+    return tmp.total_consumed();;+  }+} // namespace detail++template <typename SyncReadStream, typename MutableBufferSequence,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type*)+{+  return detail::read_buffer_sequence(s, buffers,+      asio::buffer_sequence_begin(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+}++template <typename SyncReadStream, typename MutableBufferSequence>+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);+  asio::detail::throw_error(ec, "read");+  return bytes_transferred;+}++template <typename SyncReadStream, typename MutableBufferSequence>+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,+    asio::error_code& ec,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type*)+{+  return read(s, buffers, transfer_all(), ec);+}++template <typename SyncReadStream, typename MutableBufferSequence,+    typename CompletionCondition>+inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read(s, buffers,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "read");+  return bytes_transferred;+}++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++template <typename SyncReadStream, typename DynamicBuffer_v1,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  typename decay<DynamicBuffer_v1>::type b(+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));++  ec = asio::error_code();+  std::size_t total_transferred = 0;+  std::size_t max_size = detail::adapt_completion_condition_result(+        completion_condition(ec, total_transferred));+  std::size_t bytes_available = std::min<std::size_t>(+        std::max<std::size_t>(512, b.capacity() - b.size()),+        std::min<std::size_t>(max_size, b.max_size() - b.size()));+  while (bytes_available > 0)+  {+    std::size_t bytes_transferred = s.read_some(b.prepare(bytes_available), ec);+    b.commit(bytes_transferred);+    total_transferred += bytes_transferred;+    max_size = detail::adapt_completion_condition_result(+          completion_condition(ec, total_transferred));+    bytes_available = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(max_size, b.max_size() - b.size()));+  }+  return total_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v1>+inline std::size_t read(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), transfer_all(), ec);+  asio::detail::throw_error(ec, "read");+  return bytes_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v1>+inline std::size_t read(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return read(s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      transfer_all(), ec);+}++template <typename SyncReadStream, typename DynamicBuffer_v1,+    typename CompletionCondition>+inline std::size_t read(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "read");+  return bytes_transferred;+}++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++template <typename SyncReadStream, typename Allocator,+    typename CompletionCondition>+inline std::size_t read(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition, asio::error_code& ec)+{+  return read(s, basic_streambuf_ref<Allocator>(b),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+}++template <typename SyncReadStream, typename Allocator>+inline std::size_t read(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b)+{+  return read(s, basic_streambuf_ref<Allocator>(b));+}++template <typename SyncReadStream, typename Allocator>+inline std::size_t read(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    asio::error_code& ec)+{+  return read(s, basic_streambuf_ref<Allocator>(b), ec);+}++template <typename SyncReadStream, typename Allocator,+    typename CompletionCondition>+inline std::size_t read(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition)+{+  return read(s, basic_streambuf_ref<Allocator>(b),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++template <typename SyncReadStream, typename DynamicBuffer_v2,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  DynamicBuffer_v2& b = buffers;++  ec = asio::error_code();+  std::size_t total_transferred = 0;+  std::size_t max_size = detail::adapt_completion_condition_result(+        completion_condition(ec, total_transferred));+  std::size_t bytes_available = std::min<std::size_t>(+        std::max<std::size_t>(512, b.capacity() - b.size()),+        std::min<std::size_t>(max_size, b.max_size() - b.size()));+  while (bytes_available > 0)+  {+    std::size_t pos = b.size();+    b.grow(bytes_available);+    std::size_t bytes_transferred = s.read_some(+        b.data(pos, bytes_available), ec);+    b.shrink(bytes_available - bytes_transferred);+    total_transferred += bytes_transferred;+    max_size = detail::adapt_completion_condition_result(+          completion_condition(ec, total_transferred));+    bytes_available = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(max_size, b.max_size() - b.size()));+  }+  return total_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v2>+inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), transfer_all(), ec);+  asio::detail::throw_error(ec, "read");+  return bytes_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v2>+inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,+    asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return read(s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      transfer_all(), ec);+}++template <typename SyncReadStream, typename DynamicBuffer_v2,+    typename CompletionCondition>+inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "read");+  return bytes_transferred;+}++namespace detail+{+  template <typename AsyncReadStream, typename MutableBufferSequence,+      typename MutableBufferIterator, typename CompletionCondition,+      typename ReadHandler>+  class read_op+    : detail::base_from_completion_cond<CompletionCondition>+  {+  public:+    read_op(AsyncReadStream& stream, const MutableBufferSequence& buffers,+        CompletionCondition& completion_condition, ReadHandler& handler)+      : detail::base_from_completion_cond<+          CompletionCondition>(completion_condition),+        stream_(stream),+        buffers_(buffers),+        start_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_op(const read_op& other)+      : detail::base_from_completion_cond<CompletionCondition>(other),+        stream_(other.stream_),+        buffers_(other.buffers_),+        start_(other.start_),+        handler_(other.handler_)+    {+    }++    read_op(read_op&& other)+      : detail::base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(detail::base_from_completion_cond<+            CompletionCondition>)(other)),+        stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)),+        start_(other.start_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      std::size_t max_size;+      switch (start_ = start)+      {+        case 1:+        max_size = this->check_for_completion(ec, buffers_.total_consumed());+        do+        {+          {+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));+            stream_.async_read_some(buffers_.prepare(max_size),+                ASIO_MOVE_CAST(read_op)(*this));+          }+          return; default:+          buffers_.consume(bytes_transferred);+          if ((!ec && bytes_transferred == 0) || buffers_.empty())+            break;+          max_size = this->check_for_completion(ec, buffers_.total_consumed());+        } while (max_size > 0);++        handler_(ec, buffers_.total_consumed());+      }+    }++  //private:+    typedef asio::detail::consuming_buffers<mutable_buffer,+        MutableBufferSequence, MutableBufferIterator> buffers_type;++    AsyncReadStream& stream_;+    buffers_type buffers_;+    int start_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream, typename MutableBufferSequence,+      typename MutableBufferIterator, typename CompletionCondition,+      typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,+        CompletionCondition, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename MutableBufferSequence,+      typename MutableBufferIterator, typename CompletionCondition,+      typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename MutableBufferSequence,+      typename MutableBufferIterator, typename CompletionCondition,+      typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,+        CompletionCondition, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename MutableBufferSequence, typename MutableBufferIterator,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename MutableBufferSequence, typename MutableBufferIterator,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_op<AsyncReadStream, MutableBufferSequence, MutableBufferIterator,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename MutableBufferSequence,+      typename MutableBufferIterator, typename CompletionCondition,+      typename ReadHandler>+  inline void start_read_buffer_sequence_op(AsyncReadStream& stream,+      const MutableBufferSequence& buffers, const MutableBufferIterator&,+      CompletionCondition& completion_condition, ReadHandler& handler)+  {+    detail::read_op<AsyncReadStream, MutableBufferSequence,+      MutableBufferIterator, CompletionCondition, ReadHandler>(+        stream, buffers, completion_condition, handler)(+          asio::error_code(), 0, 1);+  }++  template <typename AsyncReadStream>+  class initiate_async_read_buffer_sequence+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_buffer_sequence(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler, typename MutableBufferSequence,+        typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        const MutableBufferSequence& buffers,+        ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);+      start_read_buffer_sequence_op(stream_, buffers,+          asio::buffer_sequence_begin(buffers),+          completion_cond2.value, handler2.value);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename MutableBufferSequence,+    typename MutableBufferIterator, typename CompletionCondition,+    typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_op<AsyncReadStream, MutableBufferSequence,+      MutableBufferIterator, CompletionCondition, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_op<AsyncReadStream, MutableBufferSequence,+        MutableBufferIterator, CompletionCondition, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename MutableBufferSequence,+    typename MutableBufferIterator, typename CompletionCondition,+    typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_op<AsyncReadStream, MutableBufferSequence,+      MutableBufferIterator, CompletionCondition, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_op<AsyncReadStream, MutableBufferSequence,+        MutableBufferIterator, CompletionCondition, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream,+    typename MutableBufferSequence, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), handler,+      buffers, ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++template <typename AsyncReadStream, typename MutableBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,+    ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s),+      handler, buffers, transfer_all());+}++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++namespace detail+{+  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename CompletionCondition, typename ReadHandler>+  class read_dynbuf_v1_op+    : detail::base_from_completion_cond<CompletionCondition>+  {+  public:+    template <typename BufferSequence>+    read_dynbuf_v1_op(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        CompletionCondition& completion_condition, ReadHandler& handler)+      : detail::base_from_completion_cond<+          CompletionCondition>(completion_condition),+        stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        start_(0),+        total_transferred_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_dynbuf_v1_op(const read_dynbuf_v1_op& other)+      : detail::base_from_completion_cond<CompletionCondition>(other),+        stream_(other.stream_),+        buffers_(other.buffers_),+        start_(other.start_),+        total_transferred_(other.total_transferred_),+        handler_(other.handler_)+    {+    }++    read_dynbuf_v1_op(read_dynbuf_v1_op&& other)+      : detail::base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(detail::base_from_completion_cond<+            CompletionCondition>)(other)),+        stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),+        start_(other.start_),+        total_transferred_(other.total_transferred_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      std::size_t max_size, bytes_available;+      switch (start_ = start)+      {+        case 1:+        max_size = this->check_for_completion(ec, total_transferred_);+        bytes_available = std::min<std::size_t>(+              std::max<std::size_t>(512,+                buffers_.capacity() - buffers_.size()),+              std::min<std::size_t>(max_size,+                buffers_.max_size() - buffers_.size()));+        for (;;)+        {+          {+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));+            stream_.async_read_some(buffers_.prepare(bytes_available),+                ASIO_MOVE_CAST(read_dynbuf_v1_op)(*this));+          }+          return; default:+          total_transferred_ += bytes_transferred;+          buffers_.commit(bytes_transferred);+          max_size = this->check_for_completion(ec, total_transferred_);+          bytes_available = std::min<std::size_t>(+                std::max<std::size_t>(512,+                  buffers_.capacity() - buffers_.size()),+                std::min<std::size_t>(max_size,+                  buffers_.max_size() - buffers_.size()));+          if ((!ec && bytes_transferred == 0) || bytes_available == 0)+            break;+        }++        handler_(ec, static_cast<const std::size_t&>(total_transferred_));+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v1 buffers_;+    int start_;+    std::size_t total_transferred_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,+        CompletionCondition, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename CompletionCondition, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,+        CompletionCondition, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename CompletionCondition,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename CompletionCondition,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_dynbuf_v1+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_dynbuf_v1(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler, typename DynamicBuffer_v1,+        typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+        ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);+      read_dynbuf_v1_op<AsyncReadStream, typename decay<DynamicBuffer_v1>::type,+        CompletionCondition, typename decay<ReadHandler>::type>(+          stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+            completion_cond2.value, handler2.value)(+              asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename CompletionCondition, typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_dynbuf_v1_op<AsyncReadStream,+      DynamicBuffer_v1, CompletionCondition, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_dynbuf_v1_op<AsyncReadStream,+        DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename CompletionCondition, typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_dynbuf_v1_op<AsyncReadStream,+      DynamicBuffer_v1, CompletionCondition, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_dynbuf_v1_op<AsyncReadStream,+        DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return async_read(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));+}++template <typename AsyncReadStream,+    typename DynamicBuffer_v1, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++template <typename AsyncReadStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_read(s, basic_streambuf_ref<Allocator>(b),+      ASIO_MOVE_CAST(ReadHandler)(handler));+}++template <typename AsyncReadStream,+    typename Allocator, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_read(s, basic_streambuf_ref<Allocator>(b),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+      ASIO_MOVE_CAST(ReadHandler)(handler));+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++namespace detail+{+  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename CompletionCondition, typename ReadHandler>+  class read_dynbuf_v2_op+    : detail::base_from_completion_cond<CompletionCondition>+  {+  public:+    template <typename BufferSequence>+    read_dynbuf_v2_op(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        CompletionCondition& completion_condition, ReadHandler& handler)+      : detail::base_from_completion_cond<+          CompletionCondition>(completion_condition),+        stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        start_(0),+        total_transferred_(0),+        bytes_available_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_dynbuf_v2_op(const read_dynbuf_v2_op& other)+      : detail::base_from_completion_cond<CompletionCondition>(other),+        stream_(other.stream_),+        buffers_(other.buffers_),+        start_(other.start_),+        total_transferred_(other.total_transferred_),+        bytes_available_(other.bytes_available_),+        handler_(other.handler_)+    {+    }++    read_dynbuf_v2_op(read_dynbuf_v2_op&& other)+      : detail::base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(detail::base_from_completion_cond<+            CompletionCondition>)(other)),+        stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),+        start_(other.start_),+        total_transferred_(other.total_transferred_),+        bytes_available_(other.bytes_available_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      std::size_t max_size, pos;+      switch (start_ = start)+      {+        case 1:+        max_size = this->check_for_completion(ec, total_transferred_);+        bytes_available_ = std::min<std::size_t>(+              std::max<std::size_t>(512,+                buffers_.capacity() - buffers_.size()),+              std::min<std::size_t>(max_size,+                buffers_.max_size() - buffers_.size()));+        for (;;)+        {+          pos = buffers_.size();+          buffers_.grow(bytes_available_);+          {+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));+            stream_.async_read_some(buffers_.data(pos, bytes_available_),+                ASIO_MOVE_CAST(read_dynbuf_v2_op)(*this));+          }+          return; default:+          total_transferred_ += bytes_transferred;+          buffers_.shrink(bytes_available_ - bytes_transferred);+          max_size = this->check_for_completion(ec, total_transferred_);+          bytes_available_ = std::min<std::size_t>(+                std::max<std::size_t>(512,+                  buffers_.capacity() - buffers_.size()),+                std::min<std::size_t>(max_size,+                  buffers_.max_size() - buffers_.size()));+          if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)+            break;+        }++        handler_(ec, static_cast<const std::size_t&>(total_transferred_));+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v2 buffers_;+    int start_;+    std::size_t total_transferred_;+    std::size_t bytes_available_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,+        CompletionCondition, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename CompletionCondition, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,+        CompletionCondition, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename CompletionCondition,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename CompletionCondition,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_dynbuf_v2+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_dynbuf_v2(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler, typename DynamicBuffer_v2,+        typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,+        ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);+      read_dynbuf_v2_op<AsyncReadStream, typename decay<DynamicBuffer_v2>::type,+        CompletionCondition, typename decay<ReadHandler>::type>(+          stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+            completion_cond2.value, handler2.value)(+              asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename CompletionCondition, typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_dynbuf_v2_op<AsyncReadStream,+      DynamicBuffer_v2, CompletionCondition, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_dynbuf_v2_op<AsyncReadStream,+        DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename CompletionCondition, typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_dynbuf_v2_op<AsyncReadStream,+      DynamicBuffer_v2, CompletionCondition, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_dynbuf_v2_op<AsyncReadStream,+        DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return async_read(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));+}++template <typename AsyncReadStream,+    typename DynamicBuffer_v2, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_READ_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/read_at.hpp view
@@ -0,0 +1,744 @@+//+// impl/read_at.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_READ_AT_HPP+#define ASIO_IMPL_READ_AT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include <algorithm>+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/buffer.hpp"+#include "asio/completion_condition.hpp"+#include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_completion_cond.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/consuming_buffers.hpp"+#include "asio/detail/dependent_type.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_tracking.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 {++namespace detail+{+  template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,+      typename MutableBufferIterator, typename CompletionCondition>+  std::size_t read_at_buffer_sequence(SyncRandomAccessReadDevice& d,+      uint64_t offset, const MutableBufferSequence& buffers,+      const MutableBufferIterator&, CompletionCondition completion_condition,+      asio::error_code& ec)+  {+    ec = asio::error_code();+    asio::detail::consuming_buffers<mutable_buffer,+        MutableBufferSequence, MutableBufferIterator> tmp(buffers);+    while (!tmp.empty())+    {+      if (std::size_t max_size = detail::adapt_completion_condition_result(+            completion_condition(ec, tmp.total_consumed())))+      {+        tmp.consume(d.read_some_at(offset + tmp.total_consumed(),+              tmp.prepare(max_size), ec));+      }+      else+        break;+    }+    return tmp.total_consumed();;+  }+} // namespace detail++template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,+    typename CompletionCondition>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition, asio::error_code& ec)+{+  return detail::read_at_buffer_sequence(d, offset, buffers,+      asio::buffer_sequence_begin(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+}++template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>+inline std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_at(+      d, offset, buffers, transfer_all(), ec);+  asio::detail::throw_error(ec, "read_at");+  return bytes_transferred;+}++template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>+inline std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers,+    asio::error_code& ec)+{+  return read_at(d, offset, buffers, transfer_all(), ec);+}++template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,+    typename CompletionCondition>+inline std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_at(d, offset, buffers,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "read_at");+  return bytes_transferred;+}++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++template <typename SyncRandomAccessReadDevice, typename Allocator,+    typename CompletionCondition>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition, asio::error_code& ec)+{+  ec = asio::error_code();+  std::size_t total_transferred = 0;+  std::size_t max_size = detail::adapt_completion_condition_result(+        completion_condition(ec, total_transferred));+  std::size_t bytes_available = read_size_helper(b, max_size);+  while (bytes_available > 0)+  {+    std::size_t bytes_transferred = d.read_some_at(+        offset + total_transferred, b.prepare(bytes_available), ec);+    b.commit(bytes_transferred);+    total_transferred += bytes_transferred;+    max_size = detail::adapt_completion_condition_result(+          completion_condition(ec, total_transferred));+    bytes_available = read_size_helper(b, max_size);+  }+  return total_transferred;+}++template <typename SyncRandomAccessReadDevice, typename Allocator>+inline std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_at(+      d, offset, b, transfer_all(), ec);+  asio::detail::throw_error(ec, "read_at");+  return bytes_transferred;+}++template <typename SyncRandomAccessReadDevice, typename Allocator>+inline std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    asio::error_code& ec)+{+  return read_at(d, offset, b, transfer_all(), ec);+}++template <typename SyncRandomAccessReadDevice, typename Allocator,+    typename CompletionCondition>+inline std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_at(d, offset, b,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "read_at");+  return bytes_transferred;+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)++namespace detail+{+  template <typename AsyncRandomAccessReadDevice,+      typename MutableBufferSequence, typename MutableBufferIterator,+      typename CompletionCondition, typename ReadHandler>+  class read_at_op+    : detail::base_from_completion_cond<CompletionCondition>+  {+  public:+    read_at_op(AsyncRandomAccessReadDevice& device,+        uint64_t offset, const MutableBufferSequence& buffers,+        CompletionCondition& completion_condition, ReadHandler& handler)+      : detail::base_from_completion_cond<+          CompletionCondition>(completion_condition),+        device_(device),+        offset_(offset),+        buffers_(buffers),+        start_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_at_op(const read_at_op& other)+      : detail::base_from_completion_cond<CompletionCondition>(other),+        device_(other.device_),+        offset_(other.offset_),+        buffers_(other.buffers_),+        start_(other.start_),+        handler_(other.handler_)+    {+    }++    read_at_op(read_at_op&& other)+      : detail::base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(detail::base_from_completion_cond<+            CompletionCondition>)(other)),+        device_(other.device_),+        offset_(other.offset_),+        buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)),+        start_(other.start_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      std::size_t max_size;+      switch (start_ = start)+      {+        case 1:+        max_size = this->check_for_completion(ec, buffers_.total_consumed());+        do+        {+          {+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));+            device_.async_read_some_at(+                offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),+                ASIO_MOVE_CAST(read_at_op)(*this));+          }+          return; default:+          buffers_.consume(bytes_transferred);+          if ((!ec && bytes_transferred == 0) || buffers_.empty())+            break;+          max_size = this->check_for_completion(ec, buffers_.total_consumed());+        } while (max_size > 0);++        handler_(ec, buffers_.total_consumed());+      }+    }++  //private:+    typedef asio::detail::consuming_buffers<mutable_buffer,+        MutableBufferSequence, MutableBufferIterator> buffers_type;++    AsyncRandomAccessReadDevice& device_;+    uint64_t offset_;+    buffers_type buffers_;+    int start_;+    ReadHandler handler_;+  };++  template <typename AsyncRandomAccessReadDevice,+      typename MutableBufferSequence, typename MutableBufferIterator,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,+        MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessReadDevice,+      typename MutableBufferSequence, typename MutableBufferIterator,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,+        MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessReadDevice,+      typename MutableBufferSequence, typename MutableBufferIterator,+      typename CompletionCondition, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,+        MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncRandomAccessReadDevice,+      typename MutableBufferSequence, typename MutableBufferIterator,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,+        MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncRandomAccessReadDevice,+      typename MutableBufferSequence, typename MutableBufferIterator,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,+        MutableBufferIterator, CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessReadDevice,+      typename MutableBufferSequence, typename MutableBufferIterator,+      typename CompletionCondition, typename ReadHandler>+  inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d,+      uint64_t offset, const MutableBufferSequence& buffers,+      const MutableBufferIterator&, CompletionCondition& completion_condition,+      ReadHandler& handler)+  {+    detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,+      MutableBufferIterator, CompletionCondition, ReadHandler>(+        d, offset, buffers, completion_condition, handler)(+          asio::error_code(), 0, 1);+  }++  template <typename AsyncRandomAccessReadDevice>+  class initiate_async_read_at_buffer_sequence+  {+  public:+    typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;++    explicit initiate_async_read_at_buffer_sequence(+        AsyncRandomAccessReadDevice& device)+      : device_(device)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return device_.get_executor();+    }++    template <typename ReadHandler, typename MutableBufferSequence,+        typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        uint64_t offset, const MutableBufferSequence& buffers,+        ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);+      start_read_at_buffer_sequence_op(device_, offset, buffers,+          asio::buffer_sequence_begin(buffers),+          completion_cond2.value, handler2.value);+    }++  private:+    AsyncRandomAccessReadDevice& device_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncRandomAccessReadDevice,+    typename MutableBufferSequence, typename MutableBufferIterator,+    typename CompletionCondition, typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,+    MutableBufferIterator, CompletionCondition, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_at_op<AsyncRandomAccessReadDevice,+      MutableBufferSequence, MutableBufferIterator,+      CompletionCondition, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncRandomAccessReadDevice,+    typename MutableBufferSequence, typename MutableBufferIterator,+    typename CompletionCondition, typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,+    MutableBufferIterator, CompletionCondition, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_at_op<AsyncRandomAccessReadDevice,+      MutableBufferSequence, MutableBufferIterator,+      CompletionCondition, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncRandomAccessReadDevice,+    typename MutableBufferSequence, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_at(AsyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_at_buffer_sequence<+        AsyncRandomAccessReadDevice>(d),+      handler, offset, buffers,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_at(AsyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers,+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_at_buffer_sequence<+        AsyncRandomAccessReadDevice>(d),+      handler, offset, buffers, transfer_all());+}++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++namespace detail+{+  template <typename AsyncRandomAccessReadDevice, typename Allocator,+      typename CompletionCondition, typename ReadHandler>+  class read_at_streambuf_op+    : detail::base_from_completion_cond<CompletionCondition>+  {+  public:+    read_at_streambuf_op(AsyncRandomAccessReadDevice& device,+        uint64_t offset, basic_streambuf<Allocator>& streambuf,+        CompletionCondition& completion_condition, ReadHandler& handler)+      : detail::base_from_completion_cond<+          CompletionCondition>(completion_condition),+        device_(device),+        offset_(offset),+        streambuf_(streambuf),+        start_(0),+        total_transferred_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_at_streambuf_op(const read_at_streambuf_op& other)+      : detail::base_from_completion_cond<CompletionCondition>(other),+        device_(other.device_),+        offset_(other.offset_),+        streambuf_(other.streambuf_),+        start_(other.start_),+        total_transferred_(other.total_transferred_),+        handler_(other.handler_)+    {+    }++    read_at_streambuf_op(read_at_streambuf_op&& other)+      : detail::base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(detail::base_from_completion_cond<+            CompletionCondition>)(other)),+        device_(other.device_),+        offset_(other.offset_),+        streambuf_(other.streambuf_),+        start_(other.start_),+        total_transferred_(other.total_transferred_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      std::size_t max_size, bytes_available;+      switch (start_ = start)+      {+        case 1:+        max_size = this->check_for_completion(ec, total_transferred_);+        bytes_available = read_size_helper(streambuf_, max_size);+        for (;;)+        {+          {+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));+            device_.async_read_some_at(offset_ + total_transferred_,+                streambuf_.prepare(bytes_available),+                ASIO_MOVE_CAST(read_at_streambuf_op)(*this));+          }+          return; default:+          total_transferred_ += bytes_transferred;+          streambuf_.commit(bytes_transferred);+          max_size = this->check_for_completion(ec, total_transferred_);+          bytes_available = read_size_helper(streambuf_, max_size);+          if ((!ec && bytes_transferred == 0) || bytes_available == 0)+            break;+        }++        handler_(ec, static_cast<const std::size_t&>(total_transferred_));+      }+    }++  //private:+    AsyncRandomAccessReadDevice& device_;+    uint64_t offset_;+    asio::basic_streambuf<Allocator>& streambuf_;+    int start_;+    std::size_t total_transferred_;+    ReadHandler handler_;+  };++  template <typename AsyncRandomAccessReadDevice, typename Allocator,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,+        CompletionCondition, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessReadDevice, typename Allocator,+      typename CompletionCondition, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessReadDevice, typename Allocator,+      typename CompletionCondition, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,+        CompletionCondition, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncRandomAccessReadDevice,+      typename Allocator, typename CompletionCondition, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncRandomAccessReadDevice,+      typename Allocator, typename CompletionCondition, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,+        CompletionCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessReadDevice>+  class initiate_async_read_at_streambuf+  {+  public:+    typedef typename AsyncRandomAccessReadDevice::executor_type executor_type;++    explicit initiate_async_read_at_streambuf(+        AsyncRandomAccessReadDevice& device)+      : device_(device)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return device_.get_executor();+    }++    template <typename ReadHandler,+        typename Allocator, typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        uint64_t offset, basic_streambuf<Allocator>* b,+        ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);+      read_at_streambuf_op<AsyncRandomAccessReadDevice, Allocator,+        CompletionCondition, typename decay<ReadHandler>::type>(+          device_, offset, *b, completion_cond2.value, handler2.value)(+            asio::error_code(), 0, 1);+    }++  private:+    AsyncRandomAccessReadDevice& device_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncRandomAccessReadDevice, typename Allocator,+    typename CompletionCondition, typename ReadHandler, typename Allocator1>+struct associated_allocator<+    detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,+      Allocator, CompletionCondition, ReadHandler>,+    Allocator1>+{+  typedef typename associated_allocator<ReadHandler, Allocator1>::type type;++  static type get(+      const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,+        Allocator, CompletionCondition, ReadHandler>& h,+      const Allocator1& a = Allocator1()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);+  }+};++template <typename AsyncRandomAccessReadDevice, typename Executor,+    typename CompletionCondition, typename ReadHandler, typename Executor1>+struct associated_executor<+    detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,+      Executor, CompletionCondition, ReadHandler>,+    Executor1>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor1>::type type;++  static type get(+      const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,+        Executor, CompletionCondition, ReadHandler>& h,+      const Executor1& ex = Executor1()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncRandomAccessReadDevice,+    typename Allocator, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_at(AsyncRandomAccessReadDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),+      handler, offset, &b,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++template <typename AsyncRandomAccessReadDevice, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_at(AsyncRandomAccessReadDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),+      handler, offset, &b, transfer_all());+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_READ_AT_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/read_until.hpp view
@@ -0,0 +1,3335 @@+//+// impl/read_until.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_READ_UNTIL_HPP+#define ASIO_IMPL_READ_UNTIL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include <algorithm>+#include <string>+#include <vector>+#include <utility>+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/buffer.hpp"+#include "asio/buffers_iterator.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_tracking.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail+{+  // Algorithm that finds a subsequence of equal values in a sequence. Returns+  // (iterator,true) if a full match was found, in which case the iterator+  // points to the beginning of the match. Returns (iterator,false) if a+  // partial match was found at the end of the first sequence, in which case+  // the iterator points to the beginning of the partial match. Returns+  // (last1,false) if no full or partial match was found.+  template <typename Iterator1, typename Iterator2>+  std::pair<Iterator1, bool> partial_search(+      Iterator1 first1, Iterator1 last1, Iterator2 first2, Iterator2 last2)+  {+    for (Iterator1 iter1 = first1; iter1 != last1; ++iter1)+    {+      Iterator1 test_iter1 = iter1;+      Iterator2 test_iter2 = first2;+      for (;; ++test_iter1, ++test_iter2)+      {+        if (test_iter2 == last2)+          return std::make_pair(iter1, true);+        if (test_iter1 == last1)+        {+          if (test_iter2 != first2)+            return std::make_pair(iter1, false);+          else+            break;+        }+        if (*test_iter1 != *test_iter2)+          break;+      }+    }+    return std::make_pair(last1, false);+  }+} // namespace detail++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++template <typename SyncReadStream, typename DynamicBuffer_v1>+inline std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_until(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec);+  asio::detail::throw_error(ec, "read_until");+  return bytes_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    char delim, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  typename decay<DynamicBuffer_v1>::type b(+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));++  std::size_t search_position = 0;+  for (;;)+  {+    // Determine the range of the data to be searched.+    typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;+    typedef buffers_iterator<buffers_type> iterator;+    buffers_type data_buffers = b.data();+    iterator begin = iterator::begin(data_buffers);+    iterator start_pos = begin + search_position;+    iterator end = iterator::end(data_buffers);++    // Look for a match.+    iterator iter = std::find(start_pos, end, delim);+    if (iter != end)+    {+      // Found a match. We're done.+      ec = asio::error_code();+      return iter - begin + 1;+    }+    else+    {+      // No match. Next search can start with the new data.+      search_position = end - begin;+    }++    // Check if buffer is full.+    if (b.size() == b.max_size())+    {+      ec = error::not_found;+      return 0;+    }++    // Need more data.+    std::size_t bytes_to_read = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(65536, b.max_size() - b.size()));+    b.commit(s.read_some(b.prepare(bytes_to_read), ec));+    if (ec)+      return 0;+  }+}++template <typename SyncReadStream, typename DynamicBuffer_v1>+inline std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_STRING_VIEW_PARAM delim,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_until(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim, ec);+  asio::detail::throw_error(ec, "read_until");+  return bytes_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  typename decay<DynamicBuffer_v1>::type b(+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));++  std::size_t search_position = 0;+  for (;;)+  {+    // Determine the range of the data to be searched.+    typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;+    typedef buffers_iterator<buffers_type> iterator;+    buffers_type data_buffers = b.data();+    iterator begin = iterator::begin(data_buffers);+    iterator start_pos = begin + search_position;+    iterator end = iterator::end(data_buffers);++    // Look for a match.+    std::pair<iterator, bool> result = detail::partial_search(+        start_pos, end, delim.begin(), delim.end());+    if (result.first != end)+    {+      if (result.second)+      {+        // Full match. We're done.+        ec = asio::error_code();+        return result.first - begin + delim.length();+      }+      else+      {+        // Partial match. Next search needs to start from beginning of match.+        search_position = result.first - begin;+      }+    }+    else+    {+      // No match. Next search can start with the new data.+      search_position = end - begin;+    }++    // Check if buffer is full.+    if (b.size() == b.max_size())+    {+      ec = error::not_found;+      return 0;+    }++    // Need more data.+    std::size_t bytes_to_read = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(65536, b.max_size() - b.size()));+    b.commit(s.read_some(b.prepare(bytes_to_read), ec));+    if (ec)+      return 0;+  }+}++#if !defined(ASIO_NO_EXTENSIONS)+#if defined(ASIO_HAS_BOOST_REGEX)++template <typename SyncReadStream, typename DynamicBuffer_v1>+inline std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    const boost::regex& expr,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_until(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr, ec);+  asio::detail::throw_error(ec, "read_until");+  return bytes_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    const boost::regex& expr, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  typename decay<DynamicBuffer_v1>::type b(+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));++  std::size_t search_position = 0;+  for (;;)+  {+    // Determine the range of the data to be searched.+    typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;+    typedef buffers_iterator<buffers_type> iterator;+    buffers_type data_buffers = b.data();+    iterator begin = iterator::begin(data_buffers);+    iterator start_pos = begin + search_position;+    iterator end = iterator::end(data_buffers);++    // Look for a match.+    boost::match_results<iterator,+      typename std::vector<boost::sub_match<iterator> >::allocator_type>+        match_results;+    if (regex_search(start_pos, end, match_results, expr,+          boost::match_default | boost::match_partial))+    {+      if (match_results[0].matched)+      {+        // Full match. We're done.+        ec = asio::error_code();+        return match_results[0].second - begin;+      }+      else+      {+        // Partial match. Next search needs to start from beginning of match.+        search_position = match_results[0].first - begin;+      }+    }+    else+    {+      // No match. Next search can start with the new data.+      search_position = end - begin;+    }++    // Check if buffer is full.+    if (b.size() == b.max_size())+    {+      ec = error::not_found;+      return 0;+    }++    // Need more data.+    std::size_t bytes_to_read = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(65536, b.max_size() - b.size()));+    b.commit(s.read_some(b.prepare(bytes_to_read), ec));+    if (ec)+      return 0;+  }+}++#endif // defined(ASIO_HAS_BOOST_REGEX)++template <typename SyncReadStream,+    typename DynamicBuffer_v1, typename MatchCondition>+inline std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    MatchCondition match_condition,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_until(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      match_condition, ec);+  asio::detail::throw_error(ec, "read_until");+  return bytes_transferred;+}++template <typename SyncReadStream,+    typename DynamicBuffer_v1, typename MatchCondition>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    MatchCondition match_condition, asio::error_code& ec,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  typename decay<DynamicBuffer_v1>::type b(+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));++  std::size_t search_position = 0;+  for (;;)+  {+    // Determine the range of the data to be searched.+    typedef typename DynamicBuffer_v1::const_buffers_type buffers_type;+    typedef buffers_iterator<buffers_type> iterator;+    buffers_type data_buffers = b.data();+    iterator begin = iterator::begin(data_buffers);+    iterator start_pos = begin + search_position;+    iterator end = iterator::end(data_buffers);++    // Look for a match.+    std::pair<iterator, bool> result = match_condition(start_pos, end);+    if (result.second)+    {+      // Full match. We're done.+      ec = asio::error_code();+      return result.first - begin;+    }+    else if (result.first != end)+    {+      // Partial match. Next search needs to start from beginning of match.+      search_position = result.first - begin;+    }+    else+    {+      // No match. Next search can start with the new data.+      search_position = end - begin;+    }++    // Check if buffer is full.+    if (b.size() == b.max_size())+    {+      ec = error::not_found;+      return 0;+    }++    // Need more data.+    std::size_t bytes_to_read = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(65536, b.max_size() - b.size()));+    b.commit(s.read_some(b.prepare(bytes_to_read), ec));+    if (ec)+      return 0;+  }+}++#if !defined(ASIO_NO_IOSTREAM)++template <typename SyncReadStream, typename Allocator>+inline std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, char delim)+{+  return read_until(s, basic_streambuf_ref<Allocator>(b), delim);+}++template <typename SyncReadStream, typename Allocator>+inline std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, char delim,+    asio::error_code& ec)+{+  return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);+}++template <typename SyncReadStream, typename Allocator>+inline std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    ASIO_STRING_VIEW_PARAM delim)+{+  return read_until(s, basic_streambuf_ref<Allocator>(b), delim);+}++template <typename SyncReadStream, typename Allocator>+inline std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec)+{+  return read_until(s, basic_streambuf_ref<Allocator>(b), delim, ec);+}++#if defined(ASIO_HAS_BOOST_REGEX)++template <typename SyncReadStream, typename Allocator>+inline std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr)+{+  return read_until(s, basic_streambuf_ref<Allocator>(b), expr);+}++template <typename SyncReadStream, typename Allocator>+inline std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,+    asio::error_code& ec)+{+  return read_until(s, basic_streambuf_ref<Allocator>(b), expr, ec);+}++#endif // defined(ASIO_HAS_BOOST_REGEX)++template <typename SyncReadStream, typename Allocator, typename MatchCondition>+inline std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,+    typename enable_if<is_match_condition<MatchCondition>::value>::type*)+{+  return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition);+}++template <typename SyncReadStream, typename Allocator, typename MatchCondition>+inline std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    MatchCondition match_condition, asio::error_code& ec,+    typename enable_if<is_match_condition<MatchCondition>::value>::type*)+{+  return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec);+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++template <typename SyncReadStream, typename DynamicBuffer_v2>+inline std::size_t read_until(SyncReadStream& s,+    DynamicBuffer_v2 buffers, char delim,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_until(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec);+  asio::detail::throw_error(ec, "read_until");+  return bytes_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    char delim, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  DynamicBuffer_v2& b = buffers;++  std::size_t search_position = 0;+  for (;;)+  {+    // Determine the range of the data to be searched.+    typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;+    typedef buffers_iterator<buffers_type> iterator;+    buffers_type data_buffers =+      const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());+    iterator begin = iterator::begin(data_buffers);+    iterator start_pos = begin + search_position;+    iterator end = iterator::end(data_buffers);++    // Look for a match.+    iterator iter = std::find(start_pos, end, delim);+    if (iter != end)+    {+      // Found a match. We're done.+      ec = asio::error_code();+      return iter - begin + 1;+    }+    else+    {+      // No match. Next search can start with the new data.+      search_position = end - begin;+    }++    // Check if buffer is full.+    if (b.size() == b.max_size())+    {+      ec = error::not_found;+      return 0;+    }++    // Need more data.+    std::size_t bytes_to_read = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(65536, b.max_size() - b.size()));+    std::size_t pos = b.size();+    b.grow(bytes_to_read);+    std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);+    b.shrink(bytes_to_read - bytes_transferred);+    if (ec)+      return 0;+  }+}++template <typename SyncReadStream, typename DynamicBuffer_v2>+inline std::size_t read_until(SyncReadStream& s,+    DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_until(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim, ec);+  asio::detail::throw_error(ec, "read_until");+  return bytes_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  DynamicBuffer_v2& b = buffers;++  std::size_t search_position = 0;+  for (;;)+  {+    // Determine the range of the data to be searched.+    typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;+    typedef buffers_iterator<buffers_type> iterator;+    buffers_type data_buffers =+      const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());+    iterator begin = iterator::begin(data_buffers);+    iterator start_pos = begin + search_position;+    iterator end = iterator::end(data_buffers);++    // Look for a match.+    std::pair<iterator, bool> result = detail::partial_search(+        start_pos, end, delim.begin(), delim.end());+    if (result.first != end)+    {+      if (result.second)+      {+        // Full match. We're done.+        ec = asio::error_code();+        return result.first - begin + delim.length();+      }+      else+      {+        // Partial match. Next search needs to start from beginning of match.+        search_position = result.first - begin;+      }+    }+    else+    {+      // No match. Next search can start with the new data.+      search_position = end - begin;+    }++    // Check if buffer is full.+    if (b.size() == b.max_size())+    {+      ec = error::not_found;+      return 0;+    }++    // Need more data.+    std::size_t bytes_to_read = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(65536, b.max_size() - b.size()));+    std::size_t pos = b.size();+    b.grow(bytes_to_read);+    std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);+    b.shrink(bytes_to_read - bytes_transferred);+    if (ec)+      return 0;+  }+}++#if !defined(ASIO_NO_EXTENSIONS)+#if defined(ASIO_HAS_BOOST_REGEX)++template <typename SyncReadStream, typename DynamicBuffer_v2>+inline std::size_t read_until(SyncReadStream& s,+    DynamicBuffer_v2 buffers, const boost::regex& expr,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_until(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr, ec);+  asio::detail::throw_error(ec, "read_until");+  return bytes_transferred;+}++template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    const boost::regex& expr, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  DynamicBuffer_v2& b = buffers;++  std::size_t search_position = 0;+  for (;;)+  {+    // Determine the range of the data to be searched.+    typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;+    typedef buffers_iterator<buffers_type> iterator;+    buffers_type data_buffers =+      const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());+    iterator begin = iterator::begin(data_buffers);+    iterator start_pos = begin + search_position;+    iterator end = iterator::end(data_buffers);++    // Look for a match.+    boost::match_results<iterator,+      typename std::vector<boost::sub_match<iterator> >::allocator_type>+        match_results;+    if (regex_search(start_pos, end, match_results, expr,+          boost::match_default | boost::match_partial))+    {+      if (match_results[0].matched)+      {+        // Full match. We're done.+        ec = asio::error_code();+        return match_results[0].second - begin;+      }+      else+      {+        // Partial match. Next search needs to start from beginning of match.+        search_position = match_results[0].first - begin;+      }+    }+    else+    {+      // No match. Next search can start with the new data.+      search_position = end - begin;+    }++    // Check if buffer is full.+    if (b.size() == b.max_size())+    {+      ec = error::not_found;+      return 0;+    }++    // Need more data.+    std::size_t bytes_to_read = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(65536, b.max_size() - b.size()));+    std::size_t pos = b.size();+    b.grow(bytes_to_read);+    std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);+    b.shrink(bytes_to_read - bytes_transferred);+    if (ec)+      return 0;+  }+}++#endif // defined(ASIO_HAS_BOOST_REGEX)++template <typename SyncReadStream,+    typename DynamicBuffer_v2, typename MatchCondition>+inline std::size_t read_until(SyncReadStream& s,+    DynamicBuffer_v2 buffers, MatchCondition match_condition,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = read_until(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      match_condition, ec);+  asio::detail::throw_error(ec, "read_until");+  return bytes_transferred;+}++template <typename SyncReadStream,+    typename DynamicBuffer_v2, typename MatchCondition>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    MatchCondition match_condition, asio::error_code& ec,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  DynamicBuffer_v2& b = buffers;++  std::size_t search_position = 0;+  for (;;)+  {+    // Determine the range of the data to be searched.+    typedef typename DynamicBuffer_v2::const_buffers_type buffers_type;+    typedef buffers_iterator<buffers_type> iterator;+    buffers_type data_buffers =+      const_cast<const DynamicBuffer_v2&>(b).data(0, b.size());+    iterator begin = iterator::begin(data_buffers);+    iterator start_pos = begin + search_position;+    iterator end = iterator::end(data_buffers);++    // Look for a match.+    std::pair<iterator, bool> result = match_condition(start_pos, end);+    if (result.second)+    {+      // Full match. We're done.+      ec = asio::error_code();+      return result.first - begin;+    }+    else if (result.first != end)+    {+      // Partial match. Next search needs to start from beginning of match.+      search_position = result.first - begin;+    }+    else+    {+      // No match. Next search can start with the new data.+      search_position = end - begin;+    }++    // Check if buffer is full.+    if (b.size() == b.max_size())+    {+      ec = error::not_found;+      return 0;+    }++    // Need more data.+    std::size_t bytes_to_read = std::min<std::size_t>(+          std::max<std::size_t>(512, b.capacity() - b.size()),+          std::min<std::size_t>(65536, b.max_size() - b.size()));+    std::size_t pos = b.size();+    b.grow(bytes_to_read);+    std::size_t bytes_transferred = s.read_some(b.data(pos, bytes_to_read), ec);+    b.shrink(bytes_to_read - bytes_transferred);+    if (ec)+      return 0;+  }+}++#endif // !defined(ASIO_NO_EXTENSIONS)++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++namespace detail+{+  template <typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  class read_until_delim_op_v1+  {+  public:+    template <typename BufferSequence>+    read_until_delim_op_v1(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        char delim, ReadHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        delim_(delim),+        start_(0),+        search_position_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_until_delim_op_v1(const read_until_delim_op_v1& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        delim_(other.delim_),+        start_(other.start_),+        search_position_(other.search_position_),+        handler_(other.handler_)+    {+    }++    read_until_delim_op_v1(read_until_delim_op_v1&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),+        delim_(other.delim_),+        start_(other.start_),+        search_position_(other.search_position_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();+      std::size_t bytes_to_read;+      switch (start_ = start)+      {+      case 1:+        for (;;)+        {+          {+            // Determine the range of the data to be searched.+            typedef typename DynamicBuffer_v1::const_buffers_type+              buffers_type;+            typedef buffers_iterator<buffers_type> iterator;+            buffers_type data_buffers = buffers_.data();+            iterator begin = iterator::begin(data_buffers);+            iterator start_pos = begin + search_position_;+            iterator end = iterator::end(data_buffers);++            // Look for a match.+            iterator iter = std::find(start_pos, end, delim_);+            if (iter != end)+            {+              // Found a match. We're done.+              search_position_ = iter - begin + 1;+              bytes_to_read = 0;+            }++            // No match yet. Check if buffer is full.+            else if (buffers_.size() == buffers_.max_size())+            {+              search_position_ = not_found;+              bytes_to_read = 0;+            }++            // Need to read some more data.+            else+            {+              // Next search can start with the new data.+              search_position_ = end - begin;+              bytes_to_read = std::min<std::size_t>(+                    std::max<std::size_t>(512,+                      buffers_.capacity() - buffers_.size()),+                    std::min<std::size_t>(65536,+                      buffers_.max_size() - buffers_.size()));+            }+          }++          // Check if we're done.+          if (!start && bytes_to_read == 0)+            break;++          // Start a new asynchronous read operation to obtain more data.+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, "async_read_until"));+            stream_.async_read_some(buffers_.prepare(bytes_to_read),+                ASIO_MOVE_CAST(read_until_delim_op_v1)(*this));+          }+          return; default:+          buffers_.commit(bytes_transferred);+          if (ec || bytes_transferred == 0)+            break;+        }++        const asio::error_code result_ec =+          (search_position_ == not_found)+          ? error::not_found : ec;++        const std::size_t result_n =+          (ec || search_position_ == not_found)+          ? 0 : search_position_;++        handler_(result_ec, result_n);+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v1 buffers_;+    char delim_;+    int start_;+    std::size_t search_position_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_until_delim_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_until_delim_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_until_delim_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_until_delim_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_until_delim_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_until_delim_v1+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_until_delim_v1(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler, typename DynamicBuffer_v1>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+        char delim) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      read_until_delim_op_v1<AsyncReadStream,+        typename decay<DynamicBuffer_v1>::type,+          typename decay<ReadHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+            delim, handler2.value)(asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_until_delim_op_v1<AsyncReadStream,+      DynamicBuffer_v1, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_until_delim_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_until_delim_op_v1<AsyncReadStream,+      DynamicBuffer_v1, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_until_delim_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    char delim, ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim);+}++namespace detail+{+  template <typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  class read_until_delim_string_op_v1+  {+  public:+    template <typename BufferSequence>+    read_until_delim_string_op_v1(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        const std::string& delim, ReadHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        delim_(delim),+        start_(0),+        search_position_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        delim_(other.delim_),+        start_(other.start_),+        search_position_(other.search_position_),+        handler_(other.handler_)+    {+    }++    read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),+        delim_(ASIO_MOVE_CAST(std::string)(other.delim_)),+        start_(other.start_),+        search_position_(other.search_position_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();+      std::size_t bytes_to_read;+      switch (start_ = start)+      {+      case 1:+        for (;;)+        {+          {+            // Determine the range of the data to be searched.+            typedef typename DynamicBuffer_v1::const_buffers_type+              buffers_type;+            typedef buffers_iterator<buffers_type> iterator;+            buffers_type data_buffers = buffers_.data();+            iterator begin = iterator::begin(data_buffers);+            iterator start_pos = begin + search_position_;+            iterator end = iterator::end(data_buffers);++            // Look for a match.+            std::pair<iterator, bool> result = detail::partial_search(+                start_pos, end, delim_.begin(), delim_.end());+            if (result.first != end && result.second)+            {+              // Full match. We're done.+              search_position_ = result.first - begin + delim_.length();+              bytes_to_read = 0;+            }++            // No match yet. Check if buffer is full.+            else if (buffers_.size() == buffers_.max_size())+            {+              search_position_ = not_found;+              bytes_to_read = 0;+            }++            // Need to read some more data.+            else+            {+              if (result.first != end)+              {+                // Partial match. Next search needs to start from beginning of+                // match.+                search_position_ = result.first - begin;+              }+              else+              {+                // Next search can start with the new data.+                search_position_ = end - begin;+              }++              bytes_to_read = std::min<std::size_t>(+                    std::max<std::size_t>(512,+                      buffers_.capacity() - buffers_.size()),+                    std::min<std::size_t>(65536,+                      buffers_.max_size() - buffers_.size()));+            }+          }++          // Check if we're done.+          if (!start && bytes_to_read == 0)+            break;++          // Start a new asynchronous read operation to obtain more data.+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, "async_read_until"));+            stream_.async_read_some(buffers_.prepare(bytes_to_read),+                ASIO_MOVE_CAST(read_until_delim_string_op_v1)(*this));+          }+          return; default:+          buffers_.commit(bytes_transferred);+          if (ec || bytes_transferred == 0)+            break;+        }++        const asio::error_code result_ec =+          (search_position_ == not_found)+          ? error::not_found : ec;++        const std::size_t result_n =+          (ec || search_position_ == not_found)+          ? 0 : search_position_;++        handler_(result_ec, result_n);+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v1 buffers_;+    std::string delim_;+    int start_;+    std::size_t search_position_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_until_delim_string_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_until_delim_string_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_until_delim_string_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_until_delim_string_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_until_delim_string_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_until_delim_string_v1+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_until_delim_string_v1(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler, typename DynamicBuffer_v1>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+        const std::string& delim) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      read_until_delim_string_op_v1<AsyncReadStream,+        typename decay<DynamicBuffer_v1>::type,+          typename decay<ReadHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+            delim, handler2.value)(asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_until_delim_string_op_v1<AsyncReadStream,+      DynamicBuffer_v1, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_until_delim_string_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_until_delim_string_op_v1<AsyncReadStream,+      DynamicBuffer_v1, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_until_delim_string_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_STRING_VIEW_PARAM delim,+    ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      static_cast<std::string>(delim));+}++#if !defined(ASIO_NO_EXTENSIONS)+#if defined(ASIO_HAS_BOOST_REGEX)++namespace detail+{+  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename RegEx, typename ReadHandler>+  class read_until_expr_op_v1+  {+  public:+    template <typename BufferSequence>+    read_until_expr_op_v1(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        const boost::regex& expr, ReadHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        expr_(expr),+        start_(0),+        search_position_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_until_expr_op_v1(const read_until_expr_op_v1& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        expr_(other.expr_),+        start_(other.start_),+        search_position_(other.search_position_),+        handler_(other.handler_)+    {+    }++    read_until_expr_op_v1(read_until_expr_op_v1&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),+        expr_(other.expr_),+        start_(other.start_),+        search_position_(other.search_position_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();+      std::size_t bytes_to_read;+      switch (start_ = start)+      {+      case 1:+        for (;;)+        {+          {+            // Determine the range of the data to be searched.+            typedef typename DynamicBuffer_v1::const_buffers_type+              buffers_type;+            typedef buffers_iterator<buffers_type> iterator;+            buffers_type data_buffers = buffers_.data();+            iterator begin = iterator::begin(data_buffers);+            iterator start_pos = begin + search_position_;+            iterator end = iterator::end(data_buffers);++            // Look for a match.+            boost::match_results<iterator,+              typename std::vector<boost::sub_match<iterator> >::allocator_type>+                match_results;+            bool match = regex_search(start_pos, end, match_results, expr_,+                boost::match_default | boost::match_partial);+            if (match && match_results[0].matched)+            {+              // Full match. We're done.+              search_position_ = match_results[0].second - begin;+              bytes_to_read = 0;+            }++            // No match yet. Check if buffer is full.+            else if (buffers_.size() == buffers_.max_size())+            {+              search_position_ = not_found;+              bytes_to_read = 0;+            }++            // Need to read some more data.+            else+            {+              if (match)+              {+                // Partial match. Next search needs to start from beginning of+                // match.+                search_position_ = match_results[0].first - begin;+              }+              else+              {+                // Next search can start with the new data.+                search_position_ = end - begin;+              }++              bytes_to_read = std::min<std::size_t>(+                    std::max<std::size_t>(512,+                      buffers_.capacity() - buffers_.size()),+                    std::min<std::size_t>(65536,+                      buffers_.max_size() - buffers_.size()));+            }+          }++          // Check if we're done.+          if (!start && bytes_to_read == 0)+            break;++          // Start a new asynchronous read operation to obtain more data.+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, "async_read_until"));+            stream_.async_read_some(buffers_.prepare(bytes_to_read),+                ASIO_MOVE_CAST(read_until_expr_op_v1)(*this));+          }+          return; default:+          buffers_.commit(bytes_transferred);+          if (ec || bytes_transferred == 0)+            break;+        }++        const asio::error_code result_ec =+          (search_position_ == not_found)+          ? error::not_found : ec;++        const std::size_t result_n =+          (ec || search_position_ == not_found)+          ? 0 : search_position_;++        handler_(result_ec, result_n);+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v1 buffers_;+    RegEx expr_;+    int start_;+    std::size_t search_position_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename RegEx, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_until_expr_op_v1<AsyncReadStream,+        DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename RegEx, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_until_expr_op_v1<AsyncReadStream,+        DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename RegEx, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_until_expr_op_v1<AsyncReadStream,+        DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_until_expr_op_v1<AsyncReadStream,+        DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename RegEx, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_until_expr_op_v1<AsyncReadStream,+        DynamicBuffer_v1, RegEx, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_until_expr_v1+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_until_expr_v1(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler, typename DynamicBuffer_v1, typename RegEx>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, const RegEx& expr) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      read_until_expr_op_v1<AsyncReadStream,+        typename decay<DynamicBuffer_v1>::type,+          RegEx, typename decay<ReadHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+            expr, handler2.value)(asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename RegEx, typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_until_expr_op_v1<AsyncReadStream,+      DynamicBuffer_v1, RegEx, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_until_expr_op_v1<AsyncReadStream,+        DynamicBuffer_v1, RegEx, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename RegEx, typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_until_expr_op_v1<AsyncReadStream,+      DynamicBuffer_v1, RegEx, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_until_expr_op_v1<AsyncReadStream,+        DynamicBuffer_v1, RegEx, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    const boost::regex& expr,+    ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr);+}++#endif // defined(ASIO_HAS_BOOST_REGEX)++namespace detail+{+  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename MatchCondition, typename ReadHandler>+  class read_until_match_op_v1+  {+  public:+    template <typename BufferSequence>+    read_until_match_op_v1(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        MatchCondition match_condition, ReadHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        match_condition_(match_condition),+        start_(0),+        search_position_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_until_match_op_v1(const read_until_match_op_v1& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        match_condition_(other.match_condition_),+        start_(other.start_),+        search_position_(other.search_position_),+        handler_(other.handler_)+    {+    }++    read_until_match_op_v1(read_until_match_op_v1&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),+        match_condition_(other.match_condition_),+        start_(other.start_),+        search_position_(other.search_position_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();+      std::size_t bytes_to_read;+      switch (start_ = start)+      {+      case 1:+        for (;;)+        {+          {+            // Determine the range of the data to be searched.+            typedef typename DynamicBuffer_v1::const_buffers_type+              buffers_type;+            typedef buffers_iterator<buffers_type> iterator;+            buffers_type data_buffers = buffers_.data();+            iterator begin = iterator::begin(data_buffers);+            iterator start_pos = begin + search_position_;+            iterator end = iterator::end(data_buffers);++            // Look for a match.+            std::pair<iterator, bool> result = match_condition_(start_pos, end);+            if (result.second)+            {+              // Full match. We're done.+              search_position_ = result.first - begin;+              bytes_to_read = 0;+            }++            // No match yet. Check if buffer is full.+            else if (buffers_.size() == buffers_.max_size())+            {+              search_position_ = not_found;+              bytes_to_read = 0;+            }++            // Need to read some more data.+            else+            {+              if (result.first != end)+              {+                // Partial match. Next search needs to start from beginning of+                // match.+                search_position_ = result.first - begin;+              }+              else+              {+                // Next search can start with the new data.+                search_position_ = end - begin;+              }++              bytes_to_read = std::min<std::size_t>(+                    std::max<std::size_t>(512,+                      buffers_.capacity() - buffers_.size()),+                    std::min<std::size_t>(65536,+                      buffers_.max_size() - buffers_.size()));+            }+          }++          // Check if we're done.+          if (!start && bytes_to_read == 0)+            break;++          // Start a new asynchronous read operation to obtain more data.+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, "async_read_until"));+            stream_.async_read_some(buffers_.prepare(bytes_to_read),+                ASIO_MOVE_CAST(read_until_match_op_v1)(*this));+          }+          return; default:+          buffers_.commit(bytes_transferred);+          if (ec || bytes_transferred == 0)+            break;+        }++        const asio::error_code result_ec =+          (search_position_ == not_found)+          ? error::not_found : ec;++        const std::size_t result_n =+          (ec || search_position_ == not_found)+          ? 0 : search_position_;++        handler_(result_ec, result_n);+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v1 buffers_;+    MatchCondition match_condition_;+    int start_;+    std::size_t search_position_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename MatchCondition, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,+        MatchCondition, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename MatchCondition, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,+        MatchCondition, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v1,+      typename MatchCondition, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,+        MatchCondition, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename MatchCondition,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,+        MatchCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v1, typename MatchCondition,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_until_match_op_v1<AsyncReadStream, DynamicBuffer_v1,+      MatchCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_until_match_v1+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_until_match_v1(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler,+        typename DynamicBuffer_v1, typename MatchCondition>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+        MatchCondition match_condition) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      read_until_match_op_v1<AsyncReadStream,+        typename decay<DynamicBuffer_v1>::type,+          MatchCondition, typename decay<ReadHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+            match_condition, handler2.value)(asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename MatchCondition, typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_until_match_op_v1<AsyncReadStream,+      DynamicBuffer_v1, MatchCondition, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_until_match_op_v1<AsyncReadStream,+        DynamicBuffer_v1, MatchCondition, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v1,+    typename MatchCondition, typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_until_match_op_v1<AsyncReadStream,+      DynamicBuffer_v1, MatchCondition, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_until_match_op_v1<AsyncReadStream,+        DynamicBuffer_v1, MatchCondition, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream,+    typename DynamicBuffer_v1, typename MatchCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_until_match_v1<AsyncReadStream>(s), handler,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), match_condition);+}++#if !defined(ASIO_NO_IOSTREAM)++template <typename AsyncReadStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    char delim, ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_read_until(s, basic_streambuf_ref<Allocator>(b),+      delim, ASIO_MOVE_CAST(ReadHandler)(handler));+}++template <typename AsyncReadStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    ASIO_STRING_VIEW_PARAM delim,+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_read_until(s, basic_streambuf_ref<Allocator>(b),+      delim, ASIO_MOVE_CAST(ReadHandler)(handler));+}++#if defined(ASIO_HAS_BOOST_REGEX)++template <typename AsyncReadStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,+    ASIO_MOVE_ARG(ReadHandler) handler)+{+  return async_read_until(s, basic_streambuf_ref<Allocator>(b),+      expr, ASIO_MOVE_CAST(ReadHandler)(handler));+}++#endif // defined(ASIO_HAS_BOOST_REGEX)++template <typename AsyncReadStream, typename Allocator, typename MatchCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<is_match_condition<MatchCondition>::value>::type*)+{+  return async_read_until(s, basic_streambuf_ref<Allocator>(b),+      match_condition, ASIO_MOVE_CAST(ReadHandler)(handler));+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++namespace detail+{+  template <typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  class read_until_delim_op_v2+  {+  public:+    template <typename BufferSequence>+    read_until_delim_op_v2(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        char delim, ReadHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        delim_(delim),+        start_(0),+        search_position_(0),+        bytes_to_read_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_until_delim_op_v2(const read_until_delim_op_v2& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        delim_(other.delim_),+        start_(other.start_),+        search_position_(other.search_position_),+        bytes_to_read_(other.bytes_to_read_),+        handler_(other.handler_)+    {+    }++    read_until_delim_op_v2(read_until_delim_op_v2&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),+        delim_(other.delim_),+        start_(other.start_),+        search_position_(other.search_position_),+        bytes_to_read_(other.bytes_to_read_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();+      std::size_t pos;+      switch (start_ = start)+      {+      case 1:+        for (;;)+        {+          {+            // Determine the range of the data to be searched.+            typedef typename DynamicBuffer_v2::const_buffers_type+              buffers_type;+            typedef buffers_iterator<buffers_type> iterator;+            buffers_type data_buffers =+              const_cast<const DynamicBuffer_v2&>(buffers_).data(+                  0, buffers_.size());+            iterator begin = iterator::begin(data_buffers);+            iterator start_pos = begin + search_position_;+            iterator end = iterator::end(data_buffers);++            // Look for a match.+            iterator iter = std::find(start_pos, end, delim_);+            if (iter != end)+            {+              // Found a match. We're done.+              search_position_ = iter - begin + 1;+              bytes_to_read_ = 0;+            }++            // No match yet. Check if buffer is full.+            else if (buffers_.size() == buffers_.max_size())+            {+              search_position_ = not_found;+              bytes_to_read_ = 0;+            }++            // Need to read some more data.+            else+            {+              // Next search can start with the new data.+              search_position_ = end - begin;+              bytes_to_read_ = std::min<std::size_t>(+                    std::max<std::size_t>(512,+                      buffers_.capacity() - buffers_.size()),+                    std::min<std::size_t>(65536,+                      buffers_.max_size() - buffers_.size()));+            }+          }++          // Check if we're done.+          if (!start && bytes_to_read_ == 0)+            break;++          // Start a new asynchronous read operation to obtain more data.+          pos = buffers_.size();+          buffers_.grow(bytes_to_read_);+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, "async_read_until"));+            stream_.async_read_some(buffers_.data(pos, bytes_to_read_),+                ASIO_MOVE_CAST(read_until_delim_op_v2)(*this));+          }+          return; default:+          buffers_.shrink(bytes_to_read_ - bytes_transferred);+          if (ec || bytes_transferred == 0)+            break;+        }++        const asio::error_code result_ec =+          (search_position_ == not_found)+          ? error::not_found : ec;++        const std::size_t result_n =+          (ec || search_position_ == not_found)+          ? 0 : search_position_;++        handler_(result_ec, result_n);+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v2 buffers_;+    char delim_;+    int start_;+    std::size_t search_position_;+    std::size_t bytes_to_read_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_until_delim_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_until_delim_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_until_delim_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_until_delim_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_until_delim_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_until_delim_v2+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_until_delim_v2(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler, typename DynamicBuffer_v2>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v2) buffers, char delim) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      read_until_delim_op_v2<AsyncReadStream,+        typename decay<DynamicBuffer_v2>::type,+          typename decay<ReadHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+            delim, handler2.value)(asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_until_delim_op_v2<AsyncReadStream,+      DynamicBuffer_v2, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_until_delim_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_until_delim_op_v2<AsyncReadStream,+      DynamicBuffer_v2, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_until_delim_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    char delim, ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_until_delim_v2<AsyncReadStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim);+}++namespace detail+{+  template <typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  class read_until_delim_string_op_v2+  {+  public:+    template <typename BufferSequence>+    read_until_delim_string_op_v2(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        const std::string& delim, ReadHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        delim_(delim),+        start_(0),+        search_position_(0),+        bytes_to_read_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        delim_(other.delim_),+        start_(other.start_),+        search_position_(other.search_position_),+        bytes_to_read_(other.bytes_to_read_),+        handler_(other.handler_)+    {+    }++    read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),+        delim_(ASIO_MOVE_CAST(std::string)(other.delim_)),+        start_(other.start_),+        search_position_(other.search_position_),+        bytes_to_read_(other.bytes_to_read_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();+      std::size_t pos;+      switch (start_ = start)+      {+      case 1:+        for (;;)+        {+          {+            // Determine the range of the data to be searched.+            typedef typename DynamicBuffer_v2::const_buffers_type+              buffers_type;+            typedef buffers_iterator<buffers_type> iterator;+            buffers_type data_buffers =+              const_cast<const DynamicBuffer_v2&>(buffers_).data(+                  0, buffers_.size());+            iterator begin = iterator::begin(data_buffers);+            iterator start_pos = begin + search_position_;+            iterator end = iterator::end(data_buffers);++            // Look for a match.+            std::pair<iterator, bool> result = detail::partial_search(+                start_pos, end, delim_.begin(), delim_.end());+            if (result.first != end && result.second)+            {+              // Full match. We're done.+              search_position_ = result.first - begin + delim_.length();+              bytes_to_read_ = 0;+            }++            // No match yet. Check if buffer is full.+            else if (buffers_.size() == buffers_.max_size())+            {+              search_position_ = not_found;+              bytes_to_read_ = 0;+            }++            // Need to read some more data.+            else+            {+              if (result.first != end)+              {+                // Partial match. Next search needs to start from beginning of+                // match.+                search_position_ = result.first - begin;+              }+              else+              {+                // Next search can start with the new data.+                search_position_ = end - begin;+              }++              bytes_to_read_ = std::min<std::size_t>(+                    std::max<std::size_t>(512,+                      buffers_.capacity() - buffers_.size()),+                    std::min<std::size_t>(65536,+                      buffers_.max_size() - buffers_.size()));+            }+          }++          // Check if we're done.+          if (!start && bytes_to_read_ == 0)+            break;++          // Start a new asynchronous read operation to obtain more data.+          pos = buffers_.size();+          buffers_.grow(bytes_to_read_);+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, "async_read_until"));+            stream_.async_read_some(buffers_.data(pos, bytes_to_read_),+                ASIO_MOVE_CAST(read_until_delim_string_op_v2)(*this));+          }+          return; default:+          buffers_.shrink(bytes_to_read_ - bytes_transferred);+          if (ec || bytes_transferred == 0)+            break;+        }++        const asio::error_code result_ec =+          (search_position_ == not_found)+          ? error::not_found : ec;++        const std::size_t result_n =+          (ec || search_position_ == not_found)+          ? 0 : search_position_;++        handler_(result_ec, result_n);+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v2 buffers_;+    std::string delim_;+    int start_;+    std::size_t search_position_;+    std::size_t bytes_to_read_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_until_delim_string_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_until_delim_string_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_until_delim_string_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_until_delim_string_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_until_delim_string_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_until_delim_string_v2+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_until_delim_string_v2(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler, typename DynamicBuffer_v2>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,+        const std::string& delim) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      read_until_delim_string_op_v2<AsyncReadStream,+        typename decay<DynamicBuffer_v2>::type,+          typename decay<ReadHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+            delim, handler2.value)(asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_until_delim_string_op_v2<AsyncReadStream,+      DynamicBuffer_v2, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_until_delim_string_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_until_delim_string_op_v2<AsyncReadStream,+      DynamicBuffer_v2, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_until_delim_string_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream,+    typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    DynamicBuffer_v2 buffers, ASIO_STRING_VIEW_PARAM delim,+    ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_until_delim_string_v2<AsyncReadStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      static_cast<std::string>(delim));+}++#if !defined(ASIO_NO_EXTENSIONS)+#if defined(ASIO_HAS_BOOST_REGEX)++namespace detail+{+  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename RegEx, typename ReadHandler>+  class read_until_expr_op_v2+  {+  public:+    template <typename BufferSequence>+    read_until_expr_op_v2(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        const boost::regex& expr, ReadHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        expr_(expr),+        start_(0),+        search_position_(0),+        bytes_to_read_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_until_expr_op_v2(const read_until_expr_op_v2& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        expr_(other.expr_),+        start_(other.start_),+        search_position_(other.search_position_),+        bytes_to_read_(other.bytes_to_read_),+        handler_(other.handler_)+    {+    }++    read_until_expr_op_v2(read_until_expr_op_v2&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),+        expr_(other.expr_),+        start_(other.start_),+        search_position_(other.search_position_),+        bytes_to_read_(other.bytes_to_read_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();+      std::size_t pos;+      switch (start_ = start)+      {+      case 1:+        for (;;)+        {+          {+            // Determine the range of the data to be searched.+            typedef typename DynamicBuffer_v2::const_buffers_type+              buffers_type;+            typedef buffers_iterator<buffers_type> iterator;+            buffers_type data_buffers =+              const_cast<const DynamicBuffer_v2&>(buffers_).data(+                  0, buffers_.size());+            iterator begin = iterator::begin(data_buffers);+            iterator start_pos = begin + search_position_;+            iterator end = iterator::end(data_buffers);++            // Look for a match.+            boost::match_results<iterator,+              typename std::vector<boost::sub_match<iterator> >::allocator_type>+                match_results;+            bool match = regex_search(start_pos, end, match_results, expr_,+                boost::match_default | boost::match_partial);+            if (match && match_results[0].matched)+            {+              // Full match. We're done.+              search_position_ = match_results[0].second - begin;+              bytes_to_read_ = 0;+            }++            // No match yet. Check if buffer is full.+            else if (buffers_.size() == buffers_.max_size())+            {+              search_position_ = not_found;+              bytes_to_read_ = 0;+            }++            // Need to read some more data.+            else+            {+              if (match)+              {+                // Partial match. Next search needs to start from beginning of+                // match.+                search_position_ = match_results[0].first - begin;+              }+              else+              {+                // Next search can start with the new data.+                search_position_ = end - begin;+              }++              bytes_to_read_ = std::min<std::size_t>(+                    std::max<std::size_t>(512,+                      buffers_.capacity() - buffers_.size()),+                    std::min<std::size_t>(65536,+                      buffers_.max_size() - buffers_.size()));+            }+          }++          // Check if we're done.+          if (!start && bytes_to_read_ == 0)+            break;++          // Start a new asynchronous read operation to obtain more data.+          pos = buffers_.size();+          buffers_.grow(bytes_to_read_);+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, "async_read_until"));+            stream_.async_read_some(buffers_.data(pos, bytes_to_read_),+                ASIO_MOVE_CAST(read_until_expr_op_v2)(*this));+          }+          return; default:+          buffers_.shrink(bytes_to_read_ - bytes_transferred);+          if (ec || bytes_transferred == 0)+            break;+        }++        const asio::error_code result_ec =+          (search_position_ == not_found)+          ? error::not_found : ec;++        const std::size_t result_n =+          (ec || search_position_ == not_found)+          ? 0 : search_position_;++        handler_(result_ec, result_n);+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v2 buffers_;+    RegEx expr_;+    int start_;+    std::size_t search_position_;+    std::size_t bytes_to_read_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename RegEx, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_until_expr_op_v2<AsyncReadStream,+        DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename RegEx, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_until_expr_op_v2<AsyncReadStream,+        DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename RegEx, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_until_expr_op_v2<AsyncReadStream,+        DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_until_expr_op_v2<AsyncReadStream,+        DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename RegEx, typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_until_expr_op_v2<AsyncReadStream,+        DynamicBuffer_v2, RegEx, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_until_expr_v2+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_until_expr_v2(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler, typename DynamicBuffer_v2, typename RegEx>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,+        const RegEx& expr) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      read_until_expr_op_v2<AsyncReadStream,+        typename decay<DynamicBuffer_v2>::type,+          RegEx, typename decay<ReadHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+            expr, handler2.value)(asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename RegEx, typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_until_expr_op_v2<AsyncReadStream,+      DynamicBuffer_v2, RegEx, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_until_expr_op_v2<AsyncReadStream,+        DynamicBuffer_v2, RegEx, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename RegEx, typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_until_expr_op_v2<AsyncReadStream,+      DynamicBuffer_v2, RegEx, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_until_expr_op_v2<AsyncReadStream,+        DynamicBuffer_v2, RegEx, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    const boost::regex& expr, ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_until_expr_v2<AsyncReadStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr);+}++#endif // defined(ASIO_HAS_BOOST_REGEX)++namespace detail+{+  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename MatchCondition, typename ReadHandler>+  class read_until_match_op_v2+  {+  public:+    template <typename BufferSequence>+    read_until_match_op_v2(AsyncReadStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        MatchCondition match_condition, ReadHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        match_condition_(match_condition),+        start_(0),+        search_position_(0),+        bytes_to_read_(0),+        handler_(ASIO_MOVE_CAST(ReadHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    read_until_match_op_v2(const read_until_match_op_v2& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        match_condition_(other.match_condition_),+        start_(other.start_),+        search_position_(other.search_position_),+        bytes_to_read_(other.bytes_to_read_),+        handler_(other.handler_)+    {+    }++    read_until_match_op_v2(read_until_match_op_v2&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),+        match_condition_(other.match_condition_),+        start_(other.start_),+        search_position_(other.search_position_),+        bytes_to_read_(other.bytes_to_read_),+        handler_(ASIO_MOVE_CAST(ReadHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      const std::size_t not_found = (std::numeric_limits<std::size_t>::max)();+      std::size_t pos;+      switch (start_ = start)+      {+      case 1:+        for (;;)+        {+          {+            // Determine the range of the data to be searched.+            typedef typename DynamicBuffer_v2::const_buffers_type+              buffers_type;+            typedef buffers_iterator<buffers_type> iterator;+            buffers_type data_buffers =+              const_cast<const DynamicBuffer_v2&>(buffers_).data(+                  0, buffers_.size());+            iterator begin = iterator::begin(data_buffers);+            iterator start_pos = begin + search_position_;+            iterator end = iterator::end(data_buffers);++            // Look for a match.+            std::pair<iterator, bool> result = match_condition_(start_pos, end);+            if (result.second)+            {+              // Full match. We're done.+              search_position_ = result.first - begin;+              bytes_to_read_ = 0;+            }++            // No match yet. Check if buffer is full.+            else if (buffers_.size() == buffers_.max_size())+            {+              search_position_ = not_found;+              bytes_to_read_ = 0;+            }++            // Need to read some more data.+            else+            {+              if (result.first != end)+              {+                // Partial match. Next search needs to start from beginning of+                // match.+                search_position_ = result.first - begin;+              }+              else+              {+                // Next search can start with the new data.+                search_position_ = end - begin;+              }++              bytes_to_read_ = std::min<std::size_t>(+                    std::max<std::size_t>(512,+                      buffers_.capacity() - buffers_.size()),+                    std::min<std::size_t>(65536,+                      buffers_.max_size() - buffers_.size()));+            }+          }++          // Check if we're done.+          if (!start && bytes_to_read_ == 0)+            break;++          // Start a new asynchronous read operation to obtain more data.+          pos = buffers_.size();+          buffers_.grow(bytes_to_read_);+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, "async_read_until"));+            stream_.async_read_some(buffers_.data(pos, bytes_to_read_),+                ASIO_MOVE_CAST(read_until_match_op_v2)(*this));+          }+          return; default:+          buffers_.shrink(bytes_to_read_ - bytes_transferred);+          if (ec || bytes_transferred == 0)+            break;+        }++        const asio::error_code result_ec =+          (search_position_ == not_found)+          ? error::not_found : ec;++        const std::size_t result_n =+          (ec || search_position_ == not_found)+          ? 0 : search_position_;++        handler_(result_ec, result_n);+      }+    }++  //private:+    AsyncReadStream& stream_;+    DynamicBuffer_v2 buffers_;+    MatchCondition match_condition_;+    int start_;+    std::size_t search_position_;+    std::size_t bytes_to_read_;+    ReadHandler handler_;+  };++  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename MatchCondition, typename ReadHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,+        MatchCondition, ReadHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename MatchCondition, typename ReadHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,+        MatchCondition, ReadHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream, typename DynamicBuffer_v2,+      typename MatchCondition, typename ReadHandler>+  inline bool asio_handler_is_continuation(+      read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,+        MatchCondition, ReadHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename MatchCondition,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,+        MatchCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncReadStream,+      typename DynamicBuffer_v2, typename MatchCondition,+      typename ReadHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      read_until_match_op_v2<AsyncReadStream, DynamicBuffer_v2,+      MatchCondition, ReadHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncReadStream>+  class initiate_async_read_until_match_v2+  {+  public:+    typedef typename AsyncReadStream::executor_type executor_type;++    explicit initiate_async_read_until_match_v2(AsyncReadStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename ReadHandler,+        typename DynamicBuffer_v2, typename MatchCondition>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,+        MatchCondition match_condition) 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;++      non_const_lvalue<ReadHandler> handler2(handler);+      read_until_match_op_v2<AsyncReadStream,+        typename decay<DynamicBuffer_v2>::type,+          MatchCondition, typename decay<ReadHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+            match_condition, handler2.value)(asio::error_code(), 0, 1);+    }++  private:+    AsyncReadStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename MatchCondition, typename ReadHandler, typename Allocator>+struct associated_allocator<+    detail::read_until_match_op_v2<AsyncReadStream,+      DynamicBuffer_v2, MatchCondition, ReadHandler>,+    Allocator>+{+  typedef typename associated_allocator<ReadHandler, Allocator>::type type;++  static type get(+      const detail::read_until_match_op_v2<AsyncReadStream,+        DynamicBuffer_v2, MatchCondition, ReadHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncReadStream, typename DynamicBuffer_v2,+    typename MatchCondition, typename ReadHandler, typename Executor>+struct associated_executor<+    detail::read_until_match_op_v2<AsyncReadStream,+      DynamicBuffer_v2, MatchCondition, ReadHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<ReadHandler, Executor>+{+  typedef typename associated_executor<ReadHandler, Executor>::type type;++  static type get(+      const detail::read_until_match_op_v2<AsyncReadStream,+        DynamicBuffer_v2, MatchCondition, ReadHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncReadStream,+    typename DynamicBuffer_v2, typename MatchCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    MatchCondition match_condition, ASIO_MOVE_ARG(ReadHandler) handler,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return async_initiate<ReadHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_until_match_v2<AsyncReadStream>(s), handler,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), match_condition);+}++#endif // !defined(ASIO_NO_EXTENSIONS)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_READ_UNTIL_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/redirect_error.hpp view
@@ -0,0 +1,390 @@++// impl/redirect_error.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_REDIRECT_ERROR_HPP+#define ASIO_IMPL_REDIRECT_ERROR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_executor.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/system_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Class to adapt a redirect_error_t as a completion handler.+template <typename Handler>+class redirect_error_handler+{+public:+  typedef void result_type;++  template <typename CompletionToken>+  redirect_error_handler(redirect_error_t<CompletionToken> e)+    : ec_(e.ec_),+      handler_(ASIO_MOVE_CAST(CompletionToken)(e.token_))+  {+  }++  template <typename RedirectedHandler>+  redirect_error_handler(asio::error_code& ec,+      ASIO_MOVE_ARG(RedirectedHandler) h)+    : ec_(ec),+      handler_(ASIO_MOVE_CAST(RedirectedHandler)(h))+  {+  }++  void operator()()+  {+    handler_();+  }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Arg, typename... Args>+  typename enable_if<+    !is_same<typename decay<Arg>::type, asio::error_code>::value+  >::type+  operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_MOVE_ARG(Args)... args)+  {+    handler_(ASIO_MOVE_CAST(Arg)(arg),+        ASIO_MOVE_CAST(Args)(args)...);+  }++  template <typename... Args>+  void operator()(const asio::error_code& ec,+      ASIO_MOVE_ARG(Args)... args)+  {+    ec_ = ec;+    handler_(ASIO_MOVE_CAST(Args)(args)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Arg>+  typename enable_if<+    !is_same<typename decay<Arg>::type, asio::error_code>::value+  >::type+  operator()(ASIO_MOVE_ARG(Arg) arg)+  {+    handler_(ASIO_MOVE_CAST(Arg)(arg));+  }++  void operator()(const asio::error_code& ec)+  {+    ec_ = ec;+    handler_();+  }++#define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \+  template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \+  typename enable_if< \+    !is_same<typename decay<Arg>::type, asio::error_code>::value \+  >::type \+  operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    handler_(ASIO_MOVE_CAST(Arg)(arg), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  void operator()(const asio::error_code& ec, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    ec_ = ec; \+    handler_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF)+#undef ASIO_PRIVATE_REDIRECT_ERROR_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++//private:+  asio::error_code& ec_;+  Handler handler_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    redirect_error_handler<Handler>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    redirect_error_handler<Handler>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Handler>+inline bool asio_handler_is_continuation(+    redirect_error_handler<Handler>* this_handler)+{+  return asio_handler_cont_helpers::is_continuation(+        this_handler->handler_);+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+    redirect_error_handler<Handler>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+    redirect_error_handler<Handler>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Signature>+struct redirect_error_signature+{+  typedef Signature type;+};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename R, typename... Args>+struct redirect_error_signature<R(asio::error_code, Args...)>+{+  typedef R type(Args...);+};++template <typename R, typename... Args>+struct redirect_error_signature<R(const asio::error_code&, Args...)>+{+  typedef R type(Args...);+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename R>+struct redirect_error_signature<R(asio::error_code)>+{+  typedef R type();+};++template <typename R>+struct redirect_error_signature<R(const asio::error_code&)>+{+  typedef R type();+};++#define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct redirect_error_signature< \+      R(asio::error_code, ASIO_VARIADIC_TARGS(n))> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)); \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct redirect_error_signature< \+      R(const asio::error_code&, ASIO_VARIADIC_TARGS(n))> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)); \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF)+#undef ASIO_PRIVATE_REDIRECT_ERROR_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename Signature>+struct async_result<redirect_error_t<CompletionToken>, Signature>+{+  typedef typename async_result<CompletionToken,+    typename detail::redirect_error_signature<Signature>::type>+      ::return_type return_type;++  template <typename Initiation>+  struct init_wrapper+  {+    template <typename Init>+    init_wrapper(asio::error_code& ec, ASIO_MOVE_ARG(Init) init)+      : ec_(ec),+        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_)(+          detail::redirect_error_handler<+            typename decay<Handler>::type>(+              ec_, 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_)(+          detail::redirect_error_handler<+            typename decay<Handler>::type>(+              ec_, 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_)( \+          detail::redirect_error_handler< \+            typename decay<Handler>::type>( \+              ec_, 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)++    asio::error_code& ec_;+    Initiation initiation_;+  };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static return_type initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+  {+    return async_initiate<CompletionToken,+      typename detail::redirect_error_signature<Signature>::type>(+        init_wrapper<typename decay<Initiation>::type>(+          token.ec_, ASIO_MOVE_CAST(Initiation)(initiation)),+        token.token_, ASIO_MOVE_CAST(Args)(args)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken>+  static return_type initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token)+  {+    return async_initiate<CompletionToken,+      typename detail::redirect_error_signature<Signature>::type>(+        init_wrapper<typename decay<Initiation>::type>(+          token.ec_, ASIO_MOVE_CAST(Initiation)(initiation)),+        token.token_);+  }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, typename RawCompletionToken, \+      ASIO_VARIADIC_TPARAMS(n)> \+  static return_type initiate( \+      ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_MOVE_ARG(RawCompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return async_initiate<CompletionToken, \+      typename detail::redirect_error_signature<Signature>::type>( \+        init_wrapper<typename decay<Initiation>::type>( \+          token.ec_, ASIO_MOVE_CAST(Initiation)(initiation)), \+        token.token_, ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+};++template <typename Handler, typename Executor>+struct associated_executor<detail::redirect_error_handler<Handler>, Executor>+{+  typedef typename associated_executor<Handler, Executor>::type type;++  static type get(+      const detail::redirect_error_handler<Handler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<Handler, Executor>::get(h.handler_, ex);+  }+};++template <typename Handler, typename Allocator>+struct associated_allocator<detail::redirect_error_handler<Handler>, Allocator>+{+  typedef typename associated_allocator<Handler, Allocator>::type type;++  static type get(+      const detail::redirect_error_handler<Handler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_REDIRECT_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.hpp view
@@ -0,0 +1,59 @@+//+// impl/serial_port_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_SERIAL_PORT_BASE_HPP+#define ASIO_IMPL_SERIAL_PORT_BASE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/push_options.hpp"++namespace asio {++inline serial_port_base::baud_rate::baud_rate(unsigned int rate)+  : value_(rate)+{+}++inline unsigned int serial_port_base::baud_rate::value() const+{+  return value_;+}++inline serial_port_base::flow_control::type+serial_port_base::flow_control::value() const+{+  return value_;+}++inline serial_port_base::parity::type serial_port_base::parity::value() const+{+  return value_;+}++inline serial_port_base::stop_bits::type+serial_port_base::stop_bits::value() const+{+  return value_;+}++inline unsigned int serial_port_base::character_size::value() const+{+  return value_;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_SERIAL_PORT_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.ipp view
@@ -0,0 +1,554 @@+//+// impl/serial_port_base.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_SERIAL_PORT_BASE_IPP+#define ASIO_IMPL_SERIAL_PORT_BASE_IPP++#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)++#include <stdexcept>+#include "asio/error.hpp"+#include "asio/serial_port_base.hpp"+#include "asio/detail/throw_exception.hpp"++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_OPTION_STORAGE implementation_defined+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# define ASIO_OPTION_STORAGE DCB+#else+# define ASIO_OPTION_STORAGE termios+#endif++#include "asio/detail/push_options.hpp"++namespace asio {++ASIO_SYNC_OP_VOID serial_port_base::baud_rate::store(+    ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  storage.BaudRate = value_;+#else+  speed_t baud;+  switch (value_)+  {+  // Do POSIX-specified rates first.+  case 0: baud = B0; break;+  case 50: baud = B50; break;+  case 75: baud = B75; break;+  case 110: baud = B110; break;+  case 134: baud = B134; break;+  case 150: baud = B150; break;+  case 200: baud = B200; break;+  case 300: baud = B300; break;+  case 600: baud = B600; break;+  case 1200: baud = B1200; break;+  case 1800: baud = B1800; break;+  case 2400: baud = B2400; break;+  case 4800: baud = B4800; break;+  case 9600: baud = B9600; break;+  case 19200: baud = B19200; break;+  case 38400: baud = B38400; break;+  // And now the extended ones conditionally.+# ifdef B7200+  case 7200: baud = B7200; break;+# endif+# ifdef B14400+  case 14400: baud = B14400; break;+# endif+# ifdef B57600+  case 57600: baud = B57600; break;+# endif+# ifdef B115200+  case 115200: baud = B115200; break;+# endif+# ifdef B230400+  case 230400: baud = B230400; break;+# endif+# ifdef B460800+  case 460800: baud = B460800; break;+# endif+# ifdef B500000+  case 500000: baud = B500000; break;+# endif+# ifdef B576000+  case 576000: baud = B576000; break;+# endif+# ifdef B921600+  case 921600: baud = B921600; break;+# endif+# ifdef B1000000+  case 1000000: baud = B1000000; break;+# endif+# ifdef B1152000+  case 1152000: baud = B1152000; break;+# endif+# ifdef B2000000+  case 2000000: baud = B2000000; break;+# endif+# ifdef B3000000+  case 3000000: baud = B3000000; break;+# endif+# ifdef B3500000+  case 3500000: baud = B3500000; break;+# endif+# ifdef B4000000+  case 4000000: baud = B4000000; break;+# endif+  default:+    ec = asio::error::invalid_argument;+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)+  ::cfsetspeed(&storage, baud);+# else+  ::cfsetispeed(&storage, baud);+  ::cfsetospeed(&storage, baud);+# endif+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++ASIO_SYNC_OP_VOID serial_port_base::baud_rate::load(+    const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  value_ = storage.BaudRate;+#else+  speed_t baud = ::cfgetospeed(&storage);+  switch (baud)+  {+  // First do those specified by POSIX.+  case B0: value_ = 0; break;+  case B50: value_ = 50; break;+  case B75: value_ = 75; break;+  case B110: value_ = 110; break;+  case B134: value_ = 134; break;+  case B150: value_ = 150; break;+  case B200: value_ = 200; break;+  case B300: value_ = 300; break;+  case B600: value_ = 600; break;+  case B1200: value_ = 1200; break;+  case B1800: value_ = 1800; break;+  case B2400: value_ = 2400; break;+  case B4800: value_ = 4800; break;+  case B9600: value_ = 9600; break;+  case B19200: value_ = 19200; break;+  case B38400: value_ = 38400; break;+  // Now conditionally handle a bunch of extended rates.+# ifdef B7200+  case B7200: value_ = 7200; break;+# endif+# ifdef B14400+  case B14400: value_ = 14400; break;+# endif+# ifdef B57600+  case B57600: value_ = 57600; break;+# endif+# ifdef B115200+  case B115200: value_ = 115200; break;+# endif+# ifdef B230400+  case B230400: value_ = 230400; break;+# endif+# ifdef B460800+  case B460800: value_ = 460800; break;+# endif+# ifdef B500000+  case B500000: value_ = 500000; break;+# endif+# ifdef B576000+  case B576000: value_ = 576000; break;+# endif+# ifdef B921600+  case B921600: value_ = 921600; break;+# endif+# ifdef B1000000+  case B1000000: value_ = 1000000; break;+# endif+# ifdef B1152000+  case B1152000: value_ = 1152000; break;+# endif+# ifdef B2000000+  case B2000000: value_ = 2000000; break;+# endif+# ifdef B3000000+  case B3000000: value_ = 3000000; break;+# endif+# ifdef B3500000+  case B3500000: value_ = 3500000; break;+# endif+# ifdef B4000000+  case B4000000: value_ = 4000000; break;+# endif+  default:+    value_ = 0;+    ec = asio::error::invalid_argument;+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++serial_port_base::flow_control::flow_control(+    serial_port_base::flow_control::type t)+  : value_(t)+{+  if (t != none && t != software && t != hardware)+  {+    std::out_of_range ex("invalid flow_control value");+    asio::detail::throw_exception(ex);+  }+}++ASIO_SYNC_OP_VOID serial_port_base::flow_control::store(+    ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  storage.fOutxCtsFlow = FALSE;+  storage.fOutxDsrFlow = FALSE;+  storage.fTXContinueOnXoff = TRUE;+  storage.fDtrControl = DTR_CONTROL_ENABLE;+  storage.fDsrSensitivity = FALSE;+  storage.fOutX = FALSE;+  storage.fInX = FALSE;+  storage.fRtsControl = RTS_CONTROL_ENABLE;+  switch (value_)+  {+  case none:+    break;+  case software:+    storage.fOutX = TRUE;+    storage.fInX = TRUE;+    break;+  case hardware:+    storage.fOutxCtsFlow = TRUE;+    storage.fRtsControl = RTS_CONTROL_HANDSHAKE;+    break;+  default:+    break;+  }+#else+  switch (value_)+  {+  case none:+    storage.c_iflag &= ~(IXOFF | IXON);+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)+    storage.c_cflag &= ~CRTSCTS;+# elif defined(__QNXNTO__)+    storage.c_cflag &= ~(IHFLOW | OHFLOW);+# endif+    break;+  case software:+    storage.c_iflag |= IXOFF | IXON;+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)+    storage.c_cflag &= ~CRTSCTS;+# elif defined(__QNXNTO__)+    storage.c_cflag &= ~(IHFLOW | OHFLOW);+# endif+    break;+  case hardware:+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)+    storage.c_iflag &= ~(IXOFF | IXON);+    storage.c_cflag |= CRTSCTS;+    break;+# elif defined(__QNXNTO__)+    storage.c_iflag &= ~(IXOFF | IXON);+    storage.c_cflag |= (IHFLOW | OHFLOW);+    break;+# else+    ec = asio::error::operation_not_supported;+    ASIO_SYNC_OP_VOID_RETURN(ec);+# endif+  default:+    break;+  }+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++ASIO_SYNC_OP_VOID serial_port_base::flow_control::load(+    const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  if (storage.fOutX && storage.fInX)+  {+    value_ = software;+  }+  else if (storage.fOutxCtsFlow && storage.fRtsControl == RTS_CONTROL_HANDSHAKE)+  {+    value_ = hardware;+  }+  else+  {+    value_ = none;+  }+#else+  if (storage.c_iflag & (IXOFF | IXON))+  {+    value_ = software;+  }+# if defined(_BSD_SOURCE) || defined(_DEFAULT_SOURCE)+  else if (storage.c_cflag & CRTSCTS)+  {+    value_ = hardware;+  }+# elif defined(__QNXNTO__)+  else if (storage.c_cflag & IHFLOW && storage.c_cflag & OHFLOW)+  {+    value_ = hardware;+  }+# endif+  else+  {+    value_ = none;+  }+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++serial_port_base::parity::parity(serial_port_base::parity::type t)+  : value_(t)+{+  if (t != none && t != odd && t != even)+  {+    std::out_of_range ex("invalid parity value");+    asio::detail::throw_exception(ex);+  }+}++ASIO_SYNC_OP_VOID serial_port_base::parity::store(+    ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  switch (value_)+  {+  case none:+    storage.fParity = FALSE;+    storage.Parity = NOPARITY;+    break;+  case odd:+    storage.fParity = TRUE;+    storage.Parity = ODDPARITY;+    break;+  case even:+    storage.fParity = TRUE;+    storage.Parity = EVENPARITY;+    break;+  default:+    break;+  }+#else+  switch (value_)+  {+  case none:+    storage.c_iflag |= IGNPAR;+    storage.c_cflag &= ~(PARENB | PARODD);+    break;+  case even:+    storage.c_iflag &= ~(IGNPAR | PARMRK);+    storage.c_iflag |= INPCK;+    storage.c_cflag |= PARENB;+    storage.c_cflag &= ~PARODD;+    break;+  case odd:+    storage.c_iflag &= ~(IGNPAR | PARMRK);+    storage.c_iflag |= INPCK;+    storage.c_cflag |= (PARENB | PARODD);+    break;+  default:+    break;+  }+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++ASIO_SYNC_OP_VOID serial_port_base::parity::load(+    const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  if (storage.Parity == EVENPARITY)+  {+    value_ = even;+  }+  else if (storage.Parity == ODDPARITY)+  {+    value_ = odd;+  }+  else+  {+    value_ = none;+  }+#else+  if (storage.c_cflag & PARENB)+  {+    if (storage.c_cflag & PARODD)+    {+      value_ = odd;+    }+    else+    {+      value_ = even;+    }+  }+  else+  {+    value_ = none;+  }+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++serial_port_base::stop_bits::stop_bits(+    serial_port_base::stop_bits::type t)+  : value_(t)+{+  if (t != one && t != onepointfive && t != two)+  {+    std::out_of_range ex("invalid stop_bits value");+    asio::detail::throw_exception(ex);+  }+}++ASIO_SYNC_OP_VOID serial_port_base::stop_bits::store(+    ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  switch (value_)+  {+  case one:+    storage.StopBits = ONESTOPBIT;+    break;+  case onepointfive:+    storage.StopBits = ONE5STOPBITS;+    break;+  case two:+    storage.StopBits = TWOSTOPBITS;+    break;+  default:+    break;+  }+#else+  switch (value_)+  {+  case one:+    storage.c_cflag &= ~CSTOPB;+    break;+  case two:+    storage.c_cflag |= CSTOPB;+    break;+  default:+    ec = asio::error::operation_not_supported;+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++ASIO_SYNC_OP_VOID serial_port_base::stop_bits::load(+    const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  if (storage.StopBits == ONESTOPBIT)+  {+    value_ = one;+  }+  else if (storage.StopBits == ONE5STOPBITS)+  {+    value_ = onepointfive;+  }+  else if (storage.StopBits == TWOSTOPBITS)+  {+    value_ = two;+  }+  else+  {+    value_ = one;+  }+#else+  value_ = (storage.c_cflag & CSTOPB) ? two : one;+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++serial_port_base::character_size::character_size(unsigned int t)+  : value_(t)+{+  if (t < 5 || t > 8)+  {+    std::out_of_range ex("invalid character_size value");+    asio::detail::throw_exception(ex);+  }+}++ASIO_SYNC_OP_VOID serial_port_base::character_size::store(+    ASIO_OPTION_STORAGE& storage, asio::error_code& ec) const+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  storage.ByteSize = value_;+#else+  storage.c_cflag &= ~CSIZE;+  switch (value_)+  {+  case 5: storage.c_cflag |= CS5; break;+  case 6: storage.c_cflag |= CS6; break;+  case 7: storage.c_cflag |= CS7; break;+  case 8: storage.c_cflag |= CS8; break;+  default: break;+  }+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++ASIO_SYNC_OP_VOID serial_port_base::character_size::load(+    const ASIO_OPTION_STORAGE& storage, asio::error_code& ec)+{+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  value_ = storage.ByteSize;+#else+  if ((storage.c_cflag & CSIZE) == CS5) { value_ = 5; }+  else if ((storage.c_cflag & CSIZE) == CS6) { value_ = 6; }+  else if ((storage.c_cflag & CSIZE) == CS7) { value_ = 7; }+  else if ((storage.c_cflag & CSIZE) == CS8) { value_ = 8; }+  else+  {+    // Hmmm, use 8 for now.+    value_ = 8;+  }+#endif+  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#undef ASIO_OPTION_STORAGE++#endif // defined(ASIO_HAS_SERIAL_PORT)++#endif // ASIO_IMPL_SERIAL_PORT_BASE_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/spawn.hpp view
@@ -0,0 +1,526 @@+//+// impl/spawn.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_SPAWN_HPP+#define ASIO_IMPL_SPAWN_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/bind_executor.hpp"+#include "asio/detail/atomic_count.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/system_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++  template <typename Handler, typename T>+  class coro_handler+  {+  public:+    coro_handler(basic_yield_context<Handler> ctx)+      : coro_(ctx.coro_.lock()),+        ca_(ctx.ca_),+        handler_(ctx.handler_),+        ready_(0),+        ec_(ctx.ec_),+        value_(0)+    {+    }++    void operator()(T value)+    {+      *ec_ = asio::error_code();+      *value_ = ASIO_MOVE_CAST(T)(value);+      if (--*ready_ == 0)+        (*coro_)();+    }++    void operator()(asio::error_code ec, T value)+    {+      *ec_ = ec;+      *value_ = ASIO_MOVE_CAST(T)(value);+      if (--*ready_ == 0)+        (*coro_)();+    }++  //private:+    shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;+    typename basic_yield_context<Handler>::caller_type& ca_;+    Handler handler_;+    atomic_count* ready_;+    asio::error_code* ec_;+    T* value_;+  };++  template <typename Handler>+  class coro_handler<Handler, void>+  {+  public:+    coro_handler(basic_yield_context<Handler> ctx)+      : coro_(ctx.coro_.lock()),+        ca_(ctx.ca_),+        handler_(ctx.handler_),+        ready_(0),+        ec_(ctx.ec_)+    {+    }++    void operator()()+    {+      *ec_ = asio::error_code();+      if (--*ready_ == 0)+        (*coro_)();+    }++    void operator()(asio::error_code ec)+    {+      *ec_ = ec;+      if (--*ready_ == 0)+        (*coro_)();+    }++  //private:+    shared_ptr<typename basic_yield_context<Handler>::callee_type> coro_;+    typename basic_yield_context<Handler>::caller_type& ca_;+    Handler handler_;+    atomic_count* ready_;+    asio::error_code* ec_;+  };++  template <typename Handler, typename T>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      coro_handler<Handler, T>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Handler, typename T>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      coro_handler<Handler, T>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Handler, typename T>+  inline bool asio_handler_is_continuation(coro_handler<Handler, T>*)+  {+    return true;+  }++  template <typename Function, typename Handler, typename T>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      coro_handler<Handler, T>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename Handler, typename T>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      coro_handler<Handler, T>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Handler, typename T>+  class coro_async_result+  {+  public:+    typedef coro_handler<Handler, T> completion_handler_type;+    typedef T return_type;++    explicit coro_async_result(completion_handler_type& h)+      : handler_(h),+        ca_(h.ca_),+        ready_(2)+    {+      h.ready_ = &ready_;+      out_ec_ = h.ec_;+      if (!out_ec_) h.ec_ = &ec_;+      h.value_ = &value_;+    }++    return_type get()+    {+      // Must not hold shared_ptr to coro while suspended.+      handler_.coro_.reset();++      if (--ready_ != 0)+        ca_();+      if (!out_ec_ && ec_) throw asio::system_error(ec_);+      return ASIO_MOVE_CAST(return_type)(value_);+    }++  private:+    completion_handler_type& handler_;+    typename basic_yield_context<Handler>::caller_type& ca_;+    atomic_count ready_;+    asio::error_code* out_ec_;+    asio::error_code ec_;+    return_type value_;+  };++  template <typename Handler>+  class coro_async_result<Handler, void>+  {+  public:+    typedef coro_handler<Handler, void> completion_handler_type;+    typedef void return_type;++    explicit coro_async_result(completion_handler_type& h)+      : handler_(h),+        ca_(h.ca_),+        ready_(2)+    {+      h.ready_ = &ready_;+      out_ec_ = h.ec_;+      if (!out_ec_) h.ec_ = &ec_;+    }++    void get()+    {+      // Must not hold shared_ptr to coro while suspended.+      handler_.coro_.reset();++      if (--ready_ != 0)+        ca_();+      if (!out_ec_ && ec_) throw asio::system_error(ec_);+    }++  private:+    completion_handler_type& handler_;+    typename basic_yield_context<Handler>::caller_type& ca_;+    atomic_count ready_;+    asio::error_code* out_ec_;+    asio::error_code ec_;+  };++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename Handler, typename ReturnType>+class async_result<basic_yield_context<Handler>, ReturnType()>+  : public detail::coro_async_result<Handler, void>+{+public:+  explicit async_result(+    typename detail::coro_async_result<Handler,+      void>::completion_handler_type& h)+    : detail::coro_async_result<Handler, void>(h)+  {+  }+};++template <typename Handler, typename ReturnType, typename Arg1>+class async_result<basic_yield_context<Handler>, ReturnType(Arg1)>+  : public detail::coro_async_result<Handler, typename decay<Arg1>::type>+{+public:+  explicit async_result(+    typename detail::coro_async_result<Handler,+      typename decay<Arg1>::type>::completion_handler_type& h)+    : detail::coro_async_result<Handler, typename decay<Arg1>::type>(h)+  {+  }+};++template <typename Handler, typename ReturnType>+class async_result<basic_yield_context<Handler>,+    ReturnType(asio::error_code)>+  : public detail::coro_async_result<Handler, void>+{+public:+  explicit async_result(+    typename detail::coro_async_result<Handler,+      void>::completion_handler_type& h)+    : detail::coro_async_result<Handler, void>(h)+  {+  }+};++template <typename Handler, typename ReturnType, typename Arg2>+class async_result<basic_yield_context<Handler>,+    ReturnType(asio::error_code, Arg2)>+  : public detail::coro_async_result<Handler, typename decay<Arg2>::type>+{+public:+  explicit async_result(+    typename detail::coro_async_result<Handler,+      typename decay<Arg2>::type>::completion_handler_type& h)+    : detail::coro_async_result<Handler, typename decay<Arg2>::type>(h)+  {+  }+};++template <typename Handler, typename T, typename Allocator>+struct associated_allocator<detail::coro_handler<Handler, T>, Allocator>+{+  typedef typename associated_allocator<Handler, Allocator>::type type;++  static type get(const detail::coro_handler<Handler, T>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+  }+};++template <typename Handler, typename T, typename Executor>+struct associated_executor<detail::coro_handler<Handler, T>, Executor>+{+  typedef typename associated_executor<Handler, Executor>::type type;++  static type get(const detail::coro_handler<Handler, T>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<Handler, Executor>::get(h.handler_, ex);+  }+};++namespace detail {++  template <typename Handler, typename Function>+  struct spawn_data : private noncopyable+  {+    template <typename Hand, typename Func>+    spawn_data(ASIO_MOVE_ARG(Hand) handler,+        bool call_handler, ASIO_MOVE_ARG(Func) function)+      : handler_(ASIO_MOVE_CAST(Hand)(handler)),+        call_handler_(call_handler),+        function_(ASIO_MOVE_CAST(Func)(function))+    {+    }++    weak_ptr<typename basic_yield_context<Handler>::callee_type> coro_;+    Handler handler_;+    bool call_handler_;+    Function function_;+  };++  template <typename Handler, typename Function>+  struct coro_entry_point+  {+    void operator()(typename basic_yield_context<Handler>::caller_type& ca)+    {+      shared_ptr<spawn_data<Handler, Function> > data(data_);+#if !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2)+      ca(); // Yield until coroutine pointer has been initialised.+#endif // !defined(BOOST_COROUTINES_UNIDIRECT) && !defined(BOOST_COROUTINES_V2)+      const basic_yield_context<Handler> yield(+          data->coro_, ca, data->handler_);++      (data->function_)(yield);+      if (data->call_handler_)+        (data->handler_)();+    }++    shared_ptr<spawn_data<Handler, Function> > data_;+  };++  template <typename Handler, typename Function>+  struct spawn_helper+  {+    typedef typename associated_allocator<Handler>::type allocator_type;++    allocator_type get_allocator() const ASIO_NOEXCEPT+    {+      return (get_associated_allocator)(data_->handler_);+    }++    typedef typename associated_executor<Handler>::type executor_type;++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return (get_associated_executor)(data_->handler_);+    }++    void operator()()+    {+      typedef typename basic_yield_context<Handler>::callee_type callee_type;+      coro_entry_point<Handler, Function> entry_point = { data_ };+      shared_ptr<callee_type> coro(new callee_type(entry_point, attributes_));+      data_->coro_ = coro;+      (*coro)();+    }++    shared_ptr<spawn_data<Handler, Function> > data_;+    boost::coroutines::attributes attributes_;+  };++  template <typename Function, typename Handler, typename Function1>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      spawn_helper<Handler, Function1>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->data_->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename Handler, typename Function1>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      spawn_helper<Handler, Function1>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->data_->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  inline void default_spawn_handler() {}++} // namespace detail++template <typename Function>+inline void spawn(ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes)+{+  typedef typename decay<Function>::type function_type;++  typename associated_executor<function_type>::type ex(+      (get_associated_executor)(function));++  asio::spawn(ex, ASIO_MOVE_CAST(Function)(function), attributes);+}++template <typename Handler, typename Function>+void spawn(ASIO_MOVE_ARG(Handler) handler,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes,+    typename enable_if<+      !is_executor<typename decay<Handler>::type>::value &&+      !execution::is_executor<typename decay<Handler>::type>::value &&+      !is_convertible<Handler&, execution_context&>::value>::type*)+{+  typedef typename decay<Handler>::type handler_type;+  typedef typename decay<Function>::type function_type;++  detail::spawn_helper<handler_type, function_type> helper;+  helper.data_.reset(+      new detail::spawn_data<handler_type, function_type>(+        ASIO_MOVE_CAST(Handler)(handler), true,+        ASIO_MOVE_CAST(Function)(function)));+  helper.attributes_ = attributes;++  asio::dispatch(helper);+}++template <typename Handler, typename Function>+void spawn(basic_yield_context<Handler> ctx,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes)+{+  typedef typename decay<Function>::type function_type;++  Handler handler(ctx.handler_); // Explicit copy that might be moved from.++  detail::spawn_helper<Handler, function_type> helper;+  helper.data_.reset(+      new detail::spawn_data<Handler, function_type>(+        ASIO_MOVE_CAST(Handler)(handler), false,+        ASIO_MOVE_CAST(Function)(function)));+  helper.attributes_ = attributes;++  asio::dispatch(helper);+}++template <typename Function, typename Executor>+inline void spawn(const Executor& ex,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes,+    typename enable_if<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type*)+{+  asio::spawn(asio::strand<Executor>(ex),+      ASIO_MOVE_CAST(Function)(function), attributes);+}++template <typename Function, typename Executor>+inline void spawn(const strand<Executor>& ex,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes)+{+  asio::spawn(asio::bind_executor(+        ex, &detail::default_spawn_handler),+      ASIO_MOVE_CAST(Function)(function), attributes);+}++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Function>+inline void spawn(const asio::io_context::strand& s,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes)+{+  asio::spawn(asio::bind_executor(+        s, &detail::default_spawn_handler),+      ASIO_MOVE_CAST(Function)(function), attributes);+}++#endif // !defined(ASIO_NO_TS_EXECUTORS)++template <typename Function, typename ExecutionContext>+inline void spawn(ExecutionContext& ctx,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes,+    typename enable_if<is_convertible<+      ExecutionContext&, execution_context&>::value>::type*)+{+  asio::spawn(ctx.get_executor(),+      ASIO_MOVE_CAST(Function)(function), attributes);+}++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_SPAWN_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/src.hpp view
@@ -0,0 +1,85 @@+//+// impl/src.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_SRC_HPP+#define ASIO_IMPL_SRC_HPP++#define ASIO_SOURCE++#include "asio/detail/config.hpp"++#if defined(ASIO_HEADER_ONLY)+# error Do not compile Asio library source with ASIO_HEADER_ONLY defined+#endif++#include "asio/impl/error.ipp"+#include "asio/impl/error_code.ipp"+#include "asio/impl/execution_context.ipp"+#include "asio/impl/executor.ipp"+#include "asio/impl/handler_alloc_hook.ipp"+#include "asio/impl/io_context.ipp"+#include "asio/impl/multiple_exceptions.ipp"+#include "asio/impl/serial_port_base.ipp"+#include "asio/impl/system_context.ipp"+#include "asio/impl/thread_pool.ipp"+#include "asio/detail/impl/buffer_sequence_adapter.ipp"+#include "asio/detail/impl/descriptor_ops.ipp"+#include "asio/detail/impl/dev_poll_reactor.ipp"+#include "asio/detail/impl/epoll_reactor.ipp"+#include "asio/detail/impl/eventfd_select_interrupter.ipp"+#include "asio/detail/impl/handler_tracking.ipp"+#include "asio/detail/impl/kqueue_reactor.ipp"+#include "asio/detail/impl/null_event.ipp"+#include "asio/detail/impl/pipe_select_interrupter.ipp"+#include "asio/detail/impl/posix_event.ipp"+#include "asio/detail/impl/posix_mutex.ipp"+#include "asio/detail/impl/posix_thread.ipp"+#include "asio/detail/impl/posix_tss_ptr.ipp"+#include "asio/detail/impl/reactive_descriptor_service.ipp"+#include "asio/detail/impl/reactive_serial_port_service.ipp"+#include "asio/detail/impl/reactive_socket_service_base.ipp"+#include "asio/detail/impl/resolver_service_base.ipp"+#include "asio/detail/impl/scheduler.ipp"+#include "asio/detail/impl/select_reactor.ipp"+#include "asio/detail/impl/service_registry.ipp"+#include "asio/detail/impl/signal_set_service.ipp"+#include "asio/detail/impl/socket_ops.ipp"+#include "asio/detail/impl/socket_select_interrupter.ipp"+#include "asio/detail/impl/strand_executor_service.ipp"+#include "asio/detail/impl/strand_service.ipp"+#include "asio/detail/impl/throw_error.ipp"+#include "asio/detail/impl/timer_queue_ptime.ipp"+#include "asio/detail/impl/timer_queue_set.ipp"+#include "asio/detail/impl/win_iocp_handle_service.ipp"+#include "asio/detail/impl/win_iocp_io_context.ipp"+#include "asio/detail/impl/win_iocp_serial_port_service.ipp"+#include "asio/detail/impl/win_iocp_socket_service_base.ipp"+#include "asio/detail/impl/win_event.ipp"+#include "asio/detail/impl/win_mutex.ipp"+#include "asio/detail/impl/win_object_handle_service.ipp"+#include "asio/detail/impl/win_static_mutex.ipp"+#include "asio/detail/impl/win_thread.ipp"+#include "asio/detail/impl/win_tss_ptr.ipp"+#include "asio/detail/impl/winrt_ssocket_service_base.ipp"+#include "asio/detail/impl/winrt_timer_scheduler.ipp"+#include "asio/detail/impl/winsock_init.ipp"+#include "asio/execution/impl/bad_executor.ipp"+#include "asio/execution/impl/receiver_invocation_error.ipp"+#include "asio/generic/detail/impl/endpoint.ipp"+#include "asio/ip/impl/address.ipp"+#include "asio/ip/impl/address_v4.ipp"+#include "asio/ip/impl/address_v6.ipp"+#include "asio/ip/impl/host_name.ipp"+#include "asio/ip/impl/network_v4.ipp"+#include "asio/ip/impl/network_v6.ipp"+#include "asio/ip/detail/impl/endpoint.ipp"+#include "asio/local/detail/impl/endpoint.ipp"++#endif // ASIO_IMPL_SRC_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/system_context.hpp view
@@ -0,0 +1,34 @@+//+// impl/system_context.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_SYSTEM_CONTEXT_HPP+#define ASIO_IMPL_SYSTEM_CONTEXT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/system_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++inline system_context::executor_type+system_context::get_executor() ASIO_NOEXCEPT+{+  return system_executor();+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_SYSTEM_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/system_context.ipp view
@@ -0,0 +1,92 @@+//+// impl/system_context.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_SYSTEM_CONTEXT_IPP+#define ASIO_IMPL_SYSTEM_CONTEXT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/system_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++struct system_context::thread_function+{+  detail::scheduler* scheduler_;++  void operator()()+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+    {+#endif// !defined(ASIO_NO_EXCEPTIONS)+      asio::error_code ec;+      scheduler_->run(ec);+#if !defined(ASIO_NO_EXCEPTIONS)+    }+    catch (...)+    {+      std::terminate();+    }+#endif// !defined(ASIO_NO_EXCEPTIONS)+  }+};++system_context::system_context()+  : scheduler_(add_scheduler(new detail::scheduler(*this, 0, false)))+{+  scheduler_.work_started();++  thread_function f = { &scheduler_ };+  num_threads_ = detail::thread::hardware_concurrency() * 2;+  num_threads_ = num_threads_ ? num_threads_ : 2;+  threads_.create_threads(f, num_threads_);+}++system_context::~system_context()+{+  scheduler_.work_finished();+  scheduler_.stop();+  threads_.join();+}++void system_context::stop()+{+  scheduler_.stop();+}++bool system_context::stopped() const ASIO_NOEXCEPT+{+  return scheduler_.stopped();+}++void system_context::join()+{+  scheduler_.work_finished();+  threads_.join();+}++detail::scheduler& system_context::add_scheduler(detail::scheduler* s)+{+  detail::scoped_ptr<detail::scheduler> scoped_impl(s);+  asio::add_service<detail::scheduler>(*this, scoped_impl.get());+  return *scoped_impl.release();+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_SYSTEM_CONTEXT_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/system_executor.hpp view
@@ -0,0 +1,186 @@+//+// impl/system_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_SYSTEM_EXECUTOR_HPP+#define ASIO_IMPL_SYSTEM_EXECUTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/executor_op.hpp"+#include "asio/detail/global.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/system_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename Blocking, typename Relationship, typename Allocator>+inline system_context&+basic_system_executor<Blocking, Relationship, Allocator>::query(+    execution::context_t) ASIO_NOEXCEPT+{+  return detail::global<system_context>();+}++template <typename Blocking, typename Relationship, typename Allocator>+inline std::size_t+basic_system_executor<Blocking, Relationship, Allocator>::query(+    execution::occupancy_t) const ASIO_NOEXCEPT+{+  return detail::global<system_context>().num_threads_;+}++template <typename Blocking, typename Relationship, typename Allocator>+template <typename Function>+inline void+basic_system_executor<Blocking, Relationship, Allocator>::do_execute(+    ASIO_MOVE_ARG(Function) f, execution::blocking_t::possibly_t) const+{+  // Obtain a non-const instance of the function.+  detail::non_const_lvalue<Function> f2(f);++#if !defined(ASIO_NO_EXCEPTIONS)+  try+  {+#endif// !defined(ASIO_NO_EXCEPTIONS)+    detail::fenced_block b(detail::fenced_block::full);+    asio_handler_invoke_helpers::invoke(f2.value, f2.value);+#if !defined(ASIO_NO_EXCEPTIONS)+  }+  catch (...)+  {+    std::terminate();+  }+#endif// !defined(ASIO_NO_EXCEPTIONS)+}++template <typename Blocking, typename Relationship, typename Allocator>+template <typename Function>+inline void+basic_system_executor<Blocking, Relationship, Allocator>::do_execute(+    ASIO_MOVE_ARG(Function) f, execution::blocking_t::always_t) const+{+  // Obtain a non-const instance of the function.+  detail::non_const_lvalue<Function> f2(f);++#if !defined(ASIO_NO_EXCEPTIONS)+  try+  {+#endif// !defined(ASIO_NO_EXCEPTIONS)+    detail::fenced_block b(detail::fenced_block::full);+    asio_handler_invoke_helpers::invoke(f2.value, f2.value);+#if !defined(ASIO_NO_EXCEPTIONS)+  }+  catch (...)+  {+    std::terminate();+  }+#endif// !defined(ASIO_NO_EXCEPTIONS)+}++template <typename Blocking, typename Relationship, typename Allocator>+template <typename Function>+void basic_system_executor<Blocking, Relationship, Allocator>::do_execute(+    ASIO_MOVE_ARG(Function) f, execution::blocking_t::never_t) const+{+  system_context& ctx = detail::global<system_context>();++  // Allocate and construct an operation to wrap the function.+  typedef typename decay<Function>::type function_type;+  typedef detail::executor_op<function_type, Allocator> op;+  typename op::ptr p = { detail::addressof(allocator_),+      op::ptr::allocate(allocator_), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), allocator_);++  if (is_same<Relationship, execution::relationship_t::continuation_t>::value)+  {+    ASIO_HANDLER_CREATION((ctx, *p.p,+          "system_executor", &ctx, 0, "execute(blk=never,rel=cont)"));+  }+  else+  {+    ASIO_HANDLER_CREATION((ctx, *p.p,+          "system_executor", &ctx, 0, "execute(blk=never,rel=fork)"));+  }++  ctx.scheduler_.post_immediate_completion(p.p,+      is_same<Relationship, execution::relationship_t::continuation_t>::value);+  p.v = p.p = 0;+}++#if !defined(ASIO_NO_TS_EXECUTORS)+template <typename Blocking, typename Relationship, typename Allocator>+inline system_context& basic_system_executor<+    Blocking, Relationship, Allocator>::context() const ASIO_NOEXCEPT+{+  return detail::global<system_context>();+}++template <typename Blocking, typename Relationship, typename Allocator>+template <typename Function, typename OtherAllocator>+void basic_system_executor<Blocking, Relationship, Allocator>::dispatch(+    ASIO_MOVE_ARG(Function) f, const OtherAllocator&) const+{+  typename decay<Function>::type tmp(ASIO_MOVE_CAST(Function)(f));+  asio_handler_invoke_helpers::invoke(tmp, tmp);+}++template <typename Blocking, typename Relationship, typename Allocator>+template <typename Function, typename OtherAllocator>+void basic_system_executor<Blocking, Relationship, Allocator>::post(+    ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const+{+  typedef typename decay<Function>::type function_type;++  system_context& ctx = detail::global<system_context>();++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type, OtherAllocator> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);++  ASIO_HANDLER_CREATION((ctx, *p.p,+        "system_executor", &this->context(), 0, "post"));++  ctx.scheduler_.post_immediate_completion(p.p, false);+  p.v = p.p = 0;+}++template <typename Blocking, typename Relationship, typename Allocator>+template <typename Function, typename OtherAllocator>+void basic_system_executor<Blocking, Relationship, Allocator>::defer(+    ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const+{+  typedef typename decay<Function>::type function_type;++  system_context& ctx = detail::global<system_context>();++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type, OtherAllocator> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);++  ASIO_HANDLER_CREATION((ctx, *p.p,+        "system_executor", &this->context(), 0, "defer"));++  ctx.scheduler_.post_immediate_completion(p.p, true);+  p.v = p.p = 0;+}+#endif // !defined(ASIO_NO_TS_EXECUTORS)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_SYSTEM_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/thread_pool.hpp view
@@ -0,0 +1,350 @@+//+// impl/thread_pool.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_THREAD_POOL_HPP+#define ASIO_IMPL_THREAD_POOL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/blocking_executor_op.hpp"+#include "asio/detail/bulk_executor_op.hpp"+#include "asio/detail/executor_op.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++inline thread_pool::executor_type+thread_pool::get_executor() ASIO_NOEXCEPT+{+  return executor_type(*this);+}++inline thread_pool::executor_type+thread_pool::executor() ASIO_NOEXCEPT+{+  return executor_type(*this);+}++inline thread_pool::scheduler_type+thread_pool::scheduler() ASIO_NOEXCEPT+{+  return scheduler_type(*this);+}++template <typename Allocator, unsigned int Bits>+thread_pool::basic_executor_type<Allocator, Bits>&+thread_pool::basic_executor_type<Allocator, Bits>::operator=(+    const basic_executor_type& other) ASIO_NOEXCEPT+{+  if (this != &other)+  {+    thread_pool* old_thread_pool = pool_;+    pool_ = other.pool_;+    allocator_ = other.allocator_;+    bits_ = other.bits_;+    if (Bits & outstanding_work_tracked)+    {+      if (pool_)+        pool_->scheduler_.work_started();+      if (old_thread_pool)+        old_thread_pool->scheduler_.work_finished();+    }+  }+  return *this;+}++#if defined(ASIO_HAS_MOVE)+template <typename Allocator, unsigned int Bits>+thread_pool::basic_executor_type<Allocator, Bits>&+thread_pool::basic_executor_type<Allocator, Bits>::operator=(+    basic_executor_type&& other) ASIO_NOEXCEPT+{+  if (this != &other)+  {+    pool_ = other.pool_;+    allocator_ = std::move(other.allocator_);+    bits_ = other.bits_;+    if (Bits & outstanding_work_tracked)+      other.pool_ = 0;+  }+  return *this;+}+#endif // defined(ASIO_HAS_MOVE)++template <typename Allocator, unsigned int Bits>+inline bool thread_pool::basic_executor_type<Allocator,+    Bits>::running_in_this_thread() const ASIO_NOEXCEPT+{+  return pool_->scheduler_.can_dispatch();+}++template <typename Allocator, unsigned int Bits>+template <typename Function>+void thread_pool::basic_executor_type<Allocator,+    Bits>::do_execute(ASIO_MOVE_ARG(Function) f, false_type) const+{+  typedef typename decay<Function>::type function_type;++  // Invoke immediately if the blocking.possibly property is enabled and we are+  // already inside the thread pool.+  if ((bits_ & blocking_never) == 0 && pool_->scheduler_.can_dispatch())+  {+    // Make a local, non-const copy of the function.+    function_type tmp(ASIO_MOVE_CAST(Function)(f));++#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  && !defined(ASIO_NO_EXCEPTIONS)+    try+    {+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       //   && !defined(ASIO_NO_EXCEPTIONS)+      detail::fenced_block b(detail::fenced_block::full);+      asio_handler_invoke_helpers::invoke(tmp, tmp);+      return;+#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  && !defined(ASIO_NO_EXCEPTIONS)+    }+    catch (...)+    {+      pool_->scheduler_.capture_current_exception();+      return;+    }+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       //   && !defined(ASIO_NO_EXCEPTIONS)+  }++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type, Allocator> op;+  typename op::ptr p = { detail::addressof(allocator_),+      op::ptr::allocate(allocator_), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), allocator_);++  if ((bits_ & relationship_continuation) != 0)+  {+    ASIO_HANDLER_CREATION((*pool_, *p.p,+          "thread_pool", pool_, 0, "execute(blk=never,rel=cont)"));+  }+  else+  {+    ASIO_HANDLER_CREATION((*pool_, *p.p,+          "thread_pool", pool_, 0, "execute(blk=never,rel=fork)"));+  }++  pool_->scheduler_.post_immediate_completion(p.p,+      (bits_ & relationship_continuation) != 0);+  p.v = p.p = 0;+}++template <typename Allocator, unsigned int Bits>+template <typename Function>+void thread_pool::basic_executor_type<Allocator,+    Bits>::do_execute(ASIO_MOVE_ARG(Function) f, true_type) const+{+  // Obtain a non-const instance of the function.+  detail::non_const_lvalue<Function> f2(f);++  // Invoke immediately if we are already inside the thread pool.+  if (pool_->scheduler_.can_dispatch())+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+    {+#endif // !defined(ASIO_NO_EXCEPTIONS)+      detail::fenced_block b(detail::fenced_block::full);+      asio_handler_invoke_helpers::invoke(f2.value, f2.value);+      return;+#if !defined(ASIO_NO_EXCEPTIONS)+    }+    catch (...)+    {+      std::terminate();+    }+#endif // !defined(ASIO_NO_EXCEPTIONS)+  }++  // Construct an operation to wrap the function.+  typedef typename decay<Function>::type function_type;+  detail::blocking_executor_op<function_type> op(f2.value);++  ASIO_HANDLER_CREATION((*pool_, op,+        "thread_pool", pool_, 0, "execute(blk=always)"));++  pool_->scheduler_.post_immediate_completion(&op, false);+  op.wait();+}++template <typename Allocator, unsigned int Bits>+template <typename Function>+void thread_pool::basic_executor_type<Allocator, Bits>::do_bulk_execute(+    ASIO_MOVE_ARG(Function) f, std::size_t n, false_type) const+{+  typedef typename decay<Function>::type function_type;+  typedef detail::bulk_executor_op<function_type, Allocator> op;++  // Allocate and construct operations to wrap the function.+  detail::op_queue<detail::scheduler_operation> ops;+  for (std::size_t i = 0; i < n; ++i)+  {+    typename op::ptr p = { detail::addressof(allocator_),+        op::ptr::allocate(allocator_), 0 };+    p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), allocator_, i);+    ops.push(p.p);++    if ((bits_ & relationship_continuation) != 0)+    {+      ASIO_HANDLER_CREATION((*pool_, *p.p,+            "thread_pool", pool_, 0, "bulk_execute(blk=never,rel=cont)"));+    }+    else+    {+      ASIO_HANDLER_CREATION((*pool_, *p.p,+            "thread_pool", pool_, 0, "bulk)execute(blk=never,rel=fork)"));+    }++    p.v = p.p = 0;+  }++  pool_->scheduler_.post_immediate_completions(n,+      ops, (bits_ & relationship_continuation) != 0);+}++template <typename Function>+struct thread_pool_always_blocking_function_adapter+{+  typename decay<Function>::type* f;+  std::size_t n;++  void operator()()+  {+    for (std::size_t i = 0; i < n; ++i)+    {+      (*f)(i);+    }+  }+};++template <typename Allocator, unsigned int Bits>+template <typename Function>+void thread_pool::basic_executor_type<Allocator, Bits>::do_bulk_execute(+    ASIO_MOVE_ARG(Function) f, std::size_t n, true_type) const+{+  // Obtain a non-const instance of the function.+  detail::non_const_lvalue<Function> f2(f);++  thread_pool_always_blocking_function_adapter<Function>+    adapter = { detail::addressof(f2.value), n };++  this->do_execute(adapter, true_type());+}++#if !defined(ASIO_NO_TS_EXECUTORS)+template <typename Allocator, unsigned int Bits>+inline thread_pool& thread_pool::basic_executor_type<+    Allocator, Bits>::context() const ASIO_NOEXCEPT+{+  return *pool_;+}++template <typename Allocator, unsigned int Bits>+inline void thread_pool::basic_executor_type<Allocator,+    Bits>::on_work_started() const ASIO_NOEXCEPT+{+  pool_->scheduler_.work_started();+}++template <typename Allocator, unsigned int Bits>+inline void thread_pool::basic_executor_type<Allocator,+    Bits>::on_work_finished() const ASIO_NOEXCEPT+{+  pool_->scheduler_.work_finished();+}++template <typename Allocator, unsigned int Bits>+template <typename Function, typename OtherAllocator>+void thread_pool::basic_executor_type<Allocator, Bits>::dispatch(+    ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const+{+  typedef typename decay<Function>::type function_type;++  // Invoke immediately if we are already inside the thread pool.+  if (pool_->scheduler_.can_dispatch())+  {+    // Make a local, non-const copy of the function.+    function_type tmp(ASIO_MOVE_CAST(Function)(f));++    detail::fenced_block b(detail::fenced_block::full);+    asio_handler_invoke_helpers::invoke(tmp, tmp);+    return;+  }++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type, OtherAllocator> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);++  ASIO_HANDLER_CREATION((*pool_, *p.p,+        "thread_pool", pool_, 0, "dispatch"));++  pool_->scheduler_.post_immediate_completion(p.p, false);+  p.v = p.p = 0;+}++template <typename Allocator, unsigned int Bits>+template <typename Function, typename OtherAllocator>+void thread_pool::basic_executor_type<Allocator, Bits>::post(+    ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const+{+  typedef typename decay<Function>::type function_type;++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type, OtherAllocator> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);++  ASIO_HANDLER_CREATION((*pool_, *p.p,+        "thread_pool", pool_, 0, "post"));++  pool_->scheduler_.post_immediate_completion(p.p, false);+  p.v = p.p = 0;+}++template <typename Allocator, unsigned int Bits>+template <typename Function, typename OtherAllocator>+void thread_pool::basic_executor_type<Allocator, Bits>::defer(+    ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const+{+  typedef typename decay<Function>::type function_type;++  // Allocate and construct an operation to wrap the function.+  typedef detail::executor_op<function_type, OtherAllocator> op;+  typename op::ptr p = { detail::addressof(a), op::ptr::allocate(a), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f), a);++  ASIO_HANDLER_CREATION((*pool_, *p.p,+        "thread_pool", pool_, 0, "defer"));++  pool_->scheduler_.post_immediate_completion(p.p, true);+  p.v = p.p = 0;+}+#endif // !defined(ASIO_NO_TS_EXECUTORS)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_THREAD_POOL_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/thread_pool.ipp view
@@ -0,0 +1,141 @@+//+// impl/thread_pool.ipp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_THREAD_POOL_IPP+#define ASIO_IMPL_THREAD_POOL_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <stdexcept>+#include "asio/thread_pool.hpp"+#include "asio/detail/throw_exception.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++struct thread_pool::thread_function+{+  detail::scheduler* scheduler_;++  void operator()()+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+    {+#endif// !defined(ASIO_NO_EXCEPTIONS)+      asio::error_code ec;+      scheduler_->run(ec);+#if !defined(ASIO_NO_EXCEPTIONS)+    }+    catch (...)+    {+      std::terminate();+    }+#endif// !defined(ASIO_NO_EXCEPTIONS)+  }+};++#if !defined(ASIO_NO_TS_EXECUTORS)+namespace detail {++inline long default_thread_pool_size()+{+  std::size_t num_threads = thread::hardware_concurrency() * 2;+  num_threads = num_threads == 0 ? 2 : num_threads;+  return static_cast<long>(num_threads);+}++} // namespace detail++thread_pool::thread_pool()+  : scheduler_(add_scheduler(new detail::scheduler(*this, 0, false))),+    num_threads_(detail::default_thread_pool_size())+{+  scheduler_.work_started();++  thread_function f = { &scheduler_ };+  threads_.create_threads(f, static_cast<std::size_t>(num_threads_));+}+#endif // !defined(ASIO_NO_TS_EXECUTORS)++namespace detail {++inline long clamp_thread_pool_size(std::size_t n)+{+  if (n > 0x7FFFFFFF)+  {+    std::out_of_range ex("thread pool size");+    asio::detail::throw_exception(ex);+  }+  return static_cast<long>(n & 0x7FFFFFFF);+}++} // namespace detail++thread_pool::thread_pool(std::size_t num_threads)+  : scheduler_(add_scheduler(new detail::scheduler(+          *this, num_threads == 1 ? 1 : 0, false))),+    num_threads_(detail::clamp_thread_pool_size(num_threads))+{+  scheduler_.work_started();++  thread_function f = { &scheduler_ };+  threads_.create_threads(f, static_cast<std::size_t>(num_threads_));+}++thread_pool::~thread_pool()+{+  stop();+  join();+}++void thread_pool::stop()+{+  scheduler_.stop();+}++void thread_pool::attach()+{+  ++num_threads_;+  thread_function f = { &scheduler_ };+  f();+}++void thread_pool::join()+{+  if (!threads_.empty())+  {+    scheduler_.work_finished();+    threads_.join();+  }+}++detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s)+{+  detail::scoped_ptr<detail::scheduler> scoped_impl(s);+  asio::add_service<detail::scheduler>(*this, scoped_impl.get());+  return *scoped_impl.release();+}++void thread_pool::wait()+{+  scheduler_.work_finished();+  threads_.join();+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_THREAD_POOL_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/use_awaitable.hpp view
@@ -0,0 +1,279 @@+//+// impl/use_awaitable.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_USE_AWAITABLE_HPP+#define ASIO_IMPL_USE_AWAITABLE_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 {+namespace detail {++template <typename Executor, typename T>+class awaitable_handler_base+  : public awaitable_thread<Executor>+{+public:+  typedef void result_type;+  typedef awaitable<T, Executor> awaitable_type;++  // Construct from the entry point of a new thread of execution.+  awaitable_handler_base(awaitable<void, Executor> a, const Executor& ex)+    : awaitable_thread<Executor>(std::move(a), ex)+  {+  }++  // Transfer ownership from another awaitable_thread.+  explicit awaitable_handler_base(awaitable_thread<Executor>* h)+    : awaitable_thread<Executor>(std::move(*h))+  {+  }++protected:+  awaitable_frame<T, Executor>* frame() noexcept+  {+    return static_cast<awaitable_frame<T, Executor>*>(this->top_of_stack_);+  }+};++template <typename, typename...>+class awaitable_handler;++template <typename Executor>+class awaitable_handler<Executor>+  : public awaitable_handler_base<Executor, void>+{+public:+  using awaitable_handler_base<Executor, void>::awaitable_handler_base;++  void operator()()+  {+    this->frame()->attach_thread(this);+    this->frame()->return_void();+    this->frame()->pop_frame();+    this->pump();+  }+};++template <typename Executor>+class awaitable_handler<Executor, asio::error_code>+  : public awaitable_handler_base<Executor, void>+{+public:+  using awaitable_handler_base<Executor, void>::awaitable_handler_base;++  void operator()(const asio::error_code& ec)+  {+    this->frame()->attach_thread(this);+    if (ec)+      this->frame()->set_error(ec);+    else+      this->frame()->return_void();+    this->frame()->pop_frame();+    this->pump();+  }+};++template <typename Executor>+class awaitable_handler<Executor, std::exception_ptr>+  : public awaitable_handler_base<Executor, void>+{+public:+  using awaitable_handler_base<Executor, void>::awaitable_handler_base;++  void operator()(std::exception_ptr ex)+  {+    this->frame()->attach_thread(this);+    if (ex)+      this->frame()->set_except(ex);+    else+      this->frame()->return_void();+    this->frame()->pop_frame();+    this->pump();+  }+};++template <typename Executor, typename T>+class awaitable_handler<Executor, T>+  : public awaitable_handler_base<Executor, T>+{+public:+  using awaitable_handler_base<Executor, T>::awaitable_handler_base;++  template <typename Arg>+  void operator()(Arg&& arg)+  {+    this->frame()->attach_thread(this);+    this->frame()->return_value(std::forward<Arg>(arg));+    this->frame()->pop_frame();+    this->pump();+  }+};++template <typename Executor, typename T>+class awaitable_handler<Executor, asio::error_code, T>+  : public awaitable_handler_base<Executor, T>+{+public:+  using awaitable_handler_base<Executor, T>::awaitable_handler_base;++  template <typename Arg>+  void operator()(const asio::error_code& ec, Arg&& arg)+  {+    this->frame()->attach_thread(this);+    if (ec)+      this->frame()->set_error(ec);+    else+      this->frame()->return_value(std::forward<Arg>(arg));+    this->frame()->pop_frame();+    this->pump();+  }+};++template <typename Executor, typename T>+class awaitable_handler<Executor, std::exception_ptr, T>+  : public awaitable_handler_base<Executor, T>+{+public:+  using awaitable_handler_base<Executor, T>::awaitable_handler_base;++  template <typename Arg>+  void operator()(std::exception_ptr ex, Arg&& arg)+  {+    this->frame()->attach_thread(this);+    if (ex)+      this->frame()->set_except(ex);+    else+      this->frame()->return_value(std::forward<Arg>(arg));+    this->frame()->pop_frame();+    this->pump();+  }+};++template <typename Executor, typename... Ts>+class awaitable_handler+  : public awaitable_handler_base<Executor, std::tuple<Ts...>>+{+public:+  using awaitable_handler_base<Executor,+    std::tuple<Ts...>>::awaitable_handler_base;++  template <typename... Args>+  void operator()(Args&&... args)+  {+    this->frame()->attach_thread(this);+    this->frame()->return_values(std::forward<Args>(args)...);+    this->frame()->pop_frame();+    this->pump();+  }+};++template <typename Executor, typename... Ts>+class awaitable_handler<Executor, asio::error_code, Ts...>+  : public awaitable_handler_base<Executor, std::tuple<Ts...>>+{+public:+  using awaitable_handler_base<Executor,+    std::tuple<Ts...>>::awaitable_handler_base;++  template <typename... Args>+  void operator()(const asio::error_code& ec, Args&&... args)+  {+    this->frame()->attach_thread(this);+    if (ec)+      this->frame()->set_error(ec);+    else+      this->frame()->return_values(std::forward<Args>(args)...);+    this->frame()->pop_frame();+    this->pump();+  }+};++template <typename Executor, typename... Ts>+class awaitable_handler<Executor, std::exception_ptr, Ts...>+  : public awaitable_handler_base<Executor, std::tuple<Ts...>>+{+public:+  using awaitable_handler_base<Executor,+    std::tuple<Ts...>>::awaitable_handler_base;++  template <typename... Args>+  void operator()(std::exception_ptr ex, Args&&... args)+  {+    this->frame()->attach_thread(this);+    if (ex)+      this->frame()->set_except(ex);+    else+      this->frame()->return_values(std::forward<Args>(args)...);+    this->frame()->pop_frame();+    this->pump();+  }+};++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename Executor, typename R, typename... Args>+class async_result<use_awaitable_t<Executor>, R(Args...)>+{+public:+  typedef typename detail::awaitable_handler<+      Executor, typename decay<Args>::type...> handler_type;+  typedef typename handler_type::awaitable_type return_type;++#if defined(_MSC_VER)+  template <typename T>+  static T dummy_return()+  {+    return std::move(*static_cast<T*>(nullptr));+  }++  template <>+  static void dummy_return()+  {+  }+#endif // defined(_MSC_VER)++  template <typename Initiation, typename... InitArgs>+  static return_type initiate(Initiation initiation,+      use_awaitable_t<Executor> u, InitArgs... args)+  {+    (void)u;++    co_await [&](auto* frame)+      {+        ASIO_HANDLER_LOCATION((u.file_name_, u.line_, u.function_name_));+        handler_type handler(frame->detach_thread());+        std::move(initiation)(std::move(handler), std::move(args)...);+        return static_cast<handler_type*>(nullptr);+      };++    for (;;) {} // Never reached.+#if defined(_MSC_VER)+    co_return dummy_return<typename return_type::value_type>();+#endif // defined(_MSC_VER)+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_USE_AWAITABLE_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/use_future.hpp view
@@ -0,0 +1,1028 @@+//+// impl/use_future.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_USE_FUTURE_HPP+#define ASIO_IMPL_USE_FUTURE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <tuple>+#include "asio/async_result.hpp"+#include "asio/detail/memory.hpp"+#include "asio/dispatch.hpp"+#include "asio/error_code.hpp"+#include "asio/execution.hpp"+#include "asio/packaged_task.hpp"+#include "asio/system_error.hpp"+#include "asio/system_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename F, typename... Args>+inline void promise_invoke_and_set(std::promise<T>& p,+    F& f, ASIO_MOVE_ARG(Args)... args)+{+#if !defined(ASIO_NO_EXCEPTIONS)+  try+#endif // !defined(ASIO_NO_EXCEPTIONS)+  {+    p.set_value(f(ASIO_MOVE_CAST(Args)(args)...));+  }+#if !defined(ASIO_NO_EXCEPTIONS)+  catch (...)+  {+    p.set_exception(std::current_exception());+  }+#endif // !defined(ASIO_NO_EXCEPTIONS)+}++template <typename F, typename... Args>+inline void promise_invoke_and_set(std::promise<void>& p,+    F& f, ASIO_MOVE_ARG(Args)... args)+{+#if !defined(ASIO_NO_EXCEPTIONS)+  try+#endif // !defined(ASIO_NO_EXCEPTIONS)+  {+    f(ASIO_MOVE_CAST(Args)(args)...);+    p.set_value();+  }+#if !defined(ASIO_NO_EXCEPTIONS)+  catch (...)+  {+    p.set_exception(std::current_exception());+  }+#endif // !defined(ASIO_NO_EXCEPTIONS)+}++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename F>+inline void promise_invoke_and_set(std::promise<T>& p, F& f)+{+#if !defined(ASIO_NO_EXCEPTIONS)+  try+#endif // !defined(ASIO_NO_EXCEPTIONS)+  {+    p.set_value(f());+  }+#if !defined(ASIO_NO_EXCEPTIONS)+  catch (...)+  {+    p.set_exception(std::current_exception());+  }+#endif // !defined(ASIO_NO_EXCEPTIONS)+}++template <typename F, typename Args>+inline void promise_invoke_and_set(std::promise<void>& p, F& f)+{+#if !defined(ASIO_NO_EXCEPTIONS)+  try+#endif // !defined(ASIO_NO_EXCEPTIONS)+  {+    f();+    p.set_value();+#if !defined(ASIO_NO_EXCEPTIONS)+  }+  catch (...)+  {+    p.set_exception(std::current_exception());+  }+#endif // !defined(ASIO_NO_EXCEPTIONS)+}++#if defined(ASIO_NO_EXCEPTIONS)++#define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \+  template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \+  inline void promise_invoke_and_set(std::promise<T>& p, \+      F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \+  } \+  \+  template <typename F, ASIO_VARIADIC_TPARAMS(n)> \+  inline void promise_invoke_and_set(std::promise<void>& p, \+      F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    f(ASIO_VARIADIC_MOVE_ARGS(n)); \+    p.set_value(); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF)+#undef ASIO_PRIVATE_PROMISE_INVOKE_DEF++#else // defined(ASIO_NO_EXCEPTIONS)++#define ASIO_PRIVATE_PROMISE_INVOKE_DEF(n) \+  template <typename T, typename F, ASIO_VARIADIC_TPARAMS(n)> \+  inline void promise_invoke_and_set(std::promise<T>& p, \+      F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    try \+    { \+      p.set_value(f(ASIO_VARIADIC_MOVE_ARGS(n))); \+    } \+    catch (...) \+    { \+      p.set_exception(std::current_exception()); \+    } \+  } \+  \+  template <typename F, ASIO_VARIADIC_TPARAMS(n)> \+  inline void promise_invoke_and_set(std::promise<void>& p, \+      F& f, ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    try \+    { \+      f(ASIO_VARIADIC_MOVE_ARGS(n)); \+      p.set_value(); \+    } \+    catch (...) \+    { \+      p.set_exception(std::current_exception()); \+    } \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_PROMISE_INVOKE_DEF)+#undef ASIO_PRIVATE_PROMISE_INVOKE_DEF++#endif // defined(ASIO_NO_EXCEPTIONS)++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++// A function object adapter to invoke a nullary function object and capture+// any exception thrown into a promise.+template <typename T, typename F>+class promise_invoker+{+public:+  promise_invoker(const shared_ptr<std::promise<T> >& p,+      ASIO_MOVE_ARG(F) f)+    : p_(p), f_(ASIO_MOVE_CAST(F)(f))+  {+  }++  void operator()()+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+#endif // !defined(ASIO_NO_EXCEPTIONS)+    {+      f_();+    }+#if !defined(ASIO_NO_EXCEPTIONS)+    catch (...)+    {+      p_->set_exception(std::current_exception());+    }+#endif // !defined(ASIO_NO_EXCEPTIONS)+  }++private:+  shared_ptr<std::promise<T> > p_;+  typename decay<F>::type f_;+};++// An executor that adapts the system_executor to capture any exeption thrown+// by a submitted function object and save it into a promise.+template <typename T, typename Blocking = execution::blocking_t::possibly_t>+class promise_executor+{+public:+  explicit promise_executor(const shared_ptr<std::promise<T> >& p)+    : p_(p)+  {+  }++  static ASIO_CONSTEXPR Blocking query(execution::blocking_t)+  {+    return Blocking();+  }++  promise_executor<T, execution::blocking_t::possibly_t>+  require(execution::blocking_t::possibly_t) const+  {+    return promise_executor<T, execution::blocking_t::possibly_t>(p_);+  }++  promise_executor<T, execution::blocking_t::never_t>+  require(execution::blocking_t::never_t) const+  {+    return promise_executor<T, execution::blocking_t::never_t>(p_);+  }++  template <typename F>+  void execute(ASIO_MOVE_ARG(F) f) const+  {+    execution::execute(+        asio::require(system_executor(), Blocking()),+        promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)));+  }++#if !defined(ASIO_NO_TS_EXECUTORS)+  execution_context& context() const ASIO_NOEXCEPT+  {+    return system_executor().context();+  }++  void on_work_started() const ASIO_NOEXCEPT {}+  void on_work_finished() const ASIO_NOEXCEPT {}++  template <typename F, typename A>+  void dispatch(ASIO_MOVE_ARG(F) f, const A&) const+  {+    promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f))();+  }++  template <typename F, typename A>+  void post(ASIO_MOVE_ARG(F) f, const A& a) const+  {+    system_executor().post(+        promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a);+  }++  template <typename F, typename A>+  void defer(ASIO_MOVE_ARG(F) f, const A& a) const+  {+    system_executor().defer(+        promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)), a);+  }+#endif // !defined(ASIO_NO_TS_EXECUTORS)++  friend bool operator==(const promise_executor& a,+      const promise_executor& b) ASIO_NOEXCEPT+  {+    return a.p_ == b.p_;+  }++  friend bool operator!=(const promise_executor& a,+      const promise_executor& b) ASIO_NOEXCEPT+  {+    return a.p_ != b.p_;+  }++private:+  shared_ptr<std::promise<T> > p_;+};++// The base class for all completion handlers that create promises.+template <typename T>+class promise_creator+{+public:+  typedef promise_executor<T> executor_type;++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return executor_type(p_);+  }++  typedef std::future<T> future_type;++  future_type get_future()+  {+    return p_->get_future();+  }++protected:+  template <typename Allocator>+  void create_promise(const Allocator& a)+  {+    ASIO_REBIND_ALLOC(Allocator, char) b(a);+    p_ = std::allocate_shared<std::promise<T>>(b, std::allocator_arg, b);+  }++  shared_ptr<std::promise<T> > p_;+};++// For completion signature void().+class promise_handler_0+  : public promise_creator<void>+{+public:+  void operator()()+  {+    this->p_->set_value();+  }+};++// For completion signature void(error_code).+class promise_handler_ec_0+  : public promise_creator<void>+{+public:+  void operator()(const asio::error_code& ec)+  {+    if (ec)+    {+      this->p_->set_exception(+          std::make_exception_ptr(+            asio::system_error(ec)));+    }+    else+    {+      this->p_->set_value();+    }+  }+};++// For completion signature void(exception_ptr).+class promise_handler_ex_0+  : public promise_creator<void>+{+public:+  void operator()(const std::exception_ptr& ex)+  {+    if (ex)+    {+      this->p_->set_exception(ex);+    }+    else+    {+      this->p_->set_value();+    }+  }+};++// For completion signature void(T).+template <typename T>+class promise_handler_1+  : public promise_creator<T>+{+public:+  template <typename Arg>+  void operator()(ASIO_MOVE_ARG(Arg) arg)+  {+    this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg));+  }+};++// For completion signature void(error_code, T).+template <typename T>+class promise_handler_ec_1+  : public promise_creator<T>+{+public:+  template <typename Arg>+  void operator()(const asio::error_code& ec,+      ASIO_MOVE_ARG(Arg) arg)+  {+    if (ec)+    {+      this->p_->set_exception(+          std::make_exception_ptr(+            asio::system_error(ec)));+    }+    else+      this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg));+  }+};++// For completion signature void(exception_ptr, T).+template <typename T>+class promise_handler_ex_1+  : public promise_creator<T>+{+public:+  template <typename Arg>+  void operator()(const std::exception_ptr& ex,+      ASIO_MOVE_ARG(Arg) arg)+  {+    if (ex)+      this->p_->set_exception(ex);+    else+      this->p_->set_value(ASIO_MOVE_CAST(Arg)(arg));+  }+};++// For completion signature void(T1, ..., Tn);+template <typename T>+class promise_handler_n+  : public promise_creator<T>+{+public:+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)... args)+  {+    this->p_->set_value(+        std::forward_as_tuple(+          ASIO_MOVE_CAST(Args)(args)...));+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_CALL_OP_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \+  {\+    this->p_->set_value( \+        std::forward_as_tuple( \+          ASIO_VARIADIC_MOVE_ARGS(n))); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF)+#undef ASIO_PRIVATE_CALL_OP_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+};++// For completion signature void(error_code, T1, ..., Tn);+template <typename T>+class promise_handler_ec_n+  : public promise_creator<T>+{+public:+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename... Args>+  void operator()(const asio::error_code& ec,+      ASIO_MOVE_ARG(Args)... args)+  {+    if (ec)+    {+      this->p_->set_exception(+          std::make_exception_ptr(+            asio::system_error(ec)));+    }+    else+    {+      this->p_->set_value(+          std::forward_as_tuple(+            ASIO_MOVE_CAST(Args)(args)...));+    }+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_CALL_OP_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  void operator()(const asio::error_code& ec, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  {\+    if (ec) \+    { \+      this->p_->set_exception( \+          std::make_exception_ptr( \+            asio::system_error(ec))); \+    } \+    else \+    { \+      this->p_->set_value( \+          std::forward_as_tuple( \+            ASIO_VARIADIC_MOVE_ARGS(n))); \+    } \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF)+#undef ASIO_PRIVATE_CALL_OP_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+};++// For completion signature void(exception_ptr, T1, ..., Tn);+template <typename T>+class promise_handler_ex_n+  : public promise_creator<T>+{+public:+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename... Args>+  void operator()(const std::exception_ptr& ex,+      ASIO_MOVE_ARG(Args)... args)+  {+    if (ex)+      this->p_->set_exception(ex);+    else+    {+      this->p_->set_value(+          std::forward_as_tuple(+            ASIO_MOVE_CAST(Args)(args)...));+    }+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_CALL_OP_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  void operator()(const std::exception_ptr& ex, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  {\+    if (ex) \+      this->p_->set_exception(ex); \+    else \+    { \+      this->p_->set_value( \+          std::forward_as_tuple( \+            ASIO_VARIADIC_MOVE_ARGS(n))); \+    } \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF)+#undef ASIO_PRIVATE_CALL_OP_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+};++// Helper template to choose the appropriate concrete promise handler+// implementation based on the supplied completion signature.+template <typename> class promise_handler_selector;++template <>+class promise_handler_selector<void()>+  : public promise_handler_0 {};++template <>+class promise_handler_selector<void(asio::error_code)>+  : public promise_handler_ec_0 {};++template <>+class promise_handler_selector<void(std::exception_ptr)>+  : public promise_handler_ex_0 {};++template <typename Arg>+class promise_handler_selector<void(Arg)>+  : public promise_handler_1<Arg> {};++template <typename Arg>+class promise_handler_selector<void(asio::error_code, Arg)>+  : public promise_handler_ec_1<Arg> {};++template <typename Arg>+class promise_handler_selector<void(std::exception_ptr, Arg)>+  : public promise_handler_ex_1<Arg> {};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... Arg>+class promise_handler_selector<void(Arg...)>+  : public promise_handler_n<std::tuple<Arg...> > {};++template <typename... Arg>+class promise_handler_selector<void(asio::error_code, Arg...)>+  : public promise_handler_ec_n<std::tuple<Arg...> > {};++template <typename... Arg>+class promise_handler_selector<void(std::exception_ptr, Arg...)>+  : public promise_handler_ex_n<std::tuple<Arg...> > {};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_PRIVATE_PROMISE_SELECTOR_DEF(n) \+  template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \+  class promise_handler_selector< \+    void(Arg, ASIO_VARIADIC_TARGS(n))> \+      : public promise_handler_n< \+        std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \+  \+  template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \+  class promise_handler_selector< \+    void(asio::error_code, Arg, ASIO_VARIADIC_TARGS(n))> \+      : public promise_handler_ec_n< \+        std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \+  \+  template <typename Arg, ASIO_VARIADIC_TPARAMS(n)> \+  class promise_handler_selector< \+    void(std::exception_ptr, Arg, ASIO_VARIADIC_TARGS(n))> \+      : public promise_handler_ex_n< \+        std::tuple<Arg, ASIO_VARIADIC_TARGS(n)> > {}; \+  /**/+  ASIO_VARIADIC_GENERATE_5(ASIO_PRIVATE_PROMISE_SELECTOR_DEF)+#undef ASIO_PRIVATE_PROMISE_SELECTOR_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++// Completion handlers produced from the use_future completion token, when not+// using use_future::operator().+template <typename Signature, typename Allocator>+class promise_handler+  : public promise_handler_selector<Signature>+{+public:+  typedef Allocator allocator_type;+  typedef void result_type;++  promise_handler(use_future_t<Allocator> u)+    : allocator_(u.get_allocator())+  {+    this->create_promise(allocator_);+  }++  allocator_type get_allocator() const ASIO_NOEXCEPT+  {+    return allocator_;+  }++private:+  Allocator allocator_;+};++template <typename Function>+struct promise_function_wrapper+{+  explicit promise_function_wrapper(Function& f)+    : function_(ASIO_MOVE_CAST(Function)(f))+  {+  }++  explicit promise_function_wrapper(const Function& f)+    : function_(f)+  {+  }++  void operator()()+  {+    function_();+  }++  Function function_;+};++#if !defined(ASIO_NO_DEPRECATED)++template <typename Function, typename Signature, typename Allocator>+inline void asio_handler_invoke(Function& f,+    promise_handler<Signature, Allocator>* h)+{+  typename promise_handler<Signature, Allocator>::executor_type+    ex(h->get_executor());+  asio::dispatch(ex, promise_function_wrapper<Function>(f));+}++template <typename Function, typename Signature, typename Allocator>+inline void asio_handler_invoke(const Function& f,+    promise_handler<Signature, Allocator>* h)+{+  typename promise_handler<Signature, Allocator>::executor_type+    ex(h->get_executor());+  asio::dispatch(ex, promise_function_wrapper<Function>(f));+}++#endif // !defined(ASIO_NO_DEPRECATED)++// Helper base class for async_result specialisation.+template <typename Signature, typename Allocator>+class promise_async_result+{+public:+  typedef promise_handler<Signature, Allocator> completion_handler_type;+  typedef typename completion_handler_type::future_type return_type;++  explicit promise_async_result(completion_handler_type& h)+    : future_(h.get_future())+  {+  }++  return_type get()+  {+    return ASIO_MOVE_CAST(return_type)(future_);+  }++private:+  return_type future_;+};++// Return value from use_future::operator().+template <typename Function, typename Allocator>+class packaged_token+{+public:+  packaged_token(Function f, const Allocator& a)+    : function_(ASIO_MOVE_CAST(Function)(f)),+      allocator_(a)+  {+  }++//private:+  Function function_;+  Allocator allocator_;+};++// Completion handlers produced from the use_future completion token, when+// using use_future::operator().+template <typename Function, typename Allocator, typename Result>+class packaged_handler+  : public promise_creator<Result>+{+public:+  typedef Allocator allocator_type;+  typedef void result_type;++  packaged_handler(packaged_token<Function, Allocator> t)+    : function_(ASIO_MOVE_CAST(Function)(t.function_)),+      allocator_(t.allocator_)+  {+    this->create_promise(allocator_);+  }++  allocator_type get_allocator() const ASIO_NOEXCEPT+  {+    return allocator_;+  }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)... args)+  {+    (promise_invoke_and_set)(*this->p_,+        function_, ASIO_MOVE_CAST(Args)(args)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  void operator()()+  {+    (promise_invoke_and_set)(*this->p_, function_);+  }++#define ASIO_PRIVATE_CALL_OP_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  void operator()(ASIO_VARIADIC_MOVE_PARAMS(n)) \+  {\+    (promise_invoke_and_set)(*this->p_, \+        function_, ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_CALL_OP_DEF)+#undef ASIO_PRIVATE_CALL_OP_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++private:+  Function function_;+  Allocator allocator_;+};++#if !defined(ASIO_NO_DEPRECATED)++template <typename Function,+    typename Function1, typename Allocator, typename Result>+inline void asio_handler_invoke(Function& f,+    packaged_handler<Function1, Allocator, Result>* h)+{+  typename packaged_handler<Function1, Allocator, Result>::executor_type+    ex(h->get_executor());+  asio::dispatch(ex, promise_function_wrapper<Function>(f));+}++template <typename Function,+    typename Function1, typename Allocator, typename Result>+inline void asio_handler_invoke(const Function& f,+    packaged_handler<Function1, Allocator, Result>* h)+{+  typename packaged_handler<Function1, Allocator, Result>::executor_type+    ex(h->get_executor());+  asio::dispatch(ex, promise_function_wrapper<Function>(f));+}++#endif // !defined(ASIO_NO_DEPRECATED)++// Helper base class for async_result specialisation.+template <typename Function, typename Allocator, typename Result>+class packaged_async_result+{+public:+  typedef packaged_handler<Function, Allocator, Result> completion_handler_type;+  typedef typename completion_handler_type::future_type return_type;++  explicit packaged_async_result(completion_handler_type& h)+    : future_(h.get_future())+  {+  }++  return_type get()+  {+    return ASIO_MOVE_CAST(return_type)(future_);+  }++private:+  return_type future_;+};++} // namespace detail++template <typename Allocator> template <typename Function>+inline detail::packaged_token<typename decay<Function>::type, Allocator>+use_future_t<Allocator>::operator()(ASIO_MOVE_ARG(Function) f) const+{+  return detail::packaged_token<typename decay<Function>::type, Allocator>(+      ASIO_MOVE_CAST(Function)(f), allocator_);+}++#if !defined(GENERATING_DOCUMENTATION)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Allocator, typename Result, typename... Args>+class async_result<use_future_t<Allocator>, Result(Args...)>+  : public detail::promise_async_result<+      void(typename decay<Args>::type...), Allocator>+{+public:+  explicit async_result(+    typename detail::promise_async_result<void(typename decay<Args>::type...),+      Allocator>::completion_handler_type& h)+    : detail::promise_async_result<+        void(typename decay<Args>::type...), Allocator>(h)+  {+  }+};++template <typename Function, typename Allocator,+    typename Result, typename... Args>+class async_result<detail::packaged_token<Function, Allocator>, Result(Args...)>+  : public detail::packaged_async_result<Function, Allocator,+      typename result_of<Function(Args...)>::type>+{+public:+  explicit async_result(+    typename detail::packaged_async_result<Function, Allocator,+      typename result_of<Function(Args...)>::type>::completion_handler_type& h)+    : detail::packaged_async_result<Function, Allocator,+        typename result_of<Function(Args...)>::type>(h)+  {+  }+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename Allocator, typename Result>+class async_result<use_future_t<Allocator>, Result()>+  : public detail::promise_async_result<void(), Allocator>+{+public:+  explicit async_result(+    typename detail::promise_async_result<+      void(), Allocator>::completion_handler_type& h)+    : detail::promise_async_result<void(), Allocator>(h)+  {+  }+};++template <typename Function, typename Allocator, typename Result>+class async_result<detail::packaged_token<Function, Allocator>, Result()>+  : public detail::packaged_async_result<Function, Allocator,+      typename result_of<Function()>::type>+{+public:+  explicit async_result(+    typename detail::packaged_async_result<Function, Allocator,+      typename result_of<Function()>::type>::completion_handler_type& h)+    : detail::packaged_async_result<Function, Allocator,+        typename result_of<Function()>::type>(h)+  {+  }+};++#define ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \+  template <typename Allocator, \+      typename Result, ASIO_VARIADIC_TPARAMS(n)> \+  class async_result<use_future_t<Allocator>, \+      Result(ASIO_VARIADIC_TARGS(n))> \+    : public detail::promise_async_result< \+        void(ASIO_VARIADIC_DECAY(n)), Allocator> \+  { \+  public: \+    explicit async_result( \+      typename detail::promise_async_result< \+        void(ASIO_VARIADIC_DECAY(n)), \+        Allocator>::completion_handler_type& h) \+      : detail::promise_async_result< \+          void(ASIO_VARIADIC_DECAY(n)), Allocator>(h) \+    { \+    } \+  }; \+  \+  template <typename Function, typename Allocator, \+      typename Result, ASIO_VARIADIC_TPARAMS(n)> \+  class async_result<detail::packaged_token<Function, Allocator>, \+      Result(ASIO_VARIADIC_TARGS(n))> \+    : public detail::packaged_async_result<Function, Allocator, \+        typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type> \+  { \+  public: \+    explicit async_result( \+      typename detail::packaged_async_result<Function, Allocator, \+        typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type \+        >::completion_handler_type& h) \+      : detail::packaged_async_result<Function, Allocator, \+          typename result_of<Function(ASIO_VARIADIC_TARGS(n))>::type>(h) \+    { \+    } \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_RESULT_DEF)+#undef ASIO_PRIVATE_ASYNC_RESULT_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <typename T, typename Blocking>+struct equality_comparable<+    asio::detail::promise_executor<T, Blocking> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename T, typename Blocking, typename Function>+struct execute_member<+    asio::detail::promise_executor<T, Blocking>, Function>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)++template <typename T, typename Blocking, typename Property>+struct query_static_constexpr_member<+    asio::detail::promise_executor<T, Blocking>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::blocking_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef Blocking result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return Blocking();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename T, typename Blocking>+struct require_member<+    asio::detail::promise_executor<T, Blocking>,+    execution::blocking_t::possibly_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::detail::promise_executor<T,+      execution::blocking_t::possibly_t> result_type;+};++template <typename T, typename Blocking>+struct require_member<+    asio::detail::promise_executor<T, Blocking>,+    execution::blocking_t::never_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::detail::promise_executor<T,+      execution::blocking_t::never_t> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++} // namespace traits++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_USE_FUTURE_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/write.hpp view
@@ -0,0 +1,1104 @@+//+// impl/write.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_WRITE_HPP+#define ASIO_IMPL_WRITE_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/buffer.hpp"+#include "asio/completion_condition.hpp"+#include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_completion_cond.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/consuming_buffers.hpp"+#include "asio/detail/dependent_type.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_tracking.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail+{+  template <typename SyncWriteStream, typename ConstBufferSequence,+      typename ConstBufferIterator, typename CompletionCondition>+  std::size_t write_buffer_sequence(SyncWriteStream& s,+      const ConstBufferSequence& buffers, const ConstBufferIterator&,+      CompletionCondition completion_condition, asio::error_code& ec)+  {+    ec = asio::error_code();+    asio::detail::consuming_buffers<const_buffer,+        ConstBufferSequence, ConstBufferIterator> tmp(buffers);+    while (!tmp.empty())+    {+      if (std::size_t max_size = detail::adapt_completion_condition_result(+            completion_condition(ec, tmp.total_consumed())))+        tmp.consume(s.write_some(tmp.prepare(max_size), ec));+      else+        break;+    }+    return tmp.total_consumed();;+  }+} // namespace detail++template <typename SyncWriteStream, typename ConstBufferSequence,+    typename CompletionCondition>+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type*)+{+  return detail::write_buffer_sequence(s, buffers,+      asio::buffer_sequence_begin(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+}++template <typename SyncWriteStream, typename ConstBufferSequence>+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);+  asio::detail::throw_error(ec, "write");+  return bytes_transferred;+}++template <typename SyncWriteStream, typename ConstBufferSequence>+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,+    asio::error_code& ec,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type*)+{+  return write(s, buffers, transfer_all(), ec);+}++template <typename SyncWriteStream, typename ConstBufferSequence,+    typename CompletionCondition>+inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write(s, buffers,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "write");+  return bytes_transferred;+}++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++template <typename SyncWriteStream, typename DynamicBuffer_v1,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  typename decay<DynamicBuffer_v1>::type b(+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));++  std::size_t bytes_transferred = write(s, b.data(),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  b.consume(bytes_transferred);+  return bytes_transferred;+}++template <typename SyncWriteStream, typename DynamicBuffer_v1>+inline std::size_t write(SyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      transfer_all(), ec);+  asio::detail::throw_error(ec, "write");+  return bytes_transferred;+}++template <typename SyncWriteStream, typename DynamicBuffer_v1>+inline std::size_t write(SyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return write(s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      transfer_all(), ec);+}++template <typename SyncWriteStream, typename DynamicBuffer_v1,+    typename CompletionCondition>+inline std::size_t write(SyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "write");+  return bytes_transferred;+}++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++template <typename SyncWriteStream, typename Allocator,+    typename CompletionCondition>+inline std::size_t write(SyncWriteStream& s,+    asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition, asio::error_code& ec)+{+  return write(s, basic_streambuf_ref<Allocator>(b),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+}++template <typename SyncWriteStream, typename Allocator>+inline std::size_t write(SyncWriteStream& s,+    asio::basic_streambuf<Allocator>& b)+{+  return write(s, basic_streambuf_ref<Allocator>(b));+}++template <typename SyncWriteStream, typename Allocator>+inline std::size_t write(SyncWriteStream& s,+    asio::basic_streambuf<Allocator>& b,+    asio::error_code& ec)+{+  return write(s, basic_streambuf_ref<Allocator>(b), ec);+}++template <typename SyncWriteStream, typename Allocator,+    typename CompletionCondition>+inline std::size_t write(SyncWriteStream& s,+    asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition)+{+  return write(s, basic_streambuf_ref<Allocator>(b),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++template <typename SyncWriteStream, typename DynamicBuffer_v2,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  buffers.consume(bytes_transferred);+  return bytes_transferred;+}++template <typename SyncWriteStream, typename DynamicBuffer_v2>+inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      transfer_all(), ec);+  asio::detail::throw_error(ec, "write");+  return bytes_transferred;+}++template <typename SyncWriteStream, typename DynamicBuffer_v2>+inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,+    asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return write(s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      transfer_all(), ec);+}++template <typename SyncWriteStream, typename DynamicBuffer_v2,+    typename CompletionCondition>+inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "write");+  return bytes_transferred;+}++namespace detail+{+  template <typename AsyncWriteStream, typename ConstBufferSequence,+      typename ConstBufferIterator, typename CompletionCondition,+      typename WriteHandler>+  class write_op+    : detail::base_from_completion_cond<CompletionCondition>+  {+  public:+    write_op(AsyncWriteStream& stream, const ConstBufferSequence& buffers,+        CompletionCondition& completion_condition, WriteHandler& handler)+      : detail::base_from_completion_cond<+          CompletionCondition>(completion_condition),+        stream_(stream),+        buffers_(buffers),+        start_(0),+        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    write_op(const write_op& other)+      : detail::base_from_completion_cond<CompletionCondition>(other),+        stream_(other.stream_),+        buffers_(other.buffers_),+        start_(other.start_),+        handler_(other.handler_)+    {+    }++    write_op(write_op&& other)+      : detail::base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(detail::base_from_completion_cond<+            CompletionCondition>)(other)),+        stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)),+        start_(other.start_),+        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      std::size_t max_size;+      switch (start_ = start)+      {+        case 1:+        max_size = this->check_for_completion(ec, buffers_.total_consumed());+        do+        {+          {+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write"));+            stream_.async_write_some(buffers_.prepare(max_size),+                ASIO_MOVE_CAST(write_op)(*this));+          }+          return; default:+          buffers_.consume(bytes_transferred);+          if ((!ec && bytes_transferred == 0) || buffers_.empty())+            break;+          max_size = this->check_for_completion(ec, buffers_.total_consumed());+        } while (max_size > 0);++        handler_(ec, buffers_.total_consumed());+      }+    }++  //private:+    typedef asio::detail::consuming_buffers<const_buffer,+        ConstBufferSequence, ConstBufferIterator> buffers_type;++    AsyncWriteStream& stream_;+    buffers_type buffers_;+    int start_;+    WriteHandler handler_;+  };++  template <typename AsyncWriteStream, typename ConstBufferSequence,+      typename ConstBufferIterator, typename CompletionCondition,+      typename WriteHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,+        CompletionCondition, WriteHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncWriteStream, typename ConstBufferSequence,+      typename ConstBufferIterator, typename CompletionCondition,+      typename WriteHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,+        CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncWriteStream, typename ConstBufferSequence,+      typename ConstBufferIterator, typename CompletionCondition,+      typename WriteHandler>+  inline bool asio_handler_is_continuation(+      write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,+        CompletionCondition, WriteHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncWriteStream,+      typename ConstBufferSequence, typename ConstBufferIterator,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,+        CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncWriteStream,+      typename ConstBufferSequence, typename ConstBufferIterator,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      write_op<AsyncWriteStream, ConstBufferSequence, ConstBufferIterator,+        CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncWriteStream, typename ConstBufferSequence,+      typename ConstBufferIterator, typename CompletionCondition,+      typename WriteHandler>+  inline void start_write_buffer_sequence_op(AsyncWriteStream& stream,+      const ConstBufferSequence& buffers, const ConstBufferIterator&,+      CompletionCondition& completion_condition, WriteHandler& handler)+  {+    detail::write_op<AsyncWriteStream, ConstBufferSequence,+      ConstBufferIterator, CompletionCondition, WriteHandler>(+        stream, buffers, completion_condition, handler)(+          asio::error_code(), 0, 1);+  }++  template <typename AsyncWriteStream>+  class initiate_async_write_buffer_sequence+  {+  public:+    typedef typename AsyncWriteStream::executor_type executor_type;++    explicit initiate_async_write_buffer_sequence(AsyncWriteStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename WriteHandler, typename ConstBufferSequence,+        typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        const ConstBufferSequence& buffers,+        ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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;++      non_const_lvalue<WriteHandler> handler2(handler);+      non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);+      start_write_buffer_sequence_op(stream_, buffers,+          asio::buffer_sequence_begin(buffers),+          completion_cond2.value, handler2.value);+    }++  private:+    AsyncWriteStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncWriteStream, typename ConstBufferSequence,+    typename ConstBufferIterator, typename CompletionCondition,+    typename WriteHandler, typename Allocator>+struct associated_allocator<+    detail::write_op<AsyncWriteStream, ConstBufferSequence,+      ConstBufferIterator, CompletionCondition, WriteHandler>,+    Allocator>+{+  typedef typename associated_allocator<WriteHandler, Allocator>::type type;++  static type get(+      const detail::write_op<AsyncWriteStream, ConstBufferSequence,+        ConstBufferIterator, CompletionCondition, WriteHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncWriteStream, typename ConstBufferSequence,+    typename ConstBufferIterator, typename CompletionCondition,+    typename WriteHandler, typename Executor>+struct associated_executor<+    detail::write_op<AsyncWriteStream, ConstBufferSequence,+      ConstBufferIterator, CompletionCondition, WriteHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<WriteHandler, Executor>+{+  typedef typename associated_executor<WriteHandler, Executor>::type type;++  static type get(+      const detail::write_op<AsyncWriteStream, ConstBufferSequence,+        ConstBufferIterator, CompletionCondition, WriteHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncWriteStream,+    typename ConstBufferSequence, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type*)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),+      handler, buffers,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++template <typename AsyncWriteStream, typename ConstBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,+    ASIO_MOVE_ARG(WriteHandler) handler,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type*)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),+      handler, buffers, transfer_all());+}++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++namespace detail+{+  template <typename AsyncWriteStream, typename DynamicBuffer_v1,+      typename CompletionCondition, typename WriteHandler>+  class write_dynbuf_v1_op+  {+  public:+    template <typename BufferSequence>+    write_dynbuf_v1_op(AsyncWriteStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        CompletionCondition& completion_condition, WriteHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        completion_condition_(+          ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),+        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    write_dynbuf_v1_op(const write_dynbuf_v1_op& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        completion_condition_(other.completion_condition_),+        handler_(other.handler_)+    {+    }++    write_dynbuf_v1_op(write_dynbuf_v1_op&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),+        completion_condition_(+          ASIO_MOVE_CAST(CompletionCondition)(+            other.completion_condition_)),+        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      switch (start)+      {+        case 1:+        async_write(stream_, buffers_.data(),+            ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),+            ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this));+        return; default:+        buffers_.consume(bytes_transferred);+        handler_(ec, static_cast<const std::size_t&>(bytes_transferred));+      }+    }++  //private:+    AsyncWriteStream& stream_;+    DynamicBuffer_v1 buffers_;+    CompletionCondition completion_condition_;+    WriteHandler handler_;+  };++  template <typename AsyncWriteStream, typename DynamicBuffer_v1,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,+        CompletionCondition, WriteHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncWriteStream, typename DynamicBuffer_v1,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,+        CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncWriteStream, typename DynamicBuffer_v1,+      typename CompletionCondition, typename WriteHandler>+  inline bool asio_handler_is_continuation(+      write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,+        CompletionCondition, WriteHandler>* this_handler)+  {+    return asio_handler_cont_helpers::is_continuation(+        this_handler->handler_);+  }++  template <typename Function, typename AsyncWriteStream,+      typename DynamicBuffer_v1, typename CompletionCondition,+      typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,+        CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncWriteStream,+      typename DynamicBuffer_v1, typename CompletionCondition,+      typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,+        CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncWriteStream>+  class initiate_async_write_dynbuf_v1+  {+  public:+    typedef typename AsyncWriteStream::executor_type executor_type;++    explicit initiate_async_write_dynbuf_v1(AsyncWriteStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename WriteHandler, typename DynamicBuffer_v1,+        typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+        ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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;++      non_const_lvalue<WriteHandler> handler2(handler);+      non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);+      write_dynbuf_v1_op<AsyncWriteStream,+        typename decay<DynamicBuffer_v1>::type,+          CompletionCondition, typename decay<WriteHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+              completion_cond2.value, handler2.value)(+                asio::error_code(), 0, 1);+    }++  private:+    AsyncWriteStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncWriteStream, typename DynamicBuffer_v1,+    typename CompletionCondition, typename WriteHandler, typename Allocator>+struct associated_allocator<+    detail::write_dynbuf_v1_op<AsyncWriteStream,+      DynamicBuffer_v1, CompletionCondition, WriteHandler>,+    Allocator>+{+  typedef typename associated_allocator<WriteHandler, Allocator>::type type;++  static type get(+      const detail::write_dynbuf_v1_op<AsyncWriteStream,+        DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncWriteStream, typename DynamicBuffer_v1,+    typename CompletionCondition, typename WriteHandler, typename Executor>+struct associated_executor<+    detail::write_dynbuf_v1_op<AsyncWriteStream,+      DynamicBuffer_v1, CompletionCondition, WriteHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<WriteHandler, Executor>+{+  typedef typename associated_executor<WriteHandler, Executor>::type type;++  static type get(+      const detail::write_dynbuf_v1_op<AsyncWriteStream,+        DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncWriteStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_MOVE_ARG(WriteHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return async_write(s,+      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler));+}++template <typename AsyncWriteStream,+    typename DynamicBuffer_v1, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type*)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++template <typename AsyncWriteStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s,+    asio::basic_streambuf<Allocator>& b,+    ASIO_MOVE_ARG(WriteHandler) handler)+{+  return async_write(s, basic_streambuf_ref<Allocator>(b),+      ASIO_MOVE_CAST(WriteHandler)(handler));+}++template <typename AsyncWriteStream,+    typename Allocator, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s,+    asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler)+{+  return async_write(s, basic_streambuf_ref<Allocator>(b),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+      ASIO_MOVE_CAST(WriteHandler)(handler));+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++namespace detail+{+  template <typename AsyncWriteStream, typename DynamicBuffer_v2,+      typename CompletionCondition, typename WriteHandler>+  class write_dynbuf_v2_op+  {+  public:+    template <typename BufferSequence>+    write_dynbuf_v2_op(AsyncWriteStream& stream,+        ASIO_MOVE_ARG(BufferSequence) buffers,+        CompletionCondition& completion_condition, WriteHandler& handler)+      : stream_(stream),+        buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),+        completion_condition_(+          ASIO_MOVE_CAST(CompletionCondition)(completion_condition)),+        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    write_dynbuf_v2_op(const write_dynbuf_v2_op& other)+      : stream_(other.stream_),+        buffers_(other.buffers_),+        completion_condition_(other.completion_condition_),+        handler_(other.handler_)+    {+    }++    write_dynbuf_v2_op(write_dynbuf_v2_op&& other)+      : stream_(other.stream_),+        buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),+        completion_condition_(+          ASIO_MOVE_CAST(CompletionCondition)(+            other.completion_condition_)),+        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      switch (start)+      {+        case 1:+        async_write(stream_, buffers_.data(0, buffers_.size()),+            ASIO_MOVE_CAST(CompletionCondition)(completion_condition_),+            ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this));+        return; default:+        buffers_.consume(bytes_transferred);+        handler_(ec, static_cast<const std::size_t&>(bytes_transferred));+      }+    }++  //private:+    AsyncWriteStream& stream_;+    DynamicBuffer_v2 buffers_;+    CompletionCondition completion_condition_;+    WriteHandler handler_;+  };++  template <typename AsyncWriteStream, typename DynamicBuffer_v2,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,+        CompletionCondition, WriteHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncWriteStream, typename DynamicBuffer_v2,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,+        CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncWriteStream, typename DynamicBuffer_v2,+      typename CompletionCondition, typename WriteHandler>+  inline bool asio_handler_is_continuation(+      write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,+        CompletionCondition, WriteHandler>* this_handler)+  {+    return asio_handler_cont_helpers::is_continuation(+        this_handler->handler_);+  }++  template <typename Function, typename AsyncWriteStream,+      typename DynamicBuffer_v2, typename CompletionCondition,+      typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,+        CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncWriteStream,+      typename DynamicBuffer_v2, typename CompletionCondition,+      typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,+        CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncWriteStream>+  class initiate_async_write_dynbuf_v2+  {+  public:+    typedef typename AsyncWriteStream::executor_type executor_type;++    explicit initiate_async_write_dynbuf_v2(AsyncWriteStream& stream)+      : stream_(stream)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return stream_.get_executor();+    }++    template <typename WriteHandler, typename DynamicBuffer_v2,+        typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        ASIO_MOVE_ARG(DynamicBuffer_v2) buffers,+        ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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;++      non_const_lvalue<WriteHandler> handler2(handler);+      non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);+      write_dynbuf_v2_op<AsyncWriteStream,+        typename decay<DynamicBuffer_v2>::type,+          CompletionCondition, typename decay<WriteHandler>::type>(+            stream_, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+              completion_cond2.value, handler2.value)(+                asio::error_code(), 0, 1);+    }++  private:+    AsyncWriteStream& stream_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncWriteStream, typename DynamicBuffer_v2,+    typename CompletionCondition, typename WriteHandler, typename Allocator>+struct associated_allocator<+    detail::write_dynbuf_v2_op<AsyncWriteStream,+      DynamicBuffer_v2, CompletionCondition, WriteHandler>,+    Allocator>+{+  typedef typename associated_allocator<WriteHandler, Allocator>::type type;++  static type get(+      const detail::write_dynbuf_v2_op<AsyncWriteStream,+        DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncWriteStream, typename DynamicBuffer_v2,+    typename CompletionCondition, typename WriteHandler, typename Executor>+struct associated_executor<+    detail::write_dynbuf_v2_op<AsyncWriteStream,+      DynamicBuffer_v2, CompletionCondition, WriteHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<WriteHandler, Executor>+{+  typedef typename associated_executor<WriteHandler, Executor>::type type;++  static type get(+      const detail::write_dynbuf_v2_op<AsyncWriteStream,+        DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncWriteStream, typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,+    ASIO_MOVE_ARG(WriteHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return async_write(s,+      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler));+}++template <typename AsyncWriteStream,+    typename DynamicBuffer_v2, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type*)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),+      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_WRITE_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/write_at.hpp view
@@ -0,0 +1,666 @@+//+// impl/write_at.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IMPL_WRITE_AT_HPP+#define ASIO_IMPL_WRITE_AT_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/buffer.hpp"+#include "asio/completion_condition.hpp"+#include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_completion_cond.hpp"+#include "asio/detail/bind_handler.hpp"+#include "asio/detail/consuming_buffers.hpp"+#include "asio/detail/dependent_type.hpp"+#include "asio/detail/handler_alloc_helpers.hpp"+#include "asio/detail/handler_cont_helpers.hpp"+#include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/handler_tracking.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail+{+  template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,+      typename ConstBufferIterator, typename CompletionCondition>+  std::size_t write_at_buffer_sequence(SyncRandomAccessWriteDevice& d,+      uint64_t offset, const ConstBufferSequence& buffers,+      const ConstBufferIterator&, CompletionCondition completion_condition,+      asio::error_code& ec)+  {+    ec = asio::error_code();+    asio::detail::consuming_buffers<const_buffer,+        ConstBufferSequence, ConstBufferIterator> tmp(buffers);+    while (!tmp.empty())+    {+      if (std::size_t max_size = detail::adapt_completion_condition_result(+            completion_condition(ec, tmp.total_consumed())))+      {+        tmp.consume(d.write_some_at(offset + tmp.total_consumed(),+              tmp.prepare(max_size), ec));+      }+      else+        break;+    }+    return tmp.total_consumed();;+  }+} // namespace detail++template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,+    typename CompletionCondition>+std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition, asio::error_code& ec)+{+  return detail::write_at_buffer_sequence(d, offset, buffers,+      asio::buffer_sequence_begin(buffers),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+}++template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write_at(+      d, offset, buffers, transfer_all(), ec);+  asio::detail::throw_error(ec, "write_at");+  return bytes_transferred;+}++template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers,+    asio::error_code& ec)+{+  return write_at(d, offset, buffers, transfer_all(), ec);+}++template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,+    typename CompletionCondition>+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write_at(d, offset, buffers,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "write_at");+  return bytes_transferred;+}++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++template <typename SyncRandomAccessWriteDevice, typename Allocator,+    typename CompletionCondition>+std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition, asio::error_code& ec)+{+  std::size_t bytes_transferred = write_at(d, offset, b.data(),+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  b.consume(bytes_transferred);+  return bytes_transferred;+}++template <typename SyncRandomAccessWriteDevice, typename Allocator>+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write_at(d, offset, b, transfer_all(), ec);+  asio::detail::throw_error(ec, "write_at");+  return bytes_transferred;+}++template <typename SyncRandomAccessWriteDevice, typename Allocator>+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    asio::error_code& ec)+{+  return write_at(d, offset, b, transfer_all(), ec);+}++template <typename SyncRandomAccessWriteDevice, typename Allocator,+    typename CompletionCondition>+inline std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition)+{+  asio::error_code ec;+  std::size_t bytes_transferred = write_at(d, offset, b,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);+  asio::detail::throw_error(ec, "write_at");+  return bytes_transferred;+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)++namespace detail+{+  template <typename AsyncRandomAccessWriteDevice,+      typename ConstBufferSequence, typename ConstBufferIterator,+      typename CompletionCondition, typename WriteHandler>+  class write_at_op+    : detail::base_from_completion_cond<CompletionCondition>+  {+  public:+    write_at_op(AsyncRandomAccessWriteDevice& device,+        uint64_t offset, const ConstBufferSequence& buffers,+        CompletionCondition& completion_condition, WriteHandler& handler)+      : detail::base_from_completion_cond<+          CompletionCondition>(completion_condition),+        device_(device),+        offset_(offset),+        buffers_(buffers),+        start_(0),+        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    write_at_op(const write_at_op& other)+      : detail::base_from_completion_cond<CompletionCondition>(other),+        device_(other.device_),+        offset_(other.offset_),+        buffers_(other.buffers_),+        start_(other.start_),+        handler_(other.handler_)+    {+    }++    write_at_op(write_at_op&& other)+      : detail::base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(detail::base_from_completion_cond<+            CompletionCondition>)(other)),+        device_(other.device_),+        offset_(other.offset_),+        buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)),+        start_(other.start_),+        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        std::size_t bytes_transferred, int start = 0)+    {+      std::size_t max_size;+      switch (start_ = start)+      {+        case 1:+        max_size = this->check_for_completion(ec, buffers_.total_consumed());+        do+        {+          {+            ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write_at"));+            device_.async_write_some_at(+                offset_ + buffers_.total_consumed(), buffers_.prepare(max_size),+                ASIO_MOVE_CAST(write_at_op)(*this));+          }+          return; default:+          buffers_.consume(bytes_transferred);+          if ((!ec && bytes_transferred == 0) || buffers_.empty())+            break;+          max_size = this->check_for_completion(ec, buffers_.total_consumed());+        } while (max_size > 0);++        handler_(ec, buffers_.total_consumed());+      }+    }++  //private:+    typedef asio::detail::consuming_buffers<const_buffer,+        ConstBufferSequence, ConstBufferIterator> buffers_type;++    AsyncRandomAccessWriteDevice& device_;+    uint64_t offset_;+    buffers_type buffers_;+    int start_;+    WriteHandler handler_;+  };++  template <typename AsyncRandomAccessWriteDevice,+      typename ConstBufferSequence, typename ConstBufferIterator,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,+        ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessWriteDevice,+      typename ConstBufferSequence, typename ConstBufferIterator,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,+        ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessWriteDevice,+      typename ConstBufferSequence, typename ConstBufferIterator,+      typename CompletionCondition, typename WriteHandler>+  inline bool asio_handler_is_continuation(+      write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,+        ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)+  {+    return this_handler->start_ == 0 ? true+      : asio_handler_cont_helpers::is_continuation(+          this_handler->handler_);+  }++  template <typename Function, typename AsyncRandomAccessWriteDevice,+      typename ConstBufferSequence, typename ConstBufferIterator,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,+        ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename AsyncRandomAccessWriteDevice,+      typename ConstBufferSequence, typename ConstBufferIterator,+      typename CompletionCondition, typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,+        ConstBufferIterator, CompletionCondition, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessWriteDevice,+      typename ConstBufferSequence, typename ConstBufferIterator,+      typename CompletionCondition, typename WriteHandler>+  inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d,+      uint64_t offset, const ConstBufferSequence& buffers,+      const ConstBufferIterator&, CompletionCondition& completion_condition,+      WriteHandler& handler)+  {+    detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,+      ConstBufferIterator, CompletionCondition, WriteHandler>(+        d, offset, buffers, completion_condition, handler)(+          asio::error_code(), 0, 1);+  }++  template <typename AsyncRandomAccessWriteDevice>+  class initiate_async_write_at_buffer_sequence+  {+  public:+    typedef typename AsyncRandomAccessWriteDevice::executor_type executor_type;++    explicit initiate_async_write_at_buffer_sequence(+        AsyncRandomAccessWriteDevice& device)+      : device_(device)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return device_.get_executor();+    }++    template <typename WriteHandler, typename ConstBufferSequence,+        typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        uint64_t offset, const ConstBufferSequence& buffers,+        ASIO_MOVE_ARG(CompletionCondition) completion_cond) 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;++      non_const_lvalue<WriteHandler> handler2(handler);+      non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);+      start_write_at_buffer_sequence_op(device_, offset, buffers,+          asio::buffer_sequence_begin(buffers),+          completion_cond2.value, handler2.value);+    }++  private:+    AsyncRandomAccessWriteDevice& device_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename AsyncRandomAccessWriteDevice,+    typename ConstBufferSequence, typename ConstBufferIterator,+    typename CompletionCondition, typename WriteHandler, typename Allocator>+struct associated_allocator<+    detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,+      ConstBufferIterator, CompletionCondition, WriteHandler>,+    Allocator>+{+  typedef typename associated_allocator<WriteHandler, Allocator>::type type;++  static type get(+      const detail::write_at_op<AsyncRandomAccessWriteDevice,+        ConstBufferSequence, ConstBufferIterator,+        CompletionCondition, WriteHandler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+  }+};++template <typename AsyncRandomAccessWriteDevice,+    typename ConstBufferSequence, typename ConstBufferIterator,+    typename CompletionCondition, typename WriteHandler, typename Executor>+struct associated_executor<+    detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,+      ConstBufferIterator, CompletionCondition, WriteHandler>,+    Executor>+  : detail::associated_executor_forwarding_base<WriteHandler, Executor>+{+  typedef typename associated_executor<WriteHandler, Executor>::type type;++  static type get(+      const detail::write_at_op<AsyncRandomAccessWriteDevice,+        ConstBufferSequence, ConstBufferIterator,+        CompletionCondition, WriteHandler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncRandomAccessWriteDevice,+    typename ConstBufferSequence, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write_at(AsyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_at_buffer_sequence<+        AsyncRandomAccessWriteDevice>(d),+      handler, offset, buffers,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write_at(AsyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers,+    ASIO_MOVE_ARG(WriteHandler) handler)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_at_buffer_sequence<+        AsyncRandomAccessWriteDevice>(d),+      handler, offset, buffers, transfer_all());+}++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++namespace detail+{+  template <typename Allocator, typename WriteHandler>+  class write_at_streambuf_op+  {+  public:+    write_at_streambuf_op(+        asio::basic_streambuf<Allocator>& streambuf,+        WriteHandler& handler)+      : streambuf_(streambuf),+        handler_(ASIO_MOVE_CAST(WriteHandler)(handler))+    {+    }++#if defined(ASIO_HAS_MOVE)+    write_at_streambuf_op(const write_at_streambuf_op& other)+      : streambuf_(other.streambuf_),+        handler_(other.handler_)+    {+    }++    write_at_streambuf_op(write_at_streambuf_op&& other)+      : streambuf_(other.streambuf_),+        handler_(ASIO_MOVE_CAST(WriteHandler)(other.handler_))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    void operator()(const asio::error_code& ec,+        const std::size_t bytes_transferred)+    {+      streambuf_.consume(bytes_transferred);+      handler_(ec, bytes_transferred);+    }++  //private:+    asio::basic_streambuf<Allocator>& streambuf_;+    WriteHandler handler_;+  };++  template <typename Allocator, typename WriteHandler>+  inline asio_handler_allocate_is_deprecated+  asio_handler_allocate(std::size_t size,+      write_at_streambuf_op<Allocator, WriteHandler>* this_handler)+  {+#if defined(ASIO_NO_DEPRECATED)+    asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+    return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+    return asio_handler_alloc_helpers::allocate(+        size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Allocator, typename WriteHandler>+  inline asio_handler_deallocate_is_deprecated+  asio_handler_deallocate(void* pointer, std::size_t size,+      write_at_streambuf_op<Allocator, WriteHandler>* this_handler)+  {+    asio_handler_alloc_helpers::deallocate(+        pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Allocator, typename WriteHandler>+  inline bool asio_handler_is_continuation(+      write_at_streambuf_op<Allocator, WriteHandler>* this_handler)+  {+    return asio_handler_cont_helpers::is_continuation(+        this_handler->handler_);+  }++  template <typename Function, typename Allocator, typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(Function& function,+      write_at_streambuf_op<Allocator, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename Function, typename Allocator, typename WriteHandler>+  inline asio_handler_invoke_is_deprecated+  asio_handler_invoke(const Function& function,+      write_at_streambuf_op<Allocator, WriteHandler>* this_handler)+  {+    asio_handler_invoke_helpers::invoke(+        function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+    return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename AsyncRandomAccessWriteDevice>+  class initiate_async_write_at_streambuf+  {+  public:+    typedef typename AsyncRandomAccessWriteDevice::executor_type executor_type;++    explicit initiate_async_write_at_streambuf(+        AsyncRandomAccessWriteDevice& device)+      : device_(device)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return device_.get_executor();+    }++    template <typename WriteHandler,+        typename Allocator, typename CompletionCondition>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        uint64_t offset, basic_streambuf<Allocator>* b,+        ASIO_MOVE_ARG(CompletionCondition) completion_condition) 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;++      non_const_lvalue<WriteHandler> handler2(handler);+      async_write_at(device_, offset, b->data(),+          ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+          write_at_streambuf_op<Allocator, typename decay<WriteHandler>::type>(+            *b, handler2.value));+    }++  private:+    AsyncRandomAccessWriteDevice& device_;+  };+} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename Allocator, typename WriteHandler, typename Allocator1>+struct associated_allocator<+    detail::write_at_streambuf_op<Allocator, WriteHandler>,+    Allocator1>+{+  typedef typename associated_allocator<WriteHandler, Allocator1>::type type;++  static type get(+      const detail::write_at_streambuf_op<Allocator, WriteHandler>& h,+      const Allocator1& a = Allocator1()) ASIO_NOEXCEPT+  {+    return associated_allocator<WriteHandler, Allocator1>::get(h.handler_, a);+  }+};++template <typename Executor, typename WriteHandler, typename Executor1>+struct associated_executor<+    detail::write_at_streambuf_op<Executor, WriteHandler>,+    Executor1>+  : detail::associated_executor_forwarding_base<WriteHandler, Executor>+{+  typedef typename associated_executor<WriteHandler, Executor1>::type type;++  static type get(+      const detail::write_at_streambuf_op<Executor, WriteHandler>& h,+      const Executor1& ex = Executor1()) ASIO_NOEXCEPT+  {+    return associated_executor<WriteHandler, Executor1>::get(h.handler_, ex);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++template <typename AsyncRandomAccessWriteDevice,+    typename Allocator, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write_at(AsyncRandomAccessWriteDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_at_streambuf<+        AsyncRandomAccessWriteDevice>(d),+      handler, offset, &b,+      ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+}++template <typename AsyncRandomAccessWriteDevice, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write_at(AsyncRandomAccessWriteDevice& d,+    uint64_t offset, asio::basic_streambuf<Allocator>& b,+    ASIO_MOVE_ARG(WriteHandler) handler)+{+  return async_initiate<WriteHandler,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_at_streambuf<+        AsyncRandomAccessWriteDevice>(d),+      handler, offset, &b, transfer_all());+}++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_WRITE_AT_HPP
+ link/modules/asio-standalone/asio/include/asio/io_context.hpp view
@@ -0,0 +1,1530 @@+//+// io_context.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IO_CONTEXT_HPP+#define ASIO_IO_CONTEXT_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 <stdexcept>+#include <typeinfo>+#include "asio/async_result.hpp"+#include "asio/detail/wrapped_handler.hpp"+#include "asio/error_code.hpp"+#include "asio/execution.hpp"+#include "asio/execution_context.hpp"++#if defined(ASIO_HAS_CHRONO)+# include "asio/detail/chrono.hpp"+#endif // defined(ASIO_HAS_CHRONO)++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# include "asio/detail/winsock_init.hpp"+#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \+  || defined(__osf__)+# include "asio/detail/signal_init.hpp"+#endif++#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_io_context.hpp"+#else+# include "asio/detail/scheduler.hpp"+#endif++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail {+#if defined(ASIO_HAS_IOCP)+  typedef win_iocp_io_context io_context_impl;+  class win_iocp_overlapped_ptr;+#else+  typedef scheduler io_context_impl;+#endif++  struct io_context_bits+  {+    ASIO_STATIC_CONSTEXPR(unsigned int, blocking_never = 1);+    ASIO_STATIC_CONSTEXPR(unsigned int, relationship_continuation = 2);+    ASIO_STATIC_CONSTEXPR(unsigned int, outstanding_work_tracked = 4);+  };+} // namespace detail++/// Provides core I/O functionality.+/**+ * The io_context class provides the core I/O functionality for users of the+ * asynchronous I/O objects, including:+ *+ * @li asio::ip::tcp::socket+ * @li asio::ip::tcp::acceptor+ * @li asio::ip::udp::socket+ * @li asio::deadline_timer.+ *+ * The io_context class also includes facilities intended for developers of+ * custom asynchronous services.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe, with the specific exceptions of the restart()+ * and notify_fork() functions. Calling restart() while there are unfinished+ * run(), run_one(), run_for(), run_until(), poll() or poll_one() calls results+ * in undefined behaviour. The notify_fork() function should not be called+ * while any io_context function, or any function on an I/O object that is+ * associated with the io_context, is being called in another thread.+ *+ * @par Concepts:+ * Dispatcher.+ *+ * @par Synchronous and asynchronous operations+ *+ * Synchronous operations on I/O objects implicitly run the io_context object+ * for an individual operation. The io_context functions run(), run_one(),+ * run_for(), run_until(), poll() or poll_one() must be called for the+ * io_context to perform asynchronous operations on behalf of a C++ program.+ * Notification that an asynchronous operation has completed is delivered by+ * invocation of the associated handler. Handlers are invoked only by a thread+ * that is currently calling any overload of run(), run_one(), run_for(),+ * run_until(), poll() or poll_one() for the io_context.+ *+ * @par Effect of exceptions thrown from handlers+ *+ * If an exception is thrown from a handler, the exception is allowed to+ * propagate through the throwing thread's invocation of run(), run_one(),+ * run_for(), run_until(), poll() or poll_one(). No other threads that are+ * calling any of these functions are affected. It is then the responsibility+ * of the application to catch the exception.+ *+ * After the exception has been caught, the run(), run_one(), run_for(),+ * run_until(), poll() or poll_one() call may be restarted @em without the need+ * for an intervening call to restart(). This allows the thread to rejoin the+ * io_context object's thread pool without impacting any other threads in the+ * pool.+ *+ * For example:+ *+ * @code+ * asio::io_context io_context;+ * ...+ * for (;;)+ * {+ *   try+ *   {+ *     io_context.run();+ *     break; // run() exited normally+ *   }+ *   catch (my_exception& e)+ *   {+ *     // Deal with exception as appropriate.+ *   }+ * }+ * @endcode+ *+ * @par Submitting arbitrary tasks to the io_context+ *+ * To submit functions to the io_context, use the @ref asio::dispatch,+ * @ref asio::post or @ref asio::defer free functions.+ *+ * For example:+ *+ * @code void my_task()+ * {+ *   ...+ * }+ *+ * ...+ *+ * asio::io_context io_context;+ *+ * // Submit a function to the io_context.+ * asio::post(io_context, my_task);+ *+ * // Submit a lambda object to the io_context.+ * asio::post(io_context,+ *     []()+ *     {+ *       ...+ *     });+ *+ * // Run the io_context until it runs out of work.+ * io_context.run(); @endcode+ *+ * @par Stopping the io_context from running out of work+ *+ * Some applications may need to prevent an io_context object's run() call from+ * returning when there is no more work to do. For example, the io_context may+ * be being run in a background thread that is launched prior to the+ * application's asynchronous operations. The run() call may be kept running by+ * creating an executor that tracks work against the io_context:+ *+ * @code asio::io_context io_context;+ * auto work = asio::require(io_context.get_executor(),+ *     asio::execution::outstanding_work.tracked);+ * ... @endcode+ *+ * If using C++03, which lacks automatic variable type deduction, you may+ * compute the return type of the require call:+ *+ * @code asio::io_context io_context;+ * typename asio::require_result<+ *     asio::io_context::executor_type,+ *     asio::exeution::outstanding_work_t::tracked_t>+ *   work = asio::require(io_context.get_executor(),+ *     asio::execution::outstanding_work.tracked);+ * ... @endcode+ *+ * or store the result in the type-erasing executor wrapper, any_io_executor:+ *+ * @code asio::io_context io_context;+ * asio::any_io_executor work+ *   = asio::require(io_context.get_executor(),+ *       asio::execution::outstanding_work.tracked);+ * ... @endcode+ *+ * To effect a shutdown, the application will then need to call the io_context+ * object's stop() member function. This will cause the io_context run() call+ * to return as soon as possible, abandoning unfinished operations and without+ * permitting ready handlers to be dispatched.+ *+ * Alternatively, if the application requires that all operations and handlers+ * be allowed to finish normally, store the work-tracking executor in an+ * any_io_executor object, so that it may be explicitly reset.+ *+ * @code asio::io_context io_context;+ * asio::any_io_executor work+ *   = asio::require(io_context.get_executor(),+ *       asio::execution::outstanding_work.tracked);+ * ...+ * work = asio::any_io_executor(); // Allow run() to exit. @endcode+ */+class io_context+  : public execution_context+{+private:+  typedef detail::io_context_impl impl_type;+#if defined(ASIO_HAS_IOCP)+  friend class detail::win_iocp_overlapped_ptr;+#endif++public:+  template <typename Allocator, unsigned int Bits>+  class basic_executor_type;++  template <typename Allocator, unsigned int Bits>+  friend class basic_executor_type;++  /// Executor used to submit functions to an io_context.+  typedef basic_executor_type<std::allocator<void>, 0> executor_type;++#if !defined(ASIO_NO_DEPRECATED)+  class work;+  friend class work;+#endif // !defined(ASIO_NO_DEPRECATED)++  class service;++#if !defined(ASIO_NO_EXTENSIONS) \+  && !defined(ASIO_NO_TS_EXECUTORS)+  class strand;+#endif // !defined(ASIO_NO_EXTENSIONS)+       //   && !defined(ASIO_NO_TS_EXECUTORS)++  /// The type used to count the number of handlers executed by the context.+  typedef std::size_t count_type;++  /// Constructor.+  ASIO_DECL io_context();++  /// Constructor.+  /**+   * Construct with a hint about the required level of concurrency.+   *+   * @param concurrency_hint A suggestion to the implementation on how many+   * threads it should allow to run simultaneously.+   */+  ASIO_DECL explicit io_context(int concurrency_hint);++  /// Destructor.+  /**+   * On destruction, the io_context performs the following sequence of+   * operations:+   *+   * @li For each service object @c svc in the io_context set, in reverse order+   * of the beginning of service object lifetime, performs+   * @c svc->shutdown().+   *+   * @li Uninvoked handler objects that were scheduled for deferred invocation+   * on the io_context, or any associated strand, are destroyed.+   *+   * @li For each service object @c svc in the io_context set, in reverse order+   * of the beginning of service object lifetime, performs+   * <tt>delete static_cast<io_context::service*>(svc)</tt>.+   *+   * @note The destruction sequence described above permits programs to+   * simplify their resource management by using @c shared_ptr<>. Where an+   * object's lifetime is tied to the lifetime of a connection (or some other+   * sequence of asynchronous operations), a @c shared_ptr to the object would+   * be bound into the handlers for all asynchronous operations associated with+   * it. This works as follows:+   *+   * @li When a single connection ends, all associated asynchronous operations+   * complete. The corresponding handler objects are destroyed, and all+   * @c shared_ptr references to the objects are destroyed.+   *+   * @li To shut down the whole program, the io_context function stop() is+   * called to terminate any run() calls as soon as possible. The io_context+   * destructor defined above destroys all handlers, causing all @c shared_ptr+   * references to all connection objects to be destroyed.+   */+  ASIO_DECL ~io_context();++  /// Obtains the executor associated with the io_context.+  executor_type get_executor() ASIO_NOEXCEPT;++  /// Run the io_context object's event processing loop.+  /**+   * The run() function blocks until all work has finished and there are no+   * more handlers to be dispatched, or until the io_context has been stopped.+   *+   * Multiple threads may call the run() function to set up a pool of threads+   * from which the io_context may execute handlers. All threads that are+   * waiting in the pool are equivalent and the io_context may choose any one+   * of them to invoke a handler.+   *+   * A normal exit from the run() function implies that the io_context object+   * is stopped (the stopped() function returns @c true). Subsequent calls to+   * run(), run_one(), poll() or poll_one() will return immediately unless there+   * is a prior call to restart().+   *+   * @return The number of handlers that were executed.+   *+   * @note Calling the run() function from a thread that is currently calling+   * one of run(), run_one(), run_for(), run_until(), poll() or poll_one() on+   * the same io_context object may introduce the potential for deadlock. It is+   * the caller's reponsibility to avoid this.+   *+   * The poll() function may also be used to dispatch ready handlers, but+   * without blocking.+   */+  ASIO_DECL count_type run();++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use non-error_code overload.) Run the io_context object's+  /// event processing loop.+  /**+   * The run() function blocks until all work has finished and there are no+   * more handlers to be dispatched, or until the io_context has been stopped.+   *+   * Multiple threads may call the run() function to set up a pool of threads+   * from which the io_context may execute handlers. All threads that are+   * waiting in the pool are equivalent and the io_context may choose any one+   * of them to invoke a handler.+   *+   * A normal exit from the run() function implies that the io_context object+   * is stopped (the stopped() function returns @c true). Subsequent calls to+   * run(), run_one(), poll() or poll_one() will return immediately unless there+   * is a prior call to restart().+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @return The number of handlers that were executed.+   *+   * @note Calling the run() function from a thread that is currently calling+   * one of run(), run_one(), run_for(), run_until(), poll() or poll_one() on+   * the same io_context object may introduce the potential for deadlock. It is+   * the caller's reponsibility to avoid this.+   *+   * The poll() function may also be used to dispatch ready handlers, but+   * without blocking.+   */+  ASIO_DECL count_type run(asio::error_code& ec);+#endif // !defined(ASIO_NO_DEPRECATED)++#if defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)+  /// Run the io_context object's event processing loop for a specified+  /// duration.+  /**+   * The run_for() function blocks until all work has finished and there are no+   * more handlers to be dispatched, until the io_context has been stopped, or+   * until the specified duration has elapsed.+   *+   * @param rel_time The duration for which the call may block.+   *+   * @return The number of handlers that were executed.+   */+  template <typename Rep, typename Period>+  std::size_t run_for(const chrono::duration<Rep, Period>& rel_time);++  /// Run the io_context object's event processing loop until a specified time.+  /**+   * The run_until() function blocks until all work has finished and there are+   * no more handlers to be dispatched, until the io_context has been stopped,+   * or until the specified time has been reached.+   *+   * @param abs_time The time point until which the call may block.+   *+   * @return The number of handlers that were executed.+   */+  template <typename Clock, typename Duration>+  std::size_t run_until(const chrono::time_point<Clock, Duration>& abs_time);+#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)++  /// Run the io_context object's event processing loop to execute at most one+  /// handler.+  /**+   * The run_one() function blocks until one handler has been dispatched, or+   * until the io_context has been stopped.+   *+   * @return The number of handlers that were executed. A zero return value+   * implies that the io_context object is stopped (the stopped() function+   * returns @c true). Subsequent calls to run(), run_one(), poll() or+   * poll_one() will return immediately unless there is a prior call to+   * restart().+   *+   * @note Calling the run_one() function from a thread that is currently+   * calling one of run(), run_one(), run_for(), run_until(), poll() or+   * poll_one() on the same io_context object may introduce the potential for+   * deadlock. It is the caller's reponsibility to avoid this.+   */+  ASIO_DECL count_type run_one();++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use non-error_code overlaod.) Run the io_context object's+  /// event processing loop to execute at most one handler.+  /**+   * The run_one() function blocks until one handler has been dispatched, or+   * until the io_context has been stopped.+   *+   * @return The number of handlers that were executed. A zero return value+   * implies that the io_context object is stopped (the stopped() function+   * returns @c true). Subsequent calls to run(), run_one(), poll() or+   * poll_one() will return immediately unless there is a prior call to+   * restart().+   *+   * @return The number of handlers that were executed.+   *+   * @note Calling the run_one() function from a thread that is currently+   * calling one of run(), run_one(), run_for(), run_until(), poll() or+   * poll_one() on the same io_context object may introduce the potential for+   * deadlock. It is the caller's reponsibility to avoid this.+   */+  ASIO_DECL count_type run_one(asio::error_code& ec);+#endif // !defined(ASIO_NO_DEPRECATED)++#if defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)+  /// Run the io_context object's event processing loop for a specified duration+  /// to execute at most one handler.+  /**+   * The run_one_for() function blocks until one handler has been dispatched,+   * until the io_context has been stopped, or until the specified duration has+   * elapsed.+   *+   * @param rel_time The duration for which the call may block.+   *+   * @return The number of handlers that were executed.+   */+  template <typename Rep, typename Period>+  std::size_t run_one_for(const chrono::duration<Rep, Period>& rel_time);++  /// Run the io_context object's event processing loop until a specified time+  /// to execute at most one handler.+  /**+   * The run_one_until() function blocks until one handler has been dispatched,+   * until the io_context has been stopped, or until the specified time has+   * been reached.+   *+   * @param abs_time The time point until which the call may block.+   *+   * @return The number of handlers that were executed.+   */+  template <typename Clock, typename Duration>+  std::size_t run_one_until(+      const chrono::time_point<Clock, Duration>& abs_time);+#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)++  /// Run the io_context object's event processing loop to execute ready+  /// handlers.+  /**+   * The poll() function runs handlers that are ready to run, without blocking,+   * until the io_context has been stopped or there are no more ready handlers.+   *+   * @return The number of handlers that were executed.+   */+  ASIO_DECL count_type poll();++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use non-error_code overload.) Run the io_context object's+  /// event processing loop to execute ready handlers.+  /**+   * The poll() function runs handlers that are ready to run, without blocking,+   * until the io_context has been stopped or there are no more ready handlers.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @return The number of handlers that were executed.+   */+  ASIO_DECL count_type poll(asio::error_code& ec);+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Run the io_context object's event processing loop to execute one ready+  /// handler.+  /**+   * The poll_one() function runs at most one handler that is ready to run,+   * without blocking.+   *+   * @return The number of handlers that were executed.+   */+  ASIO_DECL count_type poll_one();++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use non-error_code overload.) Run the io_context object's+  /// event processing loop to execute one ready handler.+  /**+   * The poll_one() function runs at most one handler that is ready to run,+   * without blocking.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @return The number of handlers that were executed.+   */+  ASIO_DECL count_type poll_one(asio::error_code& ec);+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Stop the io_context object's event processing loop.+  /**+   * This function does not block, but instead simply signals the io_context to+   * stop. All invocations of its run() or run_one() member functions should+   * return as soon as possible. Subsequent calls to run(), run_one(), poll()+   * or poll_one() will return immediately until restart() is called.+   */+  ASIO_DECL void stop();++  /// Determine whether the io_context object has been stopped.+  /**+   * This function is used to determine whether an io_context object has been+   * stopped, either through an explicit call to stop(), or due to running out+   * of work. When an io_context object is stopped, calls to run(), run_one(),+   * poll() or poll_one() will return immediately without invoking any+   * handlers.+   *+   * @return @c true if the io_context object is stopped, otherwise @c false.+   */+  ASIO_DECL bool stopped() const;++  /// Restart the io_context in preparation for a subsequent run() invocation.+  /**+   * This function must be called prior to any second or later set of+   * invocations of the run(), run_one(), poll() or poll_one() functions when a+   * previous invocation of these functions returned due to the io_context+   * being stopped or running out of work. After a call to restart(), the+   * io_context object's stopped() function will return @c false.+   *+   * This function must not be called while there are any unfinished calls to+   * the run(), run_one(), poll() or poll_one() functions.+   */+  ASIO_DECL void restart();++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use restart().) Reset the io_context in preparation for a+  /// subsequent run() invocation.+  /**+   * This function must be called prior to any second or later set of+   * invocations of the run(), run_one(), poll() or poll_one() functions when a+   * previous invocation of these functions returned due to the io_context+   * being stopped or running out of work. After a call to restart(), the+   * io_context object's stopped() function will return @c false.+   *+   * This function must not be called while there are any unfinished calls to+   * the run(), run_one(), poll() or poll_one() functions.+   */+  void reset();++  /// (Deprecated: Use asio::dispatch().) Request the io_context to+  /// invoke the given handler.+  /**+   * This function is used to ask the io_context to execute the given handler.+   *+   * The io_context guarantees that the handler will only be called in a thread+   * in which the run(), run_one(), poll() or poll_one() member functions is+   * currently being invoked. The handler may be executed inside this function+   * if the guarantee can be met.+   *+   * @param handler The handler to be called. The io_context will make+   * a copy of the handler object as required. The function signature of the+   * handler must be: @code void handler(); @endcode+   *+   * @note This function throws an exception only if:+   *+   * @li the handler's @c asio_handler_allocate function; or+   *+   * @li the handler's copy constructor+   *+   * throws an exception.+   */+  template <typename LegacyCompletionHandler>+  ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+  dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler);++  /// (Deprecated: Use asio::post().) Request the io_context to invoke+  /// the given handler and return immediately.+  /**+   * This function is used to ask the io_context to execute the given handler,+   * but without allowing the io_context to call the handler from inside this+   * function.+   *+   * The io_context guarantees that the handler will only be called in a thread+   * in which the run(), run_one(), poll() or poll_one() member functions is+   * currently being invoked.+   *+   * @param handler The handler to be called. The io_context will make+   * a copy of the handler object as required. The function signature of the+   * handler must be: @code void handler(); @endcode+   *+   * @note This function throws an exception only if:+   *+   * @li the handler's @c asio_handler_allocate function; or+   *+   * @li the handler's copy constructor+   *+   * throws an exception.+   */+  template <typename LegacyCompletionHandler>+  ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+  post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler);++  /// (Deprecated: Use asio::bind_executor().) Create a new handler that+  /// automatically dispatches the wrapped handler on the io_context.+  /**+   * This function is used to create a new handler function object that, when+   * invoked, will automatically pass the wrapped handler to the io_context+   * object's dispatch function.+   *+   * @param handler The handler to be wrapped. The io_context will make a copy+   * of the handler object as required. The function signature of the handler+   * must be: @code void handler(A1 a1, ... An an); @endcode+   *+   * @return A function object that, when invoked, passes the wrapped handler to+   * the io_context object's dispatch function. Given a function object with the+   * signature:+   * @code R f(A1 a1, ... An an); @endcode+   * If this function object is passed to the wrap function like so:+   * @code io_context.wrap(f); @endcode+   * then the return value is a function object with the signature+   * @code void g(A1 a1, ... An an); @endcode+   * that, when invoked, executes code equivalent to:+   * @code io_context.dispatch(boost::bind(f, a1, ... an)); @endcode+   */+  template <typename Handler>+#if defined(GENERATING_DOCUMENTATION)+  unspecified+#else+  detail::wrapped_handler<io_context&, Handler>+#endif+  wrap(Handler handler);+#endif // !defined(ASIO_NO_DEPRECATED)++private:+  io_context(const io_context&) ASIO_DELETED;+  io_context& operator=(const io_context&) ASIO_DELETED;++#if !defined(ASIO_NO_DEPRECATED)+  struct initiate_dispatch;+  struct initiate_post;+#endif // !defined(ASIO_NO_DEPRECATED)++  // Helper function to add the implementation.+  ASIO_DECL impl_type& add_impl(impl_type* impl);++  // Backwards compatible overload for use with services derived from+  // io_context::service.+  template <typename Service>+  friend Service& use_service(io_context& ioc);++#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  detail::winsock_init<> init_;+#elif defined(__sun) || defined(__QNX__) || defined(__hpux) || defined(_AIX) \+  || defined(__osf__)+  detail::signal_init<> init_;+#endif++  // The implementation.+  impl_type& impl_;+};++namespace detail {++} // namespace detail++/// Executor implementation type used to submit functions to an io_context.+template <typename Allocator, unsigned int Bits>+class io_context::basic_executor_type : detail::io_context_bits+{+public:+  /// Copy constructor.+  basic_executor_type(+      const basic_executor_type& other) ASIO_NOEXCEPT+    : io_context_(other.io_context_),+      allocator_(other.allocator_),+      bits_(other.bits_)+  {+    if (Bits & outstanding_work_tracked)+      if (io_context_)+        io_context_->impl_.work_started();+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  basic_executor_type(basic_executor_type&& other) ASIO_NOEXCEPT+    : io_context_(other.io_context_),+      allocator_(ASIO_MOVE_CAST(Allocator)(other.allocator_)),+      bits_(other.bits_)+  {+    if (Bits & outstanding_work_tracked)+      other.io_context_ = 0;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  ~basic_executor_type() ASIO_NOEXCEPT+  {+    if (Bits & outstanding_work_tracked)+      if (io_context_)+        io_context_->impl_.work_finished();+  }++  /// Assignment operator.+  basic_executor_type& operator=(+      const basic_executor_type& other) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move assignment operator.+  basic_executor_type& operator=(+      basic_executor_type&& other) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Obtain an executor with the @c blocking.possibly property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_io_context.get_executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::blocking.possibly); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type require(+      execution::blocking_t::possibly_t) const+  {+    return basic_executor_type(io_context_,+        allocator_, bits_ & ~blocking_never);+  }++  /// Obtain an executor with the @c blocking.never property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_io_context.get_executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::blocking.never); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type require(+      execution::blocking_t::never_t) const+  {+    return basic_executor_type(io_context_,+        allocator_, bits_ | blocking_never);+  }++  /// Obtain an executor with the @c relationship.fork property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_io_context.get_executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::relationship.fork); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type require(+      execution::relationship_t::fork_t) const+  {+    return basic_executor_type(io_context_,+        allocator_, bits_ & ~relationship_continuation);+  }++  /// Obtain an executor with the @c relationship.continuation property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_io_context.get_executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::relationship.continuation); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type require(+      execution::relationship_t::continuation_t) const+  {+    return basic_executor_type(io_context_,+        allocator_, bits_ | relationship_continuation);+  }++  /// Obtain an executor with the @c outstanding_work.tracked property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_io_context.get_executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::outstanding_work.tracked); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type<Allocator,+      ASIO_UNSPECIFIED(Bits | outstanding_work_tracked)>+  require(execution::outstanding_work_t::tracked_t) const+  {+    return basic_executor_type<Allocator, Bits | outstanding_work_tracked>(+        io_context_, allocator_, bits_);+  }++  /// Obtain an executor with the @c outstanding_work.untracked property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_io_context.get_executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::outstanding_work.untracked); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type<Allocator,+      ASIO_UNSPECIFIED(Bits & ~outstanding_work_tracked)>+  require(execution::outstanding_work_t::untracked_t) const+  {+    return basic_executor_type<Allocator, Bits & ~outstanding_work_tracked>(+        io_context_, allocator_, bits_);+  }++  /// Obtain an executor with the specified @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_io_context.get_executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::allocator(my_allocator)); @endcode+   */+  template <typename OtherAllocator>+  ASIO_CONSTEXPR basic_executor_type<OtherAllocator, Bits>+  require(execution::allocator_t<OtherAllocator> a) const+  {+    return basic_executor_type<OtherAllocator, Bits>(+        io_context_, a.value(), bits_);+  }++  /// Obtain an executor with the default @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_io_context.get_executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::allocator); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type<std::allocator<void>, Bits>+  require(execution::allocator_t<void>) const+  {+    return basic_executor_type<std::allocator<void>, Bits>(+        io_context_, std::allocator<void>(), bits_);+  }++  /// Query the current value of the @c mapping property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_io_context.get_executor();+   * if (asio::query(ex, asio::execution::mapping)+   *       == asio::execution::mapping.thread)+   *   ... @endcode+   */+  static ASIO_CONSTEXPR execution::mapping_t query(+      execution::mapping_t) ASIO_NOEXCEPT+  {+    return execution::mapping.thread;+  }++  /// Query the current value of the @c context property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_io_context.get_executor();+   * asio::io_context& ctx = asio::query(+   *     ex, asio::execution::context); @endcode+   */+  io_context& query(execution::context_t) const ASIO_NOEXCEPT+  {+    return *io_context_;+  }++  /// Query the current value of the @c blocking property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_io_context.get_executor();+   * if (asio::query(ex, asio::execution::blocking)+   *       == asio::execution::blocking.always)+   *   ... @endcode+   */+  ASIO_CONSTEXPR execution::blocking_t query(+      execution::blocking_t) const ASIO_NOEXCEPT+  {+    return (bits_ & blocking_never)+      ? execution::blocking_t(execution::blocking.never)+      : execution::blocking_t(execution::blocking.possibly);+  }++  /// Query the current value of the @c relationship property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_io_context.get_executor();+   * if (asio::query(ex, asio::execution::relationship)+   *       == asio::execution::relationship.continuation)+   *   ... @endcode+   */+  ASIO_CONSTEXPR execution::relationship_t query(+      execution::relationship_t) const ASIO_NOEXCEPT+  {+    return (bits_ & relationship_continuation)+      ? execution::relationship_t(execution::relationship.continuation)+      : execution::relationship_t(execution::relationship.fork);+  }++  /// Query the current value of the @c outstanding_work property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_io_context.get_executor();+   * if (asio::query(ex, asio::execution::outstanding_work)+   *       == asio::execution::outstanding_work.tracked)+   *   ... @endcode+   */+  static ASIO_CONSTEXPR execution::outstanding_work_t query(+      execution::outstanding_work_t) ASIO_NOEXCEPT+  {+    return (Bits & outstanding_work_tracked)+      ? execution::outstanding_work_t(execution::outstanding_work.tracked)+      : execution::outstanding_work_t(execution::outstanding_work.untracked);+  }++  /// Query the current value of the @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_io_context.get_executor();+   * auto alloc = asio::query(ex,+   *     asio::execution::allocator); @endcode+   */+  template <typename OtherAllocator>+  ASIO_CONSTEXPR Allocator query(+      execution::allocator_t<OtherAllocator>) const ASIO_NOEXCEPT+  {+    return allocator_;+  }++  /// Query the current value of the @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_io_context.get_executor();+   * auto alloc = asio::query(ex,+   *     asio::execution::allocator); @endcode+   */+  ASIO_CONSTEXPR Allocator query(+      execution::allocator_t<void>) const ASIO_NOEXCEPT+  {+    return allocator_;+  }++  /// Determine whether the io_context is running in the current thread.+  /**+   * @return @c true if the current thread is running the io_context. Otherwise+   * returns @c false.+   */+  bool running_in_this_thread() const ASIO_NOEXCEPT;++  /// Compare two executors for equality.+  /**+   * Two executors are equal if they refer to the same underlying io_context.+   */+  friend bool operator==(const basic_executor_type& a,+      const basic_executor_type& b) ASIO_NOEXCEPT+  {+    return a.io_context_ == b.io_context_+      && a.allocator_ == b.allocator_+      && a.bits_ == b.bits_;+  }++  /// Compare two executors for inequality.+  /**+   * Two executors are equal if they refer to the same underlying io_context.+   */+  friend bool operator!=(const basic_executor_type& a,+      const basic_executor_type& b) ASIO_NOEXCEPT+  {+    return a.io_context_ != b.io_context_+      || a.allocator_ != b.allocator_+      || a.bits_ != b.bits_;+  }++  /// Execution function.+  /**+   * Do not call this function directly. It is intended for use with the+   * execution::execute customisation point.+   *+   * For example:+   * @code auto ex = my_io_context.get_executor();+   * execution::execute(ex, my_function_object); @endcode+   */+  template <typename Function>+  void execute(ASIO_MOVE_ARG(Function) f) const;++#if !defined(ASIO_NO_TS_EXECUTORS)+  /// Obtain the underlying execution context.+  io_context& context() const ASIO_NOEXCEPT;++  /// Inform the io_context that it has some outstanding work to do.+  /**+   * This function is used to inform the io_context that some work has begun.+   * This ensures that the io_context's run() and run_one() functions do not+   * exit while the work is underway.+   */+  void on_work_started() const ASIO_NOEXCEPT;++  /// Inform the io_context that some work is no longer outstanding.+  /**+   * This function is used to inform the io_context that some work has+   * finished. Once the count of unfinished work reaches zero, the io_context+   * is stopped and the run() and run_one() functions may exit.+   */+  void on_work_finished() const ASIO_NOEXCEPT;++  /// Request the io_context to invoke the given function object.+  /**+   * This function is used to ask the io_context to execute the given function+   * object. If the current thread is running the io_context, @c dispatch()+   * executes the function before returning. Otherwise, the function will be+   * scheduled to run on the io_context.+   *+   * @param f The function object to be called. The executor will make a copy+   * of the handler object as required. The function signature of the function+   * object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename OtherAllocator>+  void dispatch(ASIO_MOVE_ARG(Function) f,+      const OtherAllocator& a) const;++  /// Request the io_context to invoke the given function object.+  /**+   * This function is used to ask the io_context to execute the given function+   * object. The function object will never be executed inside @c post().+   * Instead, it will be scheduled to run on the io_context.+   *+   * @param f The function object to be called. The executor will make a copy+   * of the handler object as required. The function signature of the function+   * object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename OtherAllocator>+  void post(ASIO_MOVE_ARG(Function) f,+      const OtherAllocator& a) const;++  /// Request the io_context to invoke the given function object.+  /**+   * This function is used to ask the io_context to execute the given function+   * object. The function object will never be executed inside @c defer().+   * Instead, it will be scheduled to run on the io_context.+   *+   * If the current thread belongs to the io_context, @c defer() will delay+   * scheduling the function object until the current thread returns control to+   * the pool.+   *+   * @param f The function object to be called. The executor will make a copy+   * of the handler object as required. The function signature of the function+   * object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename OtherAllocator>+  void defer(ASIO_MOVE_ARG(Function) f,+      const OtherAllocator& a) const;+#endif // !defined(ASIO_NO_TS_EXECUTORS)++private:+  friend class io_context;+  template <typename, unsigned int> friend class basic_executor_type;++  // Constructor used by io_context::get_executor().+  explicit basic_executor_type(io_context& i) ASIO_NOEXCEPT+    : io_context_(&i),+      allocator_(),+      bits_(0)+  {+    if (Bits & outstanding_work_tracked)+      io_context_->impl_.work_started();+  }++  // Constructor used by require().+  basic_executor_type(io_context* i,+      const Allocator& a, unsigned int bits) ASIO_NOEXCEPT+    : io_context_(i),+      allocator_(a),+      bits_(bits)+  {+    if (Bits & outstanding_work_tracked)+      if (io_context_)+        io_context_->impl_.work_started();+  }++  // The underlying io_context.+  io_context* io_context_;++  // The allocator used for execution functions.+  Allocator allocator_;++  // The runtime-switched properties of the io_context executor.+  unsigned int bits_;+};++#if !defined(ASIO_NO_DEPRECATED)+/// (Deprecated: Use executor_work_guard.) Class to inform the io_context when+/// it has work to do.+/**+ * The work class is used to inform the io_context when work starts and+ * finishes. This ensures that the io_context object's run() function will not+ * exit while work is underway, and that it does exit when there is no+ * unfinished work remaining.+ *+ * The work class is copy-constructible so that it may be used as a data member+ * in a handler class. It is not assignable.+ */+class io_context::work+{+public:+  /// Constructor notifies the io_context that work is starting.+  /**+   * The constructor is used to inform the io_context that some work has begun.+   * This ensures that the io_context object's run() function will not exit+   * while the work is underway.+   */+  explicit work(asio::io_context& io_context);++  /// Copy constructor notifies the io_context that work is starting.+  /**+   * The constructor is used to inform the io_context that some work has begun.+   * This ensures that the io_context object's run() function will not exit+   * while the work is underway.+   */+  work(const work& other);++  /// Destructor notifies the io_context that the work is complete.+  /**+   * The destructor is used to inform the io_context that some work has+   * finished. Once the count of unfinished work reaches zero, the io_context+   * object's run() function is permitted to exit.+   */+  ~work();++  /// Get the io_context associated with the work.+  asio::io_context& get_io_context();++private:+  // Prevent assignment.+  void operator=(const work& other);++  // The io_context implementation.+  detail::io_context_impl& io_context_impl_;+};+#endif // !defined(ASIO_NO_DEPRECATED)++/// Base class for all io_context services.+class io_context::service+  : public execution_context::service+{+public:+  /// Get the io_context object that owns the service.+  asio::io_context& get_io_context();++private:+  /// Destroy all user-defined handler objects owned by the service.+  ASIO_DECL virtual void shutdown();++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use shutdown().) Destroy all user-defined handler objects+  /// owned by the service.+  ASIO_DECL virtual void shutdown_service();+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Handle notification of a fork-related event to perform any necessary+  /// housekeeping.+  /**+   * This function is not a pure virtual so that services only have to+   * implement it if necessary. The default implementation does nothing.+   */+  ASIO_DECL virtual void notify_fork(+      execution_context::fork_event event);++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use notify_fork().) Handle notification of a fork-related+  /// event to perform any necessary housekeeping.+  /**+   * This function is not a pure virtual so that services only have to+   * implement it if necessary. The default implementation does nothing.+   */+  ASIO_DECL virtual void fork_service(+      execution_context::fork_event event);+#endif // !defined(ASIO_NO_DEPRECATED)++protected:+  /// Constructor.+  /**+   * @param owner The io_context object that owns the service.+   */+  ASIO_DECL service(asio::io_context& owner);++  /// Destructor.+  ASIO_DECL virtual ~service();+};++namespace detail {++// Special service base class to keep classes header-file only.+template <typename Type>+class service_base+  : public asio::io_context::service+{+public:+  static asio::detail::service_id<Type> id;++  // Constructor.+  service_base(asio::io_context& io_context)+    : asio::io_context::service(io_context)+  {+  }+};++template <typename Type>+asio::detail::service_id<Type> service_base<Type>::id;++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <typename Allocator, unsigned int Bits>+struct equality_comparable<+    asio::io_context::basic_executor_type<Allocator, Bits>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits, typename Function>+struct execute_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    Function+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::blocking_t::possibly_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::io_context::basic_executor_type<+      Allocator, Bits> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::blocking_t::never_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::io_context::basic_executor_type<+      Allocator, Bits> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::relationship_t::fork_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::io_context::basic_executor_type<+      Allocator, Bits> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::relationship_t::continuation_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::io_context::basic_executor_type<+      Allocator, Bits> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::outstanding_work_t::tracked_t+  > : asio::detail::io_context_bits+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::io_context::basic_executor_type<+      Allocator, Bits | outstanding_work_tracked> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::outstanding_work_t::untracked_t+  > : asio::detail::io_context_bits+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::io_context::basic_executor_type<+      Allocator, Bits & ~outstanding_work_tracked> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::allocator_t<void>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::io_context::basic_executor_type<+      std::allocator<void>, Bits> result_type;+};++template <unsigned int Bits,+    typename Allocator, typename OtherAllocator>+struct require_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::allocator_t<OtherAllocator>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::io_context::basic_executor_type<+      OtherAllocator, Bits> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits, typename Property>+struct query_static_constexpr_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::outstanding_work_t+      >::value+    >::type+  > : asio::detail::io_context_bits+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::outstanding_work_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return (Bits & outstanding_work_tracked)+      ? execution::outstanding_work_t(execution::outstanding_work.tracked)+      : execution::outstanding_work_t(execution::outstanding_work.untracked);+  }+};++template <typename Allocator, unsigned int Bits, typename Property>+struct query_static_constexpr_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::mapping_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::mapping_t::thread_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits, typename Property>+struct query_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::blocking_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::blocking_t result_type;+};++template <typename Allocator, unsigned int Bits, typename Property>+struct query_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::relationship_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::relationship_t result_type;+};++template <typename Allocator, unsigned int Bits>+struct query_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::context_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::io_context& result_type;+};++template <typename Allocator, unsigned int Bits>+struct query_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::allocator_t<void>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef Allocator result_type;+};++template <typename Allocator, unsigned int Bits, typename OtherAllocator>+struct query_member<+    asio::io_context::basic_executor_type<Allocator, Bits>,+    asio::execution::allocator_t<OtherAllocator>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef Allocator result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++} // namespace traits++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/io_context.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/io_context.ipp"+#endif // defined(ASIO_HEADER_ONLY)++// If both io_context.hpp and strand.hpp have been included, automatically+// include the header file needed for the io_context::strand class.+#if !defined(ASIO_NO_EXTENSIONS)+# if defined(ASIO_STRAND_HPP)+#  include "asio/io_context_strand.hpp"+# endif // defined(ASIO_STRAND_HPP)+#endif // !defined(ASIO_NO_EXTENSIONS)++#endif // ASIO_IO_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/io_context_strand.hpp view
@@ -0,0 +1,376 @@+//+// io_context_strand.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IO_CONTEXT_STRAND_HPP+#define ASIO_IO_CONTEXT_STRAND_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_EXTENSIONS) \+  && !defined(ASIO_NO_TS_EXECUTORS)++#include "asio/async_result.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/strand_service.hpp"+#include "asio/detail/wrapped_handler.hpp"+#include "asio/io_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Provides serialised handler execution.+/**+ * The io_context::strand class provides the ability to post and dispatch+ * handlers with the guarantee that none of those handlers will execute+ * concurrently.+ *+ * @par Order of handler invocation+ * Given:+ *+ * @li a strand object @c s+ *+ * @li an object @c a meeting completion handler requirements+ *+ * @li an object @c a1 which is an arbitrary copy of @c a made by the+ * implementation+ *+ * @li an object @c b meeting completion handler requirements+ *+ * @li an object @c b1 which is an arbitrary copy of @c b made by the+ * implementation+ *+ * if any of the following conditions are true:+ *+ * @li @c s.post(a) happens-before @c s.post(b)+ * + * @li @c s.post(a) happens-before @c s.dispatch(b), where the latter is+ * performed outside the strand+ * + * @li @c s.dispatch(a) happens-before @c s.post(b), where the former is+ * performed outside the strand+ * + * @li @c s.dispatch(a) happens-before @c s.dispatch(b), where both are+ * performed outside the strand+ *   + * then @c asio_handler_invoke(a1, &a1) happens-before+ * @c asio_handler_invoke(b1, &b1).+ * + * Note that in the following case:+ * @code async_op_1(..., s.wrap(a));+ * async_op_2(..., s.wrap(b)); @endcode+ * the completion of the first async operation will perform @c s.dispatch(a),+ * and the second will perform @c s.dispatch(b), but the order in which those+ * are performed is unspecified. That is, you cannot state whether one+ * happens-before the other. Therefore none of the above conditions are met and+ * no ordering guarantee is made.+ *+ * @note The implementation makes no guarantee that handlers posted or+ * dispatched through different @c strand objects will be invoked concurrently.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Dispatcher.+ */+class io_context::strand+{+public:+  /// Constructor.+  /**+   * Constructs the strand.+   *+   * @param io_context The io_context object that the strand will use to+   * dispatch handlers that are ready to be run.+   */+  explicit strand(asio::io_context& io_context)+    : service_(asio::use_service<+        asio::detail::strand_service>(io_context))+  {+    service_.construct(impl_);+  }++  /// Destructor.+  /**+   * Destroys a strand.+   *+   * Handlers posted through the strand that have not yet been invoked will+   * still be dispatched in a way that meets the guarantee of non-concurrency.+   */+  ~strand()+  {+  }++  /// Obtain the underlying execution context.+  asio::io_context& context() const ASIO_NOEXCEPT+  {+    return service_.get_io_context();+  }++  /// Inform the strand that it has some outstanding work to do.+  /**+   * The strand delegates this call to its underlying io_context.+   */+  void on_work_started() const ASIO_NOEXCEPT+  {+    context().get_executor().on_work_started();+  }++  /// Inform the strand that some work is no longer outstanding.+  /**+   * The strand delegates this call to its underlying io_context.+   */+  void on_work_finished() const ASIO_NOEXCEPT+  {+    context().get_executor().on_work_finished();+  }++  /// Request the strand to invoke the given function object.+  /**+   * This function is used to ask the strand to execute the given function+   * object on its underlying io_context. The function object will be executed+   * inside this function if the strand is not otherwise busy and if the+   * underlying io_context's executor's @c dispatch() function is also able to+   * execute the function before returning.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename Allocator>+  void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const+  {+    typename decay<Function>::type tmp(ASIO_MOVE_CAST(Function)(f));+    service_.dispatch(impl_, tmp);+    (void)a;+  }++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use asio::dispatch().) Request the strand to invoke+  /// the given handler.+  /**+   * This function is used to ask the strand to execute the given handler.+   *+   * The strand object guarantees that handlers posted or dispatched through+   * the strand will not be executed concurrently. The handler may be executed+   * inside this function if the guarantee can be met. If this function is+   * called from within a handler that was posted or dispatched through the same+   * strand, then the new handler will be executed immediately.+   *+   * The strand's guarantee is in addition to the guarantee provided by the+   * underlying io_context. The io_context guarantees that the handler will only+   * be called in a thread in which the io_context's run member function is+   * currently being invoked.+   *+   * @param handler The handler to be called. The strand will make a copy of the+   * handler object as required. The function signature of the handler must be:+   * @code void handler(); @endcode+   */+  template <typename LegacyCompletionHandler>+  ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+  dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+  {+    return async_initiate<LegacyCompletionHandler, void ()>(+        initiate_dispatch(), handler, this);+  }+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Request the strand to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object will never be executed inside this function.+   * Instead, it will be scheduled to run by the underlying io_context.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename Allocator>+  void post(ASIO_MOVE_ARG(Function) f, const Allocator& a) const+  {+    typename decay<Function>::type tmp(ASIO_MOVE_CAST(Function)(f));+    service_.post(impl_, tmp);+    (void)a;+  }++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use asio::post().) Request the strand to invoke the+  /// given handler and return immediately.+  /**+   * This function is used to ask the strand to execute the given handler, but+   * without allowing the strand to call the handler from inside this function.+   *+   * The strand object guarantees that handlers posted or dispatched through+   * the strand will not be executed concurrently. The strand's guarantee is in+   * addition to the guarantee provided by the underlying io_context. The+   * io_context guarantees that the handler will only be called in a thread in+   * which the io_context's run member function is currently being invoked.+   *+   * @param handler The handler to be called. The strand will make a copy of the+   * handler object as required. The function signature of the handler must be:+   * @code void handler(); @endcode+   */+  template <typename LegacyCompletionHandler>+  ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+  post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+  {+    return async_initiate<LegacyCompletionHandler, void ()>(+        initiate_post(), handler, this);+  }+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Request the strand to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object will never be executed inside this function.+   * Instead, it will be scheduled to run by the underlying io_context.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename Allocator>+  void defer(ASIO_MOVE_ARG(Function) f, const Allocator& a) const+  {+    typename decay<Function>::type tmp(ASIO_MOVE_CAST(Function)(f));+    service_.post(impl_, tmp);+    (void)a;+  }++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use asio::bind_executor().) Create a new handler that+  /// automatically dispatches the wrapped handler on the strand.+  /**+   * This function is used to create a new handler function object that, when+   * invoked, will automatically pass the wrapped handler to the strand's+   * dispatch function.+   *+   * @param handler The handler to be wrapped. The strand will make a copy of+   * the handler object as required. The function signature of the handler must+   * be: @code void handler(A1 a1, ... An an); @endcode+   *+   * @return A function object that, when invoked, passes the wrapped handler to+   * the strand's dispatch function. Given a function object with the signature:+   * @code R f(A1 a1, ... An an); @endcode+   * If this function object is passed to the wrap function like so:+   * @code strand.wrap(f); @endcode+   * then the return value is a function object with the signature+   * @code void g(A1 a1, ... An an); @endcode+   * that, when invoked, executes code equivalent to:+   * @code strand.dispatch(boost::bind(f, a1, ... an)); @endcode+   */+  template <typename Handler>+#if defined(GENERATING_DOCUMENTATION)+  unspecified+#else+  detail::wrapped_handler<strand, Handler, detail::is_continuation_if_running>+#endif+  wrap(Handler handler)+  {+    return detail::wrapped_handler<io_context::strand, Handler,+        detail::is_continuation_if_running>(*this, handler);+  }+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Determine whether the strand is running in the current thread.+  /**+   * @return @c true if the current thread is executing a handler that was+   * submitted to the strand using post(), dispatch() or wrap(). Otherwise+   * returns @c false.+   */+  bool running_in_this_thread() const ASIO_NOEXCEPT+  {+    return service_.running_in_this_thread(impl_);+  }++  /// Compare two strands for equality.+  /**+   * Two strands are equal if they refer to the same ordered, non-concurrent+   * state.+   */+  friend bool operator==(const strand& a, const strand& b) ASIO_NOEXCEPT+  {+    return a.impl_ == b.impl_;+  }++  /// Compare two strands for inequality.+  /**+   * Two strands are equal if they refer to the same ordered, non-concurrent+   * state.+   */+  friend bool operator!=(const strand& a, const strand& b) ASIO_NOEXCEPT+  {+    return a.impl_ != b.impl_;+  }++private:+#if !defined(ASIO_NO_DEPRECATED)+  struct initiate_dispatch+  {+    template <typename LegacyCompletionHandler>+    void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler,+        strand* self) const+    {+      // If you get an error on the following line it means that your+      // handler does not meet the documented type requirements for a+      // LegacyCompletionHandler.+      ASIO_LEGACY_COMPLETION_HANDLER_CHECK(+          LegacyCompletionHandler, handler) type_check;++      detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler);+      self->service_.dispatch(self->impl_, handler2.value);+    }+  };++  struct initiate_post+  {+    template <typename LegacyCompletionHandler>+    void operator()(ASIO_MOVE_ARG(LegacyCompletionHandler) handler,+        strand* self) const+    {+      // If you get an error on the following line it means that your+      // handler does not meet the documented type requirements for a+      // LegacyCompletionHandler.+      ASIO_LEGACY_COMPLETION_HANDLER_CHECK(+          LegacyCompletionHandler, handler) type_check;++      detail::non_const_lvalue<LegacyCompletionHandler> handler2(handler);+      self->service_.post(self->impl_, handler2.value);+    }+  };+#endif // !defined(ASIO_NO_DEPRECATED)++  asio::detail::strand_service& service_;+  mutable asio::detail::strand_service::implementation_type impl_;+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_EXTENSIONS)+       //   && !defined(ASIO_NO_TS_EXECUTORS)++#endif // ASIO_IO_CONTEXT_STRAND_HPP
+ link/modules/asio-standalone/asio/include/asio/io_service.hpp view
@@ -0,0 +1,33 @@+//+// io_service.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IO_SERVICE_HPP+#define ASIO_IO_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/io_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_NO_DEPRECATED)+/// Typedef for backwards compatibility.+typedef io_context io_service;+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IO_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/io_service_strand.hpp view
@@ -0,0 +1,20 @@+//+// io_service_strand.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IO_SERVICE_STRAND_HPP+#define ASIO_IO_SERVICE_STRAND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/io_context_strand.hpp"++#endif // ASIO_IO_SERVICE_STRAND_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/address.hpp view
@@ -0,0 +1,268 @@+//+// ip/address.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_ADDRESS_HPP+#define ASIO_IP_ADDRESS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/detail/throw_exception.hpp"+#include "asio/detail/string_view.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error_code.hpp"+#include "asio/ip/address_v4.hpp"+#include "asio/ip/address_v6.hpp"+#include "asio/ip/bad_address_cast.hpp"++#if !defined(ASIO_NO_IOSTREAM)+# include <iosfwd>+#endif // !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Implements version-independent IP addresses.+/**+ * The asio::ip::address class provides the ability to use either IP+ * version 4 or version 6 addresses.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+class address+{+public:+  /// Default constructor.+  ASIO_DECL address() ASIO_NOEXCEPT;++  /// Construct an address from an IPv4 address.+  ASIO_DECL address(+      const asio::ip::address_v4& ipv4_address) ASIO_NOEXCEPT;++  /// Construct an address from an IPv6 address.+  ASIO_DECL address(+      const asio::ip::address_v6& ipv6_address) ASIO_NOEXCEPT;++  /// Copy constructor.+  ASIO_DECL address(const address& other) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  ASIO_DECL address(address&& other) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE)++  /// Assign from another address.+  ASIO_DECL address& operator=(const address& other) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE)+  /// Move-assign from another address.+  ASIO_DECL address& operator=(address&& other) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE)++  /// Assign from an IPv4 address.+  ASIO_DECL address& operator=(+      const asio::ip::address_v4& ipv4_address) ASIO_NOEXCEPT;++  /// Assign from an IPv6 address.+  ASIO_DECL address& operator=(+      const asio::ip::address_v6& ipv6_address) ASIO_NOEXCEPT;++  /// Get whether the address is an IP version 4 address.+  bool is_v4() const ASIO_NOEXCEPT+  {+    return type_ == ipv4;+  }++  /// Get whether the address is an IP version 6 address.+  bool is_v6() const ASIO_NOEXCEPT+  {+    return type_ == ipv6;+  }++  /// Get the address as an IP version 4 address.+  ASIO_DECL asio::ip::address_v4 to_v4() const;++  /// Get the address as an IP version 6 address.+  ASIO_DECL asio::ip::address_v6 to_v6() const;++  /// Get the address as a string.+  ASIO_DECL std::string to_string() const;++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use other overload.) Get the address as a string.+  ASIO_DECL std::string to_string(asio::error_code& ec) const;++  /// (Deprecated: Use make_address().) Create an address from an IPv4 address+  /// string in dotted decimal form, or from an IPv6 address in hexadecimal+  /// notation.+  static address from_string(const char* str);++  /// (Deprecated: Use make_address().) Create an address from an IPv4 address+  /// string in dotted decimal form, or from an IPv6 address in hexadecimal+  /// notation.+  static address from_string(const char* str, asio::error_code& ec);++  /// (Deprecated: Use make_address().) Create an address from an IPv4 address+  /// string in dotted decimal form, or from an IPv6 address in hexadecimal+  /// notation.+  static address from_string(const std::string& str);++  /// (Deprecated: Use make_address().) Create an address from an IPv4 address+  /// string in dotted decimal form, or from an IPv6 address in hexadecimal+  /// notation.+  static address from_string(+      const std::string& str, asio::error_code& ec);+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Determine whether the address is a loopback address.+  ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT;++  /// Determine whether the address is unspecified.+  ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT;++  /// Determine whether the address is a multicast address.+  ASIO_DECL bool is_multicast() const ASIO_NOEXCEPT;++  /// Compare two addresses for equality.+  ASIO_DECL friend bool operator==(const address& a1,+      const address& a2) ASIO_NOEXCEPT;++  /// Compare two addresses for inequality.+  friend bool operator!=(const address& a1,+      const address& a2) ASIO_NOEXCEPT+  {+    return !(a1 == a2);+  }++  /// Compare addresses for ordering.+  ASIO_DECL friend bool operator<(const address& a1,+      const address& a2) ASIO_NOEXCEPT;++  /// Compare addresses for ordering.+  friend bool operator>(const address& a1,+      const address& a2) ASIO_NOEXCEPT+  {+    return a2 < a1;+  }++  /// Compare addresses for ordering.+  friend bool operator<=(const address& a1,+      const address& a2) ASIO_NOEXCEPT+  {+    return !(a2 < a1);+  }++  /// Compare addresses for ordering.+  friend bool operator>=(const address& a1,+      const address& a2) ASIO_NOEXCEPT+  {+    return !(a1 < a2);+  }++private:+  // The type of the address.+  enum { ipv4, ipv6 } type_;++  // The underlying IPv4 address.+  asio::ip::address_v4 ipv4_address_;++  // The underlying IPv6 address.+  asio::ip::address_v6 ipv6_address_;+};++/// Create an address from an IPv4 address string in dotted decimal form,+/// or from an IPv6 address in hexadecimal notation.+/**+ * @relates address+ */+ASIO_DECL address make_address(const char* str);++/// Create an address from an IPv4 address string in dotted decimal form,+/// or from an IPv6 address in hexadecimal notation.+/**+ * @relates address+ */+ASIO_DECL address make_address(const char* str,+    asio::error_code& ec) ASIO_NOEXCEPT;++/// Create an address from an IPv4 address string in dotted decimal form,+/// or from an IPv6 address in hexadecimal notation.+/**+ * @relates address+ */+ASIO_DECL address make_address(const std::string& str);++/// Create an address from an IPv4 address string in dotted decimal form,+/// or from an IPv6 address in hexadecimal notation.+/**+ * @relates address+ */+ASIO_DECL address make_address(const std::string& str,+    asio::error_code& ec) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_STRING_VIEW) \+  || defined(GENERATING_DOCUMENTATION)++/// Create an address from an IPv4 address string in dotted decimal form,+/// or from an IPv6 address in hexadecimal notation.+/**+ * @relates address+ */+ASIO_DECL address make_address(string_view str);++/// Create an address from an IPv4 address string in dotted decimal form,+/// or from an IPv6 address in hexadecimal notation.+/**+ * @relates address+ */+ASIO_DECL address make_address(string_view str,+    asio::error_code& ec) ASIO_NOEXCEPT;++#endif // defined(ASIO_HAS_STRING_VIEW)+       //  || defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_NO_IOSTREAM)++/// Output an address as a string.+/**+ * Used to output a human-readable string for a specified address.+ *+ * @param os The output stream to which the string will be written.+ *+ * @param addr The address to be written.+ *+ * @return The output stream.+ *+ * @relates asio::ip::address+ */+template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const address& addr);++#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/ip/impl/address.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/ip/impl/address.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_IP_ADDRESS_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/address_v4.hpp view
@@ -0,0 +1,335 @@+//+// ip/address_v4.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_ADDRESS_V4_HPP+#define ASIO_IP_ADDRESS_V4_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/detail/array.hpp"+#include "asio/detail/cstdint.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/string_view.hpp"+#include "asio/detail/winsock_init.hpp"+#include "asio/error_code.hpp"++#if !defined(ASIO_NO_IOSTREAM)+# include <iosfwd>+#endif // !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Implements IP version 4 style addresses.+/**+ * The asio::ip::address_v4 class provides the ability to use and+ * manipulate IP version 4 addresses.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+class address_v4+{+public:+  /// The type used to represent an address as an unsigned integer.+  typedef uint_least32_t uint_type;++  /// The type used to represent an address as an array of bytes.+  /**+   * @note This type is defined in terms of the C++0x template @c std::array+   * when it is available. Otherwise, it uses @c boost:array.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef array<unsigned char, 4> bytes_type;+#else+  typedef asio::detail::array<unsigned char, 4> bytes_type;+#endif++  /// Default constructor.+  address_v4() ASIO_NOEXCEPT+  {+    addr_.s_addr = 0;+  }++  /// Construct an address from raw bytes.+  ASIO_DECL explicit address_v4(const bytes_type& bytes);++  /// Construct an address from an unsigned integer in host byte order.+  ASIO_DECL explicit address_v4(uint_type addr);++  /// Copy constructor.+  address_v4(const address_v4& other) ASIO_NOEXCEPT+    : addr_(other.addr_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  address_v4(address_v4&& other) ASIO_NOEXCEPT+    : addr_(other.addr_)+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Assign from another address.+  address_v4& operator=(const address_v4& other) ASIO_NOEXCEPT+  {+    addr_ = other.addr_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  /// Move-assign from another address.+  address_v4& operator=(address_v4&& other) ASIO_NOEXCEPT+  {+    addr_ = other.addr_;+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Get the address in bytes, in network byte order.+  ASIO_DECL bytes_type to_bytes() const ASIO_NOEXCEPT;++  /// Get the address as an unsigned integer in host byte order+  ASIO_DECL uint_type to_uint() const ASIO_NOEXCEPT;++#if !defined(ASIO_NO_DEPRECATED)+  /// Get the address as an unsigned long in host byte order+  ASIO_DECL unsigned long to_ulong() const;+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Get the address as a string in dotted decimal format.+  ASIO_DECL std::string to_string() const;++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use other overload.) Get the address as a string in dotted+  /// decimal format.+  ASIO_DECL std::string to_string(asio::error_code& ec) const;++  /// (Deprecated: Use make_address_v4().) Create an address from an IP address+  /// string in dotted decimal form.+  static address_v4 from_string(const char* str);++  /// (Deprecated: Use make_address_v4().) Create an address from an IP address+  /// string in dotted decimal form.+  static address_v4 from_string(+      const char* str, asio::error_code& ec);++  /// (Deprecated: Use make_address_v4().) Create an address from an IP address+  /// string in dotted decimal form.+  static address_v4 from_string(const std::string& str);++  /// (Deprecated: Use make_address_v4().) Create an address from an IP address+  /// string in dotted decimal form.+  static address_v4 from_string(+      const std::string& str, asio::error_code& ec);+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Determine whether the address is a loopback address.+  ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT;++  /// Determine whether the address is unspecified.+  ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT;++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use network_v4 class.) Determine whether the address is a+  /// class A address.+  ASIO_DECL bool is_class_a() const;++  /// (Deprecated: Use network_v4 class.) Determine whether the address is a+  /// class B address.+  ASIO_DECL bool is_class_b() const;++  /// (Deprecated: Use network_v4 class.) Determine whether the address is a+  /// class C address.+  ASIO_DECL bool is_class_c() const;+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Determine whether the address is a multicast address.+  ASIO_DECL bool is_multicast() const ASIO_NOEXCEPT;++  /// Compare two addresses for equality.+  friend bool operator==(const address_v4& a1,+      const address_v4& a2) ASIO_NOEXCEPT+  {+    return a1.addr_.s_addr == a2.addr_.s_addr;+  }++  /// Compare two addresses for inequality.+  friend bool operator!=(const address_v4& a1,+      const address_v4& a2) ASIO_NOEXCEPT+  {+    return a1.addr_.s_addr != a2.addr_.s_addr;+  }++  /// Compare addresses for ordering.+  friend bool operator<(const address_v4& a1,+      const address_v4& a2) ASIO_NOEXCEPT+  {+    return a1.to_uint() < a2.to_uint();+  }++  /// Compare addresses for ordering.+  friend bool operator>(const address_v4& a1,+      const address_v4& a2) ASIO_NOEXCEPT+  {+    return a1.to_uint() > a2.to_uint();+  }++  /// Compare addresses for ordering.+  friend bool operator<=(const address_v4& a1,+      const address_v4& a2) ASIO_NOEXCEPT+  {+    return a1.to_uint() <= a2.to_uint();+  }++  /// Compare addresses for ordering.+  friend bool operator>=(const address_v4& a1,+      const address_v4& a2) ASIO_NOEXCEPT+  {+    return a1.to_uint() >= a2.to_uint();+  }++  /// Obtain an address object that represents any address.+  static address_v4 any() ASIO_NOEXCEPT+  {+    return address_v4();+  }++  /// Obtain an address object that represents the loopback address.+  static address_v4 loopback() ASIO_NOEXCEPT+  {+    return address_v4(0x7F000001);+  }++  /// Obtain an address object that represents the broadcast address.+  static address_v4 broadcast() ASIO_NOEXCEPT+  {+    return address_v4(0xFFFFFFFF);+  }++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use network_v4 class.) Obtain an address object that+  /// represents the broadcast address that corresponds to the specified+  /// address and netmask.+  ASIO_DECL static address_v4 broadcast(+      const address_v4& addr, const address_v4& mask);++  /// (Deprecated: Use network_v4 class.) Obtain the netmask that corresponds+  /// to the address, based on its address class.+  ASIO_DECL static address_v4 netmask(const address_v4& addr);+#endif // !defined(ASIO_NO_DEPRECATED)++private:+  // The underlying IPv4 address.+  asio::detail::in4_addr_type addr_;+};++/// Create an IPv4 address from raw bytes in network order.+/**+ * @relates address_v4+ */+inline address_v4 make_address_v4(const address_v4::bytes_type& bytes)+{+  return address_v4(bytes);+}++/// Create an IPv4 address from an unsigned integer in host byte order.+/**+ * @relates address_v4+ */+inline address_v4 make_address_v4(address_v4::uint_type addr)+{+  return address_v4(addr);+}++/// Create an IPv4 address from an IP address string in dotted decimal form.+/**+ * @relates address_v4+ */+ASIO_DECL address_v4 make_address_v4(const char* str);++/// Create an IPv4 address from an IP address string in dotted decimal form.+/**+ * @relates address_v4+ */+ASIO_DECL address_v4 make_address_v4(const char* str,+    asio::error_code& ec) ASIO_NOEXCEPT;++/// Create an IPv4 address from an IP address string in dotted decimal form.+/**+ * @relates address_v4+ */+ASIO_DECL address_v4 make_address_v4(const std::string& str);++/// Create an IPv4 address from an IP address string in dotted decimal form.+/**+ * @relates address_v4+ */+ASIO_DECL address_v4 make_address_v4(const std::string& str,+    asio::error_code& ec) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_STRING_VIEW) \+  || defined(GENERATING_DOCUMENTATION)++/// Create an IPv4 address from an IP address string in dotted decimal form.+/**+ * @relates address_v4+ */+ASIO_DECL address_v4 make_address_v4(string_view str);++/// Create an IPv4 address from an IP address string in dotted decimal form.+/**+ * @relates address_v4+ */+ASIO_DECL address_v4 make_address_v4(string_view str,+    asio::error_code& ec) ASIO_NOEXCEPT;++#endif // defined(ASIO_HAS_STRING_VIEW)+       //  || defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_NO_IOSTREAM)++/// Output an address as a string.+/**+ * Used to output a human-readable string for a specified address.+ *+ * @param os The output stream to which the string will be written.+ *+ * @param addr The address to be written.+ *+ * @return The output stream.+ *+ * @relates asio::ip::address_v4+ */+template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const address_v4& addr);++#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/ip/impl/address_v4.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/ip/impl/address_v4.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_IP_ADDRESS_V4_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/address_v4_iterator.hpp view
@@ -0,0 +1,162 @@+//+// ip/address_v4_iterator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_ADDRESS_V4_ITERATOR_HPP+#define ASIO_IP_ADDRESS_V4_ITERATOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/ip/address_v4.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++template <typename> class basic_address_iterator;++/// An input iterator that can be used for traversing IPv4 addresses.+/**+ * In addition to satisfying the input iterator requirements, this iterator+ * also supports decrement.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <> class basic_address_iterator<address_v4>+{+public:+  /// The type of the elements pointed to by the iterator.+  typedef address_v4 value_type;++  /// Distance between two iterators.+  typedef std::ptrdiff_t difference_type;++  /// The type of a pointer to an element pointed to by the iterator.+  typedef const address_v4* pointer;++  /// The type of a reference to an element pointed to by the iterator.+  typedef const address_v4& reference;++  /// Denotes that the iterator satisfies the input iterator requirements.+  typedef std::input_iterator_tag iterator_category;++  /// Construct an iterator that points to the specified address.+  basic_address_iterator(const address_v4& addr) ASIO_NOEXCEPT+    : address_(addr)+  {+  }++  /// Copy constructor.+  basic_address_iterator(+      const basic_address_iterator& other) ASIO_NOEXCEPT+    : address_(other.address_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  basic_address_iterator(basic_address_iterator&& other) ASIO_NOEXCEPT+    : address_(ASIO_MOVE_CAST(address_v4)(other.address_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Assignment operator.+  basic_address_iterator& operator=(+      const basic_address_iterator& other) ASIO_NOEXCEPT+  {+    address_ = other.address_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  /// Move assignment operator.+  basic_address_iterator& operator=(+      basic_address_iterator&& other) ASIO_NOEXCEPT+  {+    address_ = ASIO_MOVE_CAST(address_v4)(other.address_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Dereference the iterator.+  const address_v4& operator*() const ASIO_NOEXCEPT+  {+    return address_;+  }++  /// Dereference the iterator.+  const address_v4* operator->() const ASIO_NOEXCEPT+  {+    return &address_;+  }++  /// Pre-increment operator.+  basic_address_iterator& operator++() ASIO_NOEXCEPT+  {+    address_ = address_v4((address_.to_uint() + 1) & 0xFFFFFFFF);+    return *this;+  }++  /// Post-increment operator.+  basic_address_iterator operator++(int) ASIO_NOEXCEPT+  {+    basic_address_iterator tmp(*this);+    ++*this;+    return tmp;+  }++  /// Pre-decrement operator.+  basic_address_iterator& operator--() ASIO_NOEXCEPT+  {+    address_ = address_v4((address_.to_uint() - 1) & 0xFFFFFFFF);+    return *this;+  }++  /// Post-decrement operator.+  basic_address_iterator operator--(int)+  {+    basic_address_iterator tmp(*this);+    --*this;+    return tmp;+  }++  /// Compare two addresses for equality.+  friend bool operator==(const basic_address_iterator& a,+      const basic_address_iterator& b)+  {+    return a.address_ == b.address_;+  }++  /// Compare two addresses for inequality.+  friend bool operator!=(const basic_address_iterator& a,+      const basic_address_iterator& b)+  {+    return a.address_ != b.address_;+  }++private:+  address_v4 address_;+};++/// An input iterator that can be used for traversing IPv4 addresses.+typedef basic_address_iterator<address_v4> address_v4_iterator;++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_ADDRESS_V4_ITERATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/address_v4_range.hpp view
@@ -0,0 +1,134 @@+//+// ip/address_v4_range.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_ADDRESS_V4_RANGE_HPP+#define ASIO_IP_ADDRESS_V4_RANGE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/ip/address_v4_iterator.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++template <typename> class basic_address_range;++/// Represents a range of IPv4 addresses.+/**+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <> class basic_address_range<address_v4>+{+public:+  /// The type of an iterator that points into the range.+  typedef basic_address_iterator<address_v4> iterator;++  /// Construct an empty range.+  basic_address_range() ASIO_NOEXCEPT+    : begin_(address_v4()),+      end_(address_v4())+  {+  }++  /// Construct an range that represents the given range of addresses.+  explicit basic_address_range(const iterator& first,+      const iterator& last) ASIO_NOEXCEPT+    : begin_(first),+      end_(last)+  {+  }++  /// Copy constructor.+  basic_address_range(const basic_address_range& other) ASIO_NOEXCEPT+    : begin_(other.begin_),+      end_(other.end_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  basic_address_range(basic_address_range&& other) ASIO_NOEXCEPT+    : begin_(ASIO_MOVE_CAST(iterator)(other.begin_)),+      end_(ASIO_MOVE_CAST(iterator)(other.end_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Assignment operator.+  basic_address_range& operator=(+      const basic_address_range& other) ASIO_NOEXCEPT+  {+    begin_ = other.begin_;+    end_ = other.end_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  /// Move assignment operator.+  basic_address_range& operator=(+      basic_address_range&& other) ASIO_NOEXCEPT+  {+    begin_ = ASIO_MOVE_CAST(iterator)(other.begin_);+    end_ = ASIO_MOVE_CAST(iterator)(other.end_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Obtain an iterator that points to the start of the range.+  iterator begin() const ASIO_NOEXCEPT+  {+    return begin_;+  }++  /// Obtain an iterator that points to the end of the range.+  iterator end() const ASIO_NOEXCEPT+  {+    return end_;+  }++  /// Determine whether the range is empty.+  bool empty() const ASIO_NOEXCEPT+  {+    return size() == 0;+  }++  /// Return the size of the range.+  std::size_t size() const ASIO_NOEXCEPT+  {+    return end_->to_uint() - begin_->to_uint();+  }++  /// Find an address in the range.+  iterator find(const address_v4& addr) const ASIO_NOEXCEPT+  {+    return addr >= *begin_ && addr < *end_ ? iterator(addr) : end_;+  }++private:+  iterator begin_;+  iterator end_;+};++/// Represents a range of IPv4 addresses.+typedef basic_address_range<address_v4> address_v4_range;++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_ADDRESS_V4_RANGE_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/address_v6.hpp view
@@ -0,0 +1,341 @@+//+// ip/address_v6.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_ADDRESS_V6_HPP+#define ASIO_IP_ADDRESS_V6_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/detail/array.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/string_view.hpp"+#include "asio/detail/winsock_init.hpp"+#include "asio/error_code.hpp"+#include "asio/ip/address_v4.hpp"++#if !defined(ASIO_NO_IOSTREAM)+# include <iosfwd>+#endif // !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++template <typename> class basic_address_iterator;++/// Implements IP version 6 style addresses.+/**+ * The asio::ip::address_v6 class provides the ability to use and+ * manipulate IP version 6 addresses.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+class address_v6+{+public:+  /// The type used to represent an address as an array of bytes.+  /**+   * @note This type is defined in terms of the C++0x template @c std::array+   * when it is available. Otherwise, it uses @c boost:array.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef array<unsigned char, 16> bytes_type;+#else+  typedef asio::detail::array<unsigned char, 16> bytes_type;+#endif++  /// Default constructor.+  ASIO_DECL address_v6() ASIO_NOEXCEPT;++  /// Construct an address from raw bytes and scope ID.+  ASIO_DECL explicit address_v6(const bytes_type& bytes,+      unsigned long scope_id = 0);++  /// Copy constructor.+  ASIO_DECL address_v6(const address_v6& other) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  ASIO_DECL address_v6(address_v6&& other) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE)++  /// Assign from another address.+  ASIO_DECL address_v6& operator=(+      const address_v6& other) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE)+  /// Move-assign from another address.+  ASIO_DECL address_v6& operator=(address_v6&& other) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE)++  /// The scope ID of the address.+  /**+   * Returns the scope ID associated with the IPv6 address.+   */+  unsigned long scope_id() const ASIO_NOEXCEPT+  {+    return scope_id_;+  }++  /// The scope ID of the address.+  /**+   * Modifies the scope ID associated with the IPv6 address.+   */+  void scope_id(unsigned long id) ASIO_NOEXCEPT+  {+    scope_id_ = id;+  }++  /// Get the address in bytes, in network byte order.+  ASIO_DECL bytes_type to_bytes() const ASIO_NOEXCEPT;++  /// Get the address as a string.+  ASIO_DECL std::string to_string() const;++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use other overload.) Get the address as a string.+  ASIO_DECL std::string to_string(asio::error_code& ec) const;++  /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP+  /// address string.+  static address_v6 from_string(const char* str);++  /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP+  /// address string.+  static address_v6 from_string(+      const char* str, asio::error_code& ec);++  /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP+  /// address string.+  static address_v6 from_string(const std::string& str);++  /// (Deprecated: Use make_address_v6().) Create an IPv6 address from an IP+  /// address string.+  static address_v6 from_string(+      const std::string& str, asio::error_code& ec);++  /// (Deprecated: Use make_address_v4().) Converts an IPv4-mapped or+  /// IPv4-compatible address to an IPv4 address.+  ASIO_DECL address_v4 to_v4() const;+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Determine whether the address is a loopback address.+  ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT;++  /// Determine whether the address is unspecified.+  ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT;++  /// Determine whether the address is link local.+  ASIO_DECL bool is_link_local() const ASIO_NOEXCEPT;++  /// Determine whether the address is site local.+  ASIO_DECL bool is_site_local() const ASIO_NOEXCEPT;++  /// Determine whether the address is a mapped IPv4 address.+  ASIO_DECL bool is_v4_mapped() const ASIO_NOEXCEPT;++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: No replacement.) Determine whether the address is an+  /// IPv4-compatible address.+  ASIO_DECL bool is_v4_compatible() const;+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Determine whether the address is a multicast address.+  ASIO_DECL bool is_multicast() const ASIO_NOEXCEPT;++  /// Determine whether the address is a global multicast address.+  ASIO_DECL bool is_multicast_global() const ASIO_NOEXCEPT;++  /// Determine whether the address is a link-local multicast address.+  ASIO_DECL bool is_multicast_link_local() const ASIO_NOEXCEPT;++  /// Determine whether the address is a node-local multicast address.+  ASIO_DECL bool is_multicast_node_local() const ASIO_NOEXCEPT;++  /// Determine whether the address is a org-local multicast address.+  ASIO_DECL bool is_multicast_org_local() const ASIO_NOEXCEPT;++  /// Determine whether the address is a site-local multicast address.+  ASIO_DECL bool is_multicast_site_local() const ASIO_NOEXCEPT;++  /// Compare two addresses for equality.+  ASIO_DECL friend bool operator==(const address_v6& a1,+      const address_v6& a2) ASIO_NOEXCEPT;++  /// Compare two addresses for inequality.+  friend bool operator!=(const address_v6& a1,+      const address_v6& a2) ASIO_NOEXCEPT+  {+    return !(a1 == a2);+  }++  /// Compare addresses for ordering.+  ASIO_DECL friend bool operator<(const address_v6& a1,+      const address_v6& a2) ASIO_NOEXCEPT;++  /// Compare addresses for ordering.+  friend bool operator>(const address_v6& a1,+      const address_v6& a2) ASIO_NOEXCEPT+  {+    return a2 < a1;+  }++  /// Compare addresses for ordering.+  friend bool operator<=(const address_v6& a1,+      const address_v6& a2) ASIO_NOEXCEPT+  {+    return !(a2 < a1);+  }++  /// Compare addresses for ordering.+  friend bool operator>=(const address_v6& a1,+      const address_v6& a2) ASIO_NOEXCEPT+  {+    return !(a1 < a2);+  }++  /// Obtain an address object that represents any address.+  static address_v6 any() ASIO_NOEXCEPT+  {+    return address_v6();+  }++  /// Obtain an address object that represents the loopback address.+  ASIO_DECL static address_v6 loopback() ASIO_NOEXCEPT;++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use make_address_v6().) Create an IPv4-mapped IPv6 address.+  ASIO_DECL static address_v6 v4_mapped(const address_v4& addr);++  /// (Deprecated: No replacement.) Create an IPv4-compatible IPv6 address.+  ASIO_DECL static address_v6 v4_compatible(const address_v4& addr);+#endif // !defined(ASIO_NO_DEPRECATED)++private:+  friend class basic_address_iterator<address_v6>;++  // The underlying IPv6 address.+  asio::detail::in6_addr_type addr_;++  // The scope ID associated with the address.+  unsigned long scope_id_;+};++/// Create an IPv6 address from raw bytes and scope ID.+/**+ * @relates address_v6+ */+inline address_v6 make_address_v6(const address_v6::bytes_type& bytes,+    unsigned long scope_id = 0)+{+  return address_v6(bytes, scope_id);+}++/// Create an IPv6 address from an IP address string.+/**+ * @relates address_v6+ */+ASIO_DECL address_v6 make_address_v6(const char* str);++/// Create an IPv6 address from an IP address string.+/**+ * @relates address_v6+ */+ASIO_DECL address_v6 make_address_v6(const char* str,+    asio::error_code& ec) ASIO_NOEXCEPT;++/// Createan IPv6 address from an IP address string.+/**+ * @relates address_v6+ */+ASIO_DECL address_v6 make_address_v6(const std::string& str);++/// Create an IPv6 address from an IP address string.+/**+ * @relates address_v6+ */+ASIO_DECL address_v6 make_address_v6(const std::string& str,+    asio::error_code& ec) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_STRING_VIEW) \+  || defined(GENERATING_DOCUMENTATION)++/// Create an IPv6 address from an IP address string.+/**+ * @relates address_v6+ */+ASIO_DECL address_v6 make_address_v6(string_view str);++/// Create an IPv6 address from an IP address string.+/**+ * @relates address_v6+ */+ASIO_DECL address_v6 make_address_v6(string_view str,+    asio::error_code& ec) ASIO_NOEXCEPT;++#endif // defined(ASIO_HAS_STRING_VIEW)+       //  || defined(GENERATING_DOCUMENTATION)++/// Tag type used for distinguishing overloads that deal in IPv4-mapped IPv6+/// addresses.+enum v4_mapped_t { v4_mapped };++/// Create an IPv4 address from a IPv4-mapped IPv6 address.+/**+ * @relates address_v4+ */+ASIO_DECL address_v4 make_address_v4(+    v4_mapped_t, const address_v6& v6_addr);++/// Create an IPv4-mapped IPv6 address from an IPv4 address.+/**+ * @relates address_v6+ */+ASIO_DECL address_v6 make_address_v6(+    v4_mapped_t, const address_v4& v4_addr);++#if !defined(ASIO_NO_IOSTREAM)++/// Output an address as a string.+/**+ * Used to output a human-readable string for a specified address.+ *+ * @param os The output stream to which the string will be written.+ *+ * @param addr The address to be written.+ *+ * @return The output stream.+ *+ * @relates asio::ip::address_v6+ */+template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const address_v6& addr);++#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/ip/impl/address_v6.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/ip/impl/address_v6.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_IP_ADDRESS_V6_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/address_v6_iterator.hpp view
@@ -0,0 +1,183 @@+//+// ip/address_v6_iterator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//                         Oliver Kowalke (oliver dot kowalke at gmail 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_IP_ADDRESS_V6_ITERATOR_HPP+#define ASIO_IP_ADDRESS_V6_ITERATOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/ip/address_v6.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++template <typename> class basic_address_iterator;++/// An input iterator that can be used for traversing IPv6 addresses.+/**+ * In addition to satisfying the input iterator requirements, this iterator+ * also supports decrement.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <> class basic_address_iterator<address_v6>+{+public:+  /// The type of the elements pointed to by the iterator.+  typedef address_v6 value_type;++  /// Distance between two iterators.+  typedef std::ptrdiff_t difference_type;++  /// The type of a pointer to an element pointed to by the iterator.+  typedef const address_v6* pointer;++  /// The type of a reference to an element pointed to by the iterator.+  typedef const address_v6& reference;++  /// Denotes that the iterator satisfies the input iterator requirements.+  typedef std::input_iterator_tag iterator_category;++  /// Construct an iterator that points to the specified address.+  basic_address_iterator(const address_v6& addr) ASIO_NOEXCEPT+    : address_(addr)+  {+  }++  /// Copy constructor.+  basic_address_iterator(+      const basic_address_iterator& other) ASIO_NOEXCEPT+    : address_(other.address_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  basic_address_iterator(basic_address_iterator&& other) ASIO_NOEXCEPT+    : address_(ASIO_MOVE_CAST(address_v6)(other.address_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Assignment operator.+  basic_address_iterator& operator=(+      const basic_address_iterator& other) ASIO_NOEXCEPT+  {+    address_ = other.address_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  /// Move assignment operator.+  basic_address_iterator& operator=(+      basic_address_iterator&& other) ASIO_NOEXCEPT+  {+    address_ = ASIO_MOVE_CAST(address_v6)(other.address_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Dereference the iterator.+  const address_v6& operator*() const ASIO_NOEXCEPT+  {+    return address_;+  }++  /// Dereference the iterator.+  const address_v6* operator->() const ASIO_NOEXCEPT+  {+    return &address_;+  }++  /// Pre-increment operator.+  basic_address_iterator& operator++() ASIO_NOEXCEPT+  {+    for (int i = 15; i >= 0; --i)+    {+      if (address_.addr_.s6_addr[i] < 0xFF)+      {+        ++address_.addr_.s6_addr[i];+        break;+      }++      address_.addr_.s6_addr[i] = 0;+    }++    return *this;+  }++  /// Post-increment operator.+  basic_address_iterator operator++(int) ASIO_NOEXCEPT+  {+    basic_address_iterator tmp(*this);+    ++*this;+    return tmp;+  }++  /// Pre-decrement operator.+  basic_address_iterator& operator--() ASIO_NOEXCEPT+  {+    for (int i = 15; i >= 0; --i)+    {+      if (address_.addr_.s6_addr[i] > 0)+      {+        --address_.addr_.s6_addr[i];+        break;+      }++      address_.addr_.s6_addr[i] = 0xFF;+    }++    return *this;+  }++  /// Post-decrement operator.+  basic_address_iterator operator--(int)+  {+    basic_address_iterator tmp(*this);+    --*this;+    return tmp;+  }++  /// Compare two addresses for equality.+  friend bool operator==(const basic_address_iterator& a,+      const basic_address_iterator& b)+  {+    return a.address_ == b.address_;+  }++  /// Compare two addresses for inequality.+  friend bool operator!=(const basic_address_iterator& a,+      const basic_address_iterator& b)+  {+    return a.address_ != b.address_;+  }++private:+  address_v6 address_;+};++/// An input iterator that can be used for traversing IPv6 addresses.+typedef basic_address_iterator<address_v6> address_v6_iterator;++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_ADDRESS_V6_ITERATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/address_v6_range.hpp view
@@ -0,0 +1,129 @@+//+// ip/address_v6_range.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//                         Oliver Kowalke (oliver dot kowalke at gmail 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_IP_ADDRESS_V6_RANGE_HPP+#define ASIO_IP_ADDRESS_V6_RANGE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/ip/address_v6_iterator.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++template <typename> class basic_address_range;++/// Represents a range of IPv6 addresses.+/**+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <> class basic_address_range<address_v6>+{+public:+  /// The type of an iterator that points into the range.+  typedef basic_address_iterator<address_v6> iterator;++  /// Construct an empty range.+  basic_address_range() ASIO_NOEXCEPT+    : begin_(address_v6()),+      end_(address_v6())+  {+  }++  /// Construct an range that represents the given range of addresses.+  explicit basic_address_range(const iterator& first,+      const iterator& last) ASIO_NOEXCEPT+    : begin_(first),+      end_(last)+  {+  }++  /// Copy constructor.+  basic_address_range(const basic_address_range& other) ASIO_NOEXCEPT+    : begin_(other.begin_),+      end_(other.end_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  basic_address_range(basic_address_range&& other) ASIO_NOEXCEPT+    : begin_(ASIO_MOVE_CAST(iterator)(other.begin_)),+      end_(ASIO_MOVE_CAST(iterator)(other.end_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Assignment operator.+  basic_address_range& operator=(+      const basic_address_range& other) ASIO_NOEXCEPT+  {+    begin_ = other.begin_;+    end_ = other.end_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  /// Move assignment operator.+  basic_address_range& operator=(+      basic_address_range&& other) ASIO_NOEXCEPT+  {+    begin_ = ASIO_MOVE_CAST(iterator)(other.begin_);+    end_ = ASIO_MOVE_CAST(iterator)(other.end_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Obtain an iterator that points to the start of the range.+  iterator begin() const ASIO_NOEXCEPT+  {+    return begin_;+  }++  /// Obtain an iterator that points to the end of the range.+  iterator end() const ASIO_NOEXCEPT+  {+    return end_;+  }++  /// Determine whether the range is empty.+  bool empty() const ASIO_NOEXCEPT+  {+    return begin_ == end_;+  }++  /// Find an address in the range.+  iterator find(const address_v6& addr) const ASIO_NOEXCEPT+  {+    return addr >= *begin_ && addr < *end_ ? iterator(addr) : end_;+  }++private:+  iterator begin_;+  iterator end_;+};++/// Represents a range of IPv6 addresses.+typedef basic_address_range<address_v6> address_v6_range;++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_ADDRESS_V6_RANGE_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/bad_address_cast.hpp view
@@ -0,0 +1,53 @@+//+// ip/bad_address_cast.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_BAD_ADDRESS_CAST_HPP+#define ASIO_IP_BAD_ADDRESS_CAST_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <typeinfo>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Thrown to indicate a failed address conversion.+class bad_address_cast :+#if defined(ASIO_MSVC) && defined(_HAS_EXCEPTIONS) && !_HAS_EXCEPTIONS+  public std::exception+#else+  public std::bad_cast+#endif+{+public:+  /// Default constructor.+  bad_address_cast() {}++  /// Destructor.+  virtual ~bad_address_cast() ASIO_NOEXCEPT_OR_NOTHROW {}++  /// Get the message associated with the exception.+  virtual const char* what() const ASIO_NOEXCEPT_OR_NOTHROW+  {+    return "bad address cast";+  }+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_ADDRESS_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/basic_endpoint.hpp view
@@ -0,0 +1,264 @@+//+// ip/basic_endpoint.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_BASIC_ENDPOINT_HPP+#define ASIO_IP_BASIC_ENDPOINT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/ip/address.hpp"+#include "asio/ip/detail/endpoint.hpp"++#if !defined(ASIO_NO_IOSTREAM)+# include <iosfwd>+#endif // !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Describes an endpoint for a version-independent IP socket.+/**+ * The asio::ip::basic_endpoint class template describes an endpoint that+ * may be associated with a particular socket.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * @par Concepts:+ * Endpoint.+ */+template <typename InternetProtocol>+class basic_endpoint+{+public:+  /// The protocol type associated with the endpoint.+  typedef InternetProtocol protocol_type;++  /// The type of the endpoint structure. This type is dependent on the+  /// underlying implementation of the socket layer.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined data_type;+#else+  typedef asio::detail::socket_addr_type data_type;+#endif++  /// Default constructor.+  basic_endpoint() ASIO_NOEXCEPT+    : impl_()+  {+  }++  /// Construct an endpoint using a port number, specified in the host's byte+  /// order. The IP address will be the any address (i.e. INADDR_ANY or+  /// in6addr_any). This constructor would typically be used for accepting new+  /// connections.+  /**+   * @par Examples+   * To initialise an IPv4 TCP endpoint for port 1234, use:+   * @code+   * asio::ip::tcp::endpoint ep(asio::ip::tcp::v4(), 1234);+   * @endcode+   *+   * To specify an IPv6 UDP endpoint for port 9876, use:+   * @code+   * asio::ip::udp::endpoint ep(asio::ip::udp::v6(), 9876);+   * @endcode+   */+  basic_endpoint(const InternetProtocol& internet_protocol,+      unsigned short port_num) ASIO_NOEXCEPT+    : impl_(internet_protocol.family(), port_num)+  {+  }++  /// Construct an endpoint using a port number and an IP address. This+  /// constructor may be used for accepting connections on a specific interface+  /// or for making a connection to a remote endpoint.+  basic_endpoint(const asio::ip::address& addr,+      unsigned short port_num) ASIO_NOEXCEPT+    : impl_(addr, port_num)+  {+  }++  /// Copy constructor.+  basic_endpoint(const basic_endpoint& other) ASIO_NOEXCEPT+    : impl_(other.impl_)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  basic_endpoint(basic_endpoint&& other) ASIO_NOEXCEPT+    : impl_(other.impl_)+  {+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Assign from another endpoint.+  basic_endpoint& operator=(const basic_endpoint& other) ASIO_NOEXCEPT+  {+    impl_ = other.impl_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-assign from another endpoint.+  basic_endpoint& operator=(basic_endpoint&& other) ASIO_NOEXCEPT+  {+    impl_ = other.impl_;+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// The protocol associated with the endpoint.+  protocol_type protocol() const ASIO_NOEXCEPT+  {+    if (impl_.is_v4())+      return InternetProtocol::v4();+    return InternetProtocol::v6();+  }++  /// Get the underlying endpoint in the native type.+  data_type* data() ASIO_NOEXCEPT+  {+    return impl_.data();+  }++  /// Get the underlying endpoint in the native type.+  const data_type* data() const ASIO_NOEXCEPT+  {+    return impl_.data();+  }++  /// Get the underlying size of the endpoint in the native type.+  std::size_t size() const ASIO_NOEXCEPT+  {+    return impl_.size();+  }++  /// Set the underlying size of the endpoint in the native type.+  void resize(std::size_t new_size)+  {+    impl_.resize(new_size);+  }++  /// Get the capacity of the endpoint in the native type.+  std::size_t capacity() const ASIO_NOEXCEPT+  {+    return impl_.capacity();+  }++  /// Get the port associated with the endpoint. The port number is always in+  /// the host's byte order.+  unsigned short port() const ASIO_NOEXCEPT+  {+    return impl_.port();+  }++  /// Set the port associated with the endpoint. The port number is always in+  /// the host's byte order.+  void port(unsigned short port_num) ASIO_NOEXCEPT+  {+    impl_.port(port_num);+  }++  /// Get the IP address associated with the endpoint.+  asio::ip::address address() const ASIO_NOEXCEPT+  {+    return impl_.address();+  }++  /// Set the IP address associated with the endpoint.+  void address(const asio::ip::address& addr) ASIO_NOEXCEPT+  {+    impl_.address(addr);+  }++  /// Compare two endpoints for equality.+  friend bool operator==(const basic_endpoint<InternetProtocol>& e1,+      const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT+  {+    return e1.impl_ == e2.impl_;+  }++  /// Compare two endpoints for inequality.+  friend bool operator!=(const basic_endpoint<InternetProtocol>& e1,+      const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT+  {+    return !(e1 == e2);+  }++  /// Compare endpoints for ordering.+  friend bool operator<(const basic_endpoint<InternetProtocol>& e1,+      const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT+  {+    return e1.impl_ < e2.impl_;+  }++  /// Compare endpoints for ordering.+  friend bool operator>(const basic_endpoint<InternetProtocol>& e1,+      const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT+  {+    return e2.impl_ < e1.impl_;+  }++  /// Compare endpoints for ordering.+  friend bool operator<=(const basic_endpoint<InternetProtocol>& e1,+      const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT+  {+    return !(e2 < e1);+  }++  /// Compare endpoints for ordering.+  friend bool operator>=(const basic_endpoint<InternetProtocol>& e1,+      const basic_endpoint<InternetProtocol>& e2) ASIO_NOEXCEPT+  {+    return !(e1 < e2);+  }++private:+  // The underlying IP endpoint.+  asio::ip::detail::endpoint impl_;+};++#if !defined(ASIO_NO_IOSTREAM)++/// Output an endpoint as a string.+/**+ * Used to output a human-readable string for a specified endpoint.+ *+ * @param os The output stream to which the string will be written.+ *+ * @param endpoint The endpoint to be written.+ *+ * @return The output stream.+ *+ * @relates asio::ip::basic_endpoint+ */+template <typename Elem, typename Traits, typename InternetProtocol>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os,+    const basic_endpoint<InternetProtocol>& endpoint);++#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/ip/impl/basic_endpoint.hpp"++#endif // ASIO_IP_BASIC_ENDPOINT_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/basic_resolver.hpp view
@@ -0,0 +1,1030 @@+//+// ip/basic_resolver.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_BASIC_RESOLVER_HPP+#define ASIO_IP_BASIC_RESOLVER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#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/string_view.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/ip/basic_resolver_iterator.hpp"+#include "asio/ip/basic_resolver_query.hpp"+#include "asio/ip/basic_resolver_results.hpp"+#include "asio/ip/resolver_base.hpp"+#if defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/winrt_resolver_service.hpp"+#else+# include "asio/detail/resolver_service.hpp"+#endif++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++#if !defined(ASIO_IP_BASIC_RESOLVER_FWD_DECL)+#define ASIO_IP_BASIC_RESOLVER_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename InternetProtocol, typename Executor = any_io_executor>+class basic_resolver;++#endif // !defined(ASIO_IP_BASIC_RESOLVER_FWD_DECL)++/// Provides endpoint resolution functionality.+/**+ * The basic_resolver class template provides the ability to resolve a query+ * to a list of endpoints.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename InternetProtocol, typename Executor>+class basic_resolver+  : public resolver_base+{+public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the resolver type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The resolver type when rebound to the specified executor.+    typedef basic_resolver<InternetProtocol, Executor1> other;+  };++  /// The protocol type.+  typedef InternetProtocol protocol_type;++  /// The endpoint type.+  typedef typename InternetProtocol::endpoint endpoint_type;++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated.) The query type.+  typedef basic_resolver_query<InternetProtocol> query;++  /// (Deprecated.) The iterator type.+  typedef basic_resolver_iterator<InternetProtocol> iterator;+#endif // !defined(ASIO_NO_DEPRECATED)++  /// The results type.+  typedef basic_resolver_results<InternetProtocol> results_type;++  /// Construct with executor.+  /**+   * This constructor creates a basic_resolver.+   *+   * @param ex The I/O executor that the resolver will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * resolver.+   */+  explicit basic_resolver(const executor_type& ex)+    : impl_(ex)+  {+  }++  /// Construct with execution context.+  /**+   * This constructor creates a basic_resolver.+   *+   * @param context An execution context which provides the I/O executor that+   * the resolver will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the resolver.+   */+  template <typename ExecutionContext>+  explicit basic_resolver(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_resolver from another.+  /**+   * This constructor moves a resolver from one object to another.+   *+   * @param other The other basic_resolver 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_resolver(const executor_type&) constructor.+   */+  basic_resolver(basic_resolver&& other)+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_resolver from another.+  /**+   * This assignment operator moves a resolver from one object to another.+   * Cancels any outstanding asynchronous operations associated with the target+   * object.+   *+   * @param other The other basic_resolver 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_resolver(const executor_type&) constructor.+   */+  basic_resolver& operator=(basic_resolver&& other)+  {+    impl_ = std::move(other.impl_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destroys the resolver.+  /**+   * This function destroys the resolver, cancelling any outstanding+   * asynchronous wait operations associated with the resolver as if by calling+   * @c cancel.+   */+  ~basic_resolver()+  {+  }++  /// 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 resolver.+  /**+   * This function forces the completion of any pending asynchronous+   * operations on the host resolver. The handler for each cancelled operation+   * will be invoked with the asio::error::operation_aborted error code.+   */+  void cancel()+  {+    return impl_.get_service().cancel(impl_.get_implementation());+  }++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use overload with separate host and service parameters.)+  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve a query into a list of endpoint entries.+   *+   * @param q A query object that determines what endpoints will be returned.+   *+   * @returns A range object representing the list of endpoint entries. A+   * successful call to this function is guaranteed to return a non-empty+   * range.+   *+   * @throws asio::system_error Thrown on failure.+   */+  results_type resolve(const query& q)+  {+    asio::error_code ec;+    results_type r = impl_.get_service().resolve(+        impl_.get_implementation(), q, ec);+    asio::detail::throw_error(ec, "resolve");+    return r;+  }++  /// (Deprecated: Use overload with separate host and service parameters.)+  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve a query into a list of endpoint entries.+   *+   * @param q A query object that determines what endpoints will be returned.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns A range object representing the list of endpoint entries. An+   * empty range is returned if an error occurs. A successful call to this+   * function is guaranteed to return a non-empty range.+   */+  results_type resolve(const query& q, asio::error_code& ec)+  {+    return impl_.get_service().resolve(impl_.get_implementation(), q, ec);+  }+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @returns A range object representing the list of endpoint entries. A+   * successful call to this function is guaranteed to return a non-empty+   * range.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  results_type resolve(ASIO_STRING_VIEW_PARAM host,+      ASIO_STRING_VIEW_PARAM service)+  {+    return resolve(host, service, resolver_base::flags());+  }++  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns A range object representing the list of endpoint entries. An+   * empty range is returned if an error occurs. A successful call to this+   * function is guaranteed to return a non-empty range.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  results_type resolve(ASIO_STRING_VIEW_PARAM host,+      ASIO_STRING_VIEW_PARAM service, asio::error_code& ec)+  {+    return resolve(host, service, resolver_base::flags(), ec);+  }++  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for communication with+   * remote hosts. See the @ref resolver_base documentation for the set of+   * available flags.+   *+   * @returns A range object representing the list of endpoint entries. A+   * successful call to this function is guaranteed to return a non-empty+   * range.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  results_type resolve(ASIO_STRING_VIEW_PARAM host,+      ASIO_STRING_VIEW_PARAM service, resolver_base::flags resolve_flags)+  {+    asio::error_code ec;+    basic_resolver_query<protocol_type> q(static_cast<std::string>(host),+        static_cast<std::string>(service), resolve_flags);+    results_type r = impl_.get_service().resolve(+        impl_.get_implementation(), q, ec);+    asio::detail::throw_error(ec, "resolve");+    return r;+  }++  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for communication with+   * remote hosts. See the @ref resolver_base documentation for the set of+   * available flags.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns A range object representing the list of endpoint entries. An+   * empty range is returned if an error occurs. A successful call to this+   * function is guaranteed to return a non-empty range.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  results_type resolve(ASIO_STRING_VIEW_PARAM host,+      ASIO_STRING_VIEW_PARAM service, resolver_base::flags resolve_flags,+      asio::error_code& ec)+  {+    basic_resolver_query<protocol_type> q(static_cast<std::string>(host),+        static_cast<std::string>(service), resolve_flags);+    return impl_.get_service().resolve(impl_.get_implementation(), q, ec);+  }++  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param protocol A protocol object, normally representing either the IPv4 or+   * IPv6 version of an internet protocol.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @returns A range object representing the list of endpoint entries. A+   * successful call to this function is guaranteed to return a non-empty+   * range.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  results_type resolve(const protocol_type& protocol,+      ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service)+  {+    return resolve(protocol, host, service, resolver_base::flags());+  }++  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param protocol A protocol object, normally representing either the IPv4 or+   * IPv6 version of an internet protocol.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns A range object representing the list of endpoint entries. An+   * empty range is returned if an error occurs. A successful call to this+   * function is guaranteed to return a non-empty range.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  results_type resolve(const protocol_type& protocol,+      ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service,+      asio::error_code& ec)+  {+    return resolve(protocol, host, service, resolver_base::flags(), ec);+  }++  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param protocol A protocol object, normally representing either the IPv4 or+   * IPv6 version of an internet protocol.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for communication with+   * remote hosts. See the @ref resolver_base documentation for the set of+   * available flags.+   *+   * @returns A range object representing the list of endpoint entries. A+   * successful call to this function is guaranteed to return a non-empty+   * range.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  results_type resolve(const protocol_type& protocol,+      ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service,+      resolver_base::flags resolve_flags)+  {+    asio::error_code ec;+    basic_resolver_query<protocol_type> q(+        protocol, static_cast<std::string>(host),+        static_cast<std::string>(service), resolve_flags);+    results_type r = impl_.get_service().resolve(+        impl_.get_implementation(), q, ec);+    asio::detail::throw_error(ec, "resolve");+    return r;+  }++  /// Perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param protocol A protocol object, normally representing either the IPv4 or+   * IPv6 version of an internet protocol.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for communication with+   * remote hosts. See the @ref resolver_base documentation for the set of+   * available flags.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns A range object representing the list of endpoint entries. An+   * empty range is returned if an error occurs. A successful call to this+   * function is guaranteed to return a non-empty range.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  results_type resolve(const protocol_type& protocol,+      ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service,+      resolver_base::flags resolve_flags, asio::error_code& ec)+  {+    basic_resolver_query<protocol_type> q(+        protocol, static_cast<std::string>(host),+        static_cast<std::string>(service), resolve_flags);+    return impl_.get_service().resolve(impl_.get_implementation(), q, ec);+  }++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use overload with separate host and service parameters.)+  /// Asynchronously perform forward resolution of a query to a list of entries.+  /**+   * This function is used to asynchronously resolve a query into a list of+   * endpoint entries.+   *+   * @param q A query object that determines what endpoints will be returned.+   *+   * @param handler The handler to be called when the resolve operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   resolver::results_type results // Resolved endpoints as a range.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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().+   *+   * A successful resolve operation is guaranteed to pass a non-empty range to+   * the handler.+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        results_type)) ResolveHandler+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+      void (asio::error_code, results_type))+  async_resolve(const query& q,+      ASIO_MOVE_ARG(ResolveHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return asio::async_initiate<ResolveHandler,+      void (asio::error_code, results_type)>(+        initiate_async_resolve(this), handler, q);+  }+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Asynchronously perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param handler The handler to be called when the resolve operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   resolver::results_type results // Resolved endpoints as a range.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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().+   *+   * A successful resolve operation is guaranteed to pass a non-empty range to+   * the handler.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        results_type)) ResolveHandler+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+      void (asio::error_code, results_type))+  async_resolve(ASIO_STRING_VIEW_PARAM host,+      ASIO_STRING_VIEW_PARAM service,+      ASIO_MOVE_ARG(ResolveHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_resolve(host, service, resolver_base::flags(),+        ASIO_MOVE_CAST(ResolveHandler)(handler));+  }++  /// Asynchronously perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for communication with+   * remote hosts. See the @ref resolver_base documentation for the set of+   * available flags.+   *+   * @param handler The handler to be called when the resolve operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   resolver::results_type results // Resolved endpoints as a range.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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().+   *+   * A successful resolve operation is guaranteed to pass a non-empty range to+   * the handler.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        results_type)) ResolveHandler+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+      void (asio::error_code, results_type))+  async_resolve(ASIO_STRING_VIEW_PARAM host,+      ASIO_STRING_VIEW_PARAM service,+      resolver_base::flags resolve_flags,+      ASIO_MOVE_ARG(ResolveHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    basic_resolver_query<protocol_type> q(static_cast<std::string>(host),+        static_cast<std::string>(service), resolve_flags);++    return asio::async_initiate<ResolveHandler,+      void (asio::error_code, results_type)>(+        initiate_async_resolve(this), handler, q);+  }++  /// Asynchronously perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param protocol A protocol object, normally representing either the IPv4 or+   * IPv6 version of an internet protocol.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param handler The handler to be called when the resolve operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   resolver::results_type results // Resolved endpoints as a range.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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().+   *+   * A successful resolve operation is guaranteed to pass a non-empty range to+   * the handler.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        results_type)) ResolveHandler+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+      void (asio::error_code, results_type))+  async_resolve(const protocol_type& protocol,+      ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service,+      ASIO_MOVE_ARG(ResolveHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_resolve(protocol, host, service, resolver_base::flags(),+        ASIO_MOVE_CAST(ResolveHandler)(handler));+  }++  /// Asynchronously perform forward resolution of a query to a list of entries.+  /**+   * This function is used to resolve host and service names into a list of+   * endpoint entries.+   *+   * @param protocol A protocol object, normally representing either the IPv4 or+   * IPv6 version of an internet protocol.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for communication with+   * remote hosts. See the @ref resolver_base documentation for the set of+   * available flags.+   *+   * @param handler The handler to be called when the resolve operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   resolver::results_type results // Resolved endpoints as a range.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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().+   *+   * A successful resolve operation is guaranteed to pass a non-empty range to+   * the handler.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        results_type)) ResolveHandler+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+      void (asio::error_code, results_type))+  async_resolve(const protocol_type& protocol,+      ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service,+      resolver_base::flags resolve_flags,+      ASIO_MOVE_ARG(ResolveHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    basic_resolver_query<protocol_type> q(+        protocol, static_cast<std::string>(host),+        static_cast<std::string>(service), resolve_flags);++    return asio::async_initiate<ResolveHandler,+      void (asio::error_code, results_type)>(+        initiate_async_resolve(this), handler, q);+  }++  /// Perform reverse resolution of an endpoint to a list of entries.+  /**+   * This function is used to resolve an endpoint into a list of endpoint+   * entries.+   *+   * @param e An endpoint object that determines what endpoints will be+   * returned.+   *+   * @returns A range object representing the list of endpoint entries. A+   * successful call to this function is guaranteed to return a non-empty+   * range.+   *+   * @throws asio::system_error Thrown on failure.+   */+  results_type resolve(const endpoint_type& e)+  {+    asio::error_code ec;+    results_type i = impl_.get_service().resolve(+        impl_.get_implementation(), e, ec);+    asio::detail::throw_error(ec, "resolve");+    return i;+  }++  /// Perform reverse resolution of an endpoint to a list of entries.+  /**+   * This function is used to resolve an endpoint into a list of endpoint+   * entries.+   *+   * @param e An endpoint object that determines what endpoints will be+   * returned.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns A range object representing the list of endpoint entries. An+   * empty range is returned if an error occurs. A successful call to this+   * function is guaranteed to return a non-empty range.+   */+  results_type resolve(const endpoint_type& e, asio::error_code& ec)+  {+    return impl_.get_service().resolve(impl_.get_implementation(), e, ec);+  }++  /// Asynchronously perform reverse resolution of an endpoint to a list of+  /// entries.+  /**+   * This function is used to asynchronously resolve an endpoint into a list of+   * endpoint entries.+   *+   * @param e An endpoint object that determines what endpoints will be+   * returned.+   *+   * @param handler The handler to be called when the resolve operation+   * completes. Copies will be made of the handler as required. The function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   resolver::results_type results // Resolved endpoints as a range.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the 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().+   *+   * A successful resolve operation is guaranteed to pass a non-empty range to+   * the handler.+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        results_type)) ResolveHandler+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+      void (asio::error_code, results_type))+  async_resolve(const endpoint_type& e,+      ASIO_MOVE_ARG(ResolveHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return asio::async_initiate<ResolveHandler,+      void (asio::error_code, results_type)>(+        initiate_async_resolve(this), handler, e);+  }++private:+  // Disallow copying and assignment.+  basic_resolver(const basic_resolver&) ASIO_DELETED;+  basic_resolver& operator=(const basic_resolver&) ASIO_DELETED;++  class initiate_async_resolve+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_resolve(basic_resolver* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename ResolveHandler, typename Query>+    void operator()(ASIO_MOVE_ARG(ResolveHandler) handler,+        const Query& q) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a ResolveHandler.+      ASIO_RESOLVE_HANDLER_CHECK(+          ResolveHandler, handler, results_type) type_check;++      asio::detail::non_const_lvalue<ResolveHandler> handler2(handler);+      self_->impl_.get_service().async_resolve(+          self_->impl_.get_implementation(), q,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_resolver* self_;+  };++# if defined(ASIO_WINDOWS_RUNTIME)+  asio::detail::io_object_impl<+    asio::detail::winrt_resolver_service<InternetProtocol>,+    Executor> impl_;+# else+  asio::detail::io_object_impl<+    asio::detail::resolver_service<InternetProtocol>,+    Executor> impl_;+# endif+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_BASIC_RESOLVER_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_entry.hpp view
@@ -0,0 +1,113 @@+//+// ip/basic_resolver_entry.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_BASIC_RESOLVER_ENTRY_HPP+#define ASIO_IP_BASIC_RESOLVER_ENTRY_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/detail/string_view.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// An entry produced by a resolver.+/**+ * The asio::ip::basic_resolver_entry class template describes an entry+ * as returned by a resolver.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename InternetProtocol>+class basic_resolver_entry+{+public:+  /// The protocol type associated with the endpoint entry.+  typedef InternetProtocol protocol_type;++  /// The endpoint type associated with the endpoint entry.+  typedef typename InternetProtocol::endpoint endpoint_type;++  /// Default constructor.+  basic_resolver_entry()+  {+  }++  /// Construct with specified endpoint, host name and service name.+  basic_resolver_entry(const endpoint_type& ep,+      ASIO_STRING_VIEW_PARAM host, ASIO_STRING_VIEW_PARAM service)+    : endpoint_(ep),+      host_name_(static_cast<std::string>(host)),+      service_name_(static_cast<std::string>(service))+  {+  }++  /// Get the endpoint associated with the entry.+  endpoint_type endpoint() const+  {+    return endpoint_;+  }++  /// Convert to the endpoint associated with the entry.+  operator endpoint_type() const+  {+    return endpoint_;+  }++  /// Get the host name associated with the entry.+  std::string host_name() const+  {+    return host_name_;+  }++  /// Get the host name associated with the entry.+  template <class Allocator>+  std::basic_string<char, std::char_traits<char>, Allocator> host_name(+      const Allocator& alloc = Allocator()) const+  {+    return std::basic_string<char, std::char_traits<char>, Allocator>(+        host_name_.c_str(), alloc);+  }++  /// Get the service name associated with the entry.+  std::string service_name() const+  {+    return service_name_;+  }++  /// Get the service name associated with the entry.+  template <class Allocator>+  std::basic_string<char, std::char_traits<char>, Allocator> service_name(+      const Allocator& alloc = Allocator()) const+  {+    return std::basic_string<char, std::char_traits<char>, Allocator>(+        service_name_.c_str(), alloc);+  }++private:+  endpoint_type endpoint_;+  std::string host_name_;+  std::string service_name_;+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_BASIC_RESOLVER_ENTRY_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_iterator.hpp view
@@ -0,0 +1,192 @@+//+// ip/basic_resolver_iterator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_BASIC_RESOLVER_ITERATOR_HPP+#define ASIO_IP_BASIC_RESOLVER_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 <cstring>+#include <iterator>+#include <string>+#include <vector>+#include "asio/detail/memory.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/ip/basic_resolver_entry.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/winrt_utils.hpp"+#endif // defined(ASIO_WINDOWS_RUNTIME)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// An iterator over the entries produced by a resolver.+/**+ * The asio::ip::basic_resolver_iterator class template is used to define+ * iterators over the results returned by a resolver.+ *+ * The iterator's value_type, obtained when the iterator is dereferenced, is:+ * @code const basic_resolver_entry<InternetProtocol> @endcode+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename InternetProtocol>+class basic_resolver_iterator+{+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 basic_resolver_entry<InternetProtocol> value_type;++  /// The type of the result of applying operator->() to the iterator.+  typedef const basic_resolver_entry<InternetProtocol>* pointer;++  /// The type of the result of applying operator*() to the iterator.+  typedef const basic_resolver_entry<InternetProtocol>& reference;++  /// The iterator category.+  typedef std::forward_iterator_tag iterator_category;++  /// Default constructor creates an end iterator.+  basic_resolver_iterator()+    : index_(0)+  {+  }++  /// Copy constructor.+  basic_resolver_iterator(const basic_resolver_iterator& other)+    : values_(other.values_),+      index_(other.index_)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  basic_resolver_iterator(basic_resolver_iterator&& other)+    : values_(ASIO_MOVE_CAST(values_ptr_type)(other.values_)),+      index_(other.index_)+  {+    other.index_ = 0;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Assignment operator.+  basic_resolver_iterator& operator=(const basic_resolver_iterator& other)+  {+    values_ = other.values_;+    index_ = other.index_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-assignment operator.+  basic_resolver_iterator& operator=(basic_resolver_iterator&& other)+  {+    if (this != &other)+    {+      values_ = ASIO_MOVE_CAST(values_ptr_type)(other.values_);+      index_ = other.index_;+      other.index_ = 0;+    }++    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Dereference an iterator.+  const basic_resolver_entry<InternetProtocol>& operator*() const+  {+    return dereference();+  }++  /// Dereference an iterator.+  const basic_resolver_entry<InternetProtocol>* operator->() const+  {+    return &dereference();+  }++  /// Increment operator (prefix).+  basic_resolver_iterator& operator++()+  {+    increment();+    return *this;+  }++  /// Increment operator (postfix).+  basic_resolver_iterator operator++(int)+  {+    basic_resolver_iterator tmp(*this);+    ++*this;+    return tmp;+  }++  /// Test two iterators for equality.+  friend bool operator==(const basic_resolver_iterator& a,+      const basic_resolver_iterator& b)+  {+    return a.equal(b);+  }++  /// Test two iterators for inequality.+  friend bool operator!=(const basic_resolver_iterator& a,+      const basic_resolver_iterator& b)+  {+    return !a.equal(b);+  }++protected:+  void increment()+  {+    if (++index_ == values_->size())+    {+      // Reset state to match a default constructed end iterator.+      values_.reset();+      index_ = 0;+    }+  }++  bool equal(const basic_resolver_iterator& other) const+  {+    if (!values_ && !other.values_)+      return true;+    if (values_ != other.values_)+      return false;+    return index_ == other.index_;+  }++  const basic_resolver_entry<InternetProtocol>& dereference() const+  {+    return (*values_)[index_];+  }++  typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;+  typedef asio::detail::shared_ptr<values_type> values_ptr_type;+  values_ptr_type values_;+  std::size_t index_;+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_BASIC_RESOLVER_ITERATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_query.hpp view
@@ -0,0 +1,244 @@+//+// ip/basic_resolver_query.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_BASIC_RESOLVER_QUERY_HPP+#define ASIO_IP_BASIC_RESOLVER_QUERY_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/detail/socket_ops.hpp"+#include "asio/ip/resolver_query_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// An query to be passed to a resolver.+/**+ * The asio::ip::basic_resolver_query class template describes a query+ * that can be passed to a resolver.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename InternetProtocol>+class basic_resolver_query+  : public resolver_query_base+{+public:+  /// The protocol type associated with the endpoint query.+  typedef InternetProtocol protocol_type;++  /// Construct with specified service name for any protocol.+  /**+   * This constructor is typically used to perform name resolution for local+   * service binding.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for local service+   * binding.+   *+   * @note On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  basic_resolver_query(const std::string& service,+      resolver_query_base::flags resolve_flags = passive | address_configured)+    : hints_(),+      host_name_(),+      service_name_(service)+  {+    typename InternetProtocol::endpoint endpoint;+    hints_.ai_flags = static_cast<int>(resolve_flags);+    hints_.ai_family = PF_UNSPEC;+    hints_.ai_socktype = endpoint.protocol().type();+    hints_.ai_protocol = endpoint.protocol().protocol();+    hints_.ai_addrlen = 0;+    hints_.ai_canonname = 0;+    hints_.ai_addr = 0;+    hints_.ai_next = 0;+  }++  /// Construct with specified service name for a given protocol.+  /**+   * This constructor is typically used to perform name resolution for local+   * service binding with a specific protocol version.+   *+   * @param protocol A protocol object, normally representing either the IPv4 or+   * IPv6 version of an internet protocol.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for local service+   * binding.+   *+   * @note On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  basic_resolver_query(const protocol_type& protocol,+      const std::string& service,+      resolver_query_base::flags resolve_flags = passive | address_configured)+    : hints_(),+      host_name_(),+      service_name_(service)+  {+    hints_.ai_flags = static_cast<int>(resolve_flags);+    hints_.ai_family = protocol.family();+    hints_.ai_socktype = protocol.type();+    hints_.ai_protocol = protocol.protocol();+    hints_.ai_addrlen = 0;+    hints_.ai_canonname = 0;+    hints_.ai_addr = 0;+    hints_.ai_next = 0;+  }++  /// Construct with specified host name and service name for any protocol.+  /**+   * This constructor is typically used to perform name resolution for+   * communication with remote hosts.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for communication with+   * remote hosts.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  basic_resolver_query(const std::string& host, const std::string& service,+      resolver_query_base::flags resolve_flags = address_configured)+    : hints_(),+      host_name_(host),+      service_name_(service)+  {+    typename InternetProtocol::endpoint endpoint;+    hints_.ai_flags = static_cast<int>(resolve_flags);+    hints_.ai_family = ASIO_OS_DEF(AF_UNSPEC);+    hints_.ai_socktype = endpoint.protocol().type();+    hints_.ai_protocol = endpoint.protocol().protocol();+    hints_.ai_addrlen = 0;+    hints_.ai_canonname = 0;+    hints_.ai_addr = 0;+    hints_.ai_next = 0;+  }++  /// Construct with specified host name and service name for a given protocol.+  /**+   * This constructor is typically used to perform name resolution for+   * communication with remote hosts.+   *+   * @param protocol A protocol object, normally representing either the IPv4 or+   * IPv6 version of an internet protocol.+   *+   * @param host A string identifying a location. May be a descriptive name or+   * a numeric address string. If an empty string and the passive flag has been+   * specified, the resolved endpoints are suitable for local service binding.+   * If an empty string and passive is not specified, the resolved endpoints+   * will use the loopback address.+   *+   * @param service A string identifying the requested service. This may be a+   * descriptive name or a numeric string corresponding to a port number. May+   * be an empty string, in which case all resolved endpoints will have a port+   * number of 0.+   *+   * @param resolve_flags A set of flags that determine how name resolution+   * should be performed. The default flags are suitable for communication with+   * remote hosts.+   *+   * @note On POSIX systems, host names may be locally defined in the file+   * <tt>/etc/hosts</tt>. On Windows, host names may be defined in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\hosts</tt>. Remote host name+   * resolution is performed using DNS. Operating systems may use additional+   * locations when resolving host names (such as NETBIOS names on Windows).+   *+   * On POSIX systems, service names are typically defined in the file+   * <tt>/etc/services</tt>. On Windows, service names may be found in the file+   * <tt>c:\\windows\\system32\\drivers\\etc\\services</tt>. Operating systems+   * may use additional locations when resolving service names.+   */+  basic_resolver_query(const protocol_type& protocol,+      const std::string& host, const std::string& service,+      resolver_query_base::flags resolve_flags = address_configured)+    : hints_(),+      host_name_(host),+      service_name_(service)+  {+    hints_.ai_flags = static_cast<int>(resolve_flags);+    hints_.ai_family = protocol.family();+    hints_.ai_socktype = protocol.type();+    hints_.ai_protocol = protocol.protocol();+    hints_.ai_addrlen = 0;+    hints_.ai_canonname = 0;+    hints_.ai_addr = 0;+    hints_.ai_next = 0;+  }++  /// Get the hints associated with the query.+  const asio::detail::addrinfo_type& hints() const+  {+    return hints_;+  }++  /// Get the host name associated with the query.+  std::string host_name() const+  {+    return host_name_;+  }++  /// Get the service name associated with the query.+  std::string service_name() const+  {+    return service_name_;+  }++private:+  asio::detail::addrinfo_type hints_;+  std::string host_name_;+  std::string service_name_;+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_BASIC_RESOLVER_QUERY_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_results.hpp view
@@ -0,0 +1,311 @@+//+// ip/basic_resolver_results.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_BASIC_RESOLVER_RESULTS_HPP+#define ASIO_IP_BASIC_RESOLVER_RESULTS_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 <cstring>+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/ip/basic_resolver_iterator.hpp"++#if defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/winrt_utils.hpp"+#endif // defined(ASIO_WINDOWS_RUNTIME)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// A range of entries produced by a resolver.+/**+ * The asio::ip::basic_resolver_results class template is used to define+ * a range over the results returned by a resolver.+ *+ * The iterator's value_type, obtained when a results iterator is dereferenced,+ * is: @code const basic_resolver_entry<InternetProtocol> @endcode+ *+ * @note For backward compatibility, basic_resolver_results is derived from+ * basic_resolver_iterator. This derivation is deprecated.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename InternetProtocol>+class basic_resolver_results+#if !defined(ASIO_NO_DEPRECATED)+  : public basic_resolver_iterator<InternetProtocol>+#else // !defined(ASIO_NO_DEPRECATED)+  : private basic_resolver_iterator<InternetProtocol>+#endif // !defined(ASIO_NO_DEPRECATED)+{+public:+  /// The protocol type associated with the results.+  typedef InternetProtocol protocol_type;++  /// The endpoint type associated with the results.+  typedef typename protocol_type::endpoint endpoint_type;++  /// The type of a value in the results range.+  typedef basic_resolver_entry<protocol_type> value_type;++  /// The type of a const reference to a value in the range.+  typedef const value_type& const_reference;++  /// The type of a non-const reference to a value in the range.+  typedef value_type& reference;++  /// The type of an iterator into the range.+  typedef basic_resolver_iterator<protocol_type> const_iterator;++  /// The type of an iterator into the range.+  typedef const_iterator iterator;++  /// Type used to represent the distance between two iterators in the range.+  typedef std::ptrdiff_t difference_type;++  /// Type used to represent a count of the elements in the range.+  typedef std::size_t size_type;++  /// Default constructor creates an empty range.+  basic_resolver_results()+  {+  }++  /// Copy constructor.+  basic_resolver_results(const basic_resolver_results& other)+    : basic_resolver_iterator<InternetProtocol>(other)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  basic_resolver_results(basic_resolver_results&& other)+    : basic_resolver_iterator<InternetProtocol>(+        ASIO_MOVE_CAST(basic_resolver_results)(other))+  {+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Assignment operator.+  basic_resolver_results& operator=(const basic_resolver_results& other)+  {+    basic_resolver_iterator<InternetProtocol>::operator=(other);+    return *this;+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-assignment operator.+  basic_resolver_results& operator=(basic_resolver_results&& other)+  {+    basic_resolver_iterator<InternetProtocol>::operator=(+        ASIO_MOVE_CAST(basic_resolver_results)(other));+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++#if !defined(GENERATING_DOCUMENTATION)+  // Create results from an addrinfo list returned by getaddrinfo.+  static basic_resolver_results create(+      asio::detail::addrinfo_type* address_info,+      const std::string& host_name, const std::string& service_name)+  {+    basic_resolver_results results;+    if (!address_info)+      return results;++    std::string actual_host_name = host_name;+    if (address_info->ai_canonname)+      actual_host_name = address_info->ai_canonname;++    results.values_.reset(new values_type);++    while (address_info)+    {+      if (address_info->ai_family == ASIO_OS_DEF(AF_INET)+          || address_info->ai_family == ASIO_OS_DEF(AF_INET6))+      {+        using namespace std; // For memcpy.+        typename InternetProtocol::endpoint endpoint;+        endpoint.resize(static_cast<std::size_t>(address_info->ai_addrlen));+        memcpy(endpoint.data(), address_info->ai_addr,+            address_info->ai_addrlen);+        results.values_->push_back(+            basic_resolver_entry<InternetProtocol>(endpoint,+              actual_host_name, service_name));+      }+      address_info = address_info->ai_next;+    }++    return results;+  }++  // Create results from an endpoint, host name and service name.+  static basic_resolver_results create(const endpoint_type& endpoint,+      const std::string& host_name, const std::string& service_name)+  {+    basic_resolver_results results;+    results.values_.reset(new values_type);+    results.values_->push_back(+        basic_resolver_entry<InternetProtocol>(+          endpoint, host_name, service_name));+    return results;+  }++  // Create results from a sequence of endpoints, host and service name.+  template <typename EndpointIterator>+  static basic_resolver_results create(+      EndpointIterator begin, EndpointIterator end,+      const std::string& host_name, const std::string& service_name)+  {+    basic_resolver_results results;+    if (begin != end)+    {+      results.values_.reset(new values_type);+      for (EndpointIterator ep_iter = begin; ep_iter != end; ++ep_iter)+      {+        results.values_->push_back(+            basic_resolver_entry<InternetProtocol>(+              *ep_iter, host_name, service_name));+      }+    }+    return results;+  }++# if defined(ASIO_WINDOWS_RUNTIME)+  // Create results from a Windows Runtime list of EndpointPair objects.+  static basic_resolver_results create(+      Windows::Foundation::Collections::IVectorView<+        Windows::Networking::EndpointPair^>^ endpoints,+      const asio::detail::addrinfo_type& hints,+      const std::string& host_name, const std::string& service_name)+  {+    basic_resolver_results results;+    if (endpoints->Size)+    {+      results.values_.reset(new values_type);+      for (unsigned int i = 0; i < endpoints->Size; ++i)+      {+        auto pair = endpoints->GetAt(i);++        if (hints.ai_family == ASIO_OS_DEF(AF_INET)+            && pair->RemoteHostName->Type+              != Windows::Networking::HostNameType::Ipv4)+          continue;++        if (hints.ai_family == ASIO_OS_DEF(AF_INET6)+            && pair->RemoteHostName->Type+              != Windows::Networking::HostNameType::Ipv6)+          continue;++        results.values_->push_back(+            basic_resolver_entry<InternetProtocol>(+              typename InternetProtocol::endpoint(+                ip::make_address(+                  asio::detail::winrt_utils::string(+                    pair->RemoteHostName->CanonicalName)),+                asio::detail::winrt_utils::integer(+                  pair->RemoteServiceName)),+              host_name, service_name));+      }+    }+    return results;+  }+# endif // defined(ASIO_WINDOWS_RUNTIME)+#endif // !defined(GENERATING_DOCUMENTATION)++  /// Get the number of entries in the results range.+  size_type size() const ASIO_NOEXCEPT+  {+    return this->values_ ? this->values_->size() : 0;+  }++  /// Get the maximum number of entries permitted in a results range.+  size_type max_size() const ASIO_NOEXCEPT+  {+    return this->values_ ? this->values_->max_size() : values_type().max_size();+  }++  /// Determine whether the results range is empty.+  bool empty() const ASIO_NOEXCEPT+  {+    return this->values_ ? this->values_->empty() : true;+  }++  /// Obtain a begin iterator for the results range.+  const_iterator begin() const+  {+    basic_resolver_results tmp(*this);+    tmp.index_ = 0;+    return ASIO_MOVE_CAST(basic_resolver_results)(tmp);+  }++  /// Obtain an end iterator for the results range.+  const_iterator end() const+  {+    return const_iterator();+  }++  /// Obtain a begin iterator for the results range.+  const_iterator cbegin() const+  {+    return begin();+  }++  /// Obtain an end iterator for the results range.+  const_iterator cend() const+  {+    return end();+  }++  /// Swap the results range with another.+  void swap(basic_resolver_results& that) ASIO_NOEXCEPT+  {+    if (this != &that)+    {+      this->values_.swap(that.values_);+      std::size_t index = this->index_;+      this->index_ = that.index_;+      that.index_ = index;+    }+  }++  /// Test two iterators for equality.+  friend bool operator==(const basic_resolver_results& a,+      const basic_resolver_results& b)+  {+    return a.equal(b);+  }++  /// Test two iterators for inequality.+  friend bool operator!=(const basic_resolver_results& a,+      const basic_resolver_results& b)+  {+    return !a.equal(b);+  }++private:+  typedef std::vector<basic_resolver_entry<InternetProtocol> > values_type;+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_BASIC_RESOLVER_RESULTS_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/detail/endpoint.hpp view
@@ -0,0 +1,141 @@+//+// ip/detail/endpoint.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_DETAIL_ENDPOINT_HPP+#define ASIO_IP_DETAIL_ENDPOINT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/detail/socket_types.hpp"+#include "asio/detail/winsock_init.hpp"+#include "asio/error_code.hpp"+#include "asio/ip/address.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {+namespace detail {++// Helper class for implementating an IP endpoint.+class endpoint+{+public:+  // Default constructor.+  ASIO_DECL endpoint() ASIO_NOEXCEPT;++  // Construct an endpoint using a family and port number.+  ASIO_DECL endpoint(int family,+      unsigned short port_num) ASIO_NOEXCEPT;++  // Construct an endpoint using an address and port number.+  ASIO_DECL endpoint(const asio::ip::address& addr,+      unsigned short port_num) ASIO_NOEXCEPT;++  // Copy constructor.+  endpoint(const endpoint& other) ASIO_NOEXCEPT+    : data_(other.data_)+  {+  }++  // Assign from another endpoint.+  endpoint& operator=(const endpoint& other) ASIO_NOEXCEPT+  {+    data_ = other.data_;+    return *this;+  }++  // Get the underlying endpoint in the native type.+  asio::detail::socket_addr_type* data() ASIO_NOEXCEPT+  {+    return &data_.base;+  }++  // Get the underlying endpoint in the native type.+  const asio::detail::socket_addr_type* data() const ASIO_NOEXCEPT+  {+    return &data_.base;+  }++  // Get the underlying size of the endpoint in the native type.+  std::size_t size() const ASIO_NOEXCEPT+  {+    if (is_v4())+      return sizeof(asio::detail::sockaddr_in4_type);+    else+      return sizeof(asio::detail::sockaddr_in6_type);+  }++  // Set the underlying size of the endpoint in the native type.+  ASIO_DECL void resize(std::size_t new_size);++  // Get the capacity of the endpoint in the native type.+  std::size_t capacity() const ASIO_NOEXCEPT+  {+    return sizeof(data_);+  }++  // Get the port associated with the endpoint.+  ASIO_DECL unsigned short port() const ASIO_NOEXCEPT;++  // Set the port associated with the endpoint.+  ASIO_DECL void port(unsigned short port_num) ASIO_NOEXCEPT;++  // Get the IP address associated with the endpoint.+  ASIO_DECL asio::ip::address address() const ASIO_NOEXCEPT;++  // Set the IP address associated with the endpoint.+  ASIO_DECL void address(+      const asio::ip::address& addr) ASIO_NOEXCEPT;++  // Compare two endpoints for equality.+  ASIO_DECL friend bool operator==(const endpoint& e1,+      const endpoint& e2) ASIO_NOEXCEPT;++  // Compare endpoints for ordering.+  ASIO_DECL friend bool operator<(const endpoint& e1,+      const endpoint& e2) ASIO_NOEXCEPT;++  // Determine whether the endpoint is IPv4.+  bool is_v4() const ASIO_NOEXCEPT+  {+    return data_.base.sa_family == ASIO_OS_DEF(AF_INET);+  }++#if !defined(ASIO_NO_IOSTREAM)+  // Convert to a string.+  ASIO_DECL std::string to_string() const;+#endif // !defined(ASIO_NO_IOSTREAM)++private:+  // The underlying IP socket address.+  union data_union+  {+    asio::detail::socket_addr_type base;+    asio::detail::sockaddr_in4_type v4;+    asio::detail::sockaddr_in6_type v6;+  } data_;+};++} // namespace detail+} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/ip/detail/impl/endpoint.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_IP_DETAIL_ENDPOINT_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/detail/impl/endpoint.ipp view
@@ -0,0 +1,199 @@+//+// ip/detail/impl/endpoint.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_DETAIL_IMPL_ENDPOINT_IPP+#define ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <cstring>+#if !defined(ASIO_NO_IOSTREAM)+# include <sstream>+#endif // !defined(ASIO_NO_IOSTREAM)+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"+#include "asio/ip/detail/endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {+namespace detail {++endpoint::endpoint() ASIO_NOEXCEPT+  : data_()+{+  data_.v4.sin_family = ASIO_OS_DEF(AF_INET);+  data_.v4.sin_port = 0;+  data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY);+}++endpoint::endpoint(int family, unsigned short port_num) ASIO_NOEXCEPT+  : data_()+{+  using namespace std; // For memcpy.+  if (family == ASIO_OS_DEF(AF_INET))+  {+    data_.v4.sin_family = ASIO_OS_DEF(AF_INET);+    data_.v4.sin_port =+      asio::detail::socket_ops::host_to_network_short(port_num);+    data_.v4.sin_addr.s_addr = ASIO_OS_DEF(INADDR_ANY);+  }+  else+  {+    data_.v6.sin6_family = ASIO_OS_DEF(AF_INET6);+    data_.v6.sin6_port =+      asio::detail::socket_ops::host_to_network_short(port_num);+    data_.v6.sin6_flowinfo = 0;+    data_.v6.sin6_addr.s6_addr[0] = 0; data_.v6.sin6_addr.s6_addr[1] = 0;+    data_.v6.sin6_addr.s6_addr[2] = 0; data_.v6.sin6_addr.s6_addr[3] = 0;+    data_.v6.sin6_addr.s6_addr[4] = 0; data_.v6.sin6_addr.s6_addr[5] = 0;+    data_.v6.sin6_addr.s6_addr[6] = 0; data_.v6.sin6_addr.s6_addr[7] = 0;+    data_.v6.sin6_addr.s6_addr[8] = 0; data_.v6.sin6_addr.s6_addr[9] = 0;+    data_.v6.sin6_addr.s6_addr[10] = 0; data_.v6.sin6_addr.s6_addr[11] = 0;+    data_.v6.sin6_addr.s6_addr[12] = 0; data_.v6.sin6_addr.s6_addr[13] = 0;+    data_.v6.sin6_addr.s6_addr[14] = 0; data_.v6.sin6_addr.s6_addr[15] = 0;+    data_.v6.sin6_scope_id = 0;+  }+}++endpoint::endpoint(const asio::ip::address& addr,+    unsigned short port_num) ASIO_NOEXCEPT+  : data_()+{+  using namespace std; // For memcpy.+  if (addr.is_v4())+  {+    data_.v4.sin_family = ASIO_OS_DEF(AF_INET);+    data_.v4.sin_port =+      asio::detail::socket_ops::host_to_network_short(port_num);+    data_.v4.sin_addr.s_addr =+      asio::detail::socket_ops::host_to_network_long(+        addr.to_v4().to_uint());+  }+  else+  {+    data_.v6.sin6_family = ASIO_OS_DEF(AF_INET6);+    data_.v6.sin6_port =+      asio::detail::socket_ops::host_to_network_short(port_num);+    data_.v6.sin6_flowinfo = 0;+    asio::ip::address_v6 v6_addr = addr.to_v6();+    asio::ip::address_v6::bytes_type bytes = v6_addr.to_bytes();+    memcpy(data_.v6.sin6_addr.s6_addr, bytes.data(), 16);+    data_.v6.sin6_scope_id =+      static_cast<asio::detail::u_long_type>(+        v6_addr.scope_id());+  }+}++void endpoint::resize(std::size_t new_size)+{+  if (new_size > sizeof(asio::detail::sockaddr_storage_type))+  {+    asio::error_code ec(asio::error::invalid_argument);+    asio::detail::throw_error(ec);+  }+}++unsigned short endpoint::port() const ASIO_NOEXCEPT+{+  if (is_v4())+  {+    return asio::detail::socket_ops::network_to_host_short(+        data_.v4.sin_port);+  }+  else+  {+    return asio::detail::socket_ops::network_to_host_short(+        data_.v6.sin6_port);+  }+}++void endpoint::port(unsigned short port_num) ASIO_NOEXCEPT+{+  if (is_v4())+  {+    data_.v4.sin_port+      = asio::detail::socket_ops::host_to_network_short(port_num);+  }+  else+  {+    data_.v6.sin6_port+      = asio::detail::socket_ops::host_to_network_short(port_num);+  }+}++asio::ip::address endpoint::address() const ASIO_NOEXCEPT+{+  using namespace std; // For memcpy.+  if (is_v4())+  {+    return asio::ip::address_v4(+        asio::detail::socket_ops::network_to_host_long(+          data_.v4.sin_addr.s_addr));+  }+  else+  {+    asio::ip::address_v6::bytes_type bytes;+#if defined(ASIO_HAS_STD_ARRAY)+    memcpy(bytes.data(), data_.v6.sin6_addr.s6_addr, 16);+#else // defined(ASIO_HAS_STD_ARRAY)+    memcpy(bytes.elems, data_.v6.sin6_addr.s6_addr, 16);+#endif // defined(ASIO_HAS_STD_ARRAY)+    return asio::ip::address_v6(bytes, data_.v6.sin6_scope_id);+  }+}++void endpoint::address(const asio::ip::address& addr) ASIO_NOEXCEPT+{+  endpoint tmp_endpoint(addr, port());+  data_ = tmp_endpoint.data_;+}++bool operator==(const endpoint& e1, const endpoint& e2) ASIO_NOEXCEPT+{+  return e1.address() == e2.address() && e1.port() == e2.port();+}++bool operator<(const endpoint& e1, const endpoint& e2) ASIO_NOEXCEPT+{+  if (e1.address() < e2.address())+    return true;+  if (e1.address() != e2.address())+    return false;+  return e1.port() < e2.port();+}++#if !defined(ASIO_NO_IOSTREAM)+std::string endpoint::to_string() const+{+  std::ostringstream tmp_os;+  tmp_os.imbue(std::locale::classic());+  if (is_v4())+    tmp_os << address();+  else+    tmp_os << '[' << address() << ']';+  tmp_os << ':' << port();++  return tmp_os.str();+}+#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace detail+} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_DETAIL_IMPL_ENDPOINT_IPP
+ link/modules/asio-standalone/asio/include/asio/ip/detail/socket_option.hpp view
@@ -0,0 +1,566 @@+//+// detail/socket_option.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_DETAIL_SOCKET_OPTION_HPP+#define ASIO_IP_DETAIL_SOCKET_OPTION_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 <cstring>+#include <stdexcept>+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/ip/address.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {+namespace detail {+namespace socket_option {++// Helper template for implementing multicast enable loopback options.+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>+class multicast_enable_loopback+{+public:+#if defined(__sun) || defined(__osf__)+  typedef unsigned char ipv4_value_type;+  typedef unsigned char ipv6_value_type;+#elif defined(_AIX) || defined(__hpux) || defined(__QNXNTO__) +  typedef unsigned char ipv4_value_type;+  typedef unsigned int ipv6_value_type;+#else+  typedef int ipv4_value_type;+  typedef int ipv6_value_type;+#endif++  // Default constructor.+  multicast_enable_loopback()+    : ipv4_value_(0),+      ipv6_value_(0)+  {+  }++  // Construct with a specific option value.+  explicit multicast_enable_loopback(bool v)+    : ipv4_value_(v ? 1 : 0),+      ipv6_value_(v ? 1 : 0)+  {+  }++  // Set the value of the boolean.+  multicast_enable_loopback& operator=(bool v)+  {+    ipv4_value_ = v ? 1 : 0;+    ipv6_value_ = v ? 1 : 0;+    return *this;+  }++  // Get the current value of the boolean.+  bool value() const+  {+    return !!ipv4_value_;+  }++  // Convert to bool.+  operator bool() const+  {+    return !!ipv4_value_;+  }++  // Test for false.+  bool operator!() const+  {+    return !ipv4_value_;+  }++  // Get the level of the socket option.+  template <typename Protocol>+  int level(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Level;+    return IPv4_Level;+  }++  // Get the name of the socket option.+  template <typename Protocol>+  int name(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Name;+    return IPv4_Name;+  }++  // Get the address of the boolean data.+  template <typename Protocol>+  void* data(const Protocol& protocol)+  {+    if (protocol.family() == PF_INET6)+      return &ipv6_value_;+    return &ipv4_value_;+  }++  // Get the address of the boolean data.+  template <typename Protocol>+  const void* data(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return &ipv6_value_;+    return &ipv4_value_;+  }++  // Get the size of the boolean data.+  template <typename Protocol>+  std::size_t size(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return sizeof(ipv6_value_);+    return sizeof(ipv4_value_);+  }++  // Set the size of the boolean data.+  template <typename Protocol>+  void resize(const Protocol& protocol, std::size_t s)+  {+    if (protocol.family() == PF_INET6)+    {+      if (s != sizeof(ipv6_value_))+      {+        std::length_error ex("multicast_enable_loopback socket option resize");+        asio::detail::throw_exception(ex);+      }+      ipv4_value_ = ipv6_value_ ? 1 : 0;+    }+    else+    {+      if (s != sizeof(ipv4_value_))+      {+        std::length_error ex("multicast_enable_loopback socket option resize");+        asio::detail::throw_exception(ex);+      }+      ipv6_value_ = ipv4_value_ ? 1 : 0;+    }+  }++private:+  ipv4_value_type ipv4_value_;+  ipv6_value_type ipv6_value_;+};++// Helper template for implementing unicast hops options.+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>+class unicast_hops+{+public:+  // Default constructor.+  unicast_hops()+    : value_(0)+  {+  }++  // Construct with a specific option value.+  explicit unicast_hops(int v)+    : value_(v)+  {+  }++  // Set the value of the option.+  unicast_hops& operator=(int v)+  {+    value_ = v;+    return *this;+  }++  // Get the current value of the option.+  int value() const+  {+    return value_;+  }++  // Get the level of the socket option.+  template <typename Protocol>+  int level(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Level;+    return IPv4_Level;+  }++  // Get the name of the socket option.+  template <typename Protocol>+  int name(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Name;+    return IPv4_Name;+  }++  // Get the address of the data.+  template <typename Protocol>+  int* data(const Protocol&)+  {+    return &value_;+  }++  // Get the address of the data.+  template <typename Protocol>+  const int* data(const Protocol&) const+  {+    return &value_;+  }++  // Get the size of the data.+  template <typename Protocol>+  std::size_t size(const Protocol&) const+  {+    return sizeof(value_);+  }++  // Set the size of the data.+  template <typename Protocol>+  void resize(const Protocol&, std::size_t s)+  {+    if (s != sizeof(value_))+    {+      std::length_error ex("unicast hops socket option resize");+      asio::detail::throw_exception(ex);+    }+#if defined(__hpux)+    if (value_ < 0)+      value_ = value_ & 0xFF;+#endif+  }++private:+  int value_;+};++// Helper template for implementing multicast hops options.+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>+class multicast_hops+{+public:+#if defined(ASIO_WINDOWS) && defined(UNDER_CE)+  typedef int ipv4_value_type;+#else+  typedef unsigned char ipv4_value_type;+#endif+  typedef int ipv6_value_type;++  // Default constructor.+  multicast_hops()+    : ipv4_value_(0),+      ipv6_value_(0)+  {+  }++  // Construct with a specific option value.+  explicit multicast_hops(int v)+  {+    if (v < 0 || v > 255)+    {+      std::out_of_range ex("multicast hops value out of range");+      asio::detail::throw_exception(ex);+    }+    ipv4_value_ = (ipv4_value_type)v;+    ipv6_value_ = v;+  }++  // Set the value of the option.+  multicast_hops& operator=(int v)+  {+    if (v < 0 || v > 255)+    {+      std::out_of_range ex("multicast hops value out of range");+      asio::detail::throw_exception(ex);+    }+    ipv4_value_ = (ipv4_value_type)v;+    ipv6_value_ = v;+    return *this;+  }++  // Get the current value of the option.+  int value() const+  {+    return ipv6_value_;+  }++  // Get the level of the socket option.+  template <typename Protocol>+  int level(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Level;+    return IPv4_Level;+  }++  // Get the name of the socket option.+  template <typename Protocol>+  int name(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Name;+    return IPv4_Name;+  }++  // Get the address of the data.+  template <typename Protocol>+  void* data(const Protocol& protocol)+  {+    if (protocol.family() == PF_INET6)+      return &ipv6_value_;+    return &ipv4_value_;+  }++  // Get the address of the data.+  template <typename Protocol>+  const void* data(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return &ipv6_value_;+    return &ipv4_value_;+  }++  // Get the size of the data.+  template <typename Protocol>+  std::size_t size(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return sizeof(ipv6_value_);+    return sizeof(ipv4_value_);+  }++  // Set the size of the data.+  template <typename Protocol>+  void resize(const Protocol& protocol, std::size_t s)+  {+    if (protocol.family() == PF_INET6)+    {+      if (s != sizeof(ipv6_value_))+      {+        std::length_error ex("multicast hops socket option resize");+        asio::detail::throw_exception(ex);+      }+      if (ipv6_value_ < 0)+        ipv4_value_ = 0;+      else if (ipv6_value_ > 255)+        ipv4_value_ = 255;+      else+        ipv4_value_ = (ipv4_value_type)ipv6_value_;+    }+    else+    {+      if (s != sizeof(ipv4_value_))+      {+        std::length_error ex("multicast hops socket option resize");+        asio::detail::throw_exception(ex);+      }+      ipv6_value_ = ipv4_value_;+    }+  }++private:+  ipv4_value_type ipv4_value_;+  ipv6_value_type ipv6_value_;+};++// Helper template for implementing ip_mreq-based options.+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>+class multicast_request+{+public:+  // Default constructor.+  multicast_request()+    : ipv4_value_(), // Zero-initialisation gives the "any" address.+      ipv6_value_() // Zero-initialisation gives the "any" address.+  {+  }++  // Construct with multicast address only.+  explicit multicast_request(const address& multicast_address)+    : ipv4_value_(), // Zero-initialisation gives the "any" address.+      ipv6_value_() // Zero-initialisation gives the "any" address.+  {+    if (multicast_address.is_v6())+    {+      using namespace std; // For memcpy.+      address_v6 ipv6_address = multicast_address.to_v6();+      address_v6::bytes_type bytes = ipv6_address.to_bytes();+      memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);+      ipv6_value_.ipv6mr_interface = ipv6_address.scope_id();+    }+    else+    {+      ipv4_value_.imr_multiaddr.s_addr =+        asio::detail::socket_ops::host_to_network_long(+            multicast_address.to_v4().to_uint());+      ipv4_value_.imr_interface.s_addr =+        asio::detail::socket_ops::host_to_network_long(+            address_v4::any().to_uint());+    }+  }++  // Construct with multicast address and IPv4 address specifying an interface.+  explicit multicast_request(const address_v4& multicast_address,+      const address_v4& network_interface = address_v4::any())+    : ipv6_value_() // Zero-initialisation gives the "any" address.+  {+    ipv4_value_.imr_multiaddr.s_addr =+      asio::detail::socket_ops::host_to_network_long(+          multicast_address.to_uint());+    ipv4_value_.imr_interface.s_addr =+      asio::detail::socket_ops::host_to_network_long(+          network_interface.to_uint());+  }++  // Construct with multicast address and IPv6 network interface index.+  explicit multicast_request(+      const address_v6& multicast_address,+      unsigned long network_interface = 0)+    : ipv4_value_() // Zero-initialisation gives the "any" address.+  {+    using namespace std; // For memcpy.+    address_v6::bytes_type bytes = multicast_address.to_bytes();+    memcpy(ipv6_value_.ipv6mr_multiaddr.s6_addr, bytes.data(), 16);+    if (network_interface)+      ipv6_value_.ipv6mr_interface = network_interface;+    else+      ipv6_value_.ipv6mr_interface = multicast_address.scope_id();+  }++  // Get the level of the socket option.+  template <typename Protocol>+  int level(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Level;+    return IPv4_Level;+  }++  // Get the name of the socket option.+  template <typename Protocol>+  int name(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Name;+    return IPv4_Name;+  }++  // Get the address of the option data.+  template <typename Protocol>+  const void* data(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return &ipv6_value_;+    return &ipv4_value_;+  }++  // Get the size of the option data.+  template <typename Protocol>+  std::size_t size(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return sizeof(ipv6_value_);+    return sizeof(ipv4_value_);+  }++private:+  asio::detail::in4_mreq_type ipv4_value_;+  asio::detail::in6_mreq_type ipv6_value_;+};++// Helper template for implementing options that specify a network interface.+template <int IPv4_Level, int IPv4_Name, int IPv6_Level, int IPv6_Name>+class network_interface+{+public:+  // Default constructor.+  network_interface()+  {+    ipv4_value_.s_addr =+      asio::detail::socket_ops::host_to_network_long(+          address_v4::any().to_uint());+    ipv6_value_ = 0;+  }++  // Construct with IPv4 interface.+  explicit network_interface(const address_v4& ipv4_interface)+  {+    ipv4_value_.s_addr =+      asio::detail::socket_ops::host_to_network_long(+          ipv4_interface.to_uint());+    ipv6_value_ = 0;+  }++  // Construct with IPv6 interface.+  explicit network_interface(unsigned int ipv6_interface)+  {+    ipv4_value_.s_addr =+      asio::detail::socket_ops::host_to_network_long(+          address_v4::any().to_uint());+    ipv6_value_ = ipv6_interface;+  }++  // Get the level of the socket option.+  template <typename Protocol>+  int level(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Level;+    return IPv4_Level;+  }++  // Get the name of the socket option.+  template <typename Protocol>+  int name(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return IPv6_Name;+    return IPv4_Name;+  }++  // Get the address of the option data.+  template <typename Protocol>+  const void* data(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return &ipv6_value_;+    return &ipv4_value_;+  }++  // Get the size of the option data.+  template <typename Protocol>+  std::size_t size(const Protocol& protocol) const+  {+    if (protocol.family() == PF_INET6)+      return sizeof(ipv6_value_);+    return sizeof(ipv4_value_);+  }++private:+  asio::detail::in4_addr_type ipv4_value_;+  unsigned int ipv6_value_;+};++} // namespace socket_option+} // namespace detail+} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_DETAIL_SOCKET_OPTION_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/host_name.hpp view
@@ -0,0 +1,42 @@+//+// ip/host_name.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_HOST_NAME_HPP+#define ASIO_IP_HOST_NAME_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/error_code.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Get the current host name.+ASIO_DECL std::string host_name();++/// Get the current host name.+ASIO_DECL std::string host_name(asio::error_code& ec);++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/ip/impl/host_name.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_IP_HOST_NAME_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/icmp.hpp view
@@ -0,0 +1,115 @@+//+// ip/icmp.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_ICMP_HPP+#define ASIO_IP_ICMP_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/socket_types.hpp"+#include "asio/basic_raw_socket.hpp"+#include "asio/ip/basic_endpoint.hpp"+#include "asio/ip/basic_resolver.hpp"+#include "asio/ip/basic_resolver_iterator.hpp"+#include "asio/ip/basic_resolver_query.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Encapsulates the flags needed for ICMP.+/**+ * The asio::ip::icmp class contains flags necessary for ICMP sockets.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol, InternetProtocol.+ */+class icmp+{+public:+  /// The type of a ICMP endpoint.+  typedef basic_endpoint<icmp> endpoint;++  /// Construct to represent the IPv4 ICMP protocol.+  static icmp v4() ASIO_NOEXCEPT+  {+    return icmp(ASIO_OS_DEF(IPPROTO_ICMP),+        ASIO_OS_DEF(AF_INET));+  }++  /// Construct to represent the IPv6 ICMP protocol.+  static icmp v6() ASIO_NOEXCEPT+  {+    return icmp(ASIO_OS_DEF(IPPROTO_ICMPV6),+        ASIO_OS_DEF(AF_INET6));+  }++  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return ASIO_OS_DEF(SOCK_RAW);+  }++  /// Obtain an identifier for the protocol.+  int protocol() const ASIO_NOEXCEPT+  {+    return protocol_;+  }++  /// Obtain an identifier for the protocol family.+  int family() const ASIO_NOEXCEPT+  {+    return family_;+  }++  /// The ICMP socket type.+  typedef basic_raw_socket<icmp> socket;++  /// The ICMP resolver type.+  typedef basic_resolver<icmp> resolver;++  /// Compare two protocols for equality.+  friend bool operator==(const icmp& p1, const icmp& p2)+  {+    return p1.protocol_ == p2.protocol_ && p1.family_ == p2.family_;+  }++  /// Compare two protocols for inequality.+  friend bool operator!=(const icmp& p1, const icmp& p2)+  {+    return p1.protocol_ != p2.protocol_ || p1.family_ != p2.family_;+  }++private:+  // Construct with a specific family.+  explicit icmp(int protocol_id, int protocol_family) ASIO_NOEXCEPT+    : protocol_(protocol_id),+      family_(protocol_family)+  {+  }++  int protocol_;+  int family_;+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_ICMP_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/address.hpp view
@@ -0,0 +1,67 @@+//+// ip/impl/address.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_IMPL_ADDRESS_HPP+#define ASIO_IP_IMPL_ADDRESS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++#if !defined(ASIO_NO_DEPRECATED)++inline address address::from_string(const char* str)+{+  return asio::ip::make_address(str);+}++inline address address::from_string(+    const char* str, asio::error_code& ec)+{+  return asio::ip::make_address(str, ec);+}++inline address address::from_string(const std::string& str)+{+  return asio::ip::make_address(str);+}++inline address address::from_string(+    const std::string& str, asio::error_code& ec)+{+  return asio::ip::make_address(str, ec);+}++#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const address& addr)+{+  return os << addr.to_string().c_str();+}++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_IOSTREAM)++#endif // ASIO_IP_IMPL_ADDRESS_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/address.ipp view
@@ -0,0 +1,239 @@+//+// ip/impl/address.ipp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_IMPL_ADDRESS_IPP+#define ASIO_IP_IMPL_ADDRESS_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <typeinfo>+#include "asio/detail/throw_error.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/error.hpp"+#include "asio/ip/address.hpp"+#include "asio/ip/bad_address_cast.hpp"+#include "asio/system_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++address::address() ASIO_NOEXCEPT+  : type_(ipv4),+    ipv4_address_(),+    ipv6_address_()+{+}++address::address(+    const asio::ip::address_v4& ipv4_address) ASIO_NOEXCEPT+  : type_(ipv4),+    ipv4_address_(ipv4_address),+    ipv6_address_()+{+}++address::address(+    const asio::ip::address_v6& ipv6_address) ASIO_NOEXCEPT+  : type_(ipv6),+    ipv4_address_(),+    ipv6_address_(ipv6_address)+{+}++address::address(const address& other) ASIO_NOEXCEPT+  : type_(other.type_),+    ipv4_address_(other.ipv4_address_),+    ipv6_address_(other.ipv6_address_)+{+}++#if defined(ASIO_HAS_MOVE)+address::address(address&& other) ASIO_NOEXCEPT+  : type_(other.type_),+    ipv4_address_(other.ipv4_address_),+    ipv6_address_(other.ipv6_address_)+{+}+#endif // defined(ASIO_HAS_MOVE)++address& address::operator=(const address& other) ASIO_NOEXCEPT+{+  type_ = other.type_;+  ipv4_address_ = other.ipv4_address_;+  ipv6_address_ = other.ipv6_address_;+  return *this;+}++#if defined(ASIO_HAS_MOVE)+address& address::operator=(address&& other) ASIO_NOEXCEPT+{+  type_ = other.type_;+  ipv4_address_ = other.ipv4_address_;+  ipv6_address_ = other.ipv6_address_;+  return *this;+}+#endif // defined(ASIO_HAS_MOVE)++address& address::operator=(+    const asio::ip::address_v4& ipv4_address) ASIO_NOEXCEPT+{+  type_ = ipv4;+  ipv4_address_ = ipv4_address;+  ipv6_address_ = asio::ip::address_v6();+  return *this;+}++address& address::operator=(+    const asio::ip::address_v6& ipv6_address) ASIO_NOEXCEPT+{+  type_ = ipv6;+  ipv4_address_ = asio::ip::address_v4();+  ipv6_address_ = ipv6_address;+  return *this;+}++address make_address(const char* str)+{+  asio::error_code ec;+  address addr = make_address(str, ec);+  asio::detail::throw_error(ec);+  return addr;+}++address make_address(const char* str,+    asio::error_code& ec) ASIO_NOEXCEPT+{+  asio::ip::address_v6 ipv6_address =+    asio::ip::make_address_v6(str, ec);+  if (!ec)+    return address(ipv6_address);++  asio::ip::address_v4 ipv4_address =+    asio::ip::make_address_v4(str, ec);+  if (!ec)+    return address(ipv4_address);++  return address();+}++address make_address(const std::string& str)+{+  return make_address(str.c_str());+}++address make_address(const std::string& str,+    asio::error_code& ec) ASIO_NOEXCEPT+{+  return make_address(str.c_str(), ec);+}++#if defined(ASIO_HAS_STRING_VIEW)++address make_address(string_view str)+{+  return make_address(static_cast<std::string>(str));+}++address make_address(string_view str,+    asio::error_code& ec) ASIO_NOEXCEPT+{+  return make_address(static_cast<std::string>(str), ec);+}++#endif // defined(ASIO_HAS_STRING_VIEW)++asio::ip::address_v4 address::to_v4() const+{+  if (type_ != ipv4)+  {+    bad_address_cast ex;+    asio::detail::throw_exception(ex);+  }+  return ipv4_address_;+}++asio::ip::address_v6 address::to_v6() const+{+  if (type_ != ipv6)+  {+    bad_address_cast ex;+    asio::detail::throw_exception(ex);+  }+  return ipv6_address_;+}++std::string address::to_string() const+{+  if (type_ == ipv6)+    return ipv6_address_.to_string();+  return ipv4_address_.to_string();+}++#if !defined(ASIO_NO_DEPRECATED)+std::string address::to_string(asio::error_code& ec) const+{+  if (type_ == ipv6)+    return ipv6_address_.to_string(ec);+  return ipv4_address_.to_string(ec);+}+#endif // !defined(ASIO_NO_DEPRECATED)++bool address::is_loopback() const ASIO_NOEXCEPT+{+  return (type_ == ipv4)+    ? ipv4_address_.is_loopback()+    : ipv6_address_.is_loopback();+}++bool address::is_unspecified() const ASIO_NOEXCEPT+{+  return (type_ == ipv4)+    ? ipv4_address_.is_unspecified()+    : ipv6_address_.is_unspecified();+}++bool address::is_multicast() const ASIO_NOEXCEPT+{+  return (type_ == ipv4)+    ? ipv4_address_.is_multicast()+    : ipv6_address_.is_multicast();+}++bool operator==(const address& a1, const address& a2) ASIO_NOEXCEPT+{+  if (a1.type_ != a2.type_)+    return false;+  if (a1.type_ == address::ipv6)+    return a1.ipv6_address_ == a2.ipv6_address_;+  return a1.ipv4_address_ == a2.ipv4_address_;+}++bool operator<(const address& a1, const address& a2) ASIO_NOEXCEPT+{+  if (a1.type_ < a2.type_)+    return true;+  if (a1.type_ > a2.type_)+    return false;+  if (a1.type_ == address::ipv6)+    return a1.ipv6_address_ < a2.ipv6_address_;+  return a1.ipv4_address_ < a2.ipv4_address_;+}++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_IMPL_ADDRESS_IPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.hpp view
@@ -0,0 +1,67 @@+//+// ip/impl/address_v4.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_IMPL_ADDRESS_V4_HPP+#define ASIO_IP_IMPL_ADDRESS_V4_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++#if !defined(ASIO_NO_DEPRECATED)++inline address_v4 address_v4::from_string(const char* str)+{+  return asio::ip::make_address_v4(str);+}++inline address_v4 address_v4::from_string(+    const char* str, asio::error_code& ec)+{+  return asio::ip::make_address_v4(str, ec);+}++inline address_v4 address_v4::from_string(const std::string& str)+{+  return asio::ip::make_address_v4(str);+}++inline address_v4 address_v4::from_string(+    const std::string& str, asio::error_code& ec)+{+  return asio::ip::make_address_v4(str, ec);+}++#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const address_v4& addr)+{+  return os << addr.to_string().c_str();+}++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_IOSTREAM)++#endif // ASIO_IP_IMPL_ADDRESS_V4_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.ipp view
@@ -0,0 +1,210 @@+//+// ip/impl/address_v4.ipp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_IMPL_ADDRESS_V4_IPP+#define ASIO_IP_IMPL_ADDRESS_V4_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <climits>+#include <limits>+#include <stdexcept>+#include "asio/error.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/ip/address_v4.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++address_v4::address_v4(const address_v4::bytes_type& bytes)+{+#if UCHAR_MAX > 0xFF+  if (bytes[0] > 0xFF || bytes[1] > 0xFF+      || bytes[2] > 0xFF || bytes[3] > 0xFF)+  {+    std::out_of_range ex("address_v4 from bytes_type");+    asio::detail::throw_exception(ex);+  }+#endif // UCHAR_MAX > 0xFF++  using namespace std; // For memcpy.+  memcpy(&addr_.s_addr, bytes.data(), 4);+}++address_v4::address_v4(address_v4::uint_type addr)+{+  if ((std::numeric_limits<uint_type>::max)() > 0xFFFFFFFF)+  {+    std::out_of_range ex("address_v4 from unsigned integer");+    asio::detail::throw_exception(ex);+  }++  addr_.s_addr = asio::detail::socket_ops::host_to_network_long(+      static_cast<asio::detail::u_long_type>(addr));+}++address_v4::bytes_type address_v4::to_bytes() const ASIO_NOEXCEPT+{+  using namespace std; // For memcpy.+  bytes_type bytes;+#if defined(ASIO_HAS_STD_ARRAY)+  memcpy(bytes.data(), &addr_.s_addr, 4);+#else // defined(ASIO_HAS_STD_ARRAY)+  memcpy(bytes.elems, &addr_.s_addr, 4);+#endif // defined(ASIO_HAS_STD_ARRAY)+  return bytes;+}++address_v4::uint_type address_v4::to_uint() const ASIO_NOEXCEPT+{+  return asio::detail::socket_ops::network_to_host_long(addr_.s_addr);+}++#if !defined(ASIO_NO_DEPRECATED)+unsigned long address_v4::to_ulong() const+{+  return asio::detail::socket_ops::network_to_host_long(addr_.s_addr);+}+#endif // !defined(ASIO_NO_DEPRECATED)++std::string address_v4::to_string() const+{+  asio::error_code ec;+  char addr_str[asio::detail::max_addr_v4_str_len];+  const char* addr =+    asio::detail::socket_ops::inet_ntop(+        ASIO_OS_DEF(AF_INET), &addr_, addr_str,+        asio::detail::max_addr_v4_str_len, 0, ec);+  if (addr == 0)+    asio::detail::throw_error(ec);+  return addr;+}++#if !defined(ASIO_NO_DEPRECATED)+std::string address_v4::to_string(asio::error_code& ec) const+{+  char addr_str[asio::detail::max_addr_v4_str_len];+  const char* addr =+    asio::detail::socket_ops::inet_ntop(+        ASIO_OS_DEF(AF_INET), &addr_, addr_str,+        asio::detail::max_addr_v4_str_len, 0, ec);+  if (addr == 0)+    return std::string();+  return addr;+}+#endif // !defined(ASIO_NO_DEPRECATED)++bool address_v4::is_loopback() const ASIO_NOEXCEPT+{+  return (to_uint() & 0xFF000000) == 0x7F000000;+}++bool address_v4::is_unspecified() const ASIO_NOEXCEPT+{+  return to_uint() == 0;+}++#if !defined(ASIO_NO_DEPRECATED)+bool address_v4::is_class_a() const+{+  return (to_uint() & 0x80000000) == 0;+}++bool address_v4::is_class_b() const+{+  return (to_uint() & 0xC0000000) == 0x80000000;+}++bool address_v4::is_class_c() const+{+  return (to_uint() & 0xE0000000) == 0xC0000000;+}+#endif // !defined(ASIO_NO_DEPRECATED)++bool address_v4::is_multicast() const ASIO_NOEXCEPT+{+  return (to_uint() & 0xF0000000) == 0xE0000000;+}++#if !defined(ASIO_NO_DEPRECATED)+address_v4 address_v4::broadcast(const address_v4& addr, const address_v4& mask)+{+  return address_v4(addr.to_uint() | (mask.to_uint() ^ 0xFFFFFFFF));+}++address_v4 address_v4::netmask(const address_v4& addr)+{+  if (addr.is_class_a())+    return address_v4(0xFF000000);+  if (addr.is_class_b())+    return address_v4(0xFFFF0000);+  if (addr.is_class_c())+    return address_v4(0xFFFFFF00);+  return address_v4(0xFFFFFFFF);+}+#endif // !defined(ASIO_NO_DEPRECATED)++address_v4 make_address_v4(const char* str)+{+  asio::error_code ec;+  address_v4 addr = make_address_v4(str, ec);+  asio::detail::throw_error(ec);+  return addr;+}++address_v4 make_address_v4(const char* str,+    asio::error_code& ec) ASIO_NOEXCEPT+{+  address_v4::bytes_type bytes;+  if (asio::detail::socket_ops::inet_pton(+        ASIO_OS_DEF(AF_INET), str, &bytes, 0, ec) <= 0)+    return address_v4();+  return address_v4(bytes);+}++address_v4 make_address_v4(const std::string& str)+{+  return make_address_v4(str.c_str());+}++address_v4 make_address_v4(const std::string& str,+    asio::error_code& ec) ASIO_NOEXCEPT+{+  return make_address_v4(str.c_str(), ec);+}++#if defined(ASIO_HAS_STRING_VIEW)++address_v4 make_address_v4(string_view str)+{+  return make_address_v4(static_cast<std::string>(str));+}++address_v4 make_address_v4(string_view str,+    asio::error_code& ec) ASIO_NOEXCEPT+{+  return make_address_v4(static_cast<std::string>(str), ec);+}++#endif // defined(ASIO_HAS_STRING_VIEW)++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_IMPL_ADDRESS_V4_IPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.hpp view
@@ -0,0 +1,67 @@+//+// ip/impl/address_v6.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_IMPL_ADDRESS_V6_HPP+#define ASIO_IP_IMPL_ADDRESS_V6_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++#if !defined(ASIO_NO_DEPRECATED)++inline address_v6 address_v6::from_string(const char* str)+{+  return asio::ip::make_address_v6(str);+}++inline address_v6 address_v6::from_string(+    const char* str, asio::error_code& ec)+{+  return asio::ip::make_address_v6(str, ec);+}++inline address_v6 address_v6::from_string(const std::string& str)+{+  return asio::ip::make_address_v6(str);+}++inline address_v6 address_v6::from_string(+    const std::string& str, asio::error_code& ec)+{+  return asio::ip::make_address_v6(str, ec);+}++#endif // !defined(ASIO_NO_DEPRECATED)++template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const address_v6& addr)+{+  return os << addr.to_string().c_str();+}++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_IOSTREAM)++#endif // ASIO_IP_IMPL_ADDRESS_V6_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.ipp view
@@ -0,0 +1,350 @@+//+// ip/impl/address_v6.ipp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_IMPL_ADDRESS_V6_IPP+#define ASIO_IP_IMPL_ADDRESS_V6_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <cstring>+#include <stdexcept>+#include <typeinfo>+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/error.hpp"+#include "asio/ip/address_v6.hpp"+#include "asio/ip/bad_address_cast.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++address_v6::address_v6() ASIO_NOEXCEPT+  : addr_(),+    scope_id_(0)+{+}++address_v6::address_v6(const address_v6::bytes_type& bytes,+    unsigned long scope)+  : scope_id_(scope)+{+#if UCHAR_MAX > 0xFF+  for (std::size_t i = 0; i < bytes.size(); ++i)+  {+    if (bytes[i] > 0xFF)+    {+      std::out_of_range ex("address_v6 from bytes_type");+      asio::detail::throw_exception(ex);+    }+  }+#endif // UCHAR_MAX > 0xFF++  using namespace std; // For memcpy.+  memcpy(addr_.s6_addr, bytes.data(), 16);+}++address_v6::address_v6(const address_v6& other) ASIO_NOEXCEPT+  : addr_(other.addr_),+    scope_id_(other.scope_id_)+{+}++#if defined(ASIO_HAS_MOVE)+address_v6::address_v6(address_v6&& other) ASIO_NOEXCEPT+  : addr_(other.addr_),+    scope_id_(other.scope_id_)+{+}+#endif // defined(ASIO_HAS_MOVE)++address_v6& address_v6::operator=(const address_v6& other) ASIO_NOEXCEPT+{+  addr_ = other.addr_;+  scope_id_ = other.scope_id_;+  return *this;+}++#if defined(ASIO_HAS_MOVE)+address_v6& address_v6::operator=(address_v6&& other) ASIO_NOEXCEPT+{+  addr_ = other.addr_;+  scope_id_ = other.scope_id_;+  return *this;+}+#endif // defined(ASIO_HAS_MOVE)++address_v6::bytes_type address_v6::to_bytes() const ASIO_NOEXCEPT+{+  using namespace std; // For memcpy.+  bytes_type bytes;+#if defined(ASIO_HAS_STD_ARRAY)+  memcpy(bytes.data(), addr_.s6_addr, 16);+#else // defined(ASIO_HAS_STD_ARRAY)+  memcpy(bytes.elems, addr_.s6_addr, 16);+#endif // defined(ASIO_HAS_STD_ARRAY)+  return bytes;+}++std::string address_v6::to_string() const+{+  asio::error_code ec;+  char addr_str[asio::detail::max_addr_v6_str_len];+  const char* addr =+    asio::detail::socket_ops::inet_ntop(+        ASIO_OS_DEF(AF_INET6), &addr_, addr_str,+        asio::detail::max_addr_v6_str_len, scope_id_, ec);+  if (addr == 0)+    asio::detail::throw_error(ec);+  return addr;+}++#if !defined(ASIO_NO_DEPRECATED)+std::string address_v6::to_string(asio::error_code& ec) const+{+  char addr_str[asio::detail::max_addr_v6_str_len];+  const char* addr =+    asio::detail::socket_ops::inet_ntop(+        ASIO_OS_DEF(AF_INET6), &addr_, addr_str,+        asio::detail::max_addr_v6_str_len, scope_id_, ec);+  if (addr == 0)+    return std::string();+  return addr;+}++address_v4 address_v6::to_v4() const+{+  if (!is_v4_mapped() && !is_v4_compatible())+  {+    bad_address_cast ex;+    asio::detail::throw_exception(ex);+  }++  address_v4::bytes_type v4_bytes = { { addr_.s6_addr[12],+    addr_.s6_addr[13], addr_.s6_addr[14], addr_.s6_addr[15] } };+  return address_v4(v4_bytes);+}+#endif // !defined(ASIO_NO_DEPRECATED)++bool address_v6::is_loopback() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)+      && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)+      && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)+      && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)+      && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)+      && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)+      && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)+      && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 1));+}++bool address_v6::is_unspecified() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)+      && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)+      && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)+      && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)+      && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)+      && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)+      && (addr_.s6_addr[12] == 0) && (addr_.s6_addr[13] == 0)+      && (addr_.s6_addr[14] == 0) && (addr_.s6_addr[15] == 0));+}++bool address_v6::is_link_local() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0x80));+}++bool address_v6::is_site_local() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0xfe) && ((addr_.s6_addr[1] & 0xc0) == 0xc0));+}++bool address_v6::is_v4_mapped() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)+      && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)+      && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)+      && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)+      && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)+      && (addr_.s6_addr[10] == 0xff) && (addr_.s6_addr[11] == 0xff));+}++#if !defined(ASIO_NO_DEPRECATED)+bool address_v6::is_v4_compatible() const+{+  return ((addr_.s6_addr[0] == 0) && (addr_.s6_addr[1] == 0)+      && (addr_.s6_addr[2] == 0) && (addr_.s6_addr[3] == 0)+      && (addr_.s6_addr[4] == 0) && (addr_.s6_addr[5] == 0)+      && (addr_.s6_addr[6] == 0) && (addr_.s6_addr[7] == 0)+      && (addr_.s6_addr[8] == 0) && (addr_.s6_addr[9] == 0)+      && (addr_.s6_addr[10] == 0) && (addr_.s6_addr[11] == 0)+      && !((addr_.s6_addr[12] == 0)+        && (addr_.s6_addr[13] == 0)+        && (addr_.s6_addr[14] == 0)+        && ((addr_.s6_addr[15] == 0) || (addr_.s6_addr[15] == 1))));+}+#endif // !defined(ASIO_NO_DEPRECATED)++bool address_v6::is_multicast() const ASIO_NOEXCEPT+{+  return (addr_.s6_addr[0] == 0xff);+}++bool address_v6::is_multicast_global() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x0e));+}++bool address_v6::is_multicast_link_local() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x02));+}++bool address_v6::is_multicast_node_local() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x01));+}++bool address_v6::is_multicast_org_local() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x08));+}++bool address_v6::is_multicast_site_local() const ASIO_NOEXCEPT+{+  return ((addr_.s6_addr[0] == 0xff) && ((addr_.s6_addr[1] & 0x0f) == 0x05));+}++bool operator==(const address_v6& a1, const address_v6& a2) ASIO_NOEXCEPT+{+  using namespace std; // For memcmp.+  return memcmp(&a1.addr_, &a2.addr_,+      sizeof(asio::detail::in6_addr_type)) == 0+    && a1.scope_id_ == a2.scope_id_;+}++bool operator<(const address_v6& a1, const address_v6& a2) ASIO_NOEXCEPT+{+  using namespace std; // For memcmp.+  int memcmp_result = memcmp(&a1.addr_, &a2.addr_,+      sizeof(asio::detail::in6_addr_type));+  if (memcmp_result < 0)+    return true;+  if (memcmp_result > 0)+    return false;+  return a1.scope_id_ < a2.scope_id_;+}++address_v6 address_v6::loopback() ASIO_NOEXCEPT+{+  address_v6 tmp;+  tmp.addr_.s6_addr[15] = 1;+  return tmp;+}++#if !defined(ASIO_NO_DEPRECATED)+address_v6 address_v6::v4_mapped(const address_v4& addr)+{+  address_v4::bytes_type v4_bytes = addr.to_bytes();+  bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xFF, 0xFF,+    v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };+  return address_v6(v6_bytes);+}++address_v6 address_v6::v4_compatible(const address_v4& addr)+{+  address_v4::bytes_type v4_bytes = addr.to_bytes();+  bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+    v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };+  return address_v6(v6_bytes);+}+#endif // !defined(ASIO_NO_DEPRECATED)++address_v6 make_address_v6(const char* str)+{+  asio::error_code ec;+  address_v6 addr = make_address_v6(str, ec);+  asio::detail::throw_error(ec);+  return addr;+}++address_v6 make_address_v6(const char* str,+    asio::error_code& ec) ASIO_NOEXCEPT+{+  address_v6::bytes_type bytes;+  unsigned long scope_id = 0;+  if (asio::detail::socket_ops::inet_pton(+        ASIO_OS_DEF(AF_INET6), str, &bytes[0], &scope_id, ec) <= 0)+    return address_v6();+  return address_v6(bytes, scope_id);+}++address_v6 make_address_v6(const std::string& str)+{+  return make_address_v6(str.c_str());+}++address_v6 make_address_v6(const std::string& str,+    asio::error_code& ec) ASIO_NOEXCEPT+{+  return make_address_v6(str.c_str(), ec);+}++#if defined(ASIO_HAS_STRING_VIEW)++address_v6 make_address_v6(string_view str)+{+  return make_address_v6(static_cast<std::string>(str));+}++address_v6 make_address_v6(string_view str,+    asio::error_code& ec) ASIO_NOEXCEPT+{+  return make_address_v6(static_cast<std::string>(str), ec);+}++#endif // defined(ASIO_HAS_STRING_VIEW)++address_v4 make_address_v4(+    v4_mapped_t, const address_v6& v6_addr)+{+  if (!v6_addr.is_v4_mapped())+  {+    bad_address_cast ex;+    asio::detail::throw_exception(ex);+  }++  address_v6::bytes_type v6_bytes = v6_addr.to_bytes();+  address_v4::bytes_type v4_bytes = { { v6_bytes[12],+    v6_bytes[13], v6_bytes[14], v6_bytes[15] } };+  return address_v4(v4_bytes);+}++address_v6 make_address_v6(+    v4_mapped_t, const address_v4& v4_addr)+{+  address_v4::bytes_type v4_bytes = v4_addr.to_bytes();+  address_v6::bytes_type v6_bytes = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,+    0xFF, 0xFF, v4_bytes[0], v4_bytes[1], v4_bytes[2], v4_bytes[3] } };+  return address_v6(v6_bytes);+}++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_IMPL_ADDRESS_V6_IPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/basic_endpoint.hpp view
@@ -0,0 +1,43 @@+//+// ip/impl/basic_endpoint.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_IMPL_BASIC_ENDPOINT_HPP+#define ASIO_IP_IMPL_BASIC_ENDPOINT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++template <typename Elem, typename Traits, typename InternetProtocol>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os,+    const basic_endpoint<InternetProtocol>& endpoint)+{+  asio::ip::detail::endpoint tmp_ep(endpoint.address(), endpoint.port());+  return os << tmp_ep.to_string().c_str();+}++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_IOSTREAM)++#endif // ASIO_IP_IMPL_BASIC_ENDPOINT_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/host_name.ipp view
@@ -0,0 +1,54 @@+//+// ip/impl/host_name.ipp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_IMPL_HOST_NAME_IPP+#define ASIO_IP_IMPL_HOST_NAME_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/winsock_init.hpp"+#include "asio/ip/host_name.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++std::string host_name()+{+  char name[1024];+  asio::error_code ec;+  if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)+  {+    asio::detail::throw_error(ec);+    return std::string();+  }+  return std::string(name);+}++std::string host_name(asio::error_code& ec)+{+  char name[1024];+  if (asio::detail::socket_ops::gethostname(name, sizeof(name), ec) != 0)+    return std::string();+  return std::string(name);+}++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_IMPL_HOST_NAME_IPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.hpp view
@@ -0,0 +1,54 @@+//+// ip/impl/network_v4.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail 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_IP_IMPL_NETWORK_V4_HPP+#define ASIO_IP_IMPL_NETWORK_V4_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const network_v4& addr)+{+  asio::error_code ec;+  std::string s = addr.to_string(ec);+  if (ec)+  {+    if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)+      asio::detail::throw_error(ec);+    else+      os.setstate(std::basic_ostream<Elem, Traits>::failbit);+  }+  else+    for (std::string::iterator i = s.begin(); i != s.end(); ++i)+      os << os.widen(*i);+  return os;+}++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_IOSTREAM)++#endif // ASIO_IP_IMPL_NETWORK_V4_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.ipp view
@@ -0,0 +1,216 @@+//+// ip/impl/network_v4.ipp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail 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_IP_IMPL_NETWORK_V4_IPP+#define ASIO_IP_IMPL_NETWORK_V4_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <climits>+#include <cstdio>+#include <cstdlib>+#include <stdexcept>+#include "asio/error.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/ip/network_v4.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++network_v4::network_v4(const address_v4& addr, unsigned short prefix_len)+  : address_(addr),+    prefix_length_(prefix_len)+{+  if (prefix_len > 32)+  {+    std::out_of_range ex("prefix length too large");+    asio::detail::throw_exception(ex);+  }+}++network_v4::network_v4(const address_v4& addr, const address_v4& mask)+  : address_(addr),+    prefix_length_(0)+{+  address_v4::bytes_type mask_bytes = mask.to_bytes();+  bool finished = false;+  for (std::size_t i = 0; i < mask_bytes.size(); ++i)+  {+    if (finished)+    {+      if (mask_bytes[i])+      {+        std::invalid_argument ex("non-contiguous netmask");+        asio::detail::throw_exception(ex);+      }+      continue;+    }+    else+    {+      switch (mask_bytes[i])+      {+      case 255:+        prefix_length_ += 8;+        break;+      case 254: // prefix_length_ += 7+        prefix_length_ += 1;+      case 252: // prefix_length_ += 6+        prefix_length_ += 1;+      case 248: // prefix_length_ += 5+        prefix_length_ += 1;+      case 240: // prefix_length_ += 4+        prefix_length_ += 1;+      case 224: // prefix_length_ += 3+        prefix_length_ += 1;+      case 192: // prefix_length_ += 2+        prefix_length_ += 1;+      case 128: // prefix_length_ += 1+        prefix_length_ += 1;+      case 0:   // nbits += 0+        finished = true;+        break;+      default:+        std::out_of_range ex("non-contiguous netmask");+        asio::detail::throw_exception(ex);+      }+    }+  }+}++address_v4 network_v4::netmask() const ASIO_NOEXCEPT+{+  uint32_t nmbits = 0xffffffff;+  if (prefix_length_ == 0)+    nmbits = 0;+  else+    nmbits = nmbits << (32 - prefix_length_);+  return address_v4(nmbits);+}++address_v4_range network_v4::hosts() const ASIO_NOEXCEPT+{+  return is_host()+    ? address_v4_range(address_, address_v4(address_.to_uint() + 1))+    : address_v4_range(address_v4(network().to_uint() + 1), broadcast());+}++bool network_v4::is_subnet_of(const network_v4& other) const+{+  if (other.prefix_length_ >= prefix_length_)+    return false; // Only real subsets are allowed.+  const network_v4 me(address_, other.prefix_length_);+  return other.canonical() == me.canonical();+}++std::string network_v4::to_string() const+{+  asio::error_code ec;+  std::string addr = to_string(ec);+  asio::detail::throw_error(ec);+  return addr;+}++std::string network_v4::to_string(asio::error_code& ec) const+{+  using namespace std; // For sprintf.+  ec = asio::error_code();+  char prefix_len[16];+#if defined(ASIO_HAS_SECURE_RTL)+  sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_);+#else // defined(ASIO_HAS_SECURE_RTL)+  sprintf(prefix_len, "/%u", prefix_length_);+#endif // defined(ASIO_HAS_SECURE_RTL)+  return address_.to_string() + prefix_len;+}++network_v4 make_network_v4(const char* str)+{+  return make_network_v4(std::string(str));+}++network_v4 make_network_v4(const char* str, asio::error_code& ec)+{+  return make_network_v4(std::string(str), ec);+}++network_v4 make_network_v4(const std::string& str)+{+  asio::error_code ec;+  network_v4 net = make_network_v4(str, ec);+  asio::detail::throw_error(ec);+  return net;+}++network_v4 make_network_v4(const std::string& str,+    asio::error_code& ec)+{+  std::string::size_type pos = str.find_first_of("/");++  if (pos == std::string::npos)+  {+    ec = asio::error::invalid_argument;+    return network_v4();+  }++  if (pos == str.size() - 1)+  {+    ec = asio::error::invalid_argument;+    return network_v4();+  }++  std::string::size_type end = str.find_first_not_of("0123456789", pos + 1);+  if (end != std::string::npos)+  {+    ec = asio::error::invalid_argument;+    return network_v4();+  }++  const address_v4 addr = make_address_v4(str.substr(0, pos), ec);+  if (ec)+    return network_v4();++  const int prefix_len = std::atoi(str.substr(pos + 1).c_str());+  if (prefix_len < 0 || prefix_len > 32)+  {+    ec = asio::error::invalid_argument;+    return network_v4();+  }++  return network_v4(addr, static_cast<unsigned short>(prefix_len));+}++#if defined(ASIO_HAS_STRING_VIEW)++network_v4 make_network_v4(string_view str)+{+  return make_network_v4(static_cast<std::string>(str));+}++network_v4 make_network_v4(string_view str,+    asio::error_code& ec)+{+  return make_network_v4(static_cast<std::string>(str), ec);+}++#endif // defined(ASIO_HAS_STRING_VIEW)++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_IMPL_NETWORK_V4_IPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.hpp view
@@ -0,0 +1,53 @@+//+// ip/impl/network_v6.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_IMPL_NETWORK_V6_HPP+#define ASIO_IP_IMPL_NETWORK_V6_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const network_v6& addr)+{+  asio::error_code ec;+  std::string s = addr.to_string(ec);+  if (ec)+  {+    if (os.exceptions() & std::basic_ostream<Elem, Traits>::failbit)+      asio::detail::throw_error(ec);+    else+      os.setstate(std::basic_ostream<Elem, Traits>::failbit);+  }+  else+    for (std::string::iterator i = s.begin(); i != s.end(); ++i)+      os << os.widen(*i);+  return os;+}++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_IOSTREAM)++#endif // ASIO_IP_IMPL_NETWORK_V6_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.ipp view
@@ -0,0 +1,185 @@+//+// ip/impl/network_v6.ipp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail 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_IP_IMPL_NETWORK_V6_IPP+#define ASIO_IP_IMPL_NETWORK_V6_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <climits>+#include <cstdio>+#include <cstdlib>+#include <stdexcept>+#include "asio/error.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/throw_exception.hpp"+#include "asio/ip/network_v6.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++network_v6::network_v6(const address_v6& addr, unsigned short prefix_len)+  : address_(addr),+    prefix_length_(prefix_len)+{+  if (prefix_len > 128)+  {+    std::out_of_range ex("prefix length too large");+    asio::detail::throw_exception(ex);+  }+}++ASIO_DECL address_v6 network_v6::network() const ASIO_NOEXCEPT+{+  address_v6::bytes_type bytes(address_.to_bytes());+  for (std::size_t i = 0; i < 16; ++i)+  {+    if (prefix_length_ <= i * 8)+      bytes[i] = 0;+    else if (prefix_length_ < (i + 1) * 8)+      bytes[i] &= 0xFF00 >> (prefix_length_ % 8);+  }+  return address_v6(bytes, address_.scope_id());+}++address_v6_range network_v6::hosts() const ASIO_NOEXCEPT+{+  address_v6::bytes_type begin_bytes(address_.to_bytes());+  address_v6::bytes_type end_bytes(address_.to_bytes());+  for (std::size_t i = 0; i < 16; ++i)+  {+    if (prefix_length_ <= i * 8)+    {+      begin_bytes[i] = 0;+      end_bytes[i] = 0xFF;+    }+    else if (prefix_length_ < (i + 1) * 8)+    {+      begin_bytes[i] &= 0xFF00 >> (prefix_length_ % 8);+      end_bytes[i] |= 0xFF >> (prefix_length_ % 8);+    }+  }+  return address_v6_range(+      address_v6_iterator(address_v6(begin_bytes, address_.scope_id())),+      ++address_v6_iterator(address_v6(end_bytes, address_.scope_id())));+}++bool network_v6::is_subnet_of(const network_v6& other) const+{+  if (other.prefix_length_ >= prefix_length_)+    return false; // Only real subsets are allowed.+  const network_v6 me(address_, other.prefix_length_);+  return other.canonical() == me.canonical();+}++std::string network_v6::to_string() const+{+  asio::error_code ec;+  std::string addr = to_string(ec);+  asio::detail::throw_error(ec);+  return addr;+}++std::string network_v6::to_string(asio::error_code& ec) const+{+  using namespace std; // For sprintf.+  ec = asio::error_code();+  char prefix_len[16];+#if defined(ASIO_HAS_SECURE_RTL)+  sprintf_s(prefix_len, sizeof(prefix_len), "/%u", prefix_length_);+#else // defined(ASIO_HAS_SECURE_RTL)+  sprintf(prefix_len, "/%u", prefix_length_);+#endif // defined(ASIO_HAS_SECURE_RTL)+  return address_.to_string() + prefix_len;+}++network_v6 make_network_v6(const char* str)+{+  return make_network_v6(std::string(str));+}++network_v6 make_network_v6(const char* str, asio::error_code& ec)+{+  return make_network_v6(std::string(str), ec);+}++network_v6 make_network_v6(const std::string& str)+{+  asio::error_code ec;+  network_v6 net = make_network_v6(str, ec);+  asio::detail::throw_error(ec);+  return net;+}++network_v6 make_network_v6(const std::string& str,+    asio::error_code& ec)+{+  std::string::size_type pos = str.find_first_of("/");++  if (pos == std::string::npos)+  {+    ec = asio::error::invalid_argument;+    return network_v6();+  }++  if (pos == str.size() - 1)+  {+    ec = asio::error::invalid_argument;+    return network_v6();+  }++  std::string::size_type end = str.find_first_not_of("0123456789", pos + 1);+  if (end != std::string::npos)+  {+    ec = asio::error::invalid_argument;+    return network_v6();+  }++  const address_v6 addr = make_address_v6(str.substr(0, pos), ec);+  if (ec)+    return network_v6();++  const int prefix_len = std::atoi(str.substr(pos + 1).c_str());+  if (prefix_len < 0 || prefix_len > 128)+  {+    ec = asio::error::invalid_argument;+    return network_v6();+  }++  return network_v6(addr, static_cast<unsigned short>(prefix_len));+}++#if defined(ASIO_HAS_STRING_VIEW)++network_v6 make_network_v6(string_view str)+{+  return make_network_v6(static_cast<std::string>(str));+}++network_v6 make_network_v6(string_view str,+    asio::error_code& ec)+{+  return make_network_v6(static_cast<std::string>(str), ec);+}++#endif // defined(ASIO_HAS_STRING_VIEW)++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_IMPL_NETWORK_V6_IPP
+ link/modules/asio-standalone/asio/include/asio/ip/multicast.hpp view
@@ -0,0 +1,191 @@+//+// ip/multicast.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_MULTICAST_HPP+#define ASIO_IP_MULTICAST_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/ip/detail/socket_option.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {+namespace multicast {++/// Socket option to join a multicast group on a specified interface.+/**+ * Implements the IPPROTO_IP/IP_ADD_MEMBERSHIP socket option.+ *+ * @par Examples+ * Setting the option to join a multicast group:+ * @code+ * asio::ip::udp::socket socket(my_context);+ * ...+ * asio::ip::address multicast_address =+ *   asio::ip::address::from_string("225.0.0.1");+ * asio::ip::multicast::join_group option(multicast_address);+ * socket.set_option(option);+ * @endcode+ *+ * @par Concepts:+ * SettableSocketOption.+ */+#if defined(GENERATING_DOCUMENTATION)+typedef implementation_defined join_group;+#else+typedef asio::ip::detail::socket_option::multicast_request<+  ASIO_OS_DEF(IPPROTO_IP),+  ASIO_OS_DEF(IP_ADD_MEMBERSHIP),+  ASIO_OS_DEF(IPPROTO_IPV6),+  ASIO_OS_DEF(IPV6_JOIN_GROUP)> join_group;+#endif++/// Socket option to leave a multicast group on a specified interface.+/**+ * Implements the IPPROTO_IP/IP_DROP_MEMBERSHIP socket option.+ *+ * @par Examples+ * Setting the option to leave a multicast group:+ * @code+ * asio::ip::udp::socket socket(my_context);+ * ...+ * asio::ip::address multicast_address =+ *   asio::ip::address::from_string("225.0.0.1");+ * asio::ip::multicast::leave_group option(multicast_address);+ * socket.set_option(option);+ * @endcode+ *+ * @par Concepts:+ * SettableSocketOption.+ */+#if defined(GENERATING_DOCUMENTATION)+typedef implementation_defined leave_group;+#else+typedef asio::ip::detail::socket_option::multicast_request<+  ASIO_OS_DEF(IPPROTO_IP),+  ASIO_OS_DEF(IP_DROP_MEMBERSHIP),+  ASIO_OS_DEF(IPPROTO_IPV6),+  ASIO_OS_DEF(IPV6_LEAVE_GROUP)> leave_group;+#endif++/// Socket option for local interface to use for outgoing multicast packets.+/**+ * Implements the IPPROTO_IP/IP_MULTICAST_IF socket option.+ *+ * @par Examples+ * Setting the option:+ * @code+ * asio::ip::udp::socket socket(my_context);+ * ...+ * asio::ip::address_v4 local_interface =+ *   asio::ip::address_v4::from_string("1.2.3.4");+ * asio::ip::multicast::outbound_interface option(local_interface);+ * socket.set_option(option);+ * @endcode+ *+ * @par Concepts:+ * SettableSocketOption.+ */+#if defined(GENERATING_DOCUMENTATION)+typedef implementation_defined outbound_interface;+#else+typedef asio::ip::detail::socket_option::network_interface<+  ASIO_OS_DEF(IPPROTO_IP),+  ASIO_OS_DEF(IP_MULTICAST_IF),+  ASIO_OS_DEF(IPPROTO_IPV6),+  ASIO_OS_DEF(IPV6_MULTICAST_IF)> outbound_interface;+#endif++/// Socket option for time-to-live associated with outgoing multicast packets.+/**+ * Implements the IPPROTO_IP/IP_MULTICAST_TTL socket option.+ *+ * @par Examples+ * Setting the option:+ * @code+ * asio::ip::udp::socket socket(my_context);+ * ...+ * asio::ip::multicast::hops option(4);+ * socket.set_option(option);+ * @endcode+ *+ * @par+ * Getting the current option value:+ * @code+ * asio::ip::udp::socket socket(my_context);+ * ...+ * asio::ip::multicast::hops option;+ * socket.get_option(option);+ * int ttl = option.value();+ * @endcode+ *+ * @par Concepts:+ * GettableSocketOption, SettableSocketOption.+ */+#if defined(GENERATING_DOCUMENTATION)+typedef implementation_defined hops;+#else+typedef asio::ip::detail::socket_option::multicast_hops<+  ASIO_OS_DEF(IPPROTO_IP),+  ASIO_OS_DEF(IP_MULTICAST_TTL),+  ASIO_OS_DEF(IPPROTO_IPV6),+  ASIO_OS_DEF(IPV6_MULTICAST_HOPS)> hops;+#endif++/// Socket option determining whether outgoing multicast packets will be+/// received on the same socket if it is a member of the multicast group.+/**+ * Implements the IPPROTO_IP/IP_MULTICAST_LOOP socket option.+ *+ * @par Examples+ * Setting the option:+ * @code+ * asio::ip::udp::socket socket(my_context);+ * ...+ * asio::ip::multicast::enable_loopback option(true);+ * socket.set_option(option);+ * @endcode+ *+ * @par+ * Getting the current option value:+ * @code+ * asio::ip::udp::socket socket(my_context);+ * ...+ * asio::ip::multicast::enable_loopback option;+ * socket.get_option(option);+ * bool is_set = option.value();+ * @endcode+ *+ * @par Concepts:+ * GettableSocketOption, SettableSocketOption.+ */+#if defined(GENERATING_DOCUMENTATION)+typedef implementation_defined enable_loopback;+#else+typedef asio::ip::detail::socket_option::multicast_enable_loopback<+  ASIO_OS_DEF(IPPROTO_IP),+  ASIO_OS_DEF(IP_MULTICAST_LOOP),+  ASIO_OS_DEF(IPPROTO_IPV6),+  ASIO_OS_DEF(IPV6_MULTICAST_LOOP)> enable_loopback;+#endif++} // namespace multicast+} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_MULTICAST_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/network_v4.hpp view
@@ -0,0 +1,261 @@+//+// ip/network_v4.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail 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_IP_NETWORK_V4_HPP+#define ASIO_IP_NETWORK_V4_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/detail/string_view.hpp"+#include "asio/error_code.hpp"+#include "asio/ip/address_v4_range.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Represents an IPv4 network.+/**+ * The asio::ip::network_v4 class provides the ability to use and+ * manipulate IP version 4 networks.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+class network_v4+{+public:+  /// Default constructor.+  network_v4() ASIO_NOEXCEPT+    : address_(),+      prefix_length_(0)+  {+  }++  /// Construct a network based on the specified address and prefix length.+  ASIO_DECL network_v4(const address_v4& addr,+      unsigned short prefix_len);++  /// Construct network based on the specified address and netmask.+  ASIO_DECL network_v4(const address_v4& addr,+      const address_v4& mask);++  /// Copy constructor.+  network_v4(const network_v4& other) ASIO_NOEXCEPT+    : address_(other.address_),+      prefix_length_(other.prefix_length_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  network_v4(network_v4&& other) ASIO_NOEXCEPT+    : address_(ASIO_MOVE_CAST(address_v4)(other.address_)),+      prefix_length_(other.prefix_length_)+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Assign from another network.+  network_v4& operator=(const network_v4& other) ASIO_NOEXCEPT+  {+    address_ = other.address_;+    prefix_length_ = other.prefix_length_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  /// Move-assign from another network.+  network_v4& operator=(network_v4&& other) ASIO_NOEXCEPT+  {+    address_ = ASIO_MOVE_CAST(address_v4)(other.address_);+    prefix_length_ = other.prefix_length_;+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Obtain the address object specified when the network object was created.+  address_v4 address() const ASIO_NOEXCEPT+  {+    return address_;+  }++  /// Obtain the prefix length that was specified when the network object was+  /// created.+  unsigned short prefix_length() const ASIO_NOEXCEPT+  {+    return prefix_length_;+  }++  /// Obtain the netmask that was specified when the network object was created.+  ASIO_DECL address_v4 netmask() const ASIO_NOEXCEPT;++  /// Obtain an address object that represents the network address.+  address_v4 network() const ASIO_NOEXCEPT+  {+    return address_v4(address_.to_uint() & netmask().to_uint());+  }++  /// Obtain an address object that represents the network's broadcast address.+  address_v4 broadcast() const ASIO_NOEXCEPT+  {+    return address_v4(network().to_uint() | (netmask().to_uint() ^ 0xFFFFFFFF));+  }++  /// Obtain an address range corresponding to the hosts in the network.+  ASIO_DECL address_v4_range hosts() const ASIO_NOEXCEPT;++  /// Obtain the true network address, omitting any host bits.+  network_v4 canonical() const ASIO_NOEXCEPT+  {+    return network_v4(network(), netmask());+  }++  /// Test if network is a valid host address.+  bool is_host() const ASIO_NOEXCEPT+  {+    return prefix_length_ == 32;+  }++  /// Test if a network is a real subnet of another network.+  ASIO_DECL bool is_subnet_of(const network_v4& other) const;++  /// Get the network as an address in dotted decimal format.+  ASIO_DECL std::string to_string() const;++  /// Get the network as an address in dotted decimal format.+  ASIO_DECL std::string to_string(asio::error_code& ec) const;++  /// Compare two networks for equality.+  friend bool operator==(const network_v4& a, const network_v4& b)+  {+    return a.address_ == b.address_ && a.prefix_length_ == b.prefix_length_;+  }++  /// Compare two networks for inequality.+  friend bool operator!=(const network_v4& a, const network_v4& b)+  {+    return !(a == b);+  }++private:+  address_v4 address_;+  unsigned short prefix_length_;+};++/// Create an IPv4 network from an address and prefix length.+/**+ * @relates address_v4+ */+inline network_v4 make_network_v4(+    const address_v4& addr, unsigned short prefix_len)+{+  return network_v4(addr, prefix_len);+}++/// Create an IPv4 network from an address and netmask.+/**+ * @relates address_v4+ */+inline network_v4 make_network_v4(+    const address_v4& addr, const address_v4& mask)+{+  return network_v4(addr, mask);+}++/// Create an IPv4 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v4+ */+ASIO_DECL network_v4 make_network_v4(const char* str);++/// Create an IPv4 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v4+ */+ASIO_DECL network_v4 make_network_v4(+    const char* str, asio::error_code& ec);++/// Create an IPv4 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v4+ */+ASIO_DECL network_v4 make_network_v4(const std::string& str);++/// Create an IPv4 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v4+ */+ASIO_DECL network_v4 make_network_v4(+    const std::string& str, asio::error_code& ec);++#if defined(ASIO_HAS_STRING_VIEW) \+  || defined(GENERATING_DOCUMENTATION)++/// Create an IPv4 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v4+ */+ASIO_DECL network_v4 make_network_v4(string_view str);++/// Create an IPv4 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v4+ */+ASIO_DECL network_v4 make_network_v4(+    string_view str, asio::error_code& ec);++#endif // defined(ASIO_HAS_STRING_VIEW)+       //  || defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_NO_IOSTREAM)++/// Output a network as a string.+/**+ * Used to output a human-readable string for a specified network.+ *+ * @param os The output stream to which the string will be written.+ *+ * @param net The network to be written.+ *+ * @return The output stream.+ *+ * @relates asio::ip::address_v4+ */+template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const network_v4& net);++#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/ip/impl/network_v4.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/ip/impl/network_v4.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_IP_NETWORK_V4_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/network_v6.hpp view
@@ -0,0 +1,235 @@+//+// ip/network_v6.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2014 Oliver Kowalke (oliver dot kowalke at gmail 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_IP_NETWORK_V6_HPP+#define ASIO_IP_NETWORK_V6_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <string>+#include "asio/detail/string_view.hpp"+#include "asio/error_code.hpp"+#include "asio/ip/address_v6_range.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Represents an IPv6 network.+/**+ * The asio::ip::network_v6 class provides the ability to use and+ * manipulate IP version 6 networks.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+class network_v6+{+public:+  /// Default constructor.+  network_v6() ASIO_NOEXCEPT+    : address_(),+      prefix_length_(0)+  {+  }++  /// Construct a network based on the specified address and prefix length.+  ASIO_DECL network_v6(const address_v6& addr,+      unsigned short prefix_len);++  /// Copy constructor.+  network_v6(const network_v6& other) ASIO_NOEXCEPT+    : address_(other.address_),+      prefix_length_(other.prefix_length_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  network_v6(network_v6&& other) ASIO_NOEXCEPT+    : address_(ASIO_MOVE_CAST(address_v6)(other.address_)),+      prefix_length_(other.prefix_length_)+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Assign from another network.+  network_v6& operator=(const network_v6& other) ASIO_NOEXCEPT+  {+    address_ = other.address_;+    prefix_length_ = other.prefix_length_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  /// Move-assign from another network.+  network_v6& operator=(network_v6&& other) ASIO_NOEXCEPT+  {+    address_ = ASIO_MOVE_CAST(address_v6)(other.address_);+    prefix_length_ = other.prefix_length_;+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Obtain the address object specified when the network object was created.+  address_v6 address() const ASIO_NOEXCEPT+  {+    return address_;+  }++  /// Obtain the prefix length that was specified when the network object was+  /// created.+  unsigned short prefix_length() const ASIO_NOEXCEPT+  {+    return prefix_length_;+  }++  /// Obtain an address object that represents the network address.+  ASIO_DECL address_v6 network() const ASIO_NOEXCEPT;++  /// Obtain an address range corresponding to the hosts in the network.+  ASIO_DECL address_v6_range hosts() const ASIO_NOEXCEPT;++  /// Obtain the true network address, omitting any host bits.+  network_v6 canonical() const ASIO_NOEXCEPT+  {+    return network_v6(network(), prefix_length());+  }++  /// Test if network is a valid host address.+  bool is_host() const ASIO_NOEXCEPT+  {+    return prefix_length_ == 128;+  }++  /// Test if a network is a real subnet of another network.+  ASIO_DECL bool is_subnet_of(const network_v6& other) const;++  /// Get the network as an address in dotted decimal format.+  ASIO_DECL std::string to_string() const;++  /// Get the network as an address in dotted decimal format.+  ASIO_DECL std::string to_string(asio::error_code& ec) const;++  /// Compare two networks for equality.+  friend bool operator==(const network_v6& a, const network_v6& b)+  {+    return a.address_ == b.address_ && a.prefix_length_ == b.prefix_length_;+  }++  /// Compare two networks for inequality.+  friend bool operator!=(const network_v6& a, const network_v6& b)+  {+    return !(a == b);+  }++private:+  address_v6 address_;+  unsigned short prefix_length_;+};++/// Create an IPv6 network from an address and prefix length.+/**+ * @relates address_v6+ */+inline network_v6 make_network_v6(+    const address_v6& addr, unsigned short prefix_len)+{+  return network_v6(addr, prefix_len);+}++/// Create an IPv6 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v6+ */+ASIO_DECL network_v6 make_network_v6(const char* str);++/// Create an IPv6 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v6+ */+ASIO_DECL network_v6 make_network_v6(+    const char* str, asio::error_code& ec);++/// Create an IPv6 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v6+ */+ASIO_DECL network_v6 make_network_v6(const std::string& str);++/// Create an IPv6 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v6+ */+ASIO_DECL network_v6 make_network_v6(+    const std::string& str, asio::error_code& ec);++#if defined(ASIO_HAS_STRING_VIEW) \+  || defined(GENERATING_DOCUMENTATION)++/// Create an IPv6 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v6+ */+ASIO_DECL network_v6 make_network_v6(string_view str);++/// Create an IPv6 network from a string containing IP address and prefix+/// length.+/**+ * @relates network_v6+ */+ASIO_DECL network_v6 make_network_v6(+    string_view str, asio::error_code& ec);++#endif // defined(ASIO_HAS_STRING_VIEW)+       //  || defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_NO_IOSTREAM)++/// Output a network as a string.+/**+ * Used to output a human-readable string for a specified network.+ *+ * @param os The output stream to which the string will be written.+ *+ * @param net The network to be written.+ *+ * @return The output stream.+ *+ * @relates asio::ip::address_v6+ */+template <typename Elem, typename Traits>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os, const network_v6& net);++#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/ip/impl/network_v6.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/ip/impl/network_v6.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_IP_NETWORK_V6_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/resolver_base.hpp view
@@ -0,0 +1,129 @@+//+// ip/resolver_base.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_RESOLVER_BASE_HPP+#define ASIO_IP_RESOLVER_BASE_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/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// The resolver_base class is used as a base for the basic_resolver class+/// templates to provide a common place to define the flag constants.+class resolver_base+{+public:+#if defined(GENERATING_DOCUMENTATION)+  /// A bitmask type (C++ Std [lib.bitmask.types]).+  typedef unspecified flags;++  /// Determine the canonical name of the host specified in the query.+  static const flags canonical_name = implementation_defined;++  /// Indicate that returned endpoint is intended for use as a locally bound+  /// socket endpoint.+  static const flags passive = implementation_defined;++  /// Host name should be treated as a numeric string defining an IPv4 or IPv6+  /// address and no name resolution should be attempted.+  static const flags numeric_host = implementation_defined;++  /// Service name should be treated as a numeric string defining a port number+  /// and no name resolution should be attempted.+  static const flags numeric_service = implementation_defined;++  /// If the query protocol family is specified as IPv6, return IPv4-mapped+  /// IPv6 addresses on finding no IPv6 addresses.+  static const flags v4_mapped = implementation_defined;++  /// If used with v4_mapped, return all matching IPv6 and IPv4 addresses.+  static const flags all_matching = implementation_defined;++  /// Only return IPv4 addresses if a non-loopback IPv4 address is configured+  /// for the system. Only return IPv6 addresses if a non-loopback IPv6 address+  /// is configured for the system.+  static const flags address_configured = implementation_defined;+#else+  enum flags+  {+    canonical_name = ASIO_OS_DEF(AI_CANONNAME),+    passive = ASIO_OS_DEF(AI_PASSIVE),+    numeric_host = ASIO_OS_DEF(AI_NUMERICHOST),+    numeric_service = ASIO_OS_DEF(AI_NUMERICSERV),+    v4_mapped = ASIO_OS_DEF(AI_V4MAPPED),+    all_matching = ASIO_OS_DEF(AI_ALL),+    address_configured = ASIO_OS_DEF(AI_ADDRCONFIG)+  };++  // Implement bitmask operations as shown in C++ Std [lib.bitmask.types].++  friend flags operator&(flags x, flags y)+  {+    return static_cast<flags>(+        static_cast<unsigned int>(x) & static_cast<unsigned int>(y));+  }++  friend flags operator|(flags x, flags y)+  {+    return static_cast<flags>(+        static_cast<unsigned int>(x) | static_cast<unsigned int>(y));+  }++  friend flags operator^(flags x, flags y)+  {+    return static_cast<flags>(+        static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y));+  }++  friend flags operator~(flags x)+  {+    return static_cast<flags>(~static_cast<unsigned int>(x));+  }++  friend flags& operator&=(flags& x, flags y)+  {+    x = x & y;+    return x;+  }++  friend flags& operator|=(flags& x, flags y)+  {+    x = x | y;+    return x;+  }++  friend flags& operator^=(flags& x, flags y)+  {+    x = x ^ y;+    return x;+  }+#endif++protected:+  /// Protected destructor to prevent deletion through this type.+  ~resolver_base()+  {+  }+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_RESOLVER_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/resolver_query_base.hpp view
@@ -0,0 +1,43 @@+//+// ip/resolver_query_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_RESOLVER_QUERY_BASE_HPP+#define ASIO_IP_RESOLVER_QUERY_BASE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/ip/resolver_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// The resolver_query_base class is used as a base for the+/// basic_resolver_query class templates to provide a common place to define+/// the flag constants.+class resolver_query_base : public resolver_base+{+protected:+  /// Protected destructor to prevent deletion through this type.+  ~resolver_query_base()+  {+  }+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_RESOLVER_QUERY_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/tcp.hpp view
@@ -0,0 +1,155 @@+//+// ip/tcp.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_TCP_HPP+#define ASIO_IP_TCP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/basic_socket_acceptor.hpp"+#include "asio/basic_socket_iostream.hpp"+#include "asio/basic_stream_socket.hpp"+#include "asio/detail/socket_option.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/ip/basic_endpoint.hpp"+#include "asio/ip/basic_resolver.hpp"+#include "asio/ip/basic_resolver_iterator.hpp"+#include "asio/ip/basic_resolver_query.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Encapsulates the flags needed for TCP.+/**+ * The asio::ip::tcp class contains flags necessary for TCP sockets.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol, InternetProtocol.+ */+class tcp+{+public:+  /// The type of a TCP endpoint.+  typedef basic_endpoint<tcp> endpoint;++  /// Construct to represent the IPv4 TCP protocol.+  static tcp v4() ASIO_NOEXCEPT+  {+    return tcp(ASIO_OS_DEF(AF_INET));+  }++  /// Construct to represent the IPv6 TCP protocol.+  static tcp v6() ASIO_NOEXCEPT+  {+    return tcp(ASIO_OS_DEF(AF_INET6));+  }++  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return ASIO_OS_DEF(SOCK_STREAM);+  }++  /// Obtain an identifier for the protocol.+  int protocol() const ASIO_NOEXCEPT+  {+    return ASIO_OS_DEF(IPPROTO_TCP);+  }++  /// Obtain an identifier for the protocol family.+  int family() const ASIO_NOEXCEPT+  {+    return family_;+  }++  /// The TCP socket type.+  typedef basic_stream_socket<tcp> socket;++  /// The TCP acceptor type.+  typedef basic_socket_acceptor<tcp> acceptor;++  /// The TCP resolver type.+  typedef basic_resolver<tcp> resolver;++#if !defined(ASIO_NO_IOSTREAM)+  /// The TCP iostream type.+  typedef basic_socket_iostream<tcp> iostream;+#endif // !defined(ASIO_NO_IOSTREAM)++  /// Socket option for disabling the Nagle algorithm.+  /**+   * Implements the IPPROTO_TCP/TCP_NODELAY socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::no_delay option(true);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::ip::tcp::no_delay option;+   * socket.get_option(option);+   * bool is_set = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Boolean_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined no_delay;+#else+  typedef asio::detail::socket_option::boolean<+    ASIO_OS_DEF(IPPROTO_TCP), ASIO_OS_DEF(TCP_NODELAY)> no_delay;+#endif++  /// Compare two protocols for equality.+  friend bool operator==(const tcp& p1, const tcp& p2)+  {+    return p1.family_ == p2.family_;+  }++  /// Compare two protocols for inequality.+  friend bool operator!=(const tcp& p1, const tcp& p2)+  {+    return p1.family_ != p2.family_;+  }++private:+  // Construct with a specific family.+  explicit tcp(int protocol_family) ASIO_NOEXCEPT+    : family_(protocol_family)+  {+  }++  int family_;+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_TCP_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/udp.hpp view
@@ -0,0 +1,111 @@+//+// ip/udp.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_UDP_HPP+#define ASIO_IP_UDP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/basic_datagram_socket.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/ip/basic_endpoint.hpp"+#include "asio/ip/basic_resolver.hpp"+#include "asio/ip/basic_resolver_iterator.hpp"+#include "asio/ip/basic_resolver_query.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Encapsulates the flags needed for UDP.+/**+ * The asio::ip::udp class contains flags necessary for UDP sockets.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol, InternetProtocol.+ */+class udp+{+public:+  /// The type of a UDP endpoint.+  typedef basic_endpoint<udp> endpoint;++  /// Construct to represent the IPv4 UDP protocol.+  static udp v4() ASIO_NOEXCEPT+  {+    return udp(ASIO_OS_DEF(AF_INET));+  }++  /// Construct to represent the IPv6 UDP protocol.+  static udp v6() ASIO_NOEXCEPT+  {+    return udp(ASIO_OS_DEF(AF_INET6));+  }++  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return ASIO_OS_DEF(SOCK_DGRAM);+  }++  /// Obtain an identifier for the protocol.+  int protocol() const ASIO_NOEXCEPT+  {+    return ASIO_OS_DEF(IPPROTO_UDP);+  }++  /// Obtain an identifier for the protocol family.+  int family() const ASIO_NOEXCEPT+  {+    return family_;+  }++  /// The UDP socket type.+  typedef basic_datagram_socket<udp> socket;++  /// The UDP resolver type.+  typedef basic_resolver<udp> resolver;++  /// Compare two protocols for equality.+  friend bool operator==(const udp& p1, const udp& p2)+  {+    return p1.family_ == p2.family_;+  }++  /// Compare two protocols for inequality.+  friend bool operator!=(const udp& p1, const udp& p2)+  {+    return p1.family_ != p2.family_;+  }++private:+  // Construct with a specific family.+  explicit udp(int protocol_family) ASIO_NOEXCEPT+    : family_(protocol_family)+  {+  }++  int family_;+};++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_UDP_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/unicast.hpp view
@@ -0,0 +1,70 @@+//+// ip/unicast.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_UNICAST_HPP+#define ASIO_IP_UNICAST_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/ip/detail/socket_option.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {+namespace unicast {++/// Socket option for time-to-live associated with outgoing unicast packets.+/**+ * Implements the IPPROTO_IP/IP_UNICAST_TTL socket option.+ *+ * @par Examples+ * Setting the option:+ * @code+ * asio::ip::udp::socket socket(my_context);+ * ...+ * asio::ip::unicast::hops option(4);+ * socket.set_option(option);+ * @endcode+ *+ * @par+ * Getting the current option value:+ * @code+ * asio::ip::udp::socket socket(my_context);+ * ...+ * asio::ip::unicast::hops option;+ * socket.get_option(option);+ * int ttl = option.value();+ * @endcode+ *+ * @par Concepts:+ * GettableSocketOption, SettableSocketOption.+ */+#if defined(GENERATING_DOCUMENTATION)+typedef implementation_defined hops;+#else+typedef asio::ip::detail::socket_option::unicast_hops<+  ASIO_OS_DEF(IPPROTO_IP),+  ASIO_OS_DEF(IP_TTL),+  ASIO_OS_DEF(IPPROTO_IPV6),+  ASIO_OS_DEF(IPV6_UNICAST_HOPS)> hops;+#endif++} // namespace unicast+} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_UNICAST_HPP
+ link/modules/asio-standalone/asio/include/asio/ip/v6_only.hpp view
@@ -0,0 +1,69 @@+//+// ip/v6_only.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IP_V6_ONLY_HPP+#define ASIO_IP_V6_ONLY_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/socket_option.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ip {++/// Socket option for determining whether an IPv6 socket supports IPv6+/// communication only.+/**+ * Implements the IPPROTO_IPV6/IP_V6ONLY socket option.+ *+ * @par Examples+ * Setting the option:+ * @code+ * asio::ip::tcp::socket socket(my_context);+ * ...+ * asio::ip::v6_only option(true);+ * socket.set_option(option);+ * @endcode+ *+ * @par+ * Getting the current option value:+ * @code+ * asio::ip::tcp::socket socket(my_context);+ * ...+ * asio::ip::v6_only option;+ * socket.get_option(option);+ * bool v6_only = option.value();+ * @endcode+ *+ * @par Concepts:+ * GettableSocketOption, SettableSocketOption.+ */+#if defined(GENERATING_DOCUMENTATION)+typedef implementation_defined v6_only;+#elif defined(IPV6_V6ONLY)+typedef asio::detail::socket_option::boolean<+    IPPROTO_IPV6, IPV6_V6ONLY> v6_only;+#else+typedef asio::detail::socket_option::boolean<+    asio::detail::custom_socket_option_level,+    asio::detail::always_fail_option> v6_only;+#endif++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IP_V6_ONLY_HPP
+ link/modules/asio-standalone/asio/include/asio/is_applicable_property.hpp view
@@ -0,0 +1,61 @@+//+// is_applicable_property.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IS_APPLICABLE_PROPERTY_HPP+#define ASIO_IS_APPLICABLE_PROPERTY_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"++namespace asio {+namespace detail {++template <typename T, typename Property, typename = void>+struct is_applicable_property_trait : false_type+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+struct is_applicable_property_trait<T, Property,+  typename void_type<+    typename enable_if<+      !!Property::template is_applicable_property_v<T>+    >::type+  >::type> : true_type+{+};++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++} // namespace detail++template <typename T, typename Property, typename = void>+struct is_applicable_property :+  detail::is_applicable_property_trait<T, Property>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+ASIO_CONSTEXPR const bool is_applicable_property_v+  = is_applicable_property<T, Property>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++} // namespace asio++#endif // ASIO_IS_APPLICABLE_PROPERTY_HPP
+ link/modules/asio-standalone/asio/include/asio/is_executor.hpp view
@@ -0,0 +1,46 @@+//+// is_executor.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IS_EXECUTOR_HPP+#define ASIO_IS_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/is_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// The is_executor trait detects whether a type T meets the Executor type+/// requirements.+/**+ * Class template @c is_executor is a UnaryTypeTrait that is derived from @c+ * true_type if the type @c T meets the syntactic requirements for Executor,+ * otherwise @c false_type.+ */+template <typename T>+struct is_executor+#if defined(GENERATING_DOCUMENTATION)+  : integral_constant<bool, automatically_determined>+#else // defined(GENERATING_DOCUMENTATION)+  : asio::detail::is_executor<T>+#endif // defined(GENERATING_DOCUMENTATION)+{+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IS_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/is_read_buffered.hpp view
@@ -0,0 +1,59 @@+//+// is_read_buffered.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IS_READ_BUFFERED_HPP+#define ASIO_IS_READ_BUFFERED_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/buffered_read_stream_fwd.hpp"+#include "asio/buffered_stream_fwd.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail {++template <typename Stream>+char is_read_buffered_helper(buffered_stream<Stream>* s);++template <typename Stream>+char is_read_buffered_helper(buffered_read_stream<Stream>* s);++struct is_read_buffered_big_type { char data[10]; };+is_read_buffered_big_type is_read_buffered_helper(...);++} // namespace detail++/// The is_read_buffered class is a traits class that may be used to determine+/// whether a stream type supports buffering of read data.+template <typename Stream>+class is_read_buffered+{+public:+#if defined(GENERATING_DOCUMENTATION)+  /// The value member is true only if the Stream type supports buffering of+  /// read data.+  static const bool value;+#else+  ASIO_STATIC_CONSTANT(bool,+      value = sizeof(detail::is_read_buffered_helper((Stream*)0)) == 1);+#endif+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IS_READ_BUFFERED_HPP
+ link/modules/asio-standalone/asio/include/asio/is_write_buffered.hpp view
@@ -0,0 +1,59 @@+//+// is_write_buffered.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_IS_WRITE_BUFFERED_HPP+#define ASIO_IS_WRITE_BUFFERED_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/buffered_stream_fwd.hpp"+#include "asio/buffered_write_stream_fwd.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail {++template <typename Stream>+char is_write_buffered_helper(buffered_stream<Stream>* s);++template <typename Stream>+char is_write_buffered_helper(buffered_write_stream<Stream>* s);++struct is_write_buffered_big_type { char data[10]; };+is_write_buffered_big_type is_write_buffered_helper(...);++} // namespace detail++/// The is_write_buffered class is a traits class that may be used to determine+/// whether a stream type supports buffering of written data.+template <typename Stream>+class is_write_buffered+{+public:+#if defined(GENERATING_DOCUMENTATION)+  /// The value member is true only if the Stream type supports buffering of+  /// written data.+  static const bool value;+#else+  ASIO_STATIC_CONSTANT(bool,+      value = sizeof(detail::is_write_buffered_helper((Stream*)0)) == 1);+#endif+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IS_WRITE_BUFFERED_HPP
+ link/modules/asio-standalone/asio/include/asio/local/basic_endpoint.hpp view
@@ -0,0 +1,247 @@+//+// local/basic_endpoint.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Derived from a public domain implementation written by Daniel Casimiro.+//+// 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_LOCAL_BASIC_ENDPOINT_HPP+#define ASIO_LOCAL_BASIC_ENDPOINT_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_LOCAL_SOCKETS) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/local/detail/endpoint.hpp"++#if !defined(ASIO_NO_IOSTREAM)+# include <iosfwd>+#endif // !defined(ASIO_NO_IOSTREAM)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace local {++/// Describes an endpoint for a UNIX socket.+/**+ * The asio::local::basic_endpoint class template describes an endpoint+ * that may be associated with a particular UNIX socket.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * @par Concepts:+ * Endpoint.+ */+template <typename Protocol>+class basic_endpoint+{+public:+  /// The protocol type associated with the endpoint.+  typedef Protocol protocol_type;++  /// The type of the endpoint structure. This type is dependent on the+  /// underlying implementation of the socket layer.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined data_type;+#else+  typedef asio::detail::socket_addr_type data_type;+#endif++  /// Default constructor.+  basic_endpoint() ASIO_NOEXCEPT+  {+  }++  /// Construct an endpoint using the specified path name.+  basic_endpoint(const char* path_name)+    : impl_(path_name)+  {+  }++  /// Construct an endpoint using the specified path name.+  basic_endpoint(const std::string& path_name)+    : impl_(path_name)+  {+  }++  #if defined(ASIO_HAS_STRING_VIEW)+  /// Construct an endpoint using the specified path name.+  basic_endpoint(string_view path_name)+    : impl_(path_name)+  {+  }+  #endif // defined(ASIO_HAS_STRING_VIEW)++  /// Copy constructor.+  basic_endpoint(const basic_endpoint& other)+    : impl_(other.impl_)+  {+  }++#if defined(ASIO_HAS_MOVE)+  /// Move constructor.+  basic_endpoint(basic_endpoint&& other)+    : impl_(other.impl_)+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  /// Assign from another endpoint.+  basic_endpoint& operator=(const basic_endpoint& other)+  {+    impl_ = other.impl_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  /// Move-assign from another endpoint.+  basic_endpoint& operator=(basic_endpoint&& other)+  {+    impl_ = other.impl_;+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  /// The protocol associated with the endpoint.+  protocol_type protocol() const+  {+    return protocol_type();+  }++  /// Get the underlying endpoint in the native type.+  data_type* data()+  {+    return impl_.data();+  }++  /// Get the underlying endpoint in the native type.+  const data_type* data() const+  {+    return impl_.data();+  }++  /// Get the underlying size of the endpoint in the native type.+  std::size_t size() const+  {+    return impl_.size();+  }++  /// Set the underlying size of the endpoint in the native type.+  void resize(std::size_t new_size)+  {+    impl_.resize(new_size);+  }++  /// Get the capacity of the endpoint in the native type.+  std::size_t capacity() const+  {+    return impl_.capacity();+  }++  /// Get the path associated with the endpoint.+  std::string path() const+  {+    return impl_.path();+  }++  /// Set the path associated with the endpoint.+  void path(const char* p)+  {+    impl_.path(p);+  }++  /// Set the path associated with the endpoint.+  void path(const std::string& p)+  {+    impl_.path(p);+  }++  /// Compare two endpoints for equality.+  friend bool operator==(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return e1.impl_ == e2.impl_;+  }++  /// Compare two endpoints for inequality.+  friend bool operator!=(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return !(e1.impl_ == e2.impl_);+  }++  /// Compare endpoints for ordering.+  friend bool operator<(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return e1.impl_ < e2.impl_;+  }++  /// Compare endpoints for ordering.+  friend bool operator>(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return e2.impl_ < e1.impl_;+  }++  /// Compare endpoints for ordering.+  friend bool operator<=(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return !(e2 < e1);+  }++  /// Compare endpoints for ordering.+  friend bool operator>=(const basic_endpoint<Protocol>& e1,+      const basic_endpoint<Protocol>& e2)+  {+    return !(e1 < e2);+  }++private:+  // The underlying UNIX domain endpoint.+  asio::local::detail::endpoint impl_;+};++/// Output an endpoint as a string.+/**+ * Used to output a human-readable string for a specified endpoint.+ *+ * @param os The output stream to which the string will be written.+ *+ * @param endpoint The endpoint to be written.+ *+ * @return The output stream.+ *+ * @relates asio::local::basic_endpoint+ */+template <typename Elem, typename Traits, typename Protocol>+std::basic_ostream<Elem, Traits>& operator<<(+    std::basic_ostream<Elem, Traits>& os,+    const basic_endpoint<Protocol>& endpoint)+{+  os << endpoint.path();+  return os;+}++} // namespace local+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_LOCAL_SOCKETS)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_LOCAL_BASIC_ENDPOINT_HPP
+ link/modules/asio-standalone/asio/include/asio/local/connect_pair.hpp view
@@ -0,0 +1,101 @@+//+// local/connect_pair.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_LOCAL_CONNECT_PAIR_HPP+#define ASIO_LOCAL_CONNECT_PAIR_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_LOCAL_SOCKETS) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_socket.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"+#include "asio/local/basic_endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace local {++/// Create a pair of connected sockets.+template <typename Protocol, typename Executor1, typename Executor2>+void connect_pair(basic_socket<Protocol, Executor1>& socket1,+    basic_socket<Protocol, Executor2>& socket2);++/// Create a pair of connected sockets.+template <typename Protocol, typename Executor1, typename Executor2>+ASIO_SYNC_OP_VOID connect_pair(basic_socket<Protocol, Executor1>& socket1,+    basic_socket<Protocol, Executor2>& socket2, asio::error_code& ec);++template <typename Protocol, typename Executor1, typename Executor2>+inline void connect_pair(basic_socket<Protocol, Executor1>& socket1,+    basic_socket<Protocol, Executor2>& socket2)+{+  asio::error_code ec;+  connect_pair(socket1, socket2, ec);+  asio::detail::throw_error(ec, "connect_pair");+}++template <typename Protocol, typename Executor1, typename Executor2>+inline ASIO_SYNC_OP_VOID connect_pair(+    basic_socket<Protocol, Executor1>& socket1,+    basic_socket<Protocol, Executor2>& socket2, asio::error_code& ec)+{+  // Check that this function is only being used with a UNIX domain socket.+  asio::local::basic_endpoint<Protocol>* tmp+    = static_cast<typename Protocol::endpoint*>(0);+  (void)tmp;++  Protocol protocol;+  asio::detail::socket_type sv[2];+  if (asio::detail::socket_ops::socketpair(protocol.family(),+        protocol.type(), protocol.protocol(), sv, ec)+      == asio::detail::socket_error_retval)+    ASIO_SYNC_OP_VOID_RETURN(ec);++  socket1.assign(protocol, sv[0], ec);+  if (ec)+  {+    asio::error_code temp_ec;+    asio::detail::socket_ops::state_type state[2] = { 0, 0 };+    asio::detail::socket_ops::close(sv[0], state[0], true, temp_ec);+    asio::detail::socket_ops::close(sv[1], state[1], true, temp_ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  socket2.assign(protocol, sv[1], ec);+  if (ec)+  {+    asio::error_code temp_ec;+    socket1.close(temp_ec);+    asio::detail::socket_ops::state_type state = 0;+    asio::detail::socket_ops::close(sv[1], state, true, temp_ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ASIO_SYNC_OP_VOID_RETURN(ec);+}++} // namespace local+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_LOCAL_SOCKETS)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_LOCAL_CONNECT_PAIR_HPP
+ link/modules/asio-standalone/asio/include/asio/local/datagram_protocol.hpp view
@@ -0,0 +1,80 @@+//+// local/datagram_protocol.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_LOCAL_DATAGRAM_PROTOCOL_HPP+#define ASIO_LOCAL_DATAGRAM_PROTOCOL_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_LOCAL_SOCKETS) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_datagram_socket.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/local/basic_endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace local {++/// Encapsulates the flags needed for datagram-oriented UNIX sockets.+/**+ * The asio::local::datagram_protocol class contains flags necessary for+ * datagram-oriented UNIX domain sockets.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol.+ */+class datagram_protocol+{+public:+  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return SOCK_DGRAM;+  }++  /// Obtain an identifier for the protocol.+  int protocol() const ASIO_NOEXCEPT+  {+    return 0;+  }++  /// Obtain an identifier for the protocol family.+  int family() const ASIO_NOEXCEPT+  {+    return AF_UNIX;+  }++  /// The type of a UNIX domain endpoint.+  typedef basic_endpoint<datagram_protocol> endpoint;++  /// The UNIX domain socket type.+  typedef basic_datagram_socket<datagram_protocol> socket;+};++} // namespace local+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_LOCAL_SOCKETS)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_LOCAL_DATAGRAM_PROTOCOL_HPP
+ link/modules/asio-standalone/asio/include/asio/local/detail/endpoint.hpp view
@@ -0,0 +1,139 @@+//+// local/detail/endpoint.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Derived from a public domain implementation written by Daniel Casimiro.+//+// 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_LOCAL_DETAIL_ENDPOINT_HPP+#define ASIO_LOCAL_DETAIL_ENDPOINT_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_LOCAL_SOCKETS)++#include <cstddef>+#include <string>+#include "asio/detail/socket_types.hpp"+#include "asio/detail/string_view.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace local {+namespace detail {++// Helper class for implementing a UNIX domain endpoint.+class endpoint+{+public:+  // Default constructor.+  ASIO_DECL endpoint();++  // Construct an endpoint using the specified path name.+  ASIO_DECL endpoint(const char* path_name);++  // Construct an endpoint using the specified path name.+  ASIO_DECL endpoint(const std::string& path_name);++  #if defined(ASIO_HAS_STRING_VIEW)+  // Construct an endpoint using the specified path name.+  ASIO_DECL endpoint(string_view path_name);+  #endif // defined(ASIO_HAS_STRING_VIEW)++  // Copy constructor.+  endpoint(const endpoint& other)+    : data_(other.data_),+      path_length_(other.path_length_)+  {+  }++  // Assign from another endpoint.+  endpoint& operator=(const endpoint& other)+  {+    data_ = other.data_;+    path_length_ = other.path_length_;+    return *this;+  }++  // Get the underlying endpoint in the native type.+  asio::detail::socket_addr_type* data()+  {+    return &data_.base;+  }++  // Get the underlying endpoint in the native type.+  const asio::detail::socket_addr_type* data() const+  {+    return &data_.base;+  }++  // Get the underlying size of the endpoint in the native type.+  std::size_t size() const+  {+    return path_length_+      + offsetof(asio::detail::sockaddr_un_type, sun_path);+  }++  // Set the underlying size of the endpoint in the native type.+  ASIO_DECL void resize(std::size_t size);++  // Get the capacity of the endpoint in the native type.+  std::size_t capacity() const+  {+    return sizeof(asio::detail::sockaddr_un_type);+  }++  // Get the path associated with the endpoint.+  ASIO_DECL std::string path() const;++  // Set the path associated with the endpoint.+  ASIO_DECL void path(const char* p);++  // Set the path associated with the endpoint.+  ASIO_DECL void path(const std::string& p);++  // Compare two endpoints for equality.+  ASIO_DECL friend bool operator==(+      const endpoint& e1, const endpoint& e2);++  // Compare endpoints for ordering.+  ASIO_DECL friend bool operator<(+      const endpoint& e1, const endpoint& e2);++private:+  // The underlying UNIX socket address.+  union data_union+  {+    asio::detail::socket_addr_type base;+    asio::detail::sockaddr_un_type local;+  } data_;++  // The length of the path associated with the endpoint.+  std::size_t path_length_;++  // Initialise with a specified path.+  ASIO_DECL void init(const char* path, std::size_t path_length);+};++} // namespace detail+} // namespace local+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/local/detail/impl/endpoint.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_LOCAL_SOCKETS)++#endif // ASIO_LOCAL_DETAIL_ENDPOINT_HPP
+ link/modules/asio-standalone/asio/include/asio/local/detail/impl/endpoint.ipp view
@@ -0,0 +1,136 @@+//+// local/detail/impl/endpoint.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Derived from a public domain implementation written by Daniel Casimiro.+//+// 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_LOCAL_DETAIL_IMPL_ENDPOINT_IPP+#define ASIO_LOCAL_DETAIL_IMPL_ENDPOINT_IPP++#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_LOCAL_SOCKETS)++#include <cstring>+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"+#include "asio/local/detail/endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace local {+namespace detail {++endpoint::endpoint()+{+  init("", 0);+}++endpoint::endpoint(const char* path_name)+{+  using namespace std; // For strlen.+  init(path_name, strlen(path_name));+}++endpoint::endpoint(const std::string& path_name)+{+  init(path_name.data(), path_name.length());+}++#if defined(ASIO_HAS_STRING_VIEW)+endpoint::endpoint(string_view path_name)+{+  init(path_name.data(), path_name.length());+}+#endif // defined(ASIO_HAS_STRING_VIEW)++void endpoint::resize(std::size_t new_size)+{+  if (new_size > sizeof(asio::detail::sockaddr_un_type))+  {+    asio::error_code ec(asio::error::invalid_argument);+    asio::detail::throw_error(ec);+  }+  else if (new_size == 0)+  {+    path_length_ = 0;+  }+  else+  {+    path_length_ = new_size+      - offsetof(asio::detail::sockaddr_un_type, sun_path);++    // The path returned by the operating system may be NUL-terminated.+    if (path_length_ > 0 && data_.local.sun_path[path_length_ - 1] == 0)+      --path_length_;+  }+}++std::string endpoint::path() const+{+  return std::string(data_.local.sun_path, path_length_);+}++void endpoint::path(const char* p)+{+  using namespace std; // For strlen.+  init(p, strlen(p));+}++void endpoint::path(const std::string& p)+{+  init(p.data(), p.length());+}++bool operator==(const endpoint& e1, const endpoint& e2)+{+  return e1.path() == e2.path();+}++bool operator<(const endpoint& e1, const endpoint& e2)+{+  return e1.path() < e2.path();+}++void endpoint::init(const char* path_name, std::size_t path_length)+{+  if (path_length > sizeof(data_.local.sun_path) - 1)+  {+    // The buffer is not large enough to store this address.+    asio::error_code ec(asio::error::name_too_long);+    asio::detail::throw_error(ec);+  }++  using namespace std; // For memcpy.+  data_.local = asio::detail::sockaddr_un_type();+  data_.local.sun_family = AF_UNIX;+  if (path_length > 0)+    memcpy(data_.local.sun_path, path_name, path_length);+  path_length_ = path_length;++  // NUL-terminate normal path names. Names that start with a NUL are in the+  // UNIX domain protocol's "abstract namespace" and are not NUL-terminated.+  if (path_length > 0 && data_.local.sun_path[0] == 0)+    data_.local.sun_path[path_length] = 0;+}++} // namespace detail+} // namespace local+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_LOCAL_SOCKETS)++#endif // ASIO_LOCAL_DETAIL_IMPL_ENDPOINT_IPP
+ link/modules/asio-standalone/asio/include/asio/local/stream_protocol.hpp view
@@ -0,0 +1,90 @@+//+// local/stream_protocol.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_LOCAL_STREAM_PROTOCOL_HPP+#define ASIO_LOCAL_STREAM_PROTOCOL_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_LOCAL_SOCKETS) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_socket_acceptor.hpp"+#include "asio/basic_socket_iostream.hpp"+#include "asio/basic_stream_socket.hpp"+#include "asio/detail/socket_types.hpp"+#include "asio/local/basic_endpoint.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace local {++/// Encapsulates the flags needed for stream-oriented UNIX sockets.+/**+ * The asio::local::stream_protocol class contains flags necessary for+ * stream-oriented UNIX domain sockets.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol.+ */+class stream_protocol+{+public:+  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return SOCK_STREAM;+  }++  /// Obtain an identifier for the protocol.+  int protocol() const ASIO_NOEXCEPT+  {+    return 0;+  }++  /// Obtain an identifier for the protocol family.+  int family() const ASIO_NOEXCEPT+  {+    return AF_UNIX;+  }++  /// The type of a UNIX domain endpoint.+  typedef basic_endpoint<stream_protocol> endpoint;++  /// The UNIX domain socket type.+  typedef basic_stream_socket<stream_protocol> socket;++  /// The UNIX domain acceptor type.+  typedef basic_socket_acceptor<stream_protocol> acceptor;++#if !defined(ASIO_NO_IOSTREAM)+  /// The UNIX domain iostream type.+  typedef basic_socket_iostream<stream_protocol> iostream;+#endif // !defined(ASIO_NO_IOSTREAM)+};++} // namespace local+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_LOCAL_SOCKETS)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_LOCAL_STREAM_PROTOCOL_HPP
+ link/modules/asio-standalone/asio/include/asio/multiple_exceptions.hpp view
@@ -0,0 +1,58 @@+//+// multiple_exceptions.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_MULTIPLE_EXCEPTIONS_HPP+#define ASIO_MULTIPLE_EXCEPTIONS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <exception>+#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(ASIO_HAS_STD_EXCEPTION_PTR) \+  || defined(GENERATING_DOCUMENTATION)++/// Exception thrown when there are multiple pending exceptions to rethrow.+class multiple_exceptions+  : public std::exception+{+public:+  /// Constructor.+  ASIO_DECL multiple_exceptions(+      std::exception_ptr first) ASIO_NOEXCEPT;++  /// Obtain message associated with exception.+  ASIO_DECL virtual const char* what() const+    ASIO_NOEXCEPT_OR_NOTHROW;++  /// Obtain a pointer to the first exception.+  ASIO_DECL std::exception_ptr first_exception() const;++private:+  std::exception_ptr first_;+};++#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)+       //   || defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/multiple_exceptions.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_MULTIPLE_EXCEPTIONS_HPP
+ link/modules/asio-standalone/asio/include/asio/packaged_task.hpp view
@@ -0,0 +1,126 @@+//+// packaged_task.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_PACKAGED_TASK_HPP+#define ASIO_PACKAGED_TASK_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/future.hpp"++#if defined(ASIO_HAS_STD_FUTURE_CLASS) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/async_result.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  || defined(GENERATING_DOCUMENTATION)++/// Partial specialisation of @c async_result for @c std::packaged_task.+template <typename Result, typename... Args, typename Signature>+class async_result<std::packaged_task<Result(Args...)>, Signature>+{+public:+  /// The packaged task is the concrete completion handler type.+  typedef std::packaged_task<Result(Args...)> completion_handler_type;++  /// The return type of the initiating function is the future obtained from+  /// the packaged task.+  typedef std::future<Result> return_type;++  /// The constructor extracts the future from the packaged task.+  explicit async_result(completion_handler_type& h)+    : future_(h.get_future())+  {+  }++  /// Returns the packaged task's future.+  return_type get()+  {+    return std::move(future_);+  }++private:+  return_type future_;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   || defined(GENERATING_DOCUMENTATION)++template <typename Result, typename Signature>+struct async_result<std::packaged_task<Result()>, Signature>+{+  typedef std::packaged_task<Result()> completion_handler_type;+  typedef std::future<Result> return_type;++  explicit async_result(completion_handler_type& h)+    : future_(h.get_future())+  {+  }++  return_type get()+  {+    return std::move(future_);+  }++private:+  return_type future_;+};++#define ASIO_PRIVATE_ASYNC_RESULT_DEF(n) \+  template <typename Result, \+    ASIO_VARIADIC_TPARAMS(n), typename Signature> \+  class async_result< \+    std::packaged_task<Result(ASIO_VARIADIC_TARGS(n))>, Signature> \+  { \+  public: \+    typedef std::packaged_task< \+      Result(ASIO_VARIADIC_TARGS(n))> \+        completion_handler_type; \+  \+    typedef std::future<Result> return_type; \+  \+    explicit async_result(completion_handler_type& h) \+      : future_(h.get_future()) \+    { \+    } \+  \+    return_type get() \+    { \+      return std::move(future_); \+    } \+  \+  private: \+    return_type future_; \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_ASYNC_RESULT_DEF)+#undef ASIO_PRIVATE_ASYNC_RESULT_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   || defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_STD_FUTURE_CLASS)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_PACKAGED_TASK_HPP
+ link/modules/asio-standalone/asio/include/asio/placeholders.hpp view
@@ -0,0 +1,151 @@+//+// placeholders.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_PLACEHOLDERS_HPP+#define ASIO_PLACEHOLDERS_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_BIND)+# include <boost/bind/arg.hpp>+#endif // defined(ASIO_HAS_BOOST_BIND)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace placeholders {++#if defined(GENERATING_DOCUMENTATION)++/// An argument placeholder, for use with boost::bind(), that corresponds to+/// the error argument of a handler for any of the asynchronous functions.+unspecified error;++/// An argument placeholder, for use with boost::bind(), that corresponds to+/// the bytes_transferred argument of a handler for asynchronous functions such+/// as asio::basic_stream_socket::async_write_some or+/// asio::async_write.+unspecified bytes_transferred;++/// An argument placeholder, for use with boost::bind(), that corresponds to+/// the iterator argument of a handler for asynchronous functions such as+/// asio::async_connect.+unspecified iterator;++/// An argument placeholder, for use with boost::bind(), that corresponds to+/// the results argument of a handler for asynchronous functions such as+/// asio::basic_resolver::async_resolve.+unspecified results;++/// An argument placeholder, for use with boost::bind(), that corresponds to+/// the results argument of a handler for asynchronous functions such as+/// asio::async_connect.+unspecified endpoint;++/// An argument placeholder, for use with boost::bind(), that corresponds to+/// the signal_number argument of a handler for asynchronous functions such as+/// asio::signal_set::async_wait.+unspecified signal_number;++#elif defined(ASIO_HAS_BOOST_BIND)+# if defined(__BORLANDC__) || defined(__GNUC__)++inline boost::arg<1> error()+{+  return boost::arg<1>();+}++inline boost::arg<2> bytes_transferred()+{+  return boost::arg<2>();+}++inline boost::arg<2> iterator()+{+  return boost::arg<2>();+}++inline boost::arg<2> results()+{+  return boost::arg<2>();+}++inline boost::arg<2> endpoint()+{+  return boost::arg<2>();+}++inline boost::arg<2> signal_number()+{+  return boost::arg<2>();+}++# else++namespace detail+{+  template <int Number>+  struct placeholder+  {+    static boost::arg<Number>& get()+    {+      static boost::arg<Number> result;+      return result;+    }+  };+}++#  if defined(ASIO_MSVC) && (ASIO_MSVC < 1400)++static boost::arg<1>& error+  = asio::placeholders::detail::placeholder<1>::get();+static boost::arg<2>& bytes_transferred+  = asio::placeholders::detail::placeholder<2>::get();+static boost::arg<2>& iterator+  = asio::placeholders::detail::placeholder<2>::get();+static boost::arg<2>& results+  = asio::placeholders::detail::placeholder<2>::get();+static boost::arg<2>& endpoint+  = asio::placeholders::detail::placeholder<2>::get();+static boost::arg<2>& signal_number+  = asio::placeholders::detail::placeholder<2>::get();++#  else++namespace+{+  boost::arg<1>& error+    = asio::placeholders::detail::placeholder<1>::get();+  boost::arg<2>& bytes_transferred+    = asio::placeholders::detail::placeholder<2>::get();+  boost::arg<2>& iterator+    = asio::placeholders::detail::placeholder<2>::get();+  boost::arg<2>& results+    = asio::placeholders::detail::placeholder<2>::get();+  boost::arg<2>& endpoint+    = asio::placeholders::detail::placeholder<2>::get();+  boost::arg<2>& signal_number+    = asio::placeholders::detail::placeholder<2>::get();+} // namespace++#  endif+# endif+#endif++} // namespace placeholders+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_PLACEHOLDERS_HPP
+ link/modules/asio-standalone/asio/include/asio/posix/basic_descriptor.hpp view
@@ -0,0 +1,697 @@+//+// posix/basic_descriptor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_POSIX_BASIC_DESCRIPTOR_HPP+#define ASIO_POSIX_BASIC_DESCRIPTOR_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_POSIX_STREAM_DESCRIPTOR) \+  || defined(GENERATING_DOCUMENTATION)++#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/reactive_descriptor_service.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/posix/descriptor_base.hpp"++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace posix {++/// Provides POSIX descriptor functionality.+/**+ * The posix::basic_descriptor class template provides the ability to wrap a+ * POSIX descriptor.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor = any_io_executor>+class basic_descriptor+  : public descriptor_base+{+public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the descriptor type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The descriptor type when rebound to the specified executor.+    typedef basic_descriptor<Executor1> other;+  };++  /// The native representation of a descriptor.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#else+  typedef detail::reactive_descriptor_service::native_handle_type+    native_handle_type;+#endif++  /// A descriptor is always the lowest layer.+  typedef basic_descriptor lowest_layer_type;++  /// Construct a descriptor without opening it.+  /**+   * This constructor creates a descriptor without opening it.+   *+   * @param ex The I/O executor that the descriptor will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * descriptor.+   */+  explicit basic_descriptor(const executor_type& ex)+    : impl_(ex)+  {+  }++  /// Construct a descriptor without opening it.+  /**+   * This constructor creates a descriptor without opening it.+   *+   * @param context An execution context which provides the I/O executor that+   * the descriptor will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the descriptor.+   */+  template <typename ExecutionContext>+  explicit basic_descriptor(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+  }++  /// Construct a descriptor on an existing native descriptor.+  /**+   * This constructor creates a descriptor object to hold an existing native+   * descriptor.+   *+   * @param ex The I/O executor that the descriptor will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * descriptor.+   *+   * @param native_descriptor A native descriptor.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_descriptor(const executor_type& ex,+      const native_handle_type& native_descriptor)+    : impl_(ex)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        native_descriptor, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Construct a descriptor on an existing native descriptor.+  /**+   * This constructor creates a descriptor object to hold an existing native+   * descriptor.+   *+   * @param context An execution context which provides the I/O executor that+   * the descriptor will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the descriptor.+   *+   * @param native_descriptor A native descriptor.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_descriptor(ExecutionContext& context,+      const native_handle_type& native_descriptor,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        native_descriptor, ec);+    asio::detail::throw_error(ec, "assign");+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a descriptor from another.+  /**+   * This constructor moves a descriptor from one object to another.+   *+   * @param other The other descriptor 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_descriptor(const executor_type&)+   * constructor.+   */+  basic_descriptor(basic_descriptor&& other) ASIO_NOEXCEPT+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a descriptor from another.+  /**+   * This assignment operator moves a descriptor from one object to another.+   *+   * @param other The other descriptor 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_descriptor(const executor_type&)+   * constructor.+   */+  basic_descriptor& operator=(basic_descriptor&& other)+  {+    impl_ = std::move(other.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();+  }++  /// Get a reference to the lowest layer.+  /**+   * This function returns a reference to the lowest layer in a stack of+   * layers. Since a descriptor 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 descriptor 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 descriptor to the descriptor.+  /*+   * This function opens the descriptor to hold an existing native descriptor.+   *+   * @param native_descriptor A native descriptor.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void assign(const native_handle_type& native_descriptor)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        native_descriptor, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Assign an existing native descriptor to the descriptor.+  /*+   * This function opens the descriptor to hold an existing native descriptor.+   *+   * @param native_descriptor A native descriptor.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID assign(const native_handle_type& native_descriptor,+      asio::error_code& ec)+  {+    impl_.get_service().assign(+        impl_.get_implementation(), native_descriptor, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Determine whether the descriptor is open.+  bool is_open() const+  {+    return impl_.get_service().is_open(impl_.get_implementation());+  }++  /// Close the descriptor.+  /**+   * This function is used to close the descriptor. 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 descriptor.+  /**+   * This function is used to close the descriptor. 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.+   */+  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 descriptor representation.+  /**+   * This function may be used to obtain the underlying representation of the+   * descriptor. This is intended to allow access to native descriptor+   * functionality that is not otherwise provided.+   */+  native_handle_type native_handle()+  {+    return impl_.get_service().native_handle(impl_.get_implementation());+  }++  /// Release ownership of the native descriptor implementation.+  /**+   * This function may be used to obtain the underlying representation of the+   * descriptor. After calling this function, @c is_open() returns false. The+   * caller is responsible for closing the descriptor.+   *+   * All outstanding asynchronous read or write operations will finish+   * immediately, and the handlers for cancelled operations will be passed the+   * asio::error::operation_aborted error.+   */+  native_handle_type release()+  {+    return impl_.get_service().release(impl_.get_implementation());+  }++  /// Cancel all asynchronous operations associated with the descriptor.+  /**+   * 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 descriptor.+  /**+   * 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);+  }++  /// Perform an IO control command on the descriptor.+  /**+   * This function is used to execute an IO control command on the descriptor.+   *+   * @param command The IO control command to be performed on the descriptor.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @sa IoControlCommand @n+   * asio::posix::descriptor_base::bytes_readable @n+   * asio::posix::descriptor_base::non_blocking_io+   *+   * @par Example+   * Getting the number of bytes ready to read:+   * @code+   * asio::posix::stream_descriptor descriptor(my_context);+   * ...+   * asio::posix::stream_descriptor::bytes_readable command;+   * descriptor.io_control(command);+   * std::size_t bytes_readable = command.get();+   * @endcode+   */+  template <typename IoControlCommand>+  void io_control(IoControlCommand& command)+  {+    asio::error_code ec;+    impl_.get_service().io_control(impl_.get_implementation(), command, ec);+    asio::detail::throw_error(ec, "io_control");+  }++  /// Perform an IO control command on the descriptor.+  /**+   * This function is used to execute an IO control command on the descriptor.+   *+   * @param command The IO control command to be performed on the descriptor.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @sa IoControlCommand @n+   * asio::posix::descriptor_base::bytes_readable @n+   * asio::posix::descriptor_base::non_blocking_io+   *+   * @par Example+   * Getting the number of bytes ready to read:+   * @code+   * asio::posix::stream_descriptor descriptor(my_context);+   * ...+   * asio::posix::stream_descriptor::bytes_readable command;+   * asio::error_code ec;+   * descriptor.io_control(command, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * std::size_t bytes_readable = command.get();+   * @endcode+   */+  template <typename IoControlCommand>+  ASIO_SYNC_OP_VOID io_control(IoControlCommand& command,+      asio::error_code& ec)+  {+    impl_.get_service().io_control(impl_.get_implementation(), command, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Gets the non-blocking mode of the descriptor.+  /**+   * @returns @c true if the descriptor's synchronous operations will fail with+   * asio::error::would_block if they are unable to perform the requested+   * operation immediately. If @c false, synchronous operations will block+   * until complete.+   *+   * @note The non-blocking mode has no effect on the behaviour of asynchronous+   * operations. Asynchronous operations will never fail with the error+   * asio::error::would_block.+   */+  bool non_blocking() const+  {+    return impl_.get_service().non_blocking(impl_.get_implementation());+  }++  /// Sets the non-blocking mode of the descriptor.+  /**+   * @param mode If @c true, the descriptor's synchronous operations will fail+   * with asio::error::would_block if they are unable to perform the+   * requested operation immediately. If @c false, synchronous operations will+   * block until complete.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note The non-blocking mode has no effect on the behaviour of asynchronous+   * operations. Asynchronous operations will never fail with the error+   * asio::error::would_block.+   */+  void non_blocking(bool mode)+  {+    asio::error_code ec;+    impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);+    asio::detail::throw_error(ec, "non_blocking");+  }++  /// Sets the non-blocking mode of the descriptor.+  /**+   * @param mode If @c true, the descriptor's synchronous operations will fail+   * with asio::error::would_block if they are unable to perform the+   * requested operation immediately. If @c false, synchronous operations will+   * block until complete.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note The non-blocking mode has no effect on the behaviour of asynchronous+   * operations. Asynchronous operations will never fail with the error+   * asio::error::would_block.+   */+  ASIO_SYNC_OP_VOID non_blocking(+      bool mode, asio::error_code& ec)+  {+    impl_.get_service().non_blocking(impl_.get_implementation(), mode, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Gets the non-blocking mode of the native descriptor implementation.+  /**+   * This function is used to retrieve the non-blocking mode of the underlying+   * native descriptor. This mode has no effect on the behaviour of the+   * descriptor object's synchronous operations.+   *+   * @returns @c true if the underlying descriptor is in non-blocking mode and+   * direct system calls may fail with asio::error::would_block (or the+   * equivalent system error).+   *+   * @note The current non-blocking mode is cached by the descriptor object.+   * Consequently, the return value may be incorrect if the non-blocking mode+   * was set directly on the native descriptor.+   */+  bool native_non_blocking() const+  {+    return impl_.get_service().native_non_blocking(+        impl_.get_implementation());+  }++  /// Sets the non-blocking mode of the native descriptor implementation.+  /**+   * This function is used to modify the non-blocking mode of the underlying+   * native descriptor. It has no effect on the behaviour of the descriptor+   * object's synchronous operations.+   *+   * @param mode If @c true, the underlying descriptor is put into non-blocking+   * mode and direct system calls may fail with asio::error::would_block+   * (or the equivalent system error).+   *+   * @throws asio::system_error Thrown on failure. If the @c mode is+   * @c false, but the current value of @c non_blocking() is @c true, this+   * function fails with asio::error::invalid_argument, as the+   * combination does not make sense.+   */+  void native_non_blocking(bool mode)+  {+    asio::error_code ec;+    impl_.get_service().native_non_blocking(+        impl_.get_implementation(), mode, ec);+    asio::detail::throw_error(ec, "native_non_blocking");+  }++  /// Sets the non-blocking mode of the native descriptor implementation.+  /**+   * This function is used to modify the non-blocking mode of the underlying+   * native descriptor. It has no effect on the behaviour of the descriptor+   * object's synchronous operations.+   *+   * @param mode If @c true, the underlying descriptor is put into non-blocking+   * mode and direct system calls may fail with asio::error::would_block+   * (or the equivalent system error).+   *+   * @param ec Set to indicate what error occurred, if any. If the @c mode is+   * @c false, but the current value of @c non_blocking() is @c true, this+   * function fails with asio::error::invalid_argument, as the+   * combination does not make sense.+   */+  ASIO_SYNC_OP_VOID native_non_blocking(+      bool mode, asio::error_code& ec)+  {+    impl_.get_service().native_non_blocking(+        impl_.get_implementation(), mode, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Wait for the descriptor to become ready to read, ready to write, or to+  /// have pending error conditions.+  /**+   * This function is used to perform a blocking wait for a descriptor to enter+   * a ready to read, write or error condition state.+   *+   * @param w Specifies the desired descriptor state.+   *+   * @par Example+   * Waiting for a descriptor to become readable.+   * @code+   * asio::posix::stream_descriptor descriptor(my_context);+   * ...+   * descriptor.wait(asio::posix::stream_descriptor::wait_read);+   * @endcode+   */+  void wait(wait_type w)+  {+    asio::error_code ec;+    impl_.get_service().wait(impl_.get_implementation(), w, ec);+    asio::detail::throw_error(ec, "wait");+  }++  /// Wait for the descriptor to become ready to read, ready to write, or to+  /// have pending error conditions.+  /**+   * This function is used to perform a blocking wait for a descriptor to enter+   * a ready to read, write or error condition state.+   *+   * @param w Specifies the desired descriptor state.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * Waiting for a descriptor to become readable.+   * @code+   * asio::posix::stream_descriptor descriptor(my_context);+   * ...+   * asio::error_code ec;+   * descriptor.wait(asio::posix::stream_descriptor::wait_read, ec);+   * @endcode+   */+  ASIO_SYNC_OP_VOID wait(wait_type w, asio::error_code& ec)+  {+    impl_.get_service().wait(impl_.get_implementation(), w, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Asynchronously wait for the descriptor to become ready to read, ready to+  /// write, or to have pending error conditions.+  /**+   * This function is used to perform an asynchronous wait for a descriptor to+   * enter a ready to read, write or error condition state.+   *+   * @param w Specifies the desired descriptor state.+   *+   * @param handler The handler to be called when the wait operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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 Example+   * @code+   * void wait_handler(const asio::error_code& error)+   * {+   *   if (!error)+   *   {+   *     // Wait succeeded.+   *   }+   * }+   *+   * ...+   *+   * asio::posix::stream_descriptor descriptor(my_context);+   * ...+   * descriptor.async_wait(+   *     asio::posix::stream_descriptor::wait_read,+   *     wait_handler);+   * @endcode+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+      void (asio::error_code))+  async_wait(wait_type w,+      ASIO_MOVE_ARG(WaitHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WaitHandler, void (asio::error_code)>(+        initiate_async_wait(this), handler, w);+  }++protected:+  /// Protected destructor to prevent deletion through this type.+  /**+   * This function destroys the descriptor, cancelling any outstanding+   * asynchronous wait operations associated with the descriptor as if by+   * calling @c cancel.+   */+  ~basic_descriptor()+  {+  }++  detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;++private:+  // Disallow copying and assignment.+  basic_descriptor(const basic_descriptor&) ASIO_DELETED;+  basic_descriptor& operator=(const basic_descriptor&) ASIO_DELETED;++  class initiate_async_wait+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_wait(basic_descriptor* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename WaitHandler>+    void operator()(ASIO_MOVE_ARG(WaitHandler) handler, wait_type w) 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(), w,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_descriptor* self_;+  };+};++} // namespace posix+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_POSIX_BASIC_DESCRIPTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/posix/basic_stream_descriptor.hpp view
@@ -0,0 +1,470 @@+//+// posix/basic_stream_descriptor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_POSIX_BASIC_STREAM_DESCRIPTOR_HPP+#define ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/posix/descriptor.hpp"++#if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \+  || defined(GENERATING_DOCUMENTATION)++namespace asio {+namespace posix {++/// Provides stream-oriented descriptor functionality.+/**+ * The posix::basic_stream_descriptor class template provides asynchronous and+ * blocking stream-oriented descriptor 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 = any_io_executor>+class basic_stream_descriptor+  : public basic_descriptor<Executor>+{+public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the descriptor type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The descriptor type when rebound to the specified executor.+    typedef basic_stream_descriptor<Executor1> other;+  };++  /// The native representation of a descriptor.+  typedef typename basic_descriptor<Executor>::native_handle_type+    native_handle_type;++  /// Construct a stream descriptor without opening it.+  /**+   * This constructor creates a stream descriptor without opening it. The+   * descriptor 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 descriptor will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * descriptor.+   */+  explicit basic_stream_descriptor(const executor_type& ex)+    : basic_descriptor<Executor>(ex)+  {+  }++  /// Construct a stream descriptor without opening it.+  /**+   * This constructor creates a stream descriptor without opening it. The+   * descriptor 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 descriptor will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the descriptor.+   */+  template <typename ExecutionContext>+  explicit basic_stream_descriptor(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_descriptor<Executor>(context)+  {+  }++  /// Construct a stream descriptor on an existing native descriptor.+  /**+   * This constructor creates a stream descriptor object to hold an existing+   * native descriptor.+   *+   * @param ex The I/O executor that the descriptor will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * descriptor.+   *+   * @param native_descriptor The new underlying descriptor implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_stream_descriptor(const executor_type& ex,+      const native_handle_type& native_descriptor)+    : basic_descriptor<Executor>(ex, native_descriptor)+  {+  }++  /// Construct a stream descriptor on an existing native descriptor.+  /**+   * This constructor creates a stream descriptor object to hold an existing+   * native descriptor.+   *+   * @param context An execution context which provides the I/O executor that+   * the descriptor will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the descriptor.+   *+   * @param native_descriptor The new underlying descriptor implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_stream_descriptor(ExecutionContext& context,+      const native_handle_type& native_descriptor,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_descriptor<Executor>(context, native_descriptor)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a stream descriptor from another.+  /**+   * This constructor moves a stream descriptor from one object to another.+   *+   * @param other The other stream descriptor 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_descriptor(const executor_type&)+   * constructor.+   */+  basic_stream_descriptor(basic_stream_descriptor&& other) ASIO_NOEXCEPT+    : descriptor(std::move(other))+  {+  }++  /// Move-assign a stream descriptor from another.+  /**+   * This assignment operator moves a stream descriptor from one object to+   * another.+   *+   * @param other The other stream descriptor 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_descriptor(const executor_type&)+   * constructor.+   */+  basic_stream_descriptor& operator=(basic_stream_descriptor&& other)+  {+    descriptor::operator=(std::move(other));+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Write some data to the descriptor.+  /**+   * This function is used to write data to the stream descriptor. 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 descriptor.+   *+   * @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+   * descriptor.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 descriptor.+  /**+   * This function is used to write data to the stream descriptor. 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 descriptor.+   *+   * @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+   * descriptor. The function call always returns immediately.+   *+   * @param buffers One or more data buffers to be written to the descriptor.+   * 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 handler is called.+   *+   * @param handler The handler to be called when the write operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @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+   * descriptor.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)) 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 async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_write_some(this), handler, buffers);+  }++  /// Read some data from the descriptor.+  /**+   * This function is used to read data from the stream descriptor. 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+   * descriptor.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 descriptor.+  /**+   * This function is used to read data from the stream descriptor. 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+   * descriptor. The function call 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 handler is called.+   *+   * @param handler The handler to be called when the read operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @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+   * descriptor.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)) 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 async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_read_some(this), handler, buffers);+  }++private:+  class initiate_async_write_some+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_write_some(basic_stream_descriptor* 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_descriptor* self_;+  };++  class initiate_async_read_some+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_read_some(basic_stream_descriptor* 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_descriptor* self_;+  };+};++} // namespace posix+} // namespace asio++#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_POSIX_BASIC_STREAM_DESCRIPTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/posix/descriptor.hpp view
@@ -0,0 +1,37 @@+//+// posix/descriptor.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_POSIX_DESCRIPTOR_HPP+#define ASIO_POSIX_DESCRIPTOR_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_POSIX_STREAM_DESCRIPTOR) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/posix/basic_descriptor.hpp"++namespace asio {+namespace posix {++/// Typedef for the typical usage of basic_descriptor.+typedef basic_descriptor<> descriptor;++} // namespace posix+} // namespace asio++#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)+       // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_POSIX_DESCRIPTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/posix/descriptor_base.hpp view
@@ -0,0 +1,90 @@+//+// posix/descriptor_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_POSIX_DESCRIPTOR_BASE_HPP+#define ASIO_POSIX_DESCRIPTOR_BASE_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_POSIX_STREAM_DESCRIPTOR) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/detail/io_control.hpp"+#include "asio/detail/socket_option.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace posix {++/// The descriptor_base class is used as a base for the descriptor class as a+/// place to define the associated IO control commands.+class descriptor_base+{+public:+  /// Wait types.+  /**+   * For use with descriptor::wait() and descriptor::async_wait().+   */+  enum wait_type+  {+    /// Wait for a descriptor to become ready to read.+    wait_read,++    /// Wait for a descriptor to become ready to write.+    wait_write,++    /// Wait for a descriptor to have error conditions pending.+    wait_error+  };++  /// IO control command to get the amount of data that can be read without+  /// blocking.+  /**+   * Implements the FIONREAD IO control command.+   *+   * @par Example+   * @code+   * asio::posix::stream_descriptor descriptor(my_context);+   * ...+   * asio::descriptor_base::bytes_readable command(true);+   * descriptor.io_control(command);+   * std::size_t bytes_readable = command.get();+   * @endcode+   *+   * @par Concepts:+   * IoControlCommand.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined bytes_readable;+#else+  typedef asio::detail::io_control::bytes_readable bytes_readable;+#endif++protected:+  /// Protected destructor to prevent deletion through this type.+  ~descriptor_base()+  {+  }+};++} // namespace posix+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_POSIX_DESCRIPTOR_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/posix/stream_descriptor.hpp view
@@ -0,0 +1,37 @@+//+// posix/stream_descriptor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_POSIX_STREAM_DESCRIPTOR_HPP+#define ASIO_POSIX_STREAM_DESCRIPTOR_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_POSIX_STREAM_DESCRIPTOR) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/posix/basic_stream_descriptor.hpp"++namespace asio {+namespace posix {++/// Typedef for the typical usage of a stream-oriented descriptor.+typedef basic_stream_descriptor<> stream_descriptor;++} // namespace posix+} // namespace asio++#endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_POSIX_STREAM_DESCRIPTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/post.hpp view
@@ -0,0 +1,126 @@+//+// post.hpp+// ~~~~~~~~+//+// Copyright (c) 2003-2020 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_POST_HPP+#define ASIO_POST_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>post()</tt>.+ *+ * The use of @c post(), rather than @ref defer(), indicates the caller's+ * preference that the function object be eagerly queued for execution.+ *+ * This function has the following effects:+ *+ * @li Constructs a function object handler of type @c Handler, initialized+ * with <tt>handler(forward<CompletionToken>(token))</tt>.+ *+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,+ * initializing the object as <tt>result(handler)</tt>.+ *+ * @li Obtains the handler's associated executor object @c ex by performing+ * <tt>get_associated_executor(handler)</tt>.+ *+ * @li Obtains the handler's associated allocator object @c alloc by performing+ * <tt>get_associated_allocator(handler)</tt>.+ *+ * @li Performs <tt>ex.post(std::move(handler), alloc)</tt>.+ *+ * @li Returns <tt>result.get()</tt>.+ */+template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+    ASIO_MOVE_ARG(CompletionToken) 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>post()</tt>.+ *+ * The use of @c post(), rather than @ref defer(), indicates the caller's+ * preference that the function object be eagerly queued for execution.+ *+ * This function has the following effects:+ *+ * @li Constructs a function object handler of type @c Handler, initialized+ * with <tt>handler(forward<CompletionToken>(token))</tt>.+ *+ * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,+ * initializing the object as <tt>result(handler)</tt>.+ *+ * @li Obtains the handler's associated executor object @c ex1 by performing+ * <tt>get_associated_executor(handler)</tt>.+ *+ * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.+ *+ * @li Obtains the handler's associated allocator object @c alloc by performing+ * <tt>get_associated_allocator(handler)</tt>.+ *+ * @li Constructs a function object @c f with a function call operator that+ * performs <tt>ex1.dispatch(std::move(handler), alloc)</tt> followed by+ * <tt>w.reset()</tt>.+ *+ * @li Performs <tt>Executor(ex).post(std::move(f), alloc)</tt>.+ *+ * @li Returns <tt>result.get()</tt>.+ */+template <typename Executor,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+      ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+    const Executor& ex,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+    typename enable_if<+      execution::is_executor<Executor>::value || is_executor<Executor>::value+    >::type* = 0);++/// Submits a completion token or function object for execution.+/**+ * @returns <tt>post(ctx.get_executor(), forward<CompletionToken>(token))</tt>.+ */+template <typename ExecutionContext,+    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+      ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+        typename ExecutionContext::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+    ExecutionContext& ctx,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename ExecutionContext::executor_type),+    typename enable_if<is_convertible<+      ExecutionContext&, execution_context&>::value>::type* = 0);++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/post.hpp"++#endif // ASIO_POST_HPP
+ link/modules/asio-standalone/asio/include/asio/prefer.hpp view
@@ -0,0 +1,656 @@+//+// prefer.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_PREFER_HPP+#define ASIO_PREFER_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/is_applicable_property.hpp"+#include "asio/traits/prefer_free.hpp"+#include "asio/traits/prefer_member.hpp"+#include "asio/traits/require_free.hpp"+#include "asio/traits/require_member.hpp"+#include "asio/traits/static_require.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {++/// A customisation point that attempts to apply a property to an object.+/**+ * The name <tt>prefer</tt> denotes a customisation point object. The+ * expression <tt>asio::prefer(E, P0, Pn...)</tt> for some subexpressions+ * <tt>E</tt> and <tt>P0</tt>, and where <tt>Pn...</tt> represents <tt>N</tt>+ * subexpressions (where <tt>N</tt> is 0 or more, and with types <tt>T =+ * decay_t<decltype(E)></tt> and <tt>Prop0 = decay_t<decltype(P0)></tt>) is+ * expression-equivalent to:+ *+ * @li If <tt>is_applicable_property_v<T, Prop0> && Prop0::is_preferable</tt> is+ *   not a well-formed constant expression with value <tt>true</tt>,+ *   <tt>asio::prefer(E, P0, Pn...)</tt> is ill-formed.+ *+ * @li Otherwise, <tt>E</tt> if <tt>N == 0</tt> and the expression+ *   <tt>Prop0::template static_query_v<T> == Prop0::value()</tt> is a+ *   well-formed constant expression with value <tt>true</tt>.+ *+ * @li Otherwise, <tt>(E).require(P0)</tt> if <tt>N == 0</tt> and the expression+ *   <tt>(E).require(P0)</tt> is a valid expression.+ *+ * @li Otherwise, <tt>require(E, P0)</tt> if <tt>N == 0</tt> and the expression+ *   <tt>require(E, P0)</tt> is a valid expression with overload resolution+ *   performed in a context that does not include the declaration of the+ *   <tt>require</tt> customization point object.+ *+ * @li Otherwise, <tt>(E).prefer(P0)</tt> if <tt>N == 0</tt> and the expression+ *   <tt>(E).prefer(P0)</tt> is a valid expression.+ *+ * @li Otherwise, <tt>prefer(E, P0)</tt> if <tt>N == 0</tt> and the expression+ *   <tt>prefer(E, P0)</tt> is a valid expression with overload resolution+ *   performed in a context that does not include the declaration of the+ *   <tt>prefer</tt> customization point object.+ *+ * @li Otherwise, <tt>E</tt> if <tt>N == 0</tt>.+ *+ * @li Otherwise,+ *   <tt>asio::prefer(asio::prefer(E, P0), Pn...)</tt>+ *   if <tt>N > 0</tt> and the expression+ *   <tt>asio::prefer(asio::prefer(E, P0), Pn...)</tt>+ *   is a valid expression.+ *+ * @li Otherwise, <tt>asio::prefer(E, P0, Pn...)</tt> is ill-formed.+ */+inline constexpr unspecified prefer = unspecified;++/// A type trait that determines whether a @c prefer expression is well-formed.+/**+ * Class template @c can_prefer is a trait that is derived from+ * @c true_type if the expression <tt>asio::prefer(std::declval<T>(),+ * std::declval<Properties>()...)</tt> is well formed; otherwise @c false_type.+ */+template <typename T, typename... Properties>+struct can_prefer :+  integral_constant<bool, automatically_determined>+{+};++/// A type trait that determines whether a @c prefer expression will not throw.+/**+ * Class template @c is_nothrow_prefer is a trait that is derived from+ * @c true_type if the expression <tt>asio::prefer(std::declval<T>(),+ * std::declval<Properties>()...)</tt> is @c noexcept; otherwise @c false_type.+ */+template <typename T, typename... Properties>+struct is_nothrow_prefer :+  integral_constant<bool, automatically_determined>+{+};++/// A type trait that determines the result type of a @c prefer expression.+/**+ * Class template @c prefer_result is a trait that determines the result+ * type of the expression <tt>asio::prefer(std::declval<T>(),+ * std::declval<Properties>()...)</tt>.+ */+template <typename T, typename... Properties>+struct prefer_result+{+  /// The result of the @c prefer expression.+  typedef automatically_determined type;+};++} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_prefer_fn {++using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::is_applicable_property;+using asio::traits::prefer_free;+using asio::traits::prefer_member;+using asio::traits::require_free;+using asio::traits::require_member;+using asio::traits::static_require;++void prefer();+void require();++enum overload_type+{+  identity,+  call_require_member,+  call_require_free,+  call_prefer_member,+  call_prefer_free,+  two_props,+  n_props,+  ill_formed+};++template <typename T, typename Properties, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_preferable+      &&+      static_require<T, Property>::is_valid+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++#if defined(ASIO_HAS_MOVE)+  typedef ASIO_MOVE_ARG(T) result_type;+#else // defined(ASIO_HAS_MOVE)+  typedef ASIO_MOVE_ARG(typename decay<T>::type) result_type;+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_preferable+      &&+      !static_require<T, Property>::is_valid+      &&+      require_member<T, Property>::is_valid+    )+  >::type> :+  require_member<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_member);+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_preferable+      &&+      !static_require<T, Property>::is_valid+      &&+      !require_member<T, Property>::is_valid+      &&+      require_free<T, Property>::is_valid+    )+  >::type> :+  require_free<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_free);+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_preferable+      &&+      !static_require<T, Property>::is_valid+      &&+      !require_member<T, Property>::is_valid+      &&+      !require_free<T, Property>::is_valid+      &&+      prefer_member<T, Property>::is_valid+    )+  >::type> :+  prefer_member<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_member);+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_preferable+      &&+      !static_require<T, Property>::is_valid+      &&+      !require_member<T, Property>::is_valid+      &&+      !require_free<T, Property>::is_valid+      &&+      !prefer_member<T, Property>::is_valid+      &&+      prefer_free<T, Property>::is_valid+    )+  >::type> :+  prefer_free<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_free);+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_preferable+      &&+      !static_require<T, Property>::is_valid+      &&+      !require_member<T, Property>::is_valid+      &&+      !require_free<T, Property>::is_valid+      &&+      !prefer_member<T, Property>::is_valid+      &&+      !prefer_free<T, Property>::is_valid+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++#if defined(ASIO_HAS_MOVE)+  typedef ASIO_MOVE_ARG(T) result_type;+#else // defined(ASIO_HAS_MOVE)+  typedef ASIO_MOVE_ARG(typename decay<T>::type) result_type;+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T, typename P0, typename P1>+struct call_traits<T, void(P0, P1),+  typename enable_if<+    call_traits<T, void(P0)>::overload != ill_formed+    &&+    call_traits<+      typename call_traits<T, void(P0)>::result_type,+      void(P1)+    >::overload != ill_formed+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = two_props);++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (+      call_traits<T, void(P0)>::is_noexcept+      &&+      call_traits<+        typename call_traits<T, void(P0)>::result_type,+        void(P1)+      >::is_noexcept+    ));++  typedef typename decay<+    typename call_traits<+      typename call_traits<T, void(P0)>::result_type,+      void(P1)+    >::result_type+  >::type result_type;+};++template <typename T, typename P0, typename P1, typename ASIO_ELLIPSIS PN>+struct call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS),+  typename enable_if<+    call_traits<T, void(P0)>::overload != ill_formed+    &&+    call_traits<+      typename call_traits<T, void(P0)>::result_type,+      void(P1, PN ASIO_ELLIPSIS)+    >::overload != ill_formed+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = n_props);++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (+      call_traits<T, void(P0)>::is_noexcept+      &&+      call_traits<+        typename call_traits<T, void(P0)>::result_type,+        void(P1, PN ASIO_ELLIPSIS)+      >::is_noexcept+    ));++  typedef typename decay<+    typename call_traits<+      typename call_traits<T, void(P0)>::result_type,+      void(P1, PN ASIO_ELLIPSIS)+    >::result_type+  >::type result_type;+};++struct impl+{+  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == identity,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property)) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(T)(t);+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_require_member,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(T)(t).require(+        ASIO_MOVE_CAST(Property)(p));+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_require_free,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return require(+        ASIO_MOVE_CAST(T)(t),+        ASIO_MOVE_CAST(Property)(p));+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_prefer_member,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(T)(t).prefer(+        ASIO_MOVE_CAST(Property)(p));+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_prefer_free,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return prefer(+        ASIO_MOVE_CAST(T)(t),+        ASIO_MOVE_CAST(Property)(p));+  }++  template <typename T, typename P0, typename P1>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(P0, P1)>::overload == two_props,+    typename call_traits<T, void(P0, P1)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(P0) p0,+      ASIO_MOVE_ARG(P1) p1) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(P0, P1)>::is_noexcept))+  {+    return (*this)(+        (*this)(+          ASIO_MOVE_CAST(T)(t),+          ASIO_MOVE_CAST(P0)(p0)),+        ASIO_MOVE_CAST(P1)(p1));+  }++  template <typename T, typename P0, typename P1,+    typename ASIO_ELLIPSIS PN>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,+    typename call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(P0) p0,+      ASIO_MOVE_ARG(P1) p1,+      ASIO_MOVE_ARG(PN) ASIO_ELLIPSIS pn) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept))+  {+    return (*this)(+        (*this)(+          ASIO_MOVE_CAST(T)(t),+          ASIO_MOVE_CAST(P0)(p0)),+        ASIO_MOVE_CAST(P1)(p1),+        ASIO_MOVE_CAST(PN)(pn) ASIO_ELLIPSIS);+  }+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_prefer_fn+namespace asio {+namespace {++static ASIO_CONSTEXPR const asio_prefer_fn::impl&+  prefer = asio_prefer_fn::static_instance<>::instance;++} // namespace++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Properties>+struct can_prefer :+  integral_constant<bool,+    asio_prefer_fn::call_traits<T, void(Properties...)>::overload+      != asio_prefer_fn::ill_formed>+{+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename P0 = void,+    typename P1 = void, typename P2 = void>+struct can_prefer :+  integral_constant<bool,+    asio_prefer_fn::call_traits<T, void(P0, P1, P2)>::overload+      != asio_prefer_fn::ill_formed>+{+};++template <typename T, typename P0, typename P1>+struct can_prefer<T, P0, P1> :+  integral_constant<bool,+    asio_prefer_fn::call_traits<T, void(P0, P1)>::overload+      != asio_prefer_fn::ill_formed>+{+};++template <typename T, typename P0>+struct can_prefer<T, P0> :+  integral_constant<bool,+    asio_prefer_fn::call_traits<T, void(P0)>::overload+      != asio_prefer_fn::ill_formed>+{+};++template <typename T>+struct can_prefer<T> :+  false_type+{+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename ASIO_ELLIPSIS Properties>+constexpr bool can_prefer_v+  = can_prefer<T, Properties ASIO_ELLIPSIS>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Properties>+struct is_nothrow_prefer :+  integral_constant<bool,+    asio_prefer_fn::call_traits<T, void(Properties...)>::is_noexcept>+{+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename P0 = void,+    typename P1 = void, typename P2 = void>+struct is_nothrow_prefer :+  integral_constant<bool,+    asio_prefer_fn::call_traits<T, void(P0, P1, P2)>::is_noexcept>+{+};++template <typename T, typename P0, typename P1>+struct is_nothrow_prefer<T, P0, P1> :+  integral_constant<bool,+    asio_prefer_fn::call_traits<T, void(P0, P1)>::is_noexcept>+{+};++template <typename T, typename P0>+struct is_nothrow_prefer<T, P0> :+  integral_constant<bool,+    asio_prefer_fn::call_traits<T, void(P0)>::is_noexcept>+{+};++template <typename T>+struct is_nothrow_prefer<T> :+  false_type+{+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename ASIO_ELLIPSIS Properties>+constexpr bool is_nothrow_prefer_v+  = is_nothrow_prefer<T, Properties ASIO_ELLIPSIS>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Properties>+struct prefer_result+{+  typedef typename asio_prefer_fn::call_traits<+      T, void(Properties...)>::result_type type;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename P0 = void,+    typename P1 = void, typename P2 = void>+struct prefer_result+{+  typedef typename asio_prefer_fn::call_traits<+      T, void(P0, P1, P2)>::result_type type;+};++template <typename T, typename P0, typename P1>+struct prefer_result<T, P0, P1>+{+  typedef typename asio_prefer_fn::call_traits<+      T, void(P0, P1)>::result_type type;+};++template <typename T, typename P0>+struct prefer_result<T, P0>+{+  typedef typename asio_prefer_fn::call_traits<+      T, void(P0)>::result_type type;+};++template <typename T>+struct prefer_result<T>+{+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_PREFER_HPP
+ link/modules/asio-standalone/asio/include/asio/query.hpp view
@@ -0,0 +1,296 @@+//+// query.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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_QUERY_HPP+#define ASIO_QUERY_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/is_applicable_property.hpp"+#include "asio/traits/query_member.hpp"+#include "asio/traits/query_free.hpp"+#include "asio/traits/static_query.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {++/// A customisation point that queries the value of a property.+/**+ * The name <tt>query</tt> denotes a customization point object. The+ * expression <tt>asio::query(E, P)</tt> for some+ * subexpressions <tt>E</tt> and <tt>P</tt> (with types <tt>T =+ * decay_t<decltype(E)></tt> and <tt>Prop = decay_t<decltype(P)></tt>) is+ * expression-equivalent to:+ *+ * @li If <tt>is_applicable_property_v<T, Prop></tt> is not a well-formed+ *   constant expression with value <tt>true</tt>, <tt>asio::query(E,+ *   P)</tt> is ill-formed.+ *+ * @li Otherwise, <tt>Prop::template static_query_v<T></tt> if the expression+ *   <tt>Prop::template static_query_v<T></tt> is a well-formed constant+ *   expression.+ *+ * @li Otherwise, <tt>(E).query(P)</tt> if the expression+ *   <tt>(E).query(P)</tt> is well-formed.+ *+ * @li Otherwise, <tt>query(E, P)</tt> if the expression+ *   <tt>query(E, P)</tt> is a valid expression with overload+ *   resolution performed in a context that does not include the declaration+ *   of the <tt>query</tt> customization point object.+ *+ * @li Otherwise, <tt>asio::query(E, P)</tt> is ill-formed.+ */+inline constexpr unspecified query = unspecified;++/// A type trait that determines whether a @c query expression is well-formed.+/**+ * Class template @c can_query is a trait that is derived from+ * @c true_type if the expression <tt>asio::query(std::declval<T>(),+ * std::declval<Property>())</tt> is well formed; otherwise @c false_type.+ */+template <typename T, typename Property>+struct can_query :+  integral_constant<bool, automatically_determined>+{+};++/// A type trait that determines whether a @c query expression will+/// not throw.+/**+ * Class template @c is_nothrow_query is a trait that is derived from+ * @c true_type if the expression <tt>asio::query(std::declval<T>(),+ * std::declval<Property>())</tt> is @c noexcept; otherwise @c false_type.+ */+template <typename T, typename Property>+struct is_nothrow_query :+  integral_constant<bool, automatically_determined>+{+};++/// A type trait that determines the result type of a @c query expression.+/**+ * Class template @c query_result is a trait that determines the result+ * type of the expression <tt>asio::query(std::declval<T>(),+ * std::declval<Property>())</tt>.+ */+template <typename T, typename Property>+struct query_result+{+  /// The result of the @c query expression.+  typedef automatically_determined type;+};++} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_query_fn {++using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::is_applicable_property;+using asio::traits::query_free;+using asio::traits::query_member;+using asio::traits::static_query;++void query();++enum overload_type+{+  static_value,+  call_member,+  call_free,+  ill_formed+};++template <typename T, typename Properties, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      static_query<T, Property>::is_valid+    )+  >::type> :+  static_query<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = static_value);+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      !static_query<T, Property>::is_valid+      &&+      query_member<T, Property>::is_valid+    )+  >::type> :+  query_member<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      !static_query<T, Property>::is_valid+      &&+      !query_member<T, Property>::is_valid+      &&+      query_free<T, Property>::is_valid+    )+  >::type> :+  query_free<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++struct impl+{+  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == static_value,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T),+      ASIO_MOVE_ARG(Property)) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return static_query<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value();+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_member,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(T)(t).query(ASIO_MOVE_CAST(Property)(p));+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_free,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return query(ASIO_MOVE_CAST(T)(t), ASIO_MOVE_CAST(Property)(p));+  }+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_query_fn+namespace asio {+namespace {++static ASIO_CONSTEXPR const asio_query_fn::impl&+  query = asio_query_fn::static_instance<>::instance;++} // namespace++template <typename T, typename Property>+struct can_query :+  integral_constant<bool,+    asio_query_fn::call_traits<T, void(Property)>::overload !=+      asio_query_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+constexpr bool can_query_v+  = can_query<T, Property>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+struct is_nothrow_query :+  integral_constant<bool,+    asio_query_fn::call_traits<T, void(Property)>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+constexpr bool is_nothrow_query_v+  = is_nothrow_query<T, Property>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+struct query_result+{+  typedef typename asio_query_fn::call_traits<+      T, void(Property)>::result_type type;+};++} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_QUERY_HPP
+ link/modules/asio-standalone/asio/include/asio/read.hpp view
@@ -0,0 +1,1288 @@+//+// read.hpp+// ~~~~~~~~+//+// Copyright (c) 2003-2020 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_READ_HPP+#define ASIO_READ_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/buffer.hpp"+#include "asio/error.hpp"++#if !defined(ASIO_NO_EXTENSIONS)+# include "asio/basic_streambuf_fwd.hpp"+#endif // !defined(ASIO_NO_EXTENSIONS)++#include "asio/detail/push_options.hpp"++namespace asio {++/**+ * @defgroup read asio::read+ *+ * @brief The @c read function is a composed operation that reads a certain+ * amount of data from a stream before returning.+ */+/*@{*/++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * stream.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code asio::read(s, 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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read(+ *     s, buffers,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncReadStream, typename MutableBufferSequence>+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type* = 0);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * stream.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code asio::read(s, asio::buffer(data, size), ec); @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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read(+ *     s, buffers,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncReadStream, typename MutableBufferSequence>+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,+    asio::error_code& ec,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type* = 0);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * stream.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's read_some function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code asio::read(s, asio::buffer(data, size),+ *     asio::transfer_at_least(32)); @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 SyncReadStream, typename MutableBufferSequence,+  typename CompletionCondition>+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type* = 0);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * stream.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's read_some function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes read. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncReadStream, typename MutableBufferSequence,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type* = 0);++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read(+ *     s, buffers,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffer is full (that is, it has reached maximum size).+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read(+ *     s, buffers,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's read_some function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename SyncReadStream, typename DynamicBuffer_v1,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's read_some function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes read. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncReadStream, typename DynamicBuffer_v1,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffer is full (that is, it has reached maximum size).+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b The basic_streambuf object into which the data will be read.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read(+ *     s, b,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncReadStream, typename Allocator>+std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffer is full (that is, it has reached maximum size).+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b The basic_streambuf object into which the data will be read.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read(+ *     s, b,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncReadStream, typename Allocator>+std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,+    asio::error_code& ec);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffer is full (that is, it has reached maximum size).+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b The basic_streambuf object into which the data will be read.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's read_some function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename SyncReadStream, typename Allocator,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffer is full (that is, it has reached maximum size).+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b The basic_streambuf object into which the data will be read.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's read_some function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes read. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncReadStream, typename Allocator,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition, asio::error_code& ec);++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read(+ *     s, buffers,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The supplied buffer is full (that is, it has reached maximum size).+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read(+ *     s, buffers,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,+    asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's read_some function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename SyncReadStream, typename DynamicBuffer_v2,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Attempt to read a certain amount of data from a stream before returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * stream. The call will block until one of the following conditions is true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's read_some function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes read. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncReadStream, typename DynamicBuffer_v2,+    typename CompletionCondition>+std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/*@}*/+/**+ * @defgroup async_read asio::async_read+ *+ * @brief The @c async_read function is a composed asynchronous operation that+ * reads a certain amount of data from a stream before completion.+ */+/*@{*/++/// Start an asynchronous operation to read a certain amount of data from a+/// stream.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions is+ * true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other read operations (such+ * as async_read, the stream's async_read_some function, or any other composed+ * operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * stream. 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 handler is called.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes copied into the+ *                                           // buffers. If an error occurred,+ *                                           // this will be the  number of+ *                                           // bytes successfully transferred+ *                                           // prior to the error.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code+ * asio::async_read(s, 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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::async_read(+ *     s, buffers,+ *     asio::transfer_all(),+ *     handler); @endcode+ */+template <typename AsyncReadStream, typename MutableBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type* = 0);++/// Start an asynchronous operation to read a certain amount of data from a+/// stream.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions is+ * true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * stream. 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 handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's async_read_some function.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes copied into the+ *                                           // buffers. If an error occurred,+ *                                           // this will be the  number of+ *                                           // bytes successfully transferred+ *                                           // prior to the error.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code asio::async_read(s,+ *     asio::buffer(data, size),+ *     asio::transfer_at_least(32),+ *     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 AsyncReadStream,+    typename MutableBufferSequence, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_mutable_buffer_sequence<MutableBufferSequence>::value+    >::type* = 0);++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Start an asynchronous operation to read a certain amount of data from a+/// stream.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions is+ * true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other read operations (such+ * as async_read, the stream's async_read_some function, or any other composed+ * operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes copied into the+ *                                           // buffers. If an error occurred,+ *                                           // this will be the  number of+ *                                           // bytes successfully transferred+ *                                           // prior to the error.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note This overload is equivalent to calling:+ * @code asio::async_read(+ *     s, buffers,+ *     asio::transfer_all(),+ *     handler); @endcode+ */+template <typename AsyncReadStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Start an asynchronous operation to read a certain amount of data from a+/// stream.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions is+ * true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other read operations (such+ * as async_read, the stream's async_read_some function, or any other composed+ * operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's async_read_some function.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes copied into the+ *                                           // buffers. If an error occurred,+ *                                           // this will be the  number of+ *                                           // bytes successfully transferred+ *                                           // prior to the error.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncReadStream,+    typename DynamicBuffer_v1, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++/// Start an asynchronous operation to read a certain amount of data from a+/// stream.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions is+ * true:+ *+ * @li The supplied buffer is full (that is, it has reached maximum size).+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other read operations (such+ * as async_read, the stream's async_read_some function, or any other composed+ * operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param b A basic_streambuf object into which the data will be read. Ownership+ * of the streambuf is retained by the caller, which must guarantee that it+ * remains valid until the handler is called.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes copied into the+ *                                           // buffers. If an error occurred,+ *                                           // this will be the  number of+ *                                           // bytes successfully transferred+ *                                           // prior to the error.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note This overload is equivalent to calling:+ * @code asio::async_read(+ *     s, b,+ *     asio::transfer_all(),+ *     handler); @endcode+ */+template <typename AsyncReadStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type));++/// Start an asynchronous operation to read a certain amount of data from a+/// stream.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions is+ * true:+ *+ * @li The supplied buffer is full (that is, it has reached maximum size).+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other read operations (such+ * as async_read, the stream's async_read_some function, or any other composed+ * operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param b A basic_streambuf object into which the data will be read. Ownership+ * of the streambuf is retained by the caller, which must guarantee that it+ * remains valid until the handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's async_read_some function.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes copied into the+ *                                           // buffers. If an error occurred,+ *                                           // this will be the  number of+ *                                           // bytes successfully transferred+ *                                           // prior to the error.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncReadStream,+    typename Allocator, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type));++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Start an asynchronous operation to read a certain amount of data from a+/// stream.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions is+ * true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other read operations (such+ * as async_read, the stream's async_read_some function, or any other composed+ * operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes copied into the+ *                                           // buffers. If an error occurred,+ *                                           // this will be the  number of+ *                                           // bytes successfully transferred+ *                                           // prior to the error.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note This overload is equivalent to calling:+ * @code asio::async_read(+ *     s, buffers,+ *     asio::transfer_all(),+ *     handler); @endcode+ */+template <typename AsyncReadStream, typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Start an asynchronous operation to read a certain amount of data from a+/// stream.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions is+ * true:+ *+ * @li The specified dynamic buffer sequence is full (that is, it has reached+ * maximum size).+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other read operations (such+ * as async_read, the stream's async_read_some function, or any other composed+ * operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_read_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the stream's async_read_some function.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes copied into the+ *                                           // buffers. If an error occurred,+ *                                           // this will be the  number of+ *                                           // bytes successfully transferred+ *                                           // prior to the error.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncReadStream,+    typename DynamicBuffer_v2, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/*@}*/++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/read.hpp"++#endif // ASIO_READ_HPP
+ link/modules/asio-standalone/asio/include/asio/read_at.hpp view
@@ -0,0 +1,694 @@+//+// read_at.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_READ_AT_HPP+#define ASIO_READ_AT_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/detail/cstdint.hpp"+#include "asio/error.hpp"++#if !defined(ASIO_NO_EXTENSIONS)+# include "asio/basic_streambuf_fwd.hpp"+#endif // !defined(ASIO_NO_EXTENSIONS)++#include "asio/detail/push_options.hpp"++namespace asio {++/**+ * @defgroup read_at asio::read_at+ *+ * @brief The @c read_at function is a composed operation that reads a certain+ * amount of data at the specified offset before returning.+ */+/*@{*/++/// Attempt to read a certain amount of data at the specified offset before+/// returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * random access device at the specified offset. The call will block until one+ * of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the SyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * device.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code asio::read_at(d, 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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read_at(+ *     d, 42, buffers,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers);++/// Attempt to read a certain amount of data at the specified offset before+/// returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * random access device at the specified offset. The call will block until one+ * of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the SyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * device.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code asio::read_at(d, 42,+ *     asio::buffer(data, size), ec); @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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read_at(+ *     d, 42, buffers,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers,+    asio::error_code& ec);++/// Attempt to read a certain amount of data at the specified offset before+/// returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * random access device at the specified offset. The call will block until one+ * of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the SyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * device.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the device's read_some_at function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code asio::read_at(d, 42, asio::buffer(data, size),+ *     asio::transfer_at_least(32)); @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 SyncRandomAccessReadDevice, typename MutableBufferSequence,+    typename CompletionCondition>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition);++/// Attempt to read a certain amount of data at the specified offset before+/// returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * random access device at the specified offset. The call will block until one+ * of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the SyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * device.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the device's read_some_at function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes read. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncRandomAccessReadDevice, typename MutableBufferSequence,+    typename CompletionCondition>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition, asio::error_code& ec);++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++/// Attempt to read a certain amount of data at the specified offset before+/// returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * random access device at the specified offset. The call will block until one+ * of the following conditions is true:+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the SyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param b The basic_streambuf object into which the data will be read.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read_at(+ *     d, 42, b,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncRandomAccessReadDevice, typename Allocator>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, basic_streambuf<Allocator>& b);++/// Attempt to read a certain amount of data at the specified offset before+/// returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * random access device at the specified offset. The call will block until one+ * of the following conditions is true:+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the SyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param b The basic_streambuf object into which the data will be read.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @note This overload is equivalent to calling:+ * @code asio::read_at(+ *     d, 42, b,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncRandomAccessReadDevice, typename Allocator>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, basic_streambuf<Allocator>& b,+    asio::error_code& ec);++/// Attempt to read a certain amount of data at the specified offset before+/// returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * random access device at the specified offset. The call will block until one+ * of the following conditions is true:+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the SyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param b The basic_streambuf object into which the data will be read.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the device's read_some_at function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename SyncRandomAccessReadDevice, typename Allocator,+    typename CompletionCondition>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition);++/// Attempt to read a certain amount of data at the specified offset before+/// returning.+/**+ * This function is used to read a certain number of bytes of data from a+ * random access device at the specified offset. The call will block until one+ * of the following conditions is true:+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the SyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param b The basic_streambuf object into which the data will be read.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest read_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the device's read_some_at function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes read. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncRandomAccessReadDevice, typename Allocator,+    typename CompletionCondition>+std::size_t read_at(SyncRandomAccessReadDevice& d,+    uint64_t offset, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition, asio::error_code& ec);++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)++/*@}*/+/**+ * @defgroup async_read_at asio::async_read_at+ *+ * @brief The @c async_read_at function is a composed asynchronous operation+ * that reads a certain amount of data at the specified offset.+ */+/*@{*/++/// Start an asynchronous operation to read a certain amount of data at the+/// specified offset.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a random access device at the specified offset. The function call+ * always returns immediately. The asynchronous operation will continue until+ * one of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * async_read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the AsyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * device. 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 handler is called.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes copied into the buffers. If an error+ *   // occurred, this will be the number of bytes successfully+ *   // transferred prior to the error.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code+ * asio::async_read_at(d, 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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::async_read_at(+ *     d, 42, buffers,+ *     asio::transfer_all(),+ *     handler); @endcode+ */+template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncRandomAccessReadDevice::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset,+    const MutableBufferSequence& buffers,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncRandomAccessReadDevice::executor_type));++/// Start an asynchronous operation to read a certain amount of data at the+/// specified offset.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a random access device at the specified offset. The function call+ * always returns immediately. The asynchronous operation will continue until+ * one of the following conditions is true:+ *+ * @li The supplied buffers are full. That is, the bytes transferred is equal to+ * the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * @param d The device from which the data is to be read. The type must support+ * the AsyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param buffers One or more buffers into which the data will be read. The sum+ * of the buffer sizes indicates the maximum number of bytes to read from the+ * device. 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 handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_read_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the device's async_read_some_at function.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes copied into the buffers. If an error+ *   // occurred, this will be the number of bytes successfully+ *   // transferred prior to the error.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * To read into a single data buffer use the @ref buffer function as follows:+ * @code asio::async_read_at(d, 42,+ *     asio::buffer(data, size),+ *     asio::transfer_at_least(32),+ *     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 AsyncRandomAccessReadDevice,+    typename MutableBufferSequence, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncRandomAccessReadDevice::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_at(AsyncRandomAccessReadDevice& d,+    uint64_t offset, const MutableBufferSequence& buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncRandomAccessReadDevice::executor_type));++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++/// Start an asynchronous operation to read a certain amount of data at the+/// specified offset.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a random access device at the specified offset. The function call+ * always returns immediately. The asynchronous operation will continue until+ * one of the following conditions is true:+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * async_read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the AsyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param b A basic_streambuf object into which the data will be read. Ownership+ * of the streambuf is retained by the caller, which must guarantee that it+ * remains valid until the handler is called.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes copied into the buffers. If an error+ *   // occurred, this will be the number of bytes successfully+ *   // transferred prior to the error.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note This overload is equivalent to calling:+ * @code asio::async_read_at(+ *     d, 42, b,+ *     asio::transfer_all(),+ *     handler); @endcode+ */+template <typename AsyncRandomAccessReadDevice, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncRandomAccessReadDevice::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_at(AsyncRandomAccessReadDevice& d,+    uint64_t offset, basic_streambuf<Allocator>& b,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncRandomAccessReadDevice::executor_type));++/// Start an asynchronous operation to read a certain amount of data at the+/// specified offset.+/**+ * This function is used to asynchronously read a certain number of bytes of+ * data from a random access device at the specified offset. The function call+ * always returns immediately. The asynchronous operation will continue until+ * one of the following conditions is true:+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * async_read_some_at function.+ *+ * @param d The device from which the data is to be read. The type must support+ * the AsyncRandomAccessReadDevice concept.+ *+ * @param offset The offset at which the data will be read.+ *+ * @param b A basic_streambuf object into which the data will be read. Ownership+ * of the streambuf is retained by the caller, which must guarantee that it+ * remains valid until the handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the read operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_read_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the read operation is complete. A non-zero+ * return value indicates the maximum number of bytes to be read on the next+ * call to the device's async_read_some_at function.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes copied into the buffers. If an error+ *   // occurred, this will be the number of bytes successfully+ *   // transferred prior to the error.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncRandomAccessReadDevice,+    typename Allocator, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncRandomAccessReadDevice::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_at(AsyncRandomAccessReadDevice& d,+    uint64_t offset, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncRandomAccessReadDevice::executor_type));++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)++/*@}*/++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/read_at.hpp"++#endif // ASIO_READ_AT_HPP
+ link/modules/asio-standalone/asio/include/asio/read_until.hpp view
@@ -0,0 +1,2863 @@+//+// read_until.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_READ_UNTIL_HPP+#define ASIO_READ_UNTIL_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 <string>+#include "asio/async_result.hpp"+#include "asio/buffer.hpp"+#include "asio/detail/regex_fwd.hpp"+#include "asio/detail/string_view.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"++#if !defined(ASIO_NO_EXTENSIONS)+# include "asio/basic_streambuf_fwd.hpp"+#endif // !defined(ASIO_NO_EXTENSIONS)++#include "asio/detail/push_options.hpp"++namespace asio {++namespace detail+{+  char (&has_result_type_helper(...))[2];++  template <typename T>+  char has_result_type_helper(T*, typename T::result_type* = 0);++  template <typename T>+  struct has_result_type+  {+    enum { value = (sizeof((has_result_type_helper)((T*)(0))) == 1) };+  };+} // namespace detail++/// Type trait used to determine whether a type can be used as a match condition+/// function with read_until and async_read_until.+template <typename T>+struct is_match_condition+{+#if defined(GENERATING_DOCUMENTATION)+  /// The value member is true if the type may be used as a match condition.+  static const bool value;+#else+  enum+  {+    value = asio::is_function<+        typename asio::remove_pointer<T>::type>::value+      || detail::has_result_type<T>::value+  };+#endif+};++/**+ * @defgroup read_until asio::read_until+ *+ * @brief The @c read_until function is a composed operation that reads data+ * into a dynamic buffer sequence, or into a streambuf, until it contains a+ * delimiter, matches a regular expression, or a function object indicates a+ * match.+ */+/*@{*/++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Read data into a dynamic buffer sequence until it contains a specified+/// delimiter.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains the specified+ * delimiter. The call will block until one of the following conditions is+ * true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains the delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param delim The delimiter character.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the delimiter.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond the delimiter. An application will+ * typically leave that data in the dynamic buffer sequence for a subsequent+ * read_until operation to examine.+ *+ * @par Example+ * To read data into a @c std::string until a newline is encountered:+ * @code std::string data;+ * std::size_t n = asio::read_until(s,+ *     asio::dynamic_buffer(data), '\n');+ * std::string line = data.substr(0, n);+ * data.erase(0, n); @endcode+ * After the @c read_until operation completes successfully, the string @c data+ * contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the buffer @c b as+ * follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c read_until operation.+ */+template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until it contains a specified+/// delimiter.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains the specified+ * delimiter. The call will block until one of the following conditions is+ * true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains the delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param delim The delimiter character.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the delimiter. Returns 0 if an error occurred.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond the delimiter. An application will+ * typically leave that data in the dynamic buffer sequence for a subsequent+ * read_until operation to examine.+ */+template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    char delim, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until it contains a specified+/// delimiter.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains the specified+ * delimiter. The call will block until one of the following conditions is+ * true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains the delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param delim The delimiter string.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the delimiter.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond the delimiter. An application will+ * typically leave that data in the dynamic buffer sequence for a subsequent+ * read_until operation to examine.+ *+ * @par Example+ * To read data into a @c std::string until a CR-LF sequence is encountered:+ * @code std::string data;+ * std::size_t n = asio::read_until(s,+ *     asio::dynamic_buffer(data), "\r\n");+ * std::string line = data.substr(0, n);+ * data.erase(0, n); @endcode+ * After the @c read_until operation completes successfully, the string @c data+ * contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the buffer @c b as+ * follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c read_until operation.+ */+template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_STRING_VIEW_PARAM delim,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until it contains a specified+/// delimiter.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains the specified+ * delimiter. The call will block until one of the following conditions is+ * true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains the delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param delim The delimiter string.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the delimiter. Returns 0 if an error occurred.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond the delimiter. An application will+ * typically leave that data in the dynamic buffer sequence for a subsequent+ * read_until operation to examine.+ */+template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_STRING_VIEW_PARAM delim,+    asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#if !defined(ASIO_NO_EXTENSIONS)+#if defined(ASIO_HAS_BOOST_REGEX) \+  || defined(GENERATING_DOCUMENTATION)++/// Read data into a dynamic buffer sequence until some part of the data it+/// contains matches a regular expression.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains some data+ * that matches a regular expression. The call will block until one of the+ * following conditions is true:+ *+ * @li A substring of the dynamic buffer sequence's get area matches the+ * regular expression.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains data that matches the regular expression, the function returns+ * immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers A dynamic buffer sequence into which the data will be read.+ *+ * @param expr The regular expression.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the substring that matches the regular expression.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond that which matched the regular+ * expression. An application will typically leave that data in the dynamic+ * buffer sequence for a subsequent read_until operation to examine.+ *+ * @par Example+ * To read data into a @c std::string until a CR-LF sequence is encountered:+ * @code std::string data;+ * std::size_t n = asio::read_until(s,+ *     asio::dynamic_buffer(data), boost::regex("\r\n"));+ * std::string line = data.substr(0, n);+ * data.erase(0, n); @endcode+ * After the @c read_until operation completes successfully, the string @c data+ * contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the buffer @c b as+ * follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c read_until operation.+ */+template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    const boost::regex& expr,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until some part of the data it+/// contains matches a regular expression.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains some data+ * that matches a regular expression. The call will block until one of the+ * following conditions is true:+ *+ * @li A substring of the dynamic buffer sequence's get area matches the+ * regular expression.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains data that matches the regular expression, the function returns+ * immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers A dynamic buffer sequence into which the data will be read.+ *+ * @param expr The regular expression.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the substring that matches the regular expression. Returns 0+ * if an error occurred.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond that which matched the regular+ * expression. An application will typically leave that data in the dynamic+ * buffer sequence for a subsequent read_until operation to examine.+ */+template <typename SyncReadStream, typename DynamicBuffer_v1>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    const boost::regex& expr, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#endif // defined(ASIO_HAS_BOOST_REGEX)+       // || defined(GENERATING_DOCUMENTATION)++/// Read data into a dynamic buffer sequence until a function object indicates a+/// match.++/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until a user-defined match condition function object, when applied+ * to the data contained in the dynamic buffer sequence, indicates a successful+ * match. The call will block until one of the following conditions is true:+ *+ * @li The match condition function object returns a std::pair where the second+ * element evaluates to true.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the match condition function object already indicates+ * a match, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers A dynamic buffer sequence into which the data will be read.+ *+ * @param match_condition The function object to be called to determine whether+ * a match exists. The signature of the function object must be:+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);+ * @endcode+ * where @c iterator represents the type:+ * @code buffers_iterator<typename DynamicBuffer_v1::const_buffers_type>+ * @endcode+ * The iterator parameters @c begin and @c end define the range of bytes to be+ * scanned to determine whether there is a match. The @c first member of the+ * return value is an iterator marking one-past-the-end of the bytes that have+ * been consumed by the match function. This iterator is used to calculate the+ * @c begin parameter for any subsequent invocation of the match condition. The+ * @c second member of the return value is true if a match has been found, false+ * otherwise.+ *+ * @returns The number of bytes in the dynamic_buffer's get area that+ * have been fully consumed by the match function.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond that which matched the function object.+ * An application will typically leave that data in the dynamic buffer sequence+ * for a subsequent read_until operation to examine.++ * @note The default implementation of the @c is_match_condition type trait+ * evaluates to true for function pointers and function objects with a+ * @c result_type typedef. It must be specialised for other user-defined+ * function objects.+ *+ * @par Examples+ * To read data into a dynamic buffer sequence until whitespace is encountered:+ * @code typedef asio::buffers_iterator<+ *     asio::const_buffers_1> iterator;+ *+ * std::pair<iterator, bool>+ * match_whitespace(iterator begin, iterator end)+ * {+ *   iterator i = begin;+ *   while (i != end)+ *     if (std::isspace(*i++))+ *       return std::make_pair(i, true);+ *   return std::make_pair(i, false);+ * }+ * ...+ * std::string data;+ * asio::read_until(s, data, match_whitespace);+ * @endcode+ *+ * To read data into a @c std::string until a matching character is found:+ * @code class match_char+ * {+ * public:+ *   explicit match_char(char c) : c_(c) {}+ *+ *   template <typename Iterator>+ *   std::pair<Iterator, bool> operator()(+ *       Iterator begin, Iterator end) const+ *   {+ *     Iterator i = begin;+ *     while (i != end)+ *       if (c_ == *i++)+ *         return std::make_pair(i, true);+ *     return std::make_pair(i, false);+ *   }+ *+ * private:+ *   char c_;+ * };+ *+ * namespace asio {+ *   template <> struct is_match_condition<match_char>+ *     : public boost::true_type {};+ * } // namespace asio+ * ...+ * std::string data;+ * asio::read_until(s, data, match_char('a'));+ * @endcode+ */+template <typename SyncReadStream,+    typename DynamicBuffer_v1, typename MatchCondition>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    MatchCondition match_condition,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until a function object indicates a+/// match.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until a user-defined match condition function object, when applied+ * to the data contained in the dynamic buffer sequence, indicates a successful+ * match. The call will block until one of the following conditions is true:+ *+ * @li The match condition function object returns a std::pair where the second+ * element evaluates to true.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the match condition function object already indicates+ * a match, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers A dynamic buffer sequence into which the data will be read.+ *+ * @param match_condition The function object to be called to determine whether+ * a match exists. The signature of the function object must be:+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);+ * @endcode+ * where @c iterator represents the type:+ * @code buffers_iterator<DynamicBuffer_v1::const_buffers_type>+ * @endcode+ * The iterator parameters @c begin and @c end define the range of bytes to be+ * scanned to determine whether there is a match. The @c first member of the+ * return value is an iterator marking one-past-the-end of the bytes that have+ * been consumed by the match function. This iterator is used to calculate the+ * @c begin parameter for any subsequent invocation of the match condition. The+ * @c second member of the return value is true if a match has been found, false+ * otherwise.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area that+ * have been fully consumed by the match function. Returns 0 if an error+ * occurred.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond that which matched the function object.+ * An application will typically leave that data in the dynamic buffer sequence+ * for a subsequent read_until operation to examine.+ *+ * @note The default implementation of the @c is_match_condition type trait+ * evaluates to true for function pointers and function objects with a+ * @c result_type typedef. It must be specialised for other user-defined+ * function objects.+ */+template <typename SyncReadStream,+    typename DynamicBuffer_v1, typename MatchCondition>+std::size_t read_until(SyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    MatchCondition match_condition, asio::error_code& ec,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#if !defined(ASIO_NO_IOSTREAM)++/// Read data into a streambuf until it contains a specified delimiter.+/**+ * This function is used to read data into the specified streambuf until the+ * streambuf's get area contains the specified delimiter. The call will block+ * until one of the following conditions is true:+ *+ * @li The get area of the streambuf contains the specified delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the streambuf's get area already contains the+ * delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read.+ *+ * @param delim The delimiter character.+ *+ * @returns The number of bytes in the streambuf's get area up to and including+ * the delimiter.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the streambuf may contain+ * additional data beyond the delimiter. An application will typically leave+ * that data in the streambuf for a subsequent read_until operation to examine.+ *+ * @par Example+ * To read data into a streambuf until a newline is encountered:+ * @code asio::streambuf b;+ * asio::read_until(s, b, '\n');+ * std::istream is(&b);+ * std::string line;+ * std::getline(is, line); @endcode+ * After the @c read_until operation completes successfully, the buffer @c b+ * contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode+ * The call to @c std::getline then extracts the data up to and including the+ * newline (which is discarded), so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c' } @endcode+ * The remaining data is left in the buffer @c b as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c read_until operation.+ */+template <typename SyncReadStream, typename Allocator>+std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, char delim);++/// Read data into a streambuf until it contains a specified delimiter.+/**+ * This function is used to read data into the specified streambuf until the+ * streambuf's get area contains the specified delimiter. The call will block+ * until one of the following conditions is true:+ *+ * @li The get area of the streambuf contains the specified delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the streambuf's get area already contains the+ * delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read.+ *+ * @param delim The delimiter character.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the streambuf's get area up to and including+ * the delimiter. Returns 0 if an error occurred.+ *+ * @note After a successful read_until operation, the streambuf may contain+ * additional data beyond the delimiter. An application will typically leave+ * that data in the streambuf for a subsequent read_until operation to examine.+ */+template <typename SyncReadStream, typename Allocator>+std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, char delim,+    asio::error_code& ec);++/// Read data into a streambuf until it contains a specified delimiter.+/**+ * This function is used to read data into the specified streambuf until the+ * streambuf's get area contains the specified delimiter. The call will block+ * until one of the following conditions is true:+ *+ * @li The get area of the streambuf contains the specified delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the streambuf's get area already contains the+ * delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read.+ *+ * @param delim The delimiter string.+ *+ * @returns The number of bytes in the streambuf's get area up to and including+ * the delimiter.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the streambuf may contain+ * additional data beyond the delimiter. An application will typically leave+ * that data in the streambuf for a subsequent read_until operation to examine.+ *+ * @par Example+ * To read data into a streambuf until a newline is encountered:+ * @code asio::streambuf b;+ * asio::read_until(s, b, "\r\n");+ * std::istream is(&b);+ * std::string line;+ * std::getline(is, line); @endcode+ * After the @c read_until operation completes successfully, the buffer @c b+ * contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c std::getline then extracts the data up to and including the+ * newline (which is discarded), so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r' } @endcode+ * The remaining data is left in the buffer @c b as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c read_until operation.+ */+template <typename SyncReadStream, typename Allocator>+std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    ASIO_STRING_VIEW_PARAM delim);++/// Read data into a streambuf until it contains a specified delimiter.+/**+ * This function is used to read data into the specified streambuf until the+ * streambuf's get area contains the specified delimiter. The call will block+ * until one of the following conditions is true:+ *+ * @li The get area of the streambuf contains the specified delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the streambuf's get area already contains the+ * delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read.+ *+ * @param delim The delimiter string.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the streambuf's get area up to and including+ * the delimiter. Returns 0 if an error occurred.+ *+ * @note After a successful read_until operation, the streambuf may contain+ * additional data beyond the delimiter. An application will typically leave+ * that data in the streambuf for a subsequent read_until operation to examine.+ */+template <typename SyncReadStream, typename Allocator>+std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec);++#if defined(ASIO_HAS_BOOST_REGEX) \+  || defined(GENERATING_DOCUMENTATION)++/// Read data into a streambuf until some part of the data it contains matches+/// a regular expression.+/**+ * This function is used to read data into the specified streambuf until the+ * streambuf's get area contains some data that matches a regular expression.+ * The call will block until one of the following conditions is true:+ *+ * @li A substring of the streambuf's get area matches the regular expression.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the streambuf's get area already contains data that+ * matches the regular expression, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read.+ *+ * @param expr The regular expression.+ *+ * @returns The number of bytes in the streambuf's get area up to and including+ * the substring that matches the regular expression.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the streambuf may contain+ * additional data beyond that which matched the regular expression. An+ * application will typically leave that data in the streambuf for a subsequent+ * read_until operation to examine.+ *+ * @par Example+ * To read data into a streambuf until a CR-LF sequence is encountered:+ * @code asio::streambuf b;+ * asio::read_until(s, b, boost::regex("\r\n"));+ * std::istream is(&b);+ * std::string line;+ * std::getline(is, line); @endcode+ * After the @c read_until operation completes successfully, the buffer @c b+ * contains the data which matched the regular expression:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c std::getline then extracts the data up to and including the+ * newline (which is discarded), so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r' } @endcode+ * The remaining data is left in the buffer @c b as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c read_until operation.+ */+template <typename SyncReadStream, typename Allocator>+std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr);++/// Read data into a streambuf until some part of the data it contains matches+/// a regular expression.+/**+ * This function is used to read data into the specified streambuf until the+ * streambuf's get area contains some data that matches a regular expression.+ * The call will block until one of the following conditions is true:+ *+ * @li A substring of the streambuf's get area matches the regular expression.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the streambuf's get area already contains data that+ * matches the regular expression, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read.+ *+ * @param expr The regular expression.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the streambuf's get area up to and including+ * the substring that matches the regular expression. Returns 0 if an error+ * occurred.+ *+ * @note After a successful read_until operation, the streambuf may contain+ * additional data beyond that which matched the regular expression. An+ * application will typically leave that data in the streambuf for a subsequent+ * read_until operation to examine.+ */+template <typename SyncReadStream, typename Allocator>+std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,+    asio::error_code& ec);++#endif // defined(ASIO_HAS_BOOST_REGEX)+       // || defined(GENERATING_DOCUMENTATION)++/// Read data into a streambuf until a function object indicates a match.+/**+ * This function is used to read data into the specified streambuf until a+ * user-defined match condition function object, when applied to the data+ * contained in the streambuf, indicates a successful match. The call will+ * block until one of the following conditions is true:+ *+ * @li The match condition function object returns a std::pair where the second+ * element evaluates to true.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the match condition function object already indicates+ * a match, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read.+ *+ * @param match_condition The function object to be called to determine whether+ * a match exists. The signature of the function object must be:+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);+ * @endcode+ * where @c iterator represents the type:+ * @code buffers_iterator<basic_streambuf<Allocator>::const_buffers_type>+ * @endcode+ * The iterator parameters @c begin and @c end define the range of bytes to be+ * scanned to determine whether there is a match. The @c first member of the+ * return value is an iterator marking one-past-the-end of the bytes that have+ * been consumed by the match function. This iterator is used to calculate the+ * @c begin parameter for any subsequent invocation of the match condition. The+ * @c second member of the return value is true if a match has been found, false+ * otherwise.+ *+ * @returns The number of bytes in the streambuf's get area that have been fully+ * consumed by the match function.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the streambuf may contain+ * additional data beyond that which matched the function object. An application+ * will typically leave that data in the streambuf for a subsequent read_until+ * operation to examine.+ *+ * @note The default implementation of the @c is_match_condition type trait+ * evaluates to true for function pointers and function objects with a+ * @c result_type typedef. It must be specialised for other user-defined+ * function objects.+ *+ * @par Examples+ * To read data into a streambuf until whitespace is encountered:+ * @code typedef asio::buffers_iterator<+ *     asio::streambuf::const_buffers_type> iterator;+ *+ * std::pair<iterator, bool>+ * match_whitespace(iterator begin, iterator end)+ * {+ *   iterator i = begin;+ *   while (i != end)+ *     if (std::isspace(*i++))+ *       return std::make_pair(i, true);+ *   return std::make_pair(i, false);+ * }+ * ...+ * asio::streambuf b;+ * asio::read_until(s, b, match_whitespace);+ * @endcode+ *+ * To read data into a streambuf until a matching character is found:+ * @code class match_char+ * {+ * public:+ *   explicit match_char(char c) : c_(c) {}+ *+ *   template <typename Iterator>+ *   std::pair<Iterator, bool> operator()(+ *       Iterator begin, Iterator end) const+ *   {+ *     Iterator i = begin;+ *     while (i != end)+ *       if (c_ == *i++)+ *         return std::make_pair(i, true);+ *     return std::make_pair(i, false);+ *   }+ *+ * private:+ *   char c_;+ * };+ *+ * namespace asio {+ *   template <> struct is_match_condition<match_char>+ *     : public boost::true_type {};+ * } // namespace asio+ * ...+ * asio::streambuf b;+ * asio::read_until(s, b, match_char('a'));+ * @endcode+ */+template <typename SyncReadStream, typename Allocator, typename MatchCondition>+std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, MatchCondition match_condition,+    typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);++/// Read data into a streambuf until a function object indicates a match.+/**+ * This function is used to read data into the specified streambuf until a+ * user-defined match condition function object, when applied to the data+ * contained in the streambuf, indicates a successful match. The call will+ * block until one of the following conditions is true:+ *+ * @li The match condition function object returns a std::pair where the second+ * element evaluates to true.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the match condition function object already indicates+ * a match, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read.+ *+ * @param match_condition The function object to be called to determine whether+ * a match exists. The signature of the function object must be:+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);+ * @endcode+ * where @c iterator represents the type:+ * @code buffers_iterator<basic_streambuf<Allocator>::const_buffers_type>+ * @endcode+ * The iterator parameters @c begin and @c end define the range of bytes to be+ * scanned to determine whether there is a match. The @c first member of the+ * return value is an iterator marking one-past-the-end of the bytes that have+ * been consumed by the match function. This iterator is used to calculate the+ * @c begin parameter for any subsequent invocation of the match condition. The+ * @c second member of the return value is true if a match has been found, false+ * otherwise.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the streambuf's get area that have been fully+ * consumed by the match function. Returns 0 if an error occurred.+ *+ * @note After a successful read_until operation, the streambuf may contain+ * additional data beyond that which matched the function object. An application+ * will typically leave that data in the streambuf for a subsequent read_until+ * operation to examine.+ *+ * @note The default implementation of the @c is_match_condition type trait+ * evaluates to true for function pointers and function objects with a+ * @c result_type typedef. It must be specialised for other user-defined+ * function objects.+ */+template <typename SyncReadStream, typename Allocator, typename MatchCondition>+std::size_t read_until(SyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    MatchCondition match_condition, asio::error_code& ec,+    typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Read data into a dynamic buffer sequence until it contains a specified+/// delimiter.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains the specified+ * delimiter. The call will block until one of the following conditions is+ * true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains the delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param delim The delimiter character.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the delimiter.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond the delimiter. An application will+ * typically leave that data in the dynamic buffer sequence for a subsequent+ * read_until operation to examine.+ *+ * @par Example+ * To read data into a @c std::string until a newline is encountered:+ * @code std::string data;+ * std::size_t n = asio::read_until(s,+ *     asio::dynamic_buffer(data), '\n');+ * std::string line = data.substr(0, n);+ * data.erase(0, n); @endcode+ * After the @c read_until operation completes successfully, the string @c data+ * contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the buffer @c b as+ * follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c read_until operation.+ */+template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until it contains a specified+/// delimiter.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains the specified+ * delimiter. The call will block until one of the following conditions is+ * true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains the delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param delim The delimiter character.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the delimiter. Returns 0 if an error occurred.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond the delimiter. An application will+ * typically leave that data in the dynamic buffer sequence for a subsequent+ * read_until operation to examine.+ */+template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    char delim, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until it contains a specified+/// delimiter.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains the specified+ * delimiter. The call will block until one of the following conditions is+ * true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains the delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param delim The delimiter string.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the delimiter.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond the delimiter. An application will+ * typically leave that data in the dynamic buffer sequence for a subsequent+ * read_until operation to examine.+ *+ * @par Example+ * To read data into a @c std::string until a CR-LF sequence is encountered:+ * @code std::string data;+ * std::size_t n = asio::read_until(s,+ *     asio::dynamic_buffer(data), "\r\n");+ * std::string line = data.substr(0, n);+ * data.erase(0, n); @endcode+ * After the @c read_until operation completes successfully, the string @c data+ * contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the buffer @c b as+ * follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c read_until operation.+ */+template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    ASIO_STRING_VIEW_PARAM delim,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until it contains a specified+/// delimiter.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains the specified+ * delimiter. The call will block until one of the following conditions is+ * true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains the delimiter, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence into which the data will be read.+ *+ * @param delim The delimiter string.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the delimiter. Returns 0 if an error occurred.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond the delimiter. An application will+ * typically leave that data in the dynamic buffer sequence for a subsequent+ * read_until operation to examine.+ */+template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    ASIO_STRING_VIEW_PARAM delim, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++#if !defined(ASIO_NO_EXTENSIONS)+#if defined(ASIO_HAS_BOOST_REGEX) \+  || defined(GENERATING_DOCUMENTATION)++/// Read data into a dynamic buffer sequence until some part of the data it+/// contains matches a regular expression.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains some data+ * that matches a regular expression. The call will block until one of the+ * following conditions is true:+ *+ * @li A substring of the dynamic buffer sequence's get area matches the+ * regular expression.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains data that matches the regular expression, the function returns+ * immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers A dynamic buffer sequence into which the data will be read.+ *+ * @param expr The regular expression.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the substring that matches the regular expression.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond that which matched the regular+ * expression. An application will typically leave that data in the dynamic+ * buffer sequence for a subsequent read_until operation to examine.+ *+ * @par Example+ * To read data into a @c std::string until a CR-LF sequence is encountered:+ * @code std::string data;+ * std::size_t n = asio::read_until(s,+ *     asio::dynamic_buffer(data), boost::regex("\r\n"));+ * std::string line = data.substr(0, n);+ * data.erase(0, n); @endcode+ * After the @c read_until operation completes successfully, the string @c data+ * contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the buffer @c b as+ * follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c read_until operation.+ */+template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    const boost::regex& expr,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until some part of the data it+/// contains matches a regular expression.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until the dynamic buffer sequence's get area contains some data+ * that matches a regular expression. The call will block until one of the+ * following conditions is true:+ *+ * @li A substring of the dynamic buffer sequence's get area matches the+ * regular expression.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the dynamic buffer sequence's get area already+ * contains data that matches the regular expression, the function returns+ * immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers A dynamic buffer sequence into which the data will be read.+ *+ * @param expr The regular expression.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area up to+ * and including the substring that matches the regular expression. Returns 0+ * if an error occurred.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond that which matched the regular+ * expression. An application will typically leave that data in the dynamic+ * buffer sequence for a subsequent read_until operation to examine.+ */+template <typename SyncReadStream, typename DynamicBuffer_v2>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    const boost::regex& expr, asio::error_code& ec,+    typename enable_if<+        is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++#endif // defined(ASIO_HAS_BOOST_REGEX)+       // || defined(GENERATING_DOCUMENTATION)++/// Read data into a dynamic buffer sequence until a function object indicates a+/// match.++/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until a user-defined match condition function object, when applied+ * to the data contained in the dynamic buffer sequence, indicates a successful+ * match. The call will block until one of the following conditions is true:+ *+ * @li The match condition function object returns a std::pair where the second+ * element evaluates to true.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the match condition function object already indicates+ * a match, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers A dynamic buffer sequence into which the data will be read.+ *+ * @param match_condition The function object to be called to determine whether+ * a match exists. The signature of the function object must be:+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);+ * @endcode+ * where @c iterator represents the type:+ * @code buffers_iterator<typename DynamicBuffer_v2::const_buffers_type>+ * @endcode+ * The iterator parameters @c begin and @c end define the range of bytes to be+ * scanned to determine whether there is a match. The @c first member of the+ * return value is an iterator marking one-past-the-end of the bytes that have+ * been consumed by the match function. This iterator is used to calculate the+ * @c begin parameter for any subsequent invocation of the match condition. The+ * @c second member of the return value is true if a match has been found, false+ * otherwise.+ *+ * @returns The number of bytes in the dynamic_buffer's get area that+ * have been fully consumed by the match function.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond that which matched the function object.+ * An application will typically leave that data in the dynamic buffer sequence+ * for a subsequent read_until operation to examine.++ * @note The default implementation of the @c is_match_condition type trait+ * evaluates to true for function pointers and function objects with a+ * @c result_type typedef. It must be specialised for other user-defined+ * function objects.+ *+ * @par Examples+ * To read data into a dynamic buffer sequence until whitespace is encountered:+ * @code typedef asio::buffers_iterator<+ *     asio::const_buffers_1> iterator;+ *+ * std::pair<iterator, bool>+ * match_whitespace(iterator begin, iterator end)+ * {+ *   iterator i = begin;+ *   while (i != end)+ *     if (std::isspace(*i++))+ *       return std::make_pair(i, true);+ *   return std::make_pair(i, false);+ * }+ * ...+ * std::string data;+ * asio::read_until(s, data, match_whitespace);+ * @endcode+ *+ * To read data into a @c std::string until a matching character is found:+ * @code class match_char+ * {+ * public:+ *   explicit match_char(char c) : c_(c) {}+ *+ *   template <typename Iterator>+ *   std::pair<Iterator, bool> operator()(+ *       Iterator begin, Iterator end) const+ *   {+ *     Iterator i = begin;+ *     while (i != end)+ *       if (c_ == *i++)+ *         return std::make_pair(i, true);+ *     return std::make_pair(i, false);+ *   }+ *+ * private:+ *   char c_;+ * };+ *+ * namespace asio {+ *   template <> struct is_match_condition<match_char>+ *     : public boost::true_type {};+ * } // namespace asio+ * ...+ * std::string data;+ * asio::read_until(s, data, match_char('a'));+ * @endcode+ */+template <typename SyncReadStream,+    typename DynamicBuffer_v2, typename MatchCondition>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    MatchCondition match_condition,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Read data into a dynamic buffer sequence until a function object indicates a+/// match.+/**+ * This function is used to read data into the specified dynamic buffer+ * sequence until a user-defined match condition function object, when applied+ * to the data contained in the dynamic buffer sequence, indicates a successful+ * match. The call will block until one of the following conditions is true:+ *+ * @li The match condition function object returns a std::pair where the second+ * element evaluates to true.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * read_some function. If the match condition function object already indicates+ * a match, the function returns immediately.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the SyncReadStream concept.+ *+ * @param buffers A dynamic buffer sequence into which the data will be read.+ *+ * @param match_condition The function object to be called to determine whether+ * a match exists. The signature of the function object must be:+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);+ * @endcode+ * where @c iterator represents the type:+ * @code buffers_iterator<DynamicBuffer_v2::const_buffers_type>+ * @endcode+ * The iterator parameters @c begin and @c end define the range of bytes to be+ * scanned to determine whether there is a match. The @c first member of the+ * return value is an iterator marking one-past-the-end of the bytes that have+ * been consumed by the match function. This iterator is used to calculate the+ * @c begin parameter for any subsequent invocation of the match condition. The+ * @c second member of the return value is true if a match has been found, false+ * otherwise.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes in the dynamic buffer sequence's get area that+ * have been fully consumed by the match function. Returns 0 if an error+ * occurred.+ *+ * @note After a successful read_until operation, the dynamic buffer sequence+ * may contain additional data beyond that which matched the function object.+ * An application will typically leave that data in the dynamic buffer sequence+ * for a subsequent read_until operation to examine.+ *+ * @note The default implementation of the @c is_match_condition type trait+ * evaluates to true for function pointers and function objects with a+ * @c result_type typedef. It must be specialised for other user-defined+ * function objects.+ */+template <typename SyncReadStream,+    typename DynamicBuffer_v2, typename MatchCondition>+std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,+    MatchCondition match_condition, asio::error_code& ec,+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++#endif // !defined(ASIO_NO_EXTENSIONS)++/*@}*/+/**+ * @defgroup async_read_until asio::async_read_until+ *+ * @brief The @c async_read_until function is a composed asynchronous operation+ * that reads data into a dynamic buffer sequence, or into a streambuf, until+ * it contains a delimiter, matches a regular expression, or a function object+ * indicates a match.+ */+/*@{*/++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Start an asynchronous operation to read data into a dynamic buffer sequence+/// until it contains a specified delimiter.+/**+ * This function is used to asynchronously read data into the specified dynamic+ * buffer sequence until the dynamic buffer sequence's get area contains the+ * specified delimiter. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the dynamic buffer sequence's get area already contains the delimiter, this+ * asynchronous operation completes immediately. The program must ensure that+ * the stream performs no other read operations (such as async_read,+ * async_read_until, the stream's async_read_some function, or any other+ * composed operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param delim The delimiter character.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the dynamic buffer sequence's+ *   // get area up to and including the delimiter.+ *   // 0 if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the dynamic buffer+ * sequence may contain additional data beyond the delimiter. An application+ * will typically leave that data in the dynamic buffer sequence for a+ * subsequent async_read_until operation to examine.+ *+ * @par Example+ * To asynchronously read data into a @c std::string until a newline is+ * encountered:+ * @code std::string data;+ * ...+ * void handler(const asio::error_code& e, std::size_t size)+ * {+ *   if (!e)+ *   {+ *     std::string line = data.substr(0, n);+ *     data.erase(0, n);+ *     ...+ *   }+ * }+ * ...+ * asio::async_read_until(s, data, '\n', handler); @endcode+ * After the @c async_read_until operation completes successfully, the buffer+ * @c data contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the buffer @c data+ * as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c async_read_until operation.+ */+template <typename AsyncReadStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Start an asynchronous operation to read data into a dynamic buffer sequence+/// until it contains a specified delimiter.+/**+ * This function is used to asynchronously read data into the specified dynamic+ * buffer sequence until the dynamic buffer sequence's get area contains the+ * specified delimiter. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the dynamic buffer sequence's get area already contains the delimiter, this+ * asynchronous operation completes immediately. The program must ensure that+ * the stream performs no other read operations (such as async_read,+ * async_read_until, the stream's async_read_some function, or any other+ * composed operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param delim The delimiter string.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the dynamic buffer sequence's+ *   // get area up to and including the delimiter.+ *   // 0 if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the dynamic buffer+ * sequence may contain additional data beyond the delimiter. An application+ * will typically leave that data in the dynamic buffer sequence for a+ * subsequent async_read_until operation to examine.+ *+ * @par Example+ * To asynchronously read data into a @c std::string until a CR-LF sequence is+ * encountered:+ * @code std::string data;+ * ...+ * void handler(const asio::error_code& e, std::size_t size)+ * {+ *   if (!e)+ *   {+ *     std::string line = data.substr(0, n);+ *     data.erase(0, n);+ *     ...+ *   }+ * }+ * ...+ * asio::async_read_until(s, data, "\r\n", handler); @endcode+ * After the @c async_read_until operation completes successfully, the string+ * @c data contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the string @c data+ * as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c async_read_until operation.+ */+template <typename AsyncReadStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_STRING_VIEW_PARAM delim,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#if !defined(ASIO_NO_EXTENSIONS)+#if defined(ASIO_HAS_BOOST_REGEX) \+  || defined(GENERATING_DOCUMENTATION)++/// Start an asynchronous operation to read data into a dynamic buffer sequence+/// until some part of its data matches a regular expression.+/**+ * This function is used to asynchronously read data into the specified dynamic+ * buffer sequence until the dynamic buffer sequence's get area contains some+ * data that matches a regular expression. The function call always returns+ * immediately. The asynchronous operation will continue until one of the+ * following conditions is true:+ *+ * @li A substring of the dynamic buffer sequence's get area matches the regular+ * expression.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the dynamic buffer sequence's get area already contains data that matches+ * the regular expression, this asynchronous operation completes immediately.+ * The program must ensure that the stream performs no other read operations+ * (such as async_read, async_read_until, the stream's async_read_some+ * function, or any other composed operations that perform reads) until this+ * operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param expr The regular expression.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the dynamic buffer+ *   // sequence's get area up to and including the+ *   // substring that matches the regular expression.+ *   // 0 if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the dynamic buffer+ * sequence may contain additional data beyond that which matched the regular+ * expression. An application will typically leave that data in the dynamic+ * buffer sequence for a subsequent async_read_until operation to examine.+ *+ * @par Example+ * To asynchronously read data into a @c std::string until a CR-LF sequence is+ * encountered:+ * @code std::string data;+ * ...+ * void handler(const asio::error_code& e, std::size_t size)+ * {+ *   if (!e)+ *   {+ *     std::string line = data.substr(0, n);+ *     data.erase(0, n);+ *     ...+ *   }+ * }+ * ...+ * asio::async_read_until(s, data,+ *     boost::regex("\r\n"), handler); @endcode+ * After the @c async_read_until operation completes successfully, the string+ * @c data contains the data which matched the regular expression:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the match,+ * so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the string @c data+ * as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c async_read_until operation.+ */+template <typename AsyncReadStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    const boost::regex& expr,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#endif // defined(ASIO_HAS_BOOST_REGEX)+       // || defined(GENERATING_DOCUMENTATION)++/// Start an asynchronous operation to read data into a dynamic buffer sequence+/// until a function object indicates a match.+/**+ * This function is used to asynchronously read data into the specified dynamic+ * buffer sequence until a user-defined match condition function object, when+ * applied to the data contained in the dynamic buffer sequence, indicates a+ * successful match. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li The match condition function object returns a std::pair where the second+ * element evaluates to true.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the match condition function object already indicates a match, this+ * asynchronous operation completes immediately. The program must ensure that+ * the stream performs no other read operations (such as async_read,+ * async_read_until, the stream's async_read_some function, or any other+ * composed operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param match_condition The function object to be called to determine whether+ * a match exists. The signature of the function object must be:+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);+ * @endcode+ * where @c iterator represents the type:+ * @code buffers_iterator<typename DynamicBuffer_v1::const_buffers_type>+ * @endcode+ * The iterator parameters @c begin and @c end define the range of bytes to be+ * scanned to determine whether there is a match. The @c first member of the+ * return value is an iterator marking one-past-the-end of the bytes that have+ * been consumed by the match function. This iterator is used to calculate the+ * @c begin parameter for any subsequent invocation of the match condition. The+ * @c second member of the return value is true if a match has been found, false+ * otherwise.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the dynamic buffer sequence's+ *   // get area that have been fully consumed by the match+ *   // function. O if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the dynamic buffer+ * sequence may contain additional data beyond that which matched the function+ * object. An application will typically leave that data in the dynamic buffer+ * sequence for a subsequent async_read_until operation to examine.+ *+ * @note The default implementation of the @c is_match_condition type trait+ * evaluates to true for function pointers and function objects with a+ * @c result_type typedef. It must be specialised for other user-defined+ * function objects.+ *+ * @par Examples+ * To asynchronously read data into a @c std::string until whitespace is+ * encountered:+ * @code typedef asio::buffers_iterator<+ *     asio::const_buffers_1> iterator;+ *+ * std::pair<iterator, bool>+ * match_whitespace(iterator begin, iterator end)+ * {+ *   iterator i = begin;+ *   while (i != end)+ *     if (std::isspace(*i++))+ *       return std::make_pair(i, true);+ *   return std::make_pair(i, false);+ * }+ * ...+ * void handler(const asio::error_code& e, std::size_t size);+ * ...+ * std::string data;+ * asio::async_read_until(s, data, match_whitespace, handler);+ * @endcode+ *+ * To asynchronously read data into a @c std::string until a matching character+ * is found:+ * @code class match_char+ * {+ * public:+ *   explicit match_char(char c) : c_(c) {}+ *+ *   template <typename Iterator>+ *   std::pair<Iterator, bool> operator()(+ *       Iterator begin, Iterator end) const+ *   {+ *     Iterator i = begin;+ *     while (i != end)+ *       if (c_ == *i++)+ *         return std::make_pair(i, true);+ *     return std::make_pair(i, false);+ *   }+ *+ * private:+ *   char c_;+ * };+ *+ * namespace asio {+ *   template <> struct is_match_condition<match_char>+ *     : public boost::true_type {};+ * } // namespace asio+ * ...+ * void handler(const asio::error_code& e, std::size_t size);+ * ...+ * std::string data;+ * asio::async_read_until(s, data, match_char('a'), handler);+ * @endcode+ */+template <typename AsyncReadStream,+    typename DynamicBuffer_v1, typename MatchCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    MatchCondition match_condition,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#if !defined(ASIO_NO_IOSTREAM)++/// Start an asynchronous operation to read data into a streambuf until it+/// contains a specified delimiter.+/**+ * This function is used to asynchronously read data into the specified+ * streambuf until the streambuf's get area contains the specified delimiter.+ * The function call always returns immediately. The asynchronous operation+ * will continue until one of the following conditions is true:+ *+ * @li The get area of the streambuf contains the specified delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the streambuf's get area already contains the delimiter, this asynchronous+ * operation completes immediately. The program must ensure that the stream+ * performs no other read operations (such as async_read, async_read_until, the+ * stream's async_read_some function, or any other composed operations that+ * perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read. Ownership of+ * the streambuf is retained by the caller, which must guarantee that it remains+ * valid until the handler is called.+ *+ * @param delim The delimiter character.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the streambuf's get+ *   // area up to and including the delimiter.+ *   // 0 if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the streambuf may+ * contain additional data beyond the delimiter. An application will typically+ * leave that data in the streambuf for a subsequent async_read_until operation+ * to examine.+ *+ * @par Example+ * To asynchronously read data into a streambuf until a newline is encountered:+ * @code asio::streambuf b;+ * ...+ * void handler(const asio::error_code& e, std::size_t size)+ * {+ *   if (!e)+ *   {+ *     std::istream is(&b);+ *     std::string line;+ *     std::getline(is, line);+ *     ...+ *   }+ * }+ * ...+ * asio::async_read_until(s, b, '\n', handler); @endcode+ * After the @c async_read_until operation completes successfully, the buffer+ * @c b contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode+ * The call to @c std::getline then extracts the data up to and including the+ * newline (which is discarded), so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c' } @endcode+ * The remaining data is left in the buffer @c b as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c async_read_until operation.+ */+template <typename AsyncReadStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, char delim,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type));++/// Start an asynchronous operation to read data into a streambuf until it+/// contains a specified delimiter.+/**+ * This function is used to asynchronously read data into the specified+ * streambuf until the streambuf's get area contains the specified delimiter.+ * The function call always returns immediately. The asynchronous operation+ * will continue until one of the following conditions is true:+ *+ * @li The get area of the streambuf contains the specified delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the streambuf's get area already contains the delimiter, this asynchronous+ * operation completes immediately. The program must ensure that the stream+ * performs no other read operations (such as async_read, async_read_until, the+ * stream's async_read_some function, or any other composed operations that+ * perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read. Ownership of+ * the streambuf is retained by the caller, which must guarantee that it remains+ * valid until the handler is called.+ *+ * @param delim The delimiter string.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the streambuf's get+ *   // area up to and including the delimiter.+ *   // 0 if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the streambuf may+ * contain additional data beyond the delimiter. An application will typically+ * leave that data in the streambuf for a subsequent async_read_until operation+ * to examine.+ *+ * @par Example+ * To asynchronously read data into a streambuf until a newline is encountered:+ * @code asio::streambuf b;+ * ...+ * void handler(const asio::error_code& e, std::size_t size)+ * {+ *   if (!e)+ *   {+ *     std::istream is(&b);+ *     std::string line;+ *     std::getline(is, line);+ *     ...+ *   }+ * }+ * ...+ * asio::async_read_until(s, b, "\r\n", handler); @endcode+ * After the @c async_read_until operation completes successfully, the buffer+ * @c b contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c std::getline then extracts the data up to and including the+ * newline (which is discarded), so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r' } @endcode+ * The remaining data is left in the buffer @c b as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c async_read_until operation.+ */+template <typename AsyncReadStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    ASIO_STRING_VIEW_PARAM delim,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type));++#if defined(ASIO_HAS_BOOST_REGEX) \+  || defined(GENERATING_DOCUMENTATION)++/// Start an asynchronous operation to read data into a streambuf until some+/// part of its data matches a regular expression.+/**+ * This function is used to asynchronously read data into the specified+ * streambuf until the streambuf's get area contains some data that matches a+ * regular expression. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li A substring of the streambuf's get area matches the regular expression.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the streambuf's get area already contains data that matches the regular+ * expression, this asynchronous operation completes immediately. The program+ * must ensure that the stream performs no other read operations (such as+ * async_read, async_read_until, the stream's async_read_some function, or any+ * other composed operations that perform reads) until this operation+ * completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read. Ownership of+ * the streambuf is retained by the caller, which must guarantee that it remains+ * valid until the handler is called.+ *+ * @param expr The regular expression.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the streambuf's get+ *   // area up to and including the substring+ *   // that matches the regular. expression.+ *   // 0 if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the streambuf may+ * contain additional data beyond that which matched the regular expression. An+ * application will typically leave that data in the streambuf for a subsequent+ * async_read_until operation to examine.+ *+ * @par Example+ * To asynchronously read data into a streambuf until a CR-LF sequence is+ * encountered:+ * @code asio::streambuf b;+ * ...+ * void handler(const asio::error_code& e, std::size_t size)+ * {+ *   if (!e)+ *   {+ *     std::istream is(&b);+ *     std::string line;+ *     std::getline(is, line);+ *     ...+ *   }+ * }+ * ...+ * asio::async_read_until(s, b, boost::regex("\r\n"), handler); @endcode+ * After the @c async_read_until operation completes successfully, the buffer+ * @c b contains the data which matched the regular expression:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c std::getline then extracts the data up to and including the+ * newline (which is discarded), so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r' } @endcode+ * The remaining data is left in the buffer @c b as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c async_read_until operation.+ */+template <typename AsyncReadStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    asio::basic_streambuf<Allocator>& b, const boost::regex& expr,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type));++#endif // defined(ASIO_HAS_BOOST_REGEX)+       // || defined(GENERATING_DOCUMENTATION)++/// Start an asynchronous operation to read data into a streambuf until a+/// function object indicates a match.+/**+ * This function is used to asynchronously read data into the specified+ * streambuf until a user-defined match condition function object, when applied+ * to the data contained in the streambuf, indicates a successful match. The+ * function call always returns immediately. The asynchronous operation will+ * continue until one of the following conditions is true:+ *+ * @li The match condition function object returns a std::pair where the second+ * element evaluates to true.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the match condition function object already indicates a match, this+ * asynchronous operation completes immediately. The program must ensure that+ * the stream performs no other read operations (such as async_read,+ * async_read_until, the stream's async_read_some function, or any other+ * composed operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param b A streambuf object into which the data will be read.+ *+ * @param match_condition The function object to be called to determine whether+ * a match exists. The signature of the function object must be:+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);+ * @endcode+ * where @c iterator represents the type:+ * @code buffers_iterator<basic_streambuf<Allocator>::const_buffers_type>+ * @endcode+ * The iterator parameters @c begin and @c end define the range of bytes to be+ * scanned to determine whether there is a match. The @c first member of the+ * return value is an iterator marking one-past-the-end of the bytes that have+ * been consumed by the match function. This iterator is used to calculate the+ * @c begin parameter for any subsequent invocation of the match condition. The+ * @c second member of the return value is true if a match has been found, false+ * otherwise.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the streambuf's get+ *   // area that have been fully consumed by the+ *   // match function. O if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the streambuf may+ * contain additional data beyond that which matched the function object. An+ * application will typically leave that data in the streambuf for a subsequent+ * async_read_until operation to examine.+ *+ * @note The default implementation of the @c is_match_condition type trait+ * evaluates to true for function pointers and function objects with a+ * @c result_type typedef. It must be specialised for other user-defined+ * function objects.+ *+ * @par Examples+ * To asynchronously read data into a streambuf until whitespace is encountered:+ * @code typedef asio::buffers_iterator<+ *     asio::streambuf::const_buffers_type> iterator;+ *+ * std::pair<iterator, bool>+ * match_whitespace(iterator begin, iterator end)+ * {+ *   iterator i = begin;+ *   while (i != end)+ *     if (std::isspace(*i++))+ *       return std::make_pair(i, true);+ *   return std::make_pair(i, false);+ * }+ * ...+ * void handler(const asio::error_code& e, std::size_t size);+ * ...+ * asio::streambuf b;+ * asio::async_read_until(s, b, match_whitespace, handler);+ * @endcode+ *+ * To asynchronously read data into a streambuf until a matching character is+ * found:+ * @code class match_char+ * {+ * public:+ *   explicit match_char(char c) : c_(c) {}+ *+ *   template <typename Iterator>+ *   std::pair<Iterator, bool> operator()(+ *       Iterator begin, Iterator end) const+ *   {+ *     Iterator i = begin;+ *     while (i != end)+ *       if (c_ == *i++)+ *         return std::make_pair(i, true);+ *     return std::make_pair(i, false);+ *   }+ *+ * private:+ *   char c_;+ * };+ *+ * namespace asio {+ *   template <> struct is_match_condition<match_char>+ *     : public boost::true_type {};+ * } // namespace asio+ * ...+ * void handler(const asio::error_code& e, std::size_t size);+ * ...+ * asio::streambuf b;+ * asio::async_read_until(s, b, match_char('a'), handler);+ * @endcode+ */+template <typename AsyncReadStream, typename Allocator, typename MatchCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s,+    asio::basic_streambuf<Allocator>& b,+    MatchCondition match_condition,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Start an asynchronous operation to read data into a dynamic buffer sequence+/// until it contains a specified delimiter.+/**+ * This function is used to asynchronously read data into the specified dynamic+ * buffer sequence until the dynamic buffer sequence's get area contains the+ * specified delimiter. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the dynamic buffer sequence's get area already contains the delimiter, this+ * asynchronous operation completes immediately. The program must ensure that+ * the stream performs no other read operations (such as async_read,+ * async_read_until, the stream's async_read_some function, or any other+ * composed operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param delim The delimiter character.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the dynamic buffer sequence's+ *   // get area up to and including the delimiter.+ *   // 0 if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the dynamic buffer+ * sequence may contain additional data beyond the delimiter. An application+ * will typically leave that data in the dynamic buffer sequence for a+ * subsequent async_read_until operation to examine.+ *+ * @par Example+ * To asynchronously read data into a @c std::string until a newline is+ * encountered:+ * @code std::string data;+ * ...+ * void handler(const asio::error_code& e, std::size_t size)+ * {+ *   if (!e)+ *   {+ *     std::string line = data.substr(0, n);+ *     data.erase(0, n);+ *     ...+ *   }+ * }+ * ...+ * asio::async_read_until(s, data, '\n', handler); @endcode+ * After the @c async_read_until operation completes successfully, the buffer+ * @c data contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the buffer @c data+ * as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c async_read_until operation.+ */+template <typename AsyncReadStream, typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, char delim,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Start an asynchronous operation to read data into a dynamic buffer sequence+/// until it contains a specified delimiter.+/**+ * This function is used to asynchronously read data into the specified dynamic+ * buffer sequence until the dynamic buffer sequence's get area contains the+ * specified delimiter. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li The get area of the dynamic buffer sequence contains the specified+ * delimiter.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the dynamic buffer sequence's get area already contains the delimiter, this+ * asynchronous operation completes immediately. The program must ensure that+ * the stream performs no other read operations (such as async_read,+ * async_read_until, the stream's async_read_some function, or any other+ * composed operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param delim The delimiter string.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the dynamic buffer sequence's+ *   // get area up to and including the delimiter.+ *   // 0 if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the dynamic buffer+ * sequence may contain additional data beyond the delimiter. An application+ * will typically leave that data in the dynamic buffer sequence for a+ * subsequent async_read_until operation to examine.+ *+ * @par Example+ * To asynchronously read data into a @c std::string until a CR-LF sequence is+ * encountered:+ * @code std::string data;+ * ...+ * void handler(const asio::error_code& e, std::size_t size)+ * {+ *   if (!e)+ *   {+ *     std::string line = data.substr(0, n);+ *     data.erase(0, n);+ *     ...+ *   }+ * }+ * ...+ * asio::async_read_until(s, data, "\r\n", handler); @endcode+ * After the @c async_read_until operation completes successfully, the string+ * @c data contains the delimiter:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the+ * delimiter, so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the string @c data+ * as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c async_read_until operation.+ */+template <typename AsyncReadStream, typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    ASIO_STRING_VIEW_PARAM delim,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++#if !defined(ASIO_NO_EXTENSIONS)+#if defined(ASIO_HAS_BOOST_REGEX) \+  || defined(GENERATING_DOCUMENTATION)++/// Start an asynchronous operation to read data into a dynamic buffer sequence+/// until some part of its data matches a regular expression.+/**+ * This function is used to asynchronously read data into the specified dynamic+ * buffer sequence until the dynamic buffer sequence's get area contains some+ * data that matches a regular expression. The function call always returns+ * immediately. The asynchronous operation will continue until one of the+ * following conditions is true:+ *+ * @li A substring of the dynamic buffer sequence's get area matches the regular+ * expression.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the dynamic buffer sequence's get area already contains data that matches+ * the regular expression, this asynchronous operation completes immediately.+ * The program must ensure that the stream performs no other read operations+ * (such as async_read, async_read_until, the stream's async_read_some+ * function, or any other composed operations that perform reads) until this+ * operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param expr The regular expression.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the dynamic buffer+ *   // sequence's get area up to and including the+ *   // substring that matches the regular expression.+ *   // 0 if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the dynamic buffer+ * sequence may contain additional data beyond that which matched the regular+ * expression. An application will typically leave that data in the dynamic+ * buffer sequence for a subsequent async_read_until operation to examine.+ *+ * @par Example+ * To asynchronously read data into a @c std::string until a CR-LF sequence is+ * encountered:+ * @code std::string data;+ * ...+ * void handler(const asio::error_code& e, std::size_t size)+ * {+ *   if (!e)+ *   {+ *     std::string line = data.substr(0, n);+ *     data.erase(0, n);+ *     ...+ *   }+ * }+ * ...+ * asio::async_read_until(s, data,+ *     boost::regex("\r\n"), handler); @endcode+ * After the @c async_read_until operation completes successfully, the string+ * @c data contains the data which matched the regular expression:+ * @code { 'a', 'b', ..., 'c', '\r', '\n', 'd', 'e', ... } @endcode+ * The call to @c substr then extracts the data up to and including the match,+ * so that the string @c line contains:+ * @code { 'a', 'b', ..., 'c', '\r', '\n' } @endcode+ * After the call to @c erase, the remaining data is left in the string @c data+ * as follows:+ * @code { 'd', 'e', ... } @endcode+ * This data may be the start of a new line, to be extracted by a subsequent+ * @c async_read_until operation.+ */+template <typename AsyncReadStream, typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    const boost::regex& expr,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++#endif // defined(ASIO_HAS_BOOST_REGEX)+       // || defined(GENERATING_DOCUMENTATION)++/// Start an asynchronous operation to read data into a dynamic buffer sequence+/// until a function object indicates a match.+/**+ * This function is used to asynchronously read data into the specified dynamic+ * buffer sequence until a user-defined match condition function object, when+ * applied to the data contained in the dynamic buffer sequence, indicates a+ * successful match. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li The match condition function object returns a std::pair where the second+ * element evaluates to true.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_read_some function, and is known as a <em>composed operation</em>. If+ * the match condition function object already indicates a match, this+ * asynchronous operation completes immediately. The program must ensure that+ * the stream performs no other read operations (such as async_read,+ * async_read_until, the stream's async_read_some function, or any other+ * composed operations that perform reads) until this operation completes.+ *+ * @param s The stream from which the data is to be read. The type must support+ * the AsyncReadStream concept.+ *+ * @param buffers The dynamic buffer sequence 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 handler is called.+ *+ * @param match_condition The function object to be called to determine whether+ * a match exists. The signature of the function object must be:+ * @code pair<iterator, bool> match_condition(iterator begin, iterator end);+ * @endcode+ * where @c iterator represents the type:+ * @code buffers_iterator<typename DynamicBuffer_v2::const_buffers_type>+ * @endcode+ * The iterator parameters @c begin and @c end define the range of bytes to be+ * scanned to determine whether there is a match. The @c first member of the+ * return value is an iterator marking one-past-the-end of the bytes that have+ * been consumed by the match function. This iterator is used to calculate the+ * @c begin parameter for any subsequent invocation of the match condition. The+ * @c second member of the return value is true if a match has been found, false+ * otherwise.+ *+ * @param handler The handler to be called when the read operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // The number of bytes in the dynamic buffer sequence's+ *   // get area that have been fully consumed by the match+ *   // function. O if an error occurred.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ *+ * @note After a successful async_read_until operation, the dynamic buffer+ * sequence may contain additional data beyond that which matched the function+ * object. An application will typically leave that data in the dynamic buffer+ * sequence for a subsequent async_read_until operation to examine.+ *+ * @note The default implementation of the @c is_match_condition type trait+ * evaluates to true for function pointers and function objects with a+ * @c result_type typedef. It must be specialised for other user-defined+ * function objects.+ *+ * @par Examples+ * To asynchronously read data into a @c std::string until whitespace is+ * encountered:+ * @code typedef asio::buffers_iterator<+ *     asio::const_buffers_1> iterator;+ *+ * std::pair<iterator, bool>+ * match_whitespace(iterator begin, iterator end)+ * {+ *   iterator i = begin;+ *   while (i != end)+ *     if (std::isspace(*i++))+ *       return std::make_pair(i, true);+ *   return std::make_pair(i, false);+ * }+ * ...+ * void handler(const asio::error_code& e, std::size_t size);+ * ...+ * std::string data;+ * asio::async_read_until(s, data, match_whitespace, handler);+ * @endcode+ *+ * To asynchronously read data into a @c std::string until a matching character+ * is found:+ * @code class match_char+ * {+ * public:+ *   explicit match_char(char c) : c_(c) {}+ *+ *   template <typename Iterator>+ *   std::pair<Iterator, bool> operator()(+ *       Iterator begin, Iterator end) const+ *   {+ *     Iterator i = begin;+ *     while (i != end)+ *       if (c_ == *i++)+ *         return std::make_pair(i, true);+ *     return std::make_pair(i, false);+ *   }+ *+ * private:+ *   char c_;+ * };+ *+ * namespace asio {+ *   template <> struct is_match_condition<match_char>+ *     : public boost::true_type {};+ * } // namespace asio+ * ...+ * void handler(const asio::error_code& e, std::size_t size);+ * ...+ * std::string data;+ * asio::async_read_until(s, data, match_char('a'), handler);+ * @endcode+ */+template <typename AsyncReadStream,+    typename DynamicBuffer_v2, typename MatchCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) ReadHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncReadStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+    void (asio::error_code, std::size_t))+async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,+    MatchCondition match_condition,+    ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncReadStream::executor_type),+    typename enable_if<+      is_match_condition<MatchCondition>::value+        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++#endif // !defined(ASIO_NO_EXTENSIONS)++/*@}*/++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/read_until.hpp"++#endif // ASIO_READ_UNTIL_HPP
+ link/modules/asio-standalone/asio/include/asio/redirect_error.hpp view
@@ -0,0 +1,66 @@+//+// redirect_error.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_REDIRECT_ERROR_HPP+#define ASIO_REDIRECT_ERROR_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/error_code.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Completion token type used to specify that an error produced by an+/// asynchronous operation is captured to an error_code variable.+/**+ * The redirect_error_t class is used to indicate that any error_code produced+ * by an asynchronous operation is captured to a specified variable.+ */+template <typename CompletionToken>+class redirect_error_t+{+public:+  /// Constructor. +  template <typename T>+  redirect_error_t(ASIO_MOVE_ARG(T) completion_token,+      asio::error_code& ec)+    : token_(ASIO_MOVE_CAST(T)(completion_token)),+      ec_(ec)+  {+  }++//private:+  CompletionToken token_;+  asio::error_code& ec_;+};++/// Create a completion token to capture error_code values to a variable.+template <typename CompletionToken>+inline redirect_error_t<typename decay<CompletionToken>::type> redirect_error(+    ASIO_MOVE_ARG(CompletionToken) completion_token,+    asio::error_code& ec)+{+  return redirect_error_t<typename decay<CompletionToken>::type>(+      ASIO_MOVE_CAST(CompletionToken)(completion_token), ec);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/redirect_error.hpp"++#endif // ASIO_REDIRECT_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/require.hpp view
@@ -0,0 +1,524 @@+//+// require.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_REQUIRE_HPP+#define ASIO_REQUIRE_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/is_applicable_property.hpp"+#include "asio/traits/require_member.hpp"+#include "asio/traits/require_free.hpp"+#include "asio/traits/static_require.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {++/// A customisation point that applies a concept-preserving property to an+/// object.+/**+ * The name <tt>require</tt> denotes a customisation point object. The+ * expression <tt>asio::require(E, P0, Pn...)</tt> for some+ * subexpressions <tt>E</tt> and <tt>P0</tt>, and where <tt>Pn...</tt>+ * represents <tt>N</tt> subexpressions (where <tt>N</tt> is 0 or more, and with+ * types <tt>T = decay_t<decltype(E)></tt> and <tt>Prop0 =+ * decay_t<decltype(P0)></tt>) is expression-equivalent to:+ *+ * @li If <tt>is_applicable_property_v<T, Prop0> && Prop0::is_requirable</tt> is+ *   not a well-formed constant expression with value <tt>true</tt>,+ *   <tt>asio::require(E, P0, Pn...)</tt> is ill-formed.+ *+ * @li Otherwise, <tt>E</tt> if <tt>N == 0</tt> and the expression+ *   <tt>Prop0::template static_query_v<T> == Prop0::value()</tt> is a+ *   well-formed constant expression with value <tt>true</tt>.+ *+ * @li Otherwise, <tt>(E).require(P0)</tt> if <tt>N == 0</tt> and the expression+ *   <tt>(E).require(P0)</tt> is a valid expression.+ *+ * @li Otherwise, <tt>require(E, P0)</tt> if <tt>N == 0</tt> and the expression+ *   <tt>require(E, P0)</tt> is a valid expression with overload resolution+ *   performed in a context that does not include the declaration of the+ *   <tt>require</tt> customization point object.+ *+ * @li Otherwise,+ *   <tt>asio::require(asio::require(E, P0), Pn...)</tt>+ *   if <tt>N > 0</tt> and the expression+ *   <tt>asio::require(asio::require(E, P0), Pn...)</tt>+ *   is a valid expression.+ *+ * @li Otherwise, <tt>asio::require(E, P0, Pn...)</tt> is ill-formed.+ */+inline constexpr unspecified require = unspecified;++/// A type trait that determines whether a @c require expression is well-formed.+/**+ * Class template @c can_require is a trait that is derived from+ * @c true_type if the expression <tt>asio::require(std::declval<T>(),+ * std::declval<Properties>()...)</tt> is well formed; otherwise @c false_type.+ */+template <typename T, typename... Properties>+struct can_require :+  integral_constant<bool, automatically_determined>+{+};++/// A type trait that determines whether a @c require expression will not throw.+/**+ * Class template @c is_nothrow_require is a trait that is derived from+ * @c true_type if the expression <tt>asio::require(std::declval<T>(),+ * std::declval<Properties>()...)</tt> is @c noexcept; otherwise @c false_type.+ */+template <typename T, typename... Properties>+struct is_nothrow_require :+  integral_constant<bool, automatically_determined>+{+};++/// A type trait that determines the result type of a @c require expression.+/**+ * Class template @c require_result is a trait that determines the result+ * type of the expression <tt>asio::require(std::declval<T>(),+ * std::declval<Properties>()...)</tt>.+ */+template <typename T, typename... Properties>+struct require_result+{+  /// The result of the @c require expression.+  typedef automatically_determined type;+};++} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_require_fn {++using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::is_applicable_property;+using asio::traits::require_free;+using asio::traits::require_member;+using asio::traits::static_require;++void require();++enum overload_type+{+  identity,+  call_member,+  call_free,+  two_props,+  n_props,+  ill_formed+};++template <typename T, typename Properties, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_requirable+      &&+      static_require<T, Property>::is_valid+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);++#if defined(ASIO_HAS_MOVE)+  typedef ASIO_MOVE_ARG(T) result_type;+#else // defined(ASIO_HAS_MOVE)+  typedef ASIO_MOVE_ARG(typename decay<T>::type) result_type;+#endif // defined(ASIO_HAS_MOVE)+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_requirable+      &&+      !static_require<T, Property>::is_valid+      &&+      require_member<T, Property>::is_valid+    )+  >::type> :+  require_member<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_requirable+      &&+      !static_require<T, Property>::is_valid+      &&+      !require_member<T, Property>::is_valid+      &&+      require_free<T, Property>::is_valid+    )+  >::type> :+  require_free<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++template <typename T, typename P0, typename P1>+struct call_traits<T, void(P0, P1),+  typename enable_if<+    call_traits<T, void(P0)>::overload != ill_formed+    &&+    call_traits<+      typename call_traits<T, void(P0)>::result_type,+      void(P1)+    >::overload != ill_formed+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = two_props);++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (+      call_traits<T, void(P0)>::is_noexcept+      &&+      call_traits<+        typename call_traits<T, void(P0)>::result_type,+        void(P1)+      >::is_noexcept+    ));++  typedef typename decay<+    typename call_traits<+      typename call_traits<T, void(P0)>::result_type,+      void(P1)+    >::result_type+  >::type result_type;+};++template <typename T, typename P0, typename P1, typename ASIO_ELLIPSIS PN>+struct call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS),+  typename enable_if<+    call_traits<T, void(P0)>::overload != ill_formed+    &&+    call_traits<+      typename call_traits<T, void(P0)>::result_type,+      void(P1, PN ASIO_ELLIPSIS)+    >::overload != ill_formed+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = n_props);++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    (+      call_traits<T, void(P0)>::is_noexcept+      &&+      call_traits<+        typename call_traits<T, void(P0)>::result_type,+        void(P1, PN ASIO_ELLIPSIS)+      >::is_noexcept+    ));++  typedef typename decay<+    typename call_traits<+      typename call_traits<T, void(P0)>::result_type,+      void(P1, PN ASIO_ELLIPSIS)+    >::result_type+  >::type result_type;+};++struct impl+{+  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == identity,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property)) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(T)(t);+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_member,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(T)(t).require(+        ASIO_MOVE_CAST(Property)(p));+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_free,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return require(+        ASIO_MOVE_CAST(T)(t),+        ASIO_MOVE_CAST(Property)(p));+  }++  template <typename T, typename P0, typename P1>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(P0, P1)>::overload == two_props,+    typename call_traits<T, void(P0, P1)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(P0) p0,+      ASIO_MOVE_ARG(P1) p1) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(P0, P1)>::is_noexcept))+  {+    return (*this)(+        (*this)(+          ASIO_MOVE_CAST(T)(t),+          ASIO_MOVE_CAST(P0)(p0)),+        ASIO_MOVE_CAST(P1)(p1));+  }++  template <typename T, typename P0, typename P1,+    typename ASIO_ELLIPSIS PN>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,+    typename call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(P0) p0,+      ASIO_MOVE_ARG(P1) p1,+      ASIO_MOVE_ARG(PN) ASIO_ELLIPSIS pn) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept))+  {+    return (*this)(+        (*this)(+          ASIO_MOVE_CAST(T)(t),+          ASIO_MOVE_CAST(P0)(p0)),+        ASIO_MOVE_CAST(P1)(p1),+        ASIO_MOVE_CAST(PN)(pn) ASIO_ELLIPSIS);+  }+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_require_fn+namespace asio {+namespace {++static ASIO_CONSTEXPR const asio_require_fn::impl&+  require = asio_require_fn::static_instance<>::instance;++} // namespace++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Properties>+struct can_require :+  integral_constant<bool,+    asio_require_fn::call_traits<T, void(Properties...)>::overload+      != asio_require_fn::ill_formed>+{+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename P0 = void,+    typename P1 = void, typename P2 = void>+struct can_require :+  integral_constant<bool,+    asio_require_fn::call_traits<T, void(P0, P1, P2)>::overload+      != asio_require_fn::ill_formed>+{+};++template <typename T, typename P0, typename P1>+struct can_require<T, P0, P1> :+  integral_constant<bool,+    asio_require_fn::call_traits<T, void(P0, P1)>::overload+      != asio_require_fn::ill_formed>+{+};++template <typename T, typename P0>+struct can_require<T, P0> :+  integral_constant<bool,+    asio_require_fn::call_traits<T, void(P0)>::overload+      != asio_require_fn::ill_formed>+{+};++template <typename T>+struct can_require<T> :+  false_type+{+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename ASIO_ELLIPSIS Properties>+constexpr bool can_require_v+  = can_require<T, Properties ASIO_ELLIPSIS>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Properties>+struct is_nothrow_require :+  integral_constant<bool,+    asio_require_fn::call_traits<T, void(Properties...)>::is_noexcept>+{+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename P0 = void,+    typename P1 = void, typename P2 = void>+struct is_nothrow_require :+  integral_constant<bool,+    asio_require_fn::call_traits<T, void(P0, P1, P2)>::is_noexcept>+{+};++template <typename T, typename P0, typename P1>+struct is_nothrow_require<T, P0, P1> :+  integral_constant<bool,+    asio_require_fn::call_traits<T, void(P0, P1)>::is_noexcept>+{+};++template <typename T, typename P0>+struct is_nothrow_require<T, P0> :+  integral_constant<bool,+    asio_require_fn::call_traits<T, void(P0)>::is_noexcept>+{+};++template <typename T>+struct is_nothrow_require<T> :+  false_type+{+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename ASIO_ELLIPSIS Properties>+constexpr bool is_nothrow_require_v+  = is_nothrow_require<T, Properties ASIO_ELLIPSIS>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Properties>+struct require_result+{+  typedef typename asio_require_fn::call_traits<+      T, void(Properties...)>::result_type type;+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename P0 = void,+    typename P1 = void, typename P2 = void>+struct require_result+{+  typedef typename asio_require_fn::call_traits<+      T, void(P0, P1, P2)>::result_type type;+};++template <typename T, typename P0, typename P1>+struct require_result<T, P0, P1>+{+  typedef typename asio_require_fn::call_traits<+      T, void(P0, P1)>::result_type type;+};++template <typename T, typename P0>+struct require_result<T, P0>+{+  typedef typename asio_require_fn::call_traits<+      T, void(P0)>::result_type type;+};++template <typename T>+struct require_result<T>+{+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_REQUIRE_HPP
+ link/modules/asio-standalone/asio/include/asio/require_concept.hpp view
@@ -0,0 +1,310 @@+//+// require_concept.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_REQUIRE_CONCEPT_HPP+#define ASIO_REQUIRE_CONCEPT_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/is_applicable_property.hpp"+#include "asio/traits/require_concept_member.hpp"+#include "asio/traits/require_concept_free.hpp"+#include "asio/traits/static_require_concept.hpp"++#include "asio/detail/push_options.hpp"++#if defined(GENERATING_DOCUMENTATION)++namespace asio {++/// A customisation point that applies a concept-enforcing property to an+/// object.+/**+ * The name <tt>require_concept</tt> denotes a customization point object. The+ * expression <tt>asio::require_concept(E, P)</tt> for some+ * subexpressions <tt>E</tt> and <tt>P</tt> (with types <tt>T =+ * decay_t<decltype(E)></tt> and <tt>Prop = decay_t<decltype(P)></tt>) is+ * expression-equivalent to:+ *+ * @li If <tt>is_applicable_property_v<T, Prop> &&+ *   Prop::is_requirable_concept</tt> is not a well-formed constant expression+ *   with value <tt>true</tt>, <tt>asio::require_concept(E, P)</tt> is+ *   ill-formed.+ *+ * @li Otherwise, <tt>E</tt> if the expression <tt>Prop::template+ *   static_query_v<T> == Prop::value()</tt> is a well-formed constant+ *   expression with value <tt>true</tt>.+ *+ * @li Otherwise, <tt>(E).require_concept(P)</tt> if the expression+ *   <tt>(E).require_concept(P)</tt> is well-formed.+ *+ * @li Otherwise, <tt>require_concept(E, P)</tt> if the expression+ *   <tt>require_concept(E, P)</tt> is a valid expression with overload+ *   resolution performed in a context that does not include the declaration+ *   of the <tt>require_concept</tt> customization point object.+ *+ * @li Otherwise, <tt>asio::require_concept(E, P)</tt> is ill-formed.+ */+inline constexpr unspecified require_concept = unspecified;++/// A type trait that determines whether a @c require_concept expression is+/// well-formed.+/**+ * Class template @c can_require_concept is a trait that is derived from+ * @c true_type if the expression+ * <tt>asio::require_concept(std::declval<T>(),+ * std::declval<Property>())</tt> is well formed; otherwise @c false_type.+ */+template <typename T, typename Property>+struct can_require_concept :+  integral_constant<bool, automatically_determined>+{+};++/// A type trait that determines whether a @c require_concept expression will+/// not throw.+/**+ * Class template @c is_nothrow_require_concept is a trait that is derived from+ * @c true_type if the expression+ * <tt>asio::require_concept(std::declval<T>(),+ * std::declval<Property>())</tt> is @c noexcept; otherwise @c false_type.+ */+template <typename T, typename Property>+struct is_nothrow_require_concept :+  integral_constant<bool, automatically_determined>+{+};++/// A type trait that determines the result type of a @c require_concept+/// expression.+/**+ * Class template @c require_concept_result is a trait that determines the+ * result type of the expression+ * <tt>asio::require_concept(std::declval<T>(),+ * std::declval<Property>())</tt>.+ */+template <typename T, typename Property>+struct require_concept_result+{+  /// The result of the @c require_concept expression.+  typedef automatically_determined type;+};++} // namespace asio++#else // defined(GENERATING_DOCUMENTATION)++namespace asio_require_concept_fn {++using asio::decay;+using asio::declval;+using asio::enable_if;+using asio::is_applicable_property;+using asio::traits::require_concept_free;+using asio::traits::require_concept_member;+using asio::traits::static_require_concept;++void require_concept();++enum overload_type+{+  identity,+  call_member,+  call_free,+  ill_formed+};++template <typename T, typename Properties, typename = void>+struct call_traits+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_requirable_concept+      &&+      static_require_concept<T, Property>::is_valid+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef ASIO_MOVE_ARG(T) result_type;+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_requirable_concept+      &&+      !static_require_concept<T, Property>::is_valid+      &&+      require_concept_member<T, Property>::is_valid+    )+  >::type> :+  require_concept_member<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member);+};++template <typename T, typename Property>+struct call_traits<T, void(Property),+  typename enable_if<+    (+      is_applicable_property<+        typename decay<T>::type,+        typename decay<Property>::type+      >::value+      &&+      decay<Property>::type::is_requirable_concept+      &&+      !static_require_concept<T, Property>::is_valid+      &&+      !require_concept_member<T, Property>::is_valid+      &&+      require_concept_free<T, Property>::is_valid+    )+  >::type> :+  require_concept_free<T, Property>+{+  ASIO_STATIC_CONSTEXPR(overload_type, overload = call_free);+};++struct impl+{+  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == identity,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property)) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(T)(t);+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_member,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return ASIO_MOVE_CAST(T)(t).require_concept(+        ASIO_MOVE_CAST(Property)(p));+  }++  template <typename T, typename Property>+  ASIO_NODISCARD ASIO_CONSTEXPR typename enable_if<+    call_traits<T, void(Property)>::overload == call_free,+    typename call_traits<T, void(Property)>::result_type+  >::type+  operator()(+      ASIO_MOVE_ARG(T) t,+      ASIO_MOVE_ARG(Property) p) const+    ASIO_NOEXCEPT_IF((+      call_traits<T, void(Property)>::is_noexcept))+  {+    return require_concept(+        ASIO_MOVE_CAST(T)(t),+        ASIO_MOVE_CAST(Property)(p));+  }+};++template <typename T = impl>+struct static_instance+{+  static const T instance;+};++template <typename T>+const T static_instance<T>::instance = {};++} // namespace asio_require_concept_fn+namespace asio {+namespace {++static ASIO_CONSTEXPR const asio_require_concept_fn::impl&+  require_concept = asio_require_concept_fn::static_instance<>::instance;++} // namespace++template <typename T, typename Property>+struct can_require_concept :+  integral_constant<bool,+    asio_require_concept_fn::call_traits<T, void(Property)>::overload !=+      asio_require_concept_fn::ill_formed>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+constexpr bool can_require_concept_v+  = can_require_concept<T, Property>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+struct is_nothrow_require_concept :+  integral_constant<bool,+    asio_require_concept_fn::call_traits<T, void(Property)>::is_noexcept>+{+};++#if defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+constexpr bool is_nothrow_require_concept_v+  = is_nothrow_require_concept<T, Property>::value;++#endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)++template <typename T, typename Property>+struct require_concept_result+{+  typedef typename asio_require_concept_fn::call_traits<+      T, void(Property)>::result_type type;+};++} // namespace asio++#endif // defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_REQUIRE_CONCEPT_HPP
+ link/modules/asio-standalone/asio/include/asio/serial_port.hpp view
@@ -0,0 +1,36 @@+//+// serial_port.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SERIAL_PORT_HPP+#define ASIO_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 "asio/basic_serial_port.hpp"++namespace asio {++/// Typedef for the typical usage of a serial port.+typedef basic_serial_port<> serial_port;++} // namespace asio++#endif // defined(ASIO_HAS_SERIAL_PORT)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_SERIAL_PORT_HPP
+ link/modules/asio-standalone/asio/include/asio/serial_port_base.hpp view
@@ -0,0 +1,167 @@+//+// serial_port_base.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SERIAL_PORT_BASE_HPP+#define ASIO_SERIAL_PORT_BASE_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)++#if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+# include <termios.h>+#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)++#include "asio/detail/socket_types.hpp"+#include "asio/error_code.hpp"++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_OPTION_STORAGE implementation_defined+#elif defined(ASIO_WINDOWS) || defined(__CYGWIN__)+# define ASIO_OPTION_STORAGE DCB+#else+# define ASIO_OPTION_STORAGE termios+#endif++#include "asio/detail/push_options.hpp"++namespace asio {++/// The serial_port_base class is used as a base for the basic_serial_port class+/// template so that we have a common place to define the serial port options.+class serial_port_base+{+public:+  /// Serial port option to permit changing the baud rate.+  /**+   * Implements changing the baud rate for a given serial port.+   */+  class baud_rate+  {+  public:+    explicit baud_rate(unsigned int rate = 0);+    unsigned int value() const;+    ASIO_DECL ASIO_SYNC_OP_VOID store(+        ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec) const;+    ASIO_DECL ASIO_SYNC_OP_VOID load(+        const ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec);+  private:+    unsigned int value_;+  };++  /// Serial port option to permit changing the flow control.+  /**+   * Implements changing the flow control for a given serial port.+   */+  class flow_control+  {+  public:+    enum type { none, software, hardware };+    ASIO_DECL explicit flow_control(type t = none);+    type value() const;+    ASIO_DECL ASIO_SYNC_OP_VOID store(+        ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec) const;+    ASIO_DECL ASIO_SYNC_OP_VOID load(+        const ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec);+  private:+    type value_;+  };++  /// Serial port option to permit changing the parity.+  /**+   * Implements changing the parity for a given serial port.+   */+  class parity+  {+  public:+    enum type { none, odd, even };+    ASIO_DECL explicit parity(type t = none);+    type value() const;+    ASIO_DECL ASIO_SYNC_OP_VOID store(+        ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec) const;+    ASIO_DECL ASIO_SYNC_OP_VOID load(+        const ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec);+  private:+    type value_;+  };++  /// Serial port option to permit changing the number of stop bits.+  /**+   * Implements changing the number of stop bits for a given serial port.+   */+  class stop_bits+  {+  public:+    enum type { one, onepointfive, two };+    ASIO_DECL explicit stop_bits(type t = one);+    type value() const;+    ASIO_DECL ASIO_SYNC_OP_VOID store(+        ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec) const;+    ASIO_DECL ASIO_SYNC_OP_VOID load(+        const ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec);+  private:+    type value_;+  };++  /// Serial port option to permit changing the character size.+  /**+   * Implements changing the character size for a given serial port.+   */+  class character_size+  {+  public:+    ASIO_DECL explicit character_size(unsigned int t = 8);+    unsigned int value() const;+    ASIO_DECL ASIO_SYNC_OP_VOID store(+        ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec) const;+    ASIO_DECL ASIO_SYNC_OP_VOID load(+        const ASIO_OPTION_STORAGE& storage,+        asio::error_code& ec);+  private:+    unsigned int value_;+  };++protected:+  /// Protected destructor to prevent deletion through this type.+  ~serial_port_base()+  {+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#undef ASIO_OPTION_STORAGE++#include "asio/impl/serial_port_base.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/serial_port_base.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_SERIAL_PORT)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_SERIAL_PORT_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/signal_set.hpp view
@@ -0,0 +1,28 @@+//+// signal_set.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SIGNAL_SET_HPP+#define ASIO_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/basic_signal_set.hpp"++namespace asio {++/// Typedef for the typical usage of a signal set.+typedef basic_signal_set<> signal_set;++} // namespace asio++#endif // ASIO_SIGNAL_SET_HPP
+ link/modules/asio-standalone/asio/include/asio/socket_base.hpp view
@@ -0,0 +1,559 @@+//+// socket_base.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SOCKET_BASE_HPP+#define ASIO_SOCKET_BASE_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/io_control.hpp"+#include "asio/detail/socket_option.hpp"+#include "asio/detail/socket_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// The socket_base class is used as a base for the basic_stream_socket and+/// basic_datagram_socket class templates so that we have a common place to+/// define the shutdown_type and enum.+class socket_base+{+public:+  /// Different ways a socket may be shutdown.+  enum shutdown_type+  {+#if defined(GENERATING_DOCUMENTATION)+    /// Shutdown the receive side of the socket.+    shutdown_receive = implementation_defined,++    /// Shutdown the send side of the socket.+    shutdown_send = implementation_defined,++    /// Shutdown both send and receive on the socket.+    shutdown_both = implementation_defined+#else+    shutdown_receive = ASIO_OS_DEF(SHUT_RD),+    shutdown_send = ASIO_OS_DEF(SHUT_WR),+    shutdown_both = ASIO_OS_DEF(SHUT_RDWR)+#endif+  };++  /// Bitmask type for flags that can be passed to send and receive operations.+  typedef int message_flags;++#if defined(GENERATING_DOCUMENTATION)+  /// Peek at incoming data without removing it from the input queue.+  static const int message_peek = implementation_defined;++  /// Process out-of-band data.+  static const int message_out_of_band = implementation_defined;++  /// Specify that the data should not be subject to routing.+  static const int message_do_not_route = implementation_defined;++  /// Specifies that the data marks the end of a record.+  static const int message_end_of_record = implementation_defined;+#else+  ASIO_STATIC_CONSTANT(int,+      message_peek = ASIO_OS_DEF(MSG_PEEK));+  ASIO_STATIC_CONSTANT(int,+      message_out_of_band = ASIO_OS_DEF(MSG_OOB));+  ASIO_STATIC_CONSTANT(int,+      message_do_not_route = ASIO_OS_DEF(MSG_DONTROUTE));+  ASIO_STATIC_CONSTANT(int,+      message_end_of_record = ASIO_OS_DEF(MSG_EOR));+#endif++  /// Wait types.+  /**+   * For use with basic_socket::wait() and basic_socket::async_wait().+   */+  enum wait_type+  {+    /// Wait for a socket to become ready to read.+    wait_read,++    /// Wait for a socket to become ready to write.+    wait_write,++    /// Wait for a socket to have error conditions pending.+    wait_error+  };++  /// Socket option to permit sending of broadcast messages.+  /**+   * Implements the SOL_SOCKET/SO_BROADCAST socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::udp::socket socket(my_context);+   * ...+   * asio::socket_base::broadcast option(true);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::udp::socket socket(my_context);+   * ...+   * asio::socket_base::broadcast option;+   * socket.get_option(option);+   * bool is_set = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Boolean_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined broadcast;+#else+  typedef asio::detail::socket_option::boolean<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_BROADCAST)>+      broadcast;+#endif++  /// Socket option to enable socket-level debugging.+  /**+   * Implements the SOL_SOCKET/SO_DEBUG socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::debug option(true);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::debug option;+   * socket.get_option(option);+   * bool is_set = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Boolean_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined debug;+#else+  typedef asio::detail::socket_option::boolean<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_DEBUG)> debug;+#endif++  /// Socket option to prevent routing, use local interfaces only.+  /**+   * Implements the SOL_SOCKET/SO_DONTROUTE socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::udp::socket socket(my_context);+   * ...+   * asio::socket_base::do_not_route option(true);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::udp::socket socket(my_context);+   * ...+   * asio::socket_base::do_not_route option;+   * socket.get_option(option);+   * bool is_set = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Boolean_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined do_not_route;+#else+  typedef asio::detail::socket_option::boolean<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_DONTROUTE)>+      do_not_route;+#endif++  /// Socket option to send keep-alives.+  /**+   * Implements the SOL_SOCKET/SO_KEEPALIVE socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::keep_alive option(true);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::keep_alive option;+   * socket.get_option(option);+   * bool is_set = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Boolean_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined keep_alive;+#else+  typedef asio::detail::socket_option::boolean<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_KEEPALIVE)> keep_alive;+#endif++  /// Socket option for the send buffer size of a socket.+  /**+   * Implements the SOL_SOCKET/SO_SNDBUF socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::send_buffer_size option(8192);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::send_buffer_size option;+   * socket.get_option(option);+   * int size = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Integer_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined send_buffer_size;+#else+  typedef asio::detail::socket_option::integer<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_SNDBUF)>+      send_buffer_size;+#endif++  /// Socket option for the send low watermark.+  /**+   * Implements the SOL_SOCKET/SO_SNDLOWAT socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::send_low_watermark option(1024);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::send_low_watermark option;+   * socket.get_option(option);+   * int size = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Integer_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined send_low_watermark;+#else+  typedef asio::detail::socket_option::integer<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_SNDLOWAT)>+      send_low_watermark;+#endif++  /// Socket option for the receive buffer size of a socket.+  /**+   * Implements the SOL_SOCKET/SO_RCVBUF socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::receive_buffer_size option(8192);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::receive_buffer_size option;+   * socket.get_option(option);+   * int size = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Integer_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined receive_buffer_size;+#else+  typedef asio::detail::socket_option::integer<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_RCVBUF)>+      receive_buffer_size;+#endif++  /// Socket option for the receive low watermark.+  /**+   * Implements the SOL_SOCKET/SO_RCVLOWAT socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::receive_low_watermark option(1024);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::receive_low_watermark option;+   * socket.get_option(option);+   * int size = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Integer_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined receive_low_watermark;+#else+  typedef asio::detail::socket_option::integer<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_RCVLOWAT)>+      receive_low_watermark;+#endif++  /// Socket option to allow the socket to be bound to an address that is+  /// already in use.+  /**+   * Implements the SOL_SOCKET/SO_REUSEADDR socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::socket_base::reuse_address option(true);+   * acceptor.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::socket_base::reuse_address option;+   * acceptor.get_option(option);+   * bool is_set = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Boolean_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined reuse_address;+#else+  typedef asio::detail::socket_option::boolean<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_REUSEADDR)>+      reuse_address;+#endif++  /// Socket option to specify whether the socket lingers on close if unsent+  /// data is present.+  /**+   * Implements the SOL_SOCKET/SO_LINGER socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::linger option(true, 30);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::linger option;+   * socket.get_option(option);+   * bool is_set = option.enabled();+   * unsigned short timeout = option.timeout();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Linger_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined linger;+#else+  typedef asio::detail::socket_option::linger<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_LINGER)>+      linger;+#endif++  /// Socket option for putting received out-of-band data inline.+  /**+   * Implements the SOL_SOCKET/SO_OOBINLINE socket option.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::out_of_band_inline option(true);+   * socket.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::out_of_band_inline option;+   * socket.get_option(option);+   * bool value = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Boolean_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined out_of_band_inline;+#else+  typedef asio::detail::socket_option::boolean<+    ASIO_OS_DEF(SOL_SOCKET), ASIO_OS_DEF(SO_OOBINLINE)>+      out_of_band_inline;+#endif++  /// Socket option to report aborted connections on accept.+  /**+   * Implements a custom socket option that determines whether or not an accept+   * operation is permitted to fail with asio::error::connection_aborted.+   * By default the option is false.+   *+   * @par Examples+   * Setting the option:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::socket_base::enable_connection_aborted option(true);+   * acceptor.set_option(option);+   * @endcode+   *+   * @par+   * Getting the current option value:+   * @code+   * asio::ip::tcp::acceptor acceptor(my_context);+   * ...+   * asio::socket_base::enable_connection_aborted option;+   * acceptor.get_option(option);+   * bool is_set = option.value();+   * @endcode+   *+   * @par Concepts:+   * Socket_Option, Boolean_Socket_Option.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined enable_connection_aborted;+#else+  typedef asio::detail::socket_option::boolean<+    asio::detail::custom_socket_option_level,+    asio::detail::enable_connection_aborted_option>+    enable_connection_aborted;+#endif++  /// IO control command to get the amount of data that can be read without+  /// blocking.+  /**+   * Implements the FIONREAD IO control command.+   *+   * @par Example+   * @code+   * asio::ip::tcp::socket socket(my_context);+   * ...+   * asio::socket_base::bytes_readable command(true);+   * socket.io_control(command);+   * std::size_t bytes_readable = command.get();+   * @endcode+   *+   * @par Concepts:+   * IO_Control_Command, Size_IO_Control_Command.+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined bytes_readable;+#else+  typedef asio::detail::io_control::bytes_readable bytes_readable;+#endif++  /// The maximum length of the queue of pending incoming connections.+#if defined(GENERATING_DOCUMENTATION)+  static const int max_listen_connections = implementation_defined;+#else+  ASIO_STATIC_CONSTANT(int, max_listen_connections+      = ASIO_OS_DEF(SOMAXCONN));+#endif++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use max_listen_connections.) The maximum length of the queue+  /// of pending incoming connections.+#if defined(GENERATING_DOCUMENTATION)+  static const int max_connections = implementation_defined;+#else+  ASIO_STATIC_CONSTANT(int, max_connections+      = ASIO_OS_DEF(SOMAXCONN));+#endif+#endif // !defined(ASIO_NO_DEPRECATED)++protected:+  /// Protected destructor to prevent deletion through this type.+  ~socket_base()+  {+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SOCKET_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/spawn.hpp view
@@ -0,0 +1,344 @@+//+// spawn.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SPAWN_HPP+#define ASIO_SPAWN_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <boost/coroutine/all.hpp>+#include "asio/any_io_executor.hpp"+#include "asio/bind_executor.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/wrapped_handler.hpp"+#include "asio/io_context.hpp"+#include "asio/is_executor.hpp"+#include "asio/strand.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Context object the represents the currently executing coroutine.+/**+ * The basic_yield_context class is used to represent the currently executing+ * stackful coroutine. A basic_yield_context may be passed as a handler to an+ * asynchronous operation. For example:+ *+ * @code template <typename Handler>+ * void my_coroutine(basic_yield_context<Handler> yield)+ * {+ *   ...+ *   std::size_t n = my_socket.async_read_some(buffer, yield);+ *   ...+ * } @endcode+ *+ * The initiating function (async_read_some in the above example) suspends the+ * current coroutine. The coroutine is resumed when the asynchronous operation+ * completes, and the result of the operation is returned.+ */+template <typename Handler>+class basic_yield_context+{+public:+  /// The coroutine callee type, used by the implementation.+  /**+   * When using Boost.Coroutine v1, this type is:+   * @code typename coroutine<void()> @endcode+   * When using Boost.Coroutine v2 (unidirectional coroutines), this type is:+   * @code push_coroutine<void> @endcode+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined callee_type;+#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)+  typedef boost::coroutines::push_coroutine<void> callee_type;+#else+  typedef boost::coroutines::coroutine<void()> callee_type;+#endif+  +  /// The coroutine caller type, used by the implementation.+  /**+   * When using Boost.Coroutine v1, this type is:+   * @code typename coroutine<void()>::caller_type @endcode+   * When using Boost.Coroutine v2 (unidirectional coroutines), this type is:+   * @code pull_coroutine<void> @endcode+   */+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined caller_type;+#elif defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)+  typedef boost::coroutines::pull_coroutine<void> caller_type;+#else+  typedef boost::coroutines::coroutine<void()>::caller_type caller_type;+#endif++  /// Construct a yield context to represent the specified coroutine.+  /**+   * Most applications do not need to use this constructor. Instead, the+   * spawn() function passes a yield context as an argument to the coroutine+   * function.+   */+  basic_yield_context(+      const detail::weak_ptr<callee_type>& coro,+      caller_type& ca, Handler& handler)+    : coro_(coro),+      ca_(ca),+      handler_(handler),+      ec_(0)+  {+  }++  /// Construct a yield context from another yield context type.+  /**+   * Requires that OtherHandler be convertible to Handler.+   */+  template <typename OtherHandler>+  basic_yield_context(const basic_yield_context<OtherHandler>& other)+    : coro_(other.coro_),+      ca_(other.ca_),+      handler_(other.handler_),+      ec_(other.ec_)+  {+  }++  /// Return a yield context that sets the specified error_code.+  /**+   * By default, when a yield context is used with an asynchronous operation, a+   * non-success error_code is converted to system_error and thrown. This+   * operator may be used to specify an error_code object that should instead be+   * set with the asynchronous operation's result. For example:+   *+   * @code template <typename Handler>+   * void my_coroutine(basic_yield_context<Handler> yield)+   * {+   *   ...+   *   std::size_t n = my_socket.async_read_some(buffer, yield[ec]);+   *   if (ec)+   *   {+   *     // An error occurred.+   *   }+   *   ...+   * } @endcode+   */+  basic_yield_context operator[](asio::error_code& ec) const+  {+    basic_yield_context tmp(*this);+    tmp.ec_ = &ec;+    return tmp;+  }++#if defined(GENERATING_DOCUMENTATION)+private:+#endif // defined(GENERATING_DOCUMENTATION)+  detail::weak_ptr<callee_type> coro_;+  caller_type& ca_;+  Handler handler_;+  asio::error_code* ec_;+};++#if defined(GENERATING_DOCUMENTATION)+/// Context object that represents the currently executing coroutine.+typedef basic_yield_context<unspecified> yield_context;+#else // defined(GENERATING_DOCUMENTATION)+typedef basic_yield_context<+  executor_binder<void(*)(), any_io_executor> > yield_context;+#endif // defined(GENERATING_DOCUMENTATION)++/**+ * @defgroup spawn asio::spawn+ *+ * @brief Start a new stackful coroutine.+ *+ * The spawn() function is a high-level wrapper over the Boost.Coroutine+ * library. This function enables programs to implement asynchronous logic in a+ * synchronous manner, as illustrated by the following example:+ *+ * @code asio::spawn(my_strand, do_echo);+ *+ * // ...+ *+ * void do_echo(asio::yield_context yield)+ * {+ *   try+ *   {+ *     char data[128];+ *     for (;;)+ *     {+ *       std::size_t length =+ *         my_socket.async_read_some(+ *           asio::buffer(data), yield);+ *+ *       asio::async_write(my_socket,+ *           asio::buffer(data, length), yield);+ *     }+ *   }+ *   catch (std::exception& e)+ *   {+ *     // ...+ *   }+ * } @endcode+ */+/*@{*/++/// Start a new stackful coroutine, calling the specified handler when it+/// completes.+/**+ * This function is used to launch a new coroutine.+ *+ * @param function The coroutine function. The function must have the signature:+ * @code void function(basic_yield_context<Handler> yield); @endcode+ *+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.+ */+template <typename Function>+void spawn(ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes+      = boost::coroutines::attributes());++/// Start a new stackful coroutine, calling the specified handler when it+/// completes.+/**+ * This function is used to launch a new coroutine.+ *+ * @param handler A handler to be called when the coroutine exits. More+ * importantly, the handler provides an execution context (via the the handler+ * invocation hook) for the coroutine. The handler must have the signature:+ * @code void handler(); @endcode+ *+ * @param function The coroutine function. The function must have the signature:+ * @code void function(basic_yield_context<Handler> yield); @endcode+ *+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.+ */+template <typename Handler, typename Function>+void spawn(ASIO_MOVE_ARG(Handler) handler,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes+      = boost::coroutines::attributes(),+    typename enable_if<+      !is_executor<typename decay<Handler>::type>::value &&+      !execution::is_executor<typename decay<Handler>::type>::value &&+      !is_convertible<Handler&, execution_context&>::value>::type* = 0);++/// Start a new stackful coroutine, inheriting the execution context of another.+/**+ * This function is used to launch a new coroutine.+ *+ * @param ctx Identifies the current coroutine as a parent of the new+ * coroutine. This specifies that the new coroutine should inherit the+ * execution context of the parent. For example, if the parent coroutine is+ * executing in a particular strand, then the new coroutine will execute in the+ * same strand.+ *+ * @param function The coroutine function. The function must have the signature:+ * @code void function(basic_yield_context<Handler> yield); @endcode+ *+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.+ */+template <typename Handler, typename Function>+void spawn(basic_yield_context<Handler> ctx,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes+      = boost::coroutines::attributes());++/// Start a new stackful coroutine that executes on a given executor.+/**+ * This function is used to launch a new coroutine.+ *+ * @param ex Identifies the executor that will run the coroutine. The new+ * coroutine is implicitly given its own strand within this executor.+ *+ * @param function The coroutine function. The function must have the signature:+ * @code void function(yield_context yield); @endcode+ *+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.+ */+template <typename Function, typename Executor>+void spawn(const Executor& ex,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes+      = boost::coroutines::attributes(),+    typename enable_if<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type* = 0);++/// Start a new stackful coroutine that executes on a given strand.+/**+ * This function is used to launch a new coroutine.+ *+ * @param ex Identifies the strand that will run the coroutine.+ *+ * @param function The coroutine function. The function must have the signature:+ * @code void function(yield_context yield); @endcode+ *+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.+ */+template <typename Function, typename Executor>+void spawn(const strand<Executor>& ex,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes+      = boost::coroutines::attributes());++#if !defined(ASIO_NO_TS_EXECUTORS)++/// Start a new stackful coroutine that executes in the context of a strand.+/**+ * This function is used to launch a new coroutine.+ *+ * @param s Identifies a strand. By starting multiple coroutines on the same+ * strand, the implementation ensures that none of those coroutines can execute+ * simultaneously.+ *+ * @param function The coroutine function. The function must have the signature:+ * @code void function(yield_context yield); @endcode+ *+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.+ */+template <typename Function>+void spawn(const asio::io_context::strand& s,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes+      = boost::coroutines::attributes());++#endif // !defined(ASIO_NO_TS_EXECUTORS)++/// Start a new stackful coroutine that executes on a given execution context.+/**+ * This function is used to launch a new coroutine.+ *+ * @param ctx Identifies the execution context that will run the coroutine. The+ * new coroutine is implicitly given its own strand within this execution+ * context.+ *+ * @param function The coroutine function. The function must have the signature:+ * @code void function(yield_context yield); @endcode+ *+ * @param attributes Boost.Coroutine attributes used to customise the coroutine.+ */+template <typename Function, typename ExecutionContext>+void spawn(ExecutionContext& ctx,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes+      = boost::coroutines::attributes(),+    typename enable_if<is_convertible<+      ExecutionContext&, execution_context&>::value>::type* = 0);++/*@}*/++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/spawn.hpp"++#endif // ASIO_SPAWN_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl.hpp view
@@ -0,0 +1,28 @@+//+// ssl.hpp+// ~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_HPP+#define ASIO_SSL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/ssl/context.hpp"+#include "asio/ssl/context_base.hpp"+#include "asio/ssl/error.hpp"+#include "asio/ssl/rfc2818_verification.hpp"+#include "asio/ssl/host_name_verification.hpp"+#include "asio/ssl/stream.hpp"+#include "asio/ssl/stream_base.hpp"+#include "asio/ssl/verify_context.hpp"+#include "asio/ssl/verify_mode.hpp"++#endif // ASIO_SSL_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/context.hpp view
@@ -0,0 +1,761 @@+//+// ssl/context.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_CONTEXT_HPP+#define ASIO_SSL_CONTEXT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <string>+#include "asio/buffer.hpp"+#include "asio/io_context.hpp"+#include "asio/ssl/context_base.hpp"+#include "asio/ssl/detail/openssl_types.hpp"+#include "asio/ssl/detail/openssl_init.hpp"+#include "asio/ssl/detail/password_callback.hpp"+#include "asio/ssl/detail/verify_callback.hpp"+#include "asio/ssl/verify_mode.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++class context+  : public context_base,+    private noncopyable+{+public:+  /// The native handle type of the SSL context.+  typedef SSL_CTX* native_handle_type;++  /// Constructor.+  ASIO_DECL explicit context(method m);++  /// Construct to take ownership of a native handle.+  ASIO_DECL explicit context(native_handle_type native_handle);++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a context from another.+  /**+   * This constructor moves an SSL context from one object to another.+   *+   * @param other The other context object from which the move will occur.+   *+   * @note Following the move, the following operations only are valid for the+   * moved-from object:+   * @li Destruction.+   * @li As a target for move-assignment.+   */+  ASIO_DECL context(context&& other);++  /// Move-assign a context from another.+  /**+   * This assignment operator moves an SSL context from one object to another.+   *+   * @param other The other context object from which the move will occur.+   *+   * @note Following the move, the following operations only are valid for the+   * moved-from object:+   * @li Destruction.+   * @li As a target for move-assignment.+   */+  ASIO_DECL context& operator=(context&& other);+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  ASIO_DECL ~context();++  /// Get the underlying implementation in the native type.+  /**+   * This function may be used to obtain the underlying implementation of the+   * context. This is intended to allow access to context functionality that is+   * not otherwise provided.+   */+  ASIO_DECL native_handle_type native_handle();++  /// Clear options on the context.+  /**+   * This function may be used to configure the SSL options used by the context.+   *+   * @param o A bitmask of options. The available option values are defined in+   * the context_base class. The specified options, if currently enabled on the+   * context, are cleared.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_clear_options.+   */+  ASIO_DECL void clear_options(options o);++  /// Clear options on the context.+  /**+   * This function may be used to configure the SSL options used by the context.+   *+   * @param o A bitmask of options. The available option values are defined in+   * the context_base class. The specified options, if currently enabled on the+   * context, are cleared.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_clear_options.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID clear_options(options o,+      asio::error_code& ec);++  /// Set options on the context.+  /**+   * This function may be used to configure the SSL options used by the context.+   *+   * @param o A bitmask of options. The available option values are defined in+   * the context_base class. The options are bitwise-ored with any existing+   * value for the options.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_set_options.+   */+  ASIO_DECL void set_options(options o);++  /// Set options on the context.+  /**+   * This function may be used to configure the SSL options used by the context.+   *+   * @param o A bitmask of options. The available option values are defined in+   * the context_base class. The options are bitwise-ored with any existing+   * value for the options.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_set_options.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID set_options(options o,+      asio::error_code& ec);++  /// Set the peer verification mode.+  /**+   * This function may be used to configure the peer verification mode used by+   * the context.+   *+   * @param v A bitmask of peer verification modes. See @ref verify_mode for+   * available values.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_set_verify.+   */+  ASIO_DECL void set_verify_mode(verify_mode v);++  /// Set the peer verification mode.+  /**+   * This function may be used to configure the peer verification mode used by+   * the context.+   *+   * @param v A bitmask of peer verification modes. See @ref verify_mode for+   * available values.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_set_verify.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID set_verify_mode(+      verify_mode v, asio::error_code& ec);++  /// Set the peer verification depth.+  /**+   * This function may be used to configure the maximum verification depth+   * allowed by the context.+   *+   * @param depth Maximum depth for the certificate chain verification that+   * shall be allowed.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_set_verify_depth.+   */+  ASIO_DECL void set_verify_depth(int depth);++  /// Set the peer verification depth.+  /**+   * This function may be used to configure the maximum verification depth+   * allowed by the context.+   *+   * @param depth Maximum depth for the certificate chain verification that+   * shall be allowed.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_set_verify_depth.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID set_verify_depth(+      int depth, asio::error_code& ec);++  /// Set the callback used to verify peer certificates.+  /**+   * This function is used to specify a callback function that will be called+   * by the implementation when it needs to verify a peer certificate.+   *+   * @param callback The function object to be used for verifying a certificate.+   * The function signature of the handler must be:+   * @code bool verify_callback(+   *   bool preverified, // True if the certificate passed pre-verification.+   *   verify_context& ctx // The peer certificate and other context.+   * ); @endcode+   * The return value of the callback is true if the certificate has passed+   * verification, false otherwise.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_set_verify.+   */+  template <typename VerifyCallback>+  void set_verify_callback(VerifyCallback callback);++  /// Set the callback used to verify peer certificates.+  /**+   * This function is used to specify a callback function that will be called+   * by the implementation when it needs to verify a peer certificate.+   *+   * @param callback The function object to be used for verifying a certificate.+   * The function signature of the handler must be:+   * @code bool verify_callback(+   *   bool preverified, // True if the certificate passed pre-verification.+   *   verify_context& ctx // The peer certificate and other context.+   * ); @endcode+   * The return value of the callback is true if the certificate has passed+   * verification, false otherwise.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_set_verify.+   */+  template <typename VerifyCallback>+  ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback,+      asio::error_code& ec);++  /// Load a certification authority file for performing verification.+  /**+   * This function is used to load one or more trusted certification authorities+   * from a file.+   *+   * @param filename The name of a file containing certification authority+   * certificates in PEM format.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_load_verify_locations.+   */+  ASIO_DECL void load_verify_file(const std::string& filename);++  /// Load a certification authority file for performing verification.+  /**+   * This function is used to load the certificates for one or more trusted+   * certification authorities from a file.+   *+   * @param filename The name of a file containing certification authority+   * certificates in PEM format.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_load_verify_locations.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID load_verify_file(+      const std::string& filename, asio::error_code& ec);++  /// Add certification authority for performing verification.+  /**+   * This function is used to add one trusted certification authority+   * from a memory buffer.+   *+   * @param ca The buffer containing the certification authority certificate.+   * The certificate must use the PEM format.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_get_cert_store and @c X509_STORE_add_cert.+   */+  ASIO_DECL void add_certificate_authority(const const_buffer& ca);++  /// Add certification authority for performing verification.+  /**+   * This function is used to add one trusted certification authority+   * from a memory buffer.+   *+   * @param ca The buffer containing the certification authority certificate.+   * The certificate must use the PEM format.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_get_cert_store and @c X509_STORE_add_cert.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID add_certificate_authority(+      const const_buffer& ca, asio::error_code& ec);++  /// Configures the context to use the default directories for finding+  /// certification authority certificates.+  /**+   * This function specifies that the context should use the default,+   * system-dependent directories for locating certification authority+   * certificates.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_set_default_verify_paths.+   */+  ASIO_DECL void set_default_verify_paths();++  /// Configures the context to use the default directories for finding+  /// certification authority certificates.+  /**+   * This function specifies that the context should use the default,+   * system-dependent directories for locating certification authority+   * certificates.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_set_default_verify_paths.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID set_default_verify_paths(+      asio::error_code& ec);++  /// Add a directory containing certificate authority files to be used for+  /// performing verification.+  /**+   * This function is used to specify the name of a directory containing+   * certification authority certificates. Each file in the directory must+   * contain a single certificate. The files must be named using the subject+   * name's hash and an extension of ".0".+   *+   * @param path The name of a directory containing the certificates.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_load_verify_locations.+   */+  ASIO_DECL void add_verify_path(const std::string& path);++  /// Add a directory containing certificate authority files to be used for+  /// performing verification.+  /**+   * This function is used to specify the name of a directory containing+   * certification authority certificates. Each file in the directory must+   * contain a single certificate. The files must be named using the subject+   * name's hash and an extension of ".0".+   *+   * @param path The name of a directory containing the certificates.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_load_verify_locations.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID add_verify_path(+      const std::string& path, asio::error_code& ec);++  /// Use a certificate from a memory buffer.+  /**+   * This function is used to load a certificate into the context from a buffer.+   *+   * @param certificate The buffer containing the certificate.+   *+   * @param format The certificate format (ASN.1 or PEM).+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_use_certificate or SSL_CTX_use_certificate_ASN1.+   */+  ASIO_DECL void use_certificate(+      const const_buffer& certificate, file_format format);++  /// Use a certificate from a memory buffer.+  /**+   * This function is used to load a certificate into the context from a buffer.+   *+   * @param certificate The buffer containing the certificate.+   *+   * @param format The certificate format (ASN.1 or PEM).+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_use_certificate or SSL_CTX_use_certificate_ASN1.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_certificate(+      const const_buffer& certificate, file_format format,+      asio::error_code& ec);++  /// Use a certificate from a file.+  /**+   * This function is used to load a certificate into the context from a file.+   *+   * @param filename The name of the file containing the certificate.+   *+   * @param format The file format (ASN.1 or PEM).+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_use_certificate_file.+   */+  ASIO_DECL void use_certificate_file(+      const std::string& filename, file_format format);++  /// Use a certificate from a file.+  /**+   * This function is used to load a certificate into the context from a file.+   *+   * @param filename The name of the file containing the certificate.+   *+   * @param format The file format (ASN.1 or PEM).+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_use_certificate_file.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_certificate_file(+      const std::string& filename, file_format format,+      asio::error_code& ec);++  /// Use a certificate chain from a memory buffer.+  /**+   * This function is used to load a certificate chain into the context from a+   * buffer.+   *+   * @param chain The buffer containing the certificate chain. The certificate+   * chain must use the PEM format.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_use_certificate and SSL_CTX_add_extra_chain_cert.+   */+  ASIO_DECL void use_certificate_chain(const const_buffer& chain);++  /// Use a certificate chain from a memory buffer.+  /**+   * This function is used to load a certificate chain into the context from a+   * buffer.+   *+   * @param chain The buffer containing the certificate chain. The certificate+   * chain must use the PEM format.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_use_certificate and SSL_CTX_add_extra_chain_cert.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_certificate_chain(+      const const_buffer& chain, asio::error_code& ec);++  /// Use a certificate chain from a file.+  /**+   * This function is used to load a certificate chain into the context from a+   * file.+   *+   * @param filename The name of the file containing the certificate. The file+   * must use the PEM format.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_use_certificate_chain_file.+   */+  ASIO_DECL void use_certificate_chain_file(const std::string& filename);++  /// Use a certificate chain from a file.+  /**+   * This function is used to load a certificate chain into the context from a+   * file.+   *+   * @param filename The name of the file containing the certificate. The file+   * must use the PEM format.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_use_certificate_chain_file.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_certificate_chain_file(+      const std::string& filename, asio::error_code& ec);++  /// Use a private key from a memory buffer.+  /**+   * This function is used to load a private key into the context from a buffer.+   *+   * @param private_key The buffer containing the private key.+   *+   * @param format The private key format (ASN.1 or PEM).+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_use_PrivateKey or SSL_CTX_use_PrivateKey_ASN1.+   */+  ASIO_DECL void use_private_key(+      const const_buffer& private_key, file_format format);++  /// Use a private key from a memory buffer.+  /**+   * This function is used to load a private key into the context from a buffer.+   *+   * @param private_key The buffer containing the private key.+   *+   * @param format The private key format (ASN.1 or PEM).+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_use_PrivateKey or SSL_CTX_use_PrivateKey_ASN1.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_private_key(+      const const_buffer& private_key, file_format format,+      asio::error_code& ec);++  /// Use a private key from a file.+  /**+   * This function is used to load a private key into the context from a file.+   *+   * @param filename The name of the file containing the private key.+   *+   * @param format The file format (ASN.1 or PEM).+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_use_PrivateKey_file.+   */+  ASIO_DECL void use_private_key_file(+      const std::string& filename, file_format format);++  /// Use a private key from a file.+  /**+   * This function is used to load a private key into the context from a file.+   *+   * @param filename The name of the file containing the private key.+   *+   * @param format The file format (ASN.1 or PEM).+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_use_PrivateKey_file.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_private_key_file(+      const std::string& filename, file_format format,+      asio::error_code& ec);++  /// Use an RSA private key from a memory buffer.+  /**+   * This function is used to load an RSA private key into the context from a+   * buffer.+   *+   * @param private_key The buffer containing the RSA private key.+   *+   * @param format The private key format (ASN.1 or PEM).+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_use_RSAPrivateKey or SSL_CTX_use_RSAPrivateKey_ASN1.+   */+  ASIO_DECL void use_rsa_private_key(+      const const_buffer& private_key, file_format format);++  /// Use an RSA private key from a memory buffer.+  /**+   * This function is used to load an RSA private key into the context from a+   * buffer.+   *+   * @param private_key The buffer containing the RSA private key.+   *+   * @param format The private key format (ASN.1 or PEM).+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_use_RSAPrivateKey or SSL_CTX_use_RSAPrivateKey_ASN1.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_rsa_private_key(+      const const_buffer& private_key, file_format format,+      asio::error_code& ec);++  /// Use an RSA private key from a file.+  /**+   * This function is used to load an RSA private key into the context from a+   * file.+   *+   * @param filename The name of the file containing the RSA private key.+   *+   * @param format The file format (ASN.1 or PEM).+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_use_RSAPrivateKey_file.+   */+  ASIO_DECL void use_rsa_private_key_file(+      const std::string& filename, file_format format);++  /// Use an RSA private key from a file.+  /**+   * This function is used to load an RSA private key into the context from a+   * file.+   *+   * @param filename The name of the file containing the RSA private key.+   *+   * @param format The file format (ASN.1 or PEM).+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_use_RSAPrivateKey_file.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_rsa_private_key_file(+      const std::string& filename, file_format format,+      asio::error_code& ec);++  /// Use the specified memory buffer to obtain the temporary Diffie-Hellman+  /// parameters.+  /**+   * This function is used to load Diffie-Hellman parameters into the context+   * from a buffer.+   *+   * @param dh The memory buffer containing the Diffie-Hellman parameters. The+   * buffer must use the PEM format.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_set_tmp_dh.+   */+  ASIO_DECL void use_tmp_dh(const const_buffer& dh);++  /// Use the specified memory buffer to obtain the temporary Diffie-Hellman+  /// parameters.+  /**+   * This function is used to load Diffie-Hellman parameters into the context+   * from a buffer.+   *+   * @param dh The memory buffer containing the Diffie-Hellman parameters. The+   * buffer must use the PEM format.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_set_tmp_dh.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_tmp_dh(+      const const_buffer& dh, asio::error_code& ec);++  /// Use the specified file to obtain the temporary Diffie-Hellman parameters.+  /**+   * This function is used to load Diffie-Hellman parameters into the context+   * from a file.+   *+   * @param filename The name of the file containing the Diffie-Hellman+   * parameters. The file must use the PEM format.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_set_tmp_dh.+   */+  ASIO_DECL void use_tmp_dh_file(const std::string& filename);++  /// Use the specified file to obtain the temporary Diffie-Hellman parameters.+  /**+   * This function is used to load Diffie-Hellman parameters into the context+   * from a file.+   *+   * @param filename The name of the file containing the Diffie-Hellman+   * parameters. The file must use the PEM format.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_set_tmp_dh.+   */+  ASIO_DECL ASIO_SYNC_OP_VOID use_tmp_dh_file(+      const std::string& filename, asio::error_code& ec);++  /// Set the password callback.+  /**+   * This function is used to specify a callback function to obtain password+   * information about an encrypted key in PEM format.+   *+   * @param callback The function object to be used for obtaining the password.+   * The function signature of the handler must be:+   * @code std::string password_callback(+   *   std::size_t max_length,  // The maximum size for a password.+   *   password_purpose purpose // Whether password is for reading or writing.+   * ); @endcode+   * The return value of the callback is a string containing the password.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_CTX_set_default_passwd_cb.+   */+  template <typename PasswordCallback>+  void set_password_callback(PasswordCallback callback);++  /// Set the password callback.+  /**+   * This function is used to specify a callback function to obtain password+   * information about an encrypted key in PEM format.+   *+   * @param callback The function object to be used for obtaining the password.+   * The function signature of the handler must be:+   * @code std::string password_callback(+   *   std::size_t max_length,  // The maximum size for a password.+   *   password_purpose purpose // Whether password is for reading or writing.+   * ); @endcode+   * The return value of the callback is a string containing the password.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_CTX_set_default_passwd_cb.+   */+  template <typename PasswordCallback>+  ASIO_SYNC_OP_VOID set_password_callback(PasswordCallback callback,+      asio::error_code& ec);++private:+  struct bio_cleanup;+  struct x509_cleanup;+  struct evp_pkey_cleanup;+  struct rsa_cleanup;+  struct dh_cleanup;++  // Helper function used to set a peer certificate verification callback.+  ASIO_DECL ASIO_SYNC_OP_VOID do_set_verify_callback(+      detail::verify_callback_base* callback, asio::error_code& ec);++  // Callback used when the SSL implementation wants to verify a certificate.+  ASIO_DECL static int verify_callback_function(+      int preverified, X509_STORE_CTX* ctx);++  // Helper function used to set a password callback.+  ASIO_DECL ASIO_SYNC_OP_VOID do_set_password_callback(+      detail::password_callback_base* callback, asio::error_code& ec);++  // Callback used when the SSL implementation wants a password.+  ASIO_DECL static int password_callback_function(+      char* buf, int size, int purpose, void* data);++  // Helper function to set the temporary Diffie-Hellman parameters from a BIO.+  ASIO_DECL ASIO_SYNC_OP_VOID do_use_tmp_dh(+      BIO* bio, asio::error_code& ec);++  // Helper function to make a BIO from a memory buffer.+  ASIO_DECL BIO* make_buffer_bio(const const_buffer& b);++  // The underlying native implementation.+  native_handle_type handle_;++  // Ensure openssl is initialised.+  asio::ssl::detail::openssl_init<> init_;+};++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/ssl/impl/context.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/ssl/impl/context.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_SSL_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/context_base.hpp view
@@ -0,0 +1,209 @@+//+// ssl/context_base.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_CONTEXT_BASE_HPP+#define ASIO_SSL_CONTEXT_BASE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/ssl/detail/openssl_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++/// The context_base class is used as a base for the basic_context class+/// template so that we have a common place to define various enums.+class context_base+{+public:+  /// Different methods supported by a context.+  enum method+  {+    /// Generic SSL version 2.+    sslv2,++    /// SSL version 2 client.+    sslv2_client,++    /// SSL version 2 server.+    sslv2_server,++    /// Generic SSL version 3.+    sslv3,++    /// SSL version 3 client.+    sslv3_client,++    /// SSL version 3 server.+    sslv3_server,++    /// Generic TLS version 1.+    tlsv1,++    /// TLS version 1 client.+    tlsv1_client,++    /// TLS version 1 server.+    tlsv1_server,++    /// Generic SSL/TLS.+    sslv23,++    /// SSL/TLS client.+    sslv23_client,++    /// SSL/TLS server.+    sslv23_server,++    /// Generic TLS version 1.1.+    tlsv11,++    /// TLS version 1.1 client.+    tlsv11_client,++    /// TLS version 1.1 server.+    tlsv11_server,++    /// Generic TLS version 1.2.+    tlsv12,++    /// TLS version 1.2 client.+    tlsv12_client,++    /// TLS version 1.2 server.+    tlsv12_server,++    /// Generic TLS version 1.3.+    tlsv13,++    /// TLS version 1.3 client.+    tlsv13_client,++    /// TLS version 1.3 server.+    tlsv13_server,++    /// Generic TLS.+    tls,++    /// TLS client.+    tls_client,++    /// TLS server.+    tls_server+  };++  /// Bitmask type for SSL options.+  typedef long options;++#if defined(GENERATING_DOCUMENTATION)+  /// Implement various bug workarounds.+  static const long default_workarounds = implementation_defined;++  /// Always create a new key when using tmp_dh parameters.+  static const long single_dh_use = implementation_defined;++  /// Disable SSL v2.+  static const long no_sslv2 = implementation_defined;++  /// Disable SSL v3.+  static const long no_sslv3 = implementation_defined;++  /// Disable TLS v1.+  static const long no_tlsv1 = implementation_defined;++  /// Disable TLS v1.1.+  static const long no_tlsv1_1 = implementation_defined;++  /// Disable TLS v1.2.+  static const long no_tlsv1_2 = implementation_defined;++  /// Disable TLS v1.3.+  static const long no_tlsv1_3 = implementation_defined;++  /// Disable compression. Compression is disabled by default.+  static const long no_compression = implementation_defined;+#else+  ASIO_STATIC_CONSTANT(long, default_workarounds = SSL_OP_ALL);+  ASIO_STATIC_CONSTANT(long, single_dh_use = SSL_OP_SINGLE_DH_USE);+  ASIO_STATIC_CONSTANT(long, no_sslv2 = SSL_OP_NO_SSLv2);+  ASIO_STATIC_CONSTANT(long, no_sslv3 = SSL_OP_NO_SSLv3);+  ASIO_STATIC_CONSTANT(long, no_tlsv1 = SSL_OP_NO_TLSv1);+# if defined(SSL_OP_NO_TLSv1_1)+  ASIO_STATIC_CONSTANT(long, no_tlsv1_1 = SSL_OP_NO_TLSv1_1);+# else // defined(SSL_OP_NO_TLSv1_1)+  ASIO_STATIC_CONSTANT(long, no_tlsv1_1 = 0x10000000L);+# endif // defined(SSL_OP_NO_TLSv1_1)+# if defined(SSL_OP_NO_TLSv1_2)+  ASIO_STATIC_CONSTANT(long, no_tlsv1_2 = SSL_OP_NO_TLSv1_2);+# else // defined(SSL_OP_NO_TLSv1_2)+  ASIO_STATIC_CONSTANT(long, no_tlsv1_2 = 0x08000000L);+# endif // defined(SSL_OP_NO_TLSv1_2)+# if defined(SSL_OP_NO_TLSv1_3)+  ASIO_STATIC_CONSTANT(long, no_tlsv1_3 = SSL_OP_NO_TLSv1_3);+# else // defined(SSL_OP_NO_TLSv1_3)+  ASIO_STATIC_CONSTANT(long, no_tlsv1_3 = 0x20000000L);+# endif // defined(SSL_OP_NO_TLSv1_3)+# if defined(SSL_OP_NO_COMPRESSION)+  ASIO_STATIC_CONSTANT(long, no_compression = SSL_OP_NO_COMPRESSION);+# else // defined(SSL_OP_NO_COMPRESSION)+  ASIO_STATIC_CONSTANT(long, no_compression = 0x20000L);+# endif // defined(SSL_OP_NO_COMPRESSION)+#endif++  /// File format types.+  enum file_format+  {+    /// ASN.1 file.+    asn1,++    /// PEM file.+    pem+  };++#if !defined(GENERATING_DOCUMENTATION)+  // The following types and constants are preserved for backward compatibility.+  // New programs should use the equivalents of the same names that are defined+  // in the asio::ssl namespace.+  typedef int verify_mode;+  ASIO_STATIC_CONSTANT(int, verify_none = SSL_VERIFY_NONE);+  ASIO_STATIC_CONSTANT(int, verify_peer = SSL_VERIFY_PEER);+  ASIO_STATIC_CONSTANT(int,+      verify_fail_if_no_peer_cert = SSL_VERIFY_FAIL_IF_NO_PEER_CERT);+  ASIO_STATIC_CONSTANT(int, verify_client_once = SSL_VERIFY_CLIENT_ONCE);+#endif++  /// Purpose of PEM password.+  enum password_purpose+  {+    /// The password is needed for reading/decryption.+    for_reading,++    /// The password is needed for writing/encryption.+    for_writing+  };++protected:+  /// Protected destructor to prevent deletion through this type.+  ~context_base()+  {+  }+};++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_CONTEXT_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/buffered_handshake_op.hpp view
@@ -0,0 +1,119 @@+//+// ssl/detail/buffered_handshake_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_BUFFERED_HANDSHAKE_OP_HPP+#define ASIO_SSL_DETAIL_BUFFERED_HANDSHAKE_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/ssl/detail/engine.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++template <typename ConstBufferSequence>+class buffered_handshake_op+{+public:+  static ASIO_CONSTEXPR const char* tracking_name()+  {+    return "ssl::stream<>::async_buffered_handshake";+  }++  buffered_handshake_op(stream_base::handshake_type type,+      const ConstBufferSequence& buffers)+    : type_(type),+      buffers_(buffers),+      total_buffer_size_(asio::buffer_size(buffers_))+  {+  }++  engine::want operator()(engine& eng,+      asio::error_code& ec,+      std::size_t& bytes_transferred) const+  {+    return this->process(eng, ec, bytes_transferred,+        asio::buffer_sequence_begin(buffers_),+        asio::buffer_sequence_end(buffers_));+  }++  template <typename Handler>+  void call_handler(Handler& handler,+      const asio::error_code& ec,+      const std::size_t& bytes_transferred) const+  {+    handler(ec, bytes_transferred);+  }++private:+  template <typename Iterator>+  engine::want process(engine& eng,+      asio::error_code& ec,+      std::size_t& bytes_transferred,+      Iterator begin, Iterator end) const+  {+    Iterator iter = begin;+    std::size_t accumulated_size = 0;++    for (;;)+    {+      engine::want want = eng.handshake(type_, ec);+      if (want != engine::want_input_and_retry+          || bytes_transferred == total_buffer_size_)+        return want;++      // Find the next buffer piece to be fed to the engine.+      while (iter != end)+      {+        const_buffer buffer(*iter);++        // Skip over any buffers which have already been consumed by the engine.+        if (bytes_transferred >= accumulated_size + buffer.size())+        {+          accumulated_size += buffer.size();+          ++iter;+          continue;+        }++        // The current buffer may have been partially consumed by the engine on+        // a previous iteration. If so, adjust the buffer to point to the+        // unused portion.+        if (bytes_transferred > accumulated_size)+          buffer = buffer + (bytes_transferred - accumulated_size);++        // Pass the buffer to the engine, and update the bytes transferred to+        // reflect the total number of bytes consumed so far.+        bytes_transferred += buffer.size();+        buffer = eng.put_input(buffer);+        bytes_transferred -= buffer.size();+        break;+      }+    }+  }++  stream_base::handshake_type type_;+  ConstBufferSequence buffers_;+  std::size_t total_buffer_size_;+};++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_BUFFERED_HANDSHAKE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/engine.hpp view
@@ -0,0 +1,165 @@+//+// ssl/detail/engine.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_ENGINE_HPP+#define ASIO_SSL_DETAIL_ENGINE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/buffer.hpp"+#include "asio/detail/static_mutex.hpp"+#include "asio/ssl/detail/openssl_types.hpp"+#include "asio/ssl/detail/verify_callback.hpp"+#include "asio/ssl/stream_base.hpp"+#include "asio/ssl/verify_mode.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++class engine+{+public:+  enum want+  {+    // Returned by functions to indicate that the engine wants input. The input+    // buffer should be updated to point to the data. The engine then needs to+    // be called again to retry the operation.+    want_input_and_retry = -2,++    // Returned by functions to indicate that the engine wants to write output.+    // The output buffer points to the data to be written. The engine then+    // needs to be called again to retry the operation.+    want_output_and_retry = -1,++    // Returned by functions to indicate that the engine doesn't need input or+    // output.+    want_nothing = 0,++    // Returned by functions to indicate that the engine wants to write output.+    // The output buffer points to the data to be written. After that the+    // operation is complete, and the engine does not need to be called again.+    want_output = 1+  };++  // Construct a new engine for the specified context.+  ASIO_DECL explicit engine(SSL_CTX* context);++#if defined(ASIO_HAS_MOVE)+  // Move construct from another engine.+  ASIO_DECL engine(engine&& other) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE)++  // Destructor.+  ASIO_DECL ~engine();++  // Get the underlying implementation in the native type.+  ASIO_DECL SSL* native_handle();++  // Set the peer verification mode.+  ASIO_DECL asio::error_code set_verify_mode(+      verify_mode v, asio::error_code& ec);++  // Set the peer verification depth.+  ASIO_DECL asio::error_code set_verify_depth(+      int depth, asio::error_code& ec);++  // Set a peer certificate verification callback.+  ASIO_DECL asio::error_code set_verify_callback(+      verify_callback_base* callback, asio::error_code& ec);++  // Perform an SSL handshake using either SSL_connect (client-side) or+  // SSL_accept (server-side).+  ASIO_DECL want handshake(+      stream_base::handshake_type type, asio::error_code& ec);++  // Perform a graceful shutdown of the SSL session.+  ASIO_DECL want shutdown(asio::error_code& ec);++  // Write bytes to the SSL session.+  ASIO_DECL want write(const asio::const_buffer& data,+      asio::error_code& ec, std::size_t& bytes_transferred);++  // Read bytes from the SSL session.+  ASIO_DECL want read(const asio::mutable_buffer& data,+      asio::error_code& ec, std::size_t& bytes_transferred);++  // Get output data to be written to the transport.+  ASIO_DECL asio::mutable_buffer get_output(+      const asio::mutable_buffer& data);++  // Put input data that was read from the transport.+  ASIO_DECL asio::const_buffer put_input(+      const asio::const_buffer& data);++  // Map an error::eof code returned by the underlying transport according to+  // the type and state of the SSL session. Returns a const reference to the+  // error code object, suitable for passing to a completion handler.+  ASIO_DECL const asio::error_code& map_error_code(+      asio::error_code& ec) const;++private:+  // Disallow copying and assignment.+  engine(const engine&);+  engine& operator=(const engine&);++  // Callback used when the SSL implementation wants to verify a certificate.+  ASIO_DECL static int verify_callback_function(+      int preverified, X509_STORE_CTX* ctx);++#if (OPENSSL_VERSION_NUMBER < 0x10000000L)+  // The SSL_accept function may not be thread safe. This mutex is used to+  // protect all calls to the SSL_accept function.+  ASIO_DECL static asio::detail::static_mutex& accept_mutex();+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)++  // Perform one operation. Returns >= 0 on success or error, want_read if the+  // operation needs more input, or want_write if it needs to write some output+  // before the operation can complete.+  ASIO_DECL want perform(int (engine::* op)(void*, std::size_t),+      void* data, std::size_t length, asio::error_code& ec,+      std::size_t* bytes_transferred);++  // Adapt the SSL_accept function to the signature needed for perform().+  ASIO_DECL int do_accept(void*, std::size_t);++  // Adapt the SSL_connect function to the signature needed for perform().+  ASIO_DECL int do_connect(void*, std::size_t);++  // Adapt the SSL_shutdown function to the signature needed for perform().+  ASIO_DECL int do_shutdown(void*, std::size_t);++  // Adapt the SSL_read function to the signature needed for perform().+  ASIO_DECL int do_read(void* data, std::size_t length);++  // Adapt the SSL_write function to the signature needed for perform().+  ASIO_DECL int do_write(void* data, std::size_t length);++  SSL* ssl_;+  BIO* ext_bio_;+};++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/ssl/detail/impl/engine.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_SSL_DETAIL_ENGINE_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/handshake_op.hpp view
@@ -0,0 +1,67 @@+//+// ssl/detail/handshake_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_HANDSHAKE_OP_HPP+#define ASIO_SSL_DETAIL_HANDSHAKE_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/ssl/detail/engine.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++class handshake_op+{+public:+  static ASIO_CONSTEXPR const char* tracking_name()+  {+    return "ssl::stream<>::async_handshake";+  }++  handshake_op(stream_base::handshake_type type)+    : type_(type)+  {+  }++  engine::want operator()(engine& eng,+      asio::error_code& ec,+      std::size_t& bytes_transferred) const+  {+    bytes_transferred = 0;+    return eng.handshake(type_, ec);+  }++  template <typename Handler>+  void call_handler(Handler& handler,+      const asio::error_code& ec,+      const std::size_t&) const+  {+    handler(ec);+  }++private:+  stream_base::handshake_type type_;+};++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_HANDSHAKE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/engine.ipp view
@@ -0,0 +1,349 @@+//+// ssl/detail/impl/engine.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_IMPL_ENGINE_IPP+#define ASIO_SSL_DETAIL_IMPL_ENGINE_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"+#include "asio/ssl/detail/engine.hpp"+#include "asio/ssl/error.hpp"+#include "asio/ssl/verify_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++engine::engine(SSL_CTX* context)+  : ssl_(::SSL_new(context))+{+  if (!ssl_)+  {+    asio::error_code ec(+        static_cast<int>(::ERR_get_error()),+        asio::error::get_ssl_category());+    asio::detail::throw_error(ec, "engine");+  }++#if (OPENSSL_VERSION_NUMBER < 0x10000000L)+  accept_mutex().init();+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)++  ::SSL_set_mode(ssl_, SSL_MODE_ENABLE_PARTIAL_WRITE);+  ::SSL_set_mode(ssl_, SSL_MODE_ACCEPT_MOVING_WRITE_BUFFER);+#if defined(SSL_MODE_RELEASE_BUFFERS)+  ::SSL_set_mode(ssl_, SSL_MODE_RELEASE_BUFFERS);+#endif // defined(SSL_MODE_RELEASE_BUFFERS)++  ::BIO* int_bio = 0;+  ::BIO_new_bio_pair(&int_bio, 0, &ext_bio_, 0);+  ::SSL_set_bio(ssl_, int_bio, int_bio);+}++#if defined(ASIO_HAS_MOVE)+engine::engine(engine&& other) ASIO_NOEXCEPT+  : ssl_(other.ssl_),+    ext_bio_(other.ext_bio_)+{+  other.ssl_ = 0;+  other.ext_bio_ = 0;+}+#endif // defined(ASIO_HAS_MOVE)++engine::~engine()+{+  if (ssl_ && SSL_get_app_data(ssl_))+  {+    delete static_cast<verify_callback_base*>(SSL_get_app_data(ssl_));+    SSL_set_app_data(ssl_, 0);+  }++  if (ext_bio_)+    ::BIO_free(ext_bio_);++  if (ssl_)+    ::SSL_free(ssl_);+}++SSL* engine::native_handle()+{+  return ssl_;+}++asio::error_code engine::set_verify_mode(+    verify_mode v, asio::error_code& ec)+{+  ::SSL_set_verify(ssl_, v, ::SSL_get_verify_callback(ssl_));++  ec = asio::error_code();+  return ec;+}++asio::error_code engine::set_verify_depth(+    int depth, asio::error_code& ec)+{+  ::SSL_set_verify_depth(ssl_, depth);++  ec = asio::error_code();+  return ec;+}++asio::error_code engine::set_verify_callback(+    verify_callback_base* callback, asio::error_code& ec)+{+  if (SSL_get_app_data(ssl_))+    delete static_cast<verify_callback_base*>(SSL_get_app_data(ssl_));++  SSL_set_app_data(ssl_, callback);++  ::SSL_set_verify(ssl_, ::SSL_get_verify_mode(ssl_),+      &engine::verify_callback_function);++  ec = asio::error_code();+  return ec;+}++int engine::verify_callback_function(int preverified, X509_STORE_CTX* ctx)+{+  if (ctx)+  {+    if (SSL* ssl = static_cast<SSL*>(+          ::X509_STORE_CTX_get_ex_data(+            ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))+    {+      if (SSL_get_app_data(ssl))+      {+        verify_callback_base* callback =+          static_cast<verify_callback_base*>(+              SSL_get_app_data(ssl));++        verify_context verify_ctx(ctx);+        return callback->call(preverified != 0, verify_ctx) ? 1 : 0;+      }+    }+  }++  return 0;+}++engine::want engine::handshake(+    stream_base::handshake_type type, asio::error_code& ec)+{+  return perform((type == asio::ssl::stream_base::client)+      ? &engine::do_connect : &engine::do_accept, 0, 0, ec, 0);+}++engine::want engine::shutdown(asio::error_code& ec)+{+  return perform(&engine::do_shutdown, 0, 0, ec, 0);+}++engine::want engine::write(const asio::const_buffer& data,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  if (data.size() == 0)+  {+    ec = asio::error_code();+    return engine::want_nothing;+  }++  return perform(&engine::do_write,+      const_cast<void*>(data.data()),+      data.size(), ec, &bytes_transferred);+}++engine::want engine::read(const asio::mutable_buffer& data,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  if (data.size() == 0)+  {+    ec = asio::error_code();+    return engine::want_nothing;+  }++  return perform(&engine::do_read, data.data(),+      data.size(), ec, &bytes_transferred);+}++asio::mutable_buffer engine::get_output(+    const asio::mutable_buffer& data)+{+  int length = ::BIO_read(ext_bio_,+      data.data(), static_cast<int>(data.size()));++  return asio::buffer(data,+      length > 0 ? static_cast<std::size_t>(length) : 0);+}++asio::const_buffer engine::put_input(+    const asio::const_buffer& data)+{+  int length = ::BIO_write(ext_bio_,+      data.data(), static_cast<int>(data.size()));++  return asio::buffer(data ++      (length > 0 ? static_cast<std::size_t>(length) : 0));+}++const asio::error_code& engine::map_error_code(+    asio::error_code& ec) const+{+  // We only want to map the error::eof code.+  if (ec != asio::error::eof)+    return ec;++  // If there's data yet to be read, it's an error.+  if (BIO_wpending(ext_bio_))+  {+    ec = asio::ssl::error::stream_truncated;+    return ec;+  }++  // SSL v2 doesn't provide a protocol-level shutdown, so an eof on the+  // underlying transport is passed through.+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)+  if (SSL_version(ssl_) == SSL2_VERSION)+    return ec;+#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)++  // Otherwise, the peer should have negotiated a proper shutdown.+  if ((::SSL_get_shutdown(ssl_) & SSL_RECEIVED_SHUTDOWN) == 0)+  {+    ec = asio::ssl::error::stream_truncated;+  }++  return ec;+}++#if (OPENSSL_VERSION_NUMBER < 0x10000000L)+asio::detail::static_mutex& engine::accept_mutex()+{+  static asio::detail::static_mutex mutex = ASIO_STATIC_MUTEX_INIT;+  return mutex;+}+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)++engine::want engine::perform(int (engine::* op)(void*, std::size_t),+    void* data, std::size_t length, asio::error_code& ec,+    std::size_t* bytes_transferred)+{+  std::size_t pending_output_before = ::BIO_ctrl_pending(ext_bio_);+  ::ERR_clear_error();+  int result = (this->*op)(data, length);+  int ssl_error = ::SSL_get_error(ssl_, result);+  int sys_error = static_cast<int>(::ERR_get_error());+  std::size_t pending_output_after = ::BIO_ctrl_pending(ext_bio_);++  if (ssl_error == SSL_ERROR_SSL)+  {+    ec = asio::error_code(sys_error,+        asio::error::get_ssl_category());+    return pending_output_after > pending_output_before+      ? want_output : want_nothing;+  }++  if (ssl_error == SSL_ERROR_SYSCALL)+  {+    if (sys_error == 0)+    {+      ec = asio::ssl::error::unspecified_system_error;+    }+    else+    {+      ec = asio::error_code(sys_error,+          asio::error::get_ssl_category());+    }+    return pending_output_after > pending_output_before+      ? want_output : want_nothing;+  }++  if (result > 0 && bytes_transferred)+    *bytes_transferred = static_cast<std::size_t>(result);++  if (ssl_error == SSL_ERROR_WANT_WRITE)+  {+    ec = asio::error_code();+    return want_output_and_retry;+  }+  else if (pending_output_after > pending_output_before)+  {+    ec = asio::error_code();+    return result > 0 ? want_output : want_output_and_retry;+  }+  else if (ssl_error == SSL_ERROR_WANT_READ)+  {+    ec = asio::error_code();+    return want_input_and_retry;+  }+  else if (ssl_error == SSL_ERROR_ZERO_RETURN)+  {+    ec = asio::error::eof;+    return want_nothing;+  }+  else if (ssl_error == SSL_ERROR_NONE)+  {+    ec = asio::error_code();+    return want_nothing;+  }+  else+  {+    ec = asio::ssl::error::unexpected_result;+    return want_nothing;+  }+}++int engine::do_accept(void*, std::size_t)+{+#if (OPENSSL_VERSION_NUMBER < 0x10000000L)+  asio::detail::static_mutex::scoped_lock lock(accept_mutex());+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)+  return ::SSL_accept(ssl_);+}++int engine::do_connect(void*, std::size_t)+{+  return ::SSL_connect(ssl_);+}++int engine::do_shutdown(void*, std::size_t)+{+  int result = ::SSL_shutdown(ssl_);+  if (result == 0)+    result = ::SSL_shutdown(ssl_);+  return result;+}++int engine::do_read(void* data, std::size_t length)+{+  return ::SSL_read(ssl_, data,+      length < INT_MAX ? static_cast<int>(length) : INT_MAX);+}++int engine::do_write(void* data, std::size_t length)+{+  return ::SSL_write(ssl_, data,+      length < INT_MAX ? static_cast<int>(length) : INT_MAX);+}++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_IMPL_ENGINE_IPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/openssl_init.ipp view
@@ -0,0 +1,165 @@+//+// ssl/detail/impl/openssl_init.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com+// Copyright (c) 2005-2020 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_SSL_DETAIL_IMPL_OPENSSL_INIT_IPP+#define ASIO_SSL_DETAIL_IMPL_OPENSSL_INIT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <vector>+#include "asio/detail/assert.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/tss_ptr.hpp"+#include "asio/ssl/detail/openssl_init.hpp"+#include "asio/ssl/detail/openssl_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++class openssl_init_base::do_init+{+public:+  do_init()+  {+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)+    ::SSL_library_init();+    ::SSL_load_error_strings();        +    ::OpenSSL_add_all_algorithms();++    mutexes_.resize(::CRYPTO_num_locks());+    for (size_t i = 0; i < mutexes_.size(); ++i)+      mutexes_[i].reset(new asio::detail::mutex);+    ::CRYPTO_set_locking_callback(&do_init::openssl_locking_func);+#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)+#if (OPENSSL_VERSION_NUMBER < 0x10000000L)+    ::CRYPTO_set_id_callback(&do_init::openssl_id_func);+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)++#if !defined(SSL_OP_NO_COMPRESSION) \+  && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+    null_compression_methods_ = sk_SSL_COMP_new_null();+#endif // !defined(SSL_OP_NO_COMPRESSION)+       // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+  }++  ~do_init()+  {+#if !defined(SSL_OP_NO_COMPRESSION) \+  && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+    sk_SSL_COMP_free(null_compression_methods_);+#endif // !defined(SSL_OP_NO_COMPRESSION)+       // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)++#if (OPENSSL_VERSION_NUMBER < 0x10000000L)+    ::CRYPTO_set_id_callback(0);+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)+#if (OPENSSL_VERSION_NUMBER < 0x10100000L)+    ::CRYPTO_set_locking_callback(0);+    ::ERR_free_strings();+    ::EVP_cleanup();+    ::CRYPTO_cleanup_all_ex_data();+#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)+#if (OPENSSL_VERSION_NUMBER < 0x10000000L)+    ::ERR_remove_state(0);+#elif (OPENSSL_VERSION_NUMBER < 0x10100000L)+    ::ERR_remove_thread_state(NULL);+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L) \+    && (OPENSSL_VERSION_NUMBER < 0x10100000L) \+    && !defined(SSL_OP_NO_COMPRESSION)+    ::SSL_COMP_free_compression_methods();+#endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)+       // && (OPENSSL_VERSION_NUMBER < 0x10100000L)+       // && !defined(SSL_OP_NO_COMPRESSION)+#if !defined(OPENSSL_IS_BORINGSSL) && !defined(ASIO_USE_WOLFSSL)+    ::CONF_modules_unload(1);+#endif // !defined(OPENSSL_IS_BORINGSSL) && !defined(ASIO_USE_WOLFSSL)+#if !defined(OPENSSL_NO_ENGINE) \+  && (OPENSSL_VERSION_NUMBER < 0x10100000L)+    ::ENGINE_cleanup();+#endif // !defined(OPENSSL_NO_ENGINE)+       // && (OPENSSL_VERSION_NUMBER < 0x10100000L)+  }++#if !defined(SSL_OP_NO_COMPRESSION) \+  && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+  STACK_OF(SSL_COMP)* get_null_compression_methods() const+  {+    return null_compression_methods_;+  }+#endif // !defined(SSL_OP_NO_COMPRESSION)+       // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)++private:+#if (OPENSSL_VERSION_NUMBER < 0x10000000L)+  static unsigned long openssl_id_func()+  {+#if defined(ASIO_WINDOWS) || defined(__CYGWIN__)+    return ::GetCurrentThreadId();+#else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+    void* id = &errno;+    ASIO_ASSERT(sizeof(unsigned long) >= sizeof(void*));+    return reinterpret_cast<unsigned long>(id);+#endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)+  }+#endif // (OPENSSL_VERSION_NUMBER < 0x10000000L)++#if (OPENSSL_VERSION_NUMBER < 0x10100000L)+  static void openssl_locking_func(int mode, int n, +    const char* /*file*/, int /*line*/)+  {+    if (mode & CRYPTO_LOCK)+      instance()->mutexes_[n]->lock();+    else+      instance()->mutexes_[n]->unlock();+  }++  // Mutexes to be used in locking callbacks.+  std::vector<asio::detail::shared_ptr<+        asio::detail::mutex> > mutexes_;+#endif // (OPENSSL_VERSION_NUMBER < 0x10100000L)++#if !defined(SSL_OP_NO_COMPRESSION) \+  && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+  STACK_OF(SSL_COMP)* null_compression_methods_;+#endif // !defined(SSL_OP_NO_COMPRESSION)+       // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+};++asio::detail::shared_ptr<openssl_init_base::do_init>+openssl_init_base::instance()+{+  static asio::detail::shared_ptr<do_init> init(new do_init);+  return init;+}++#if !defined(SSL_OP_NO_COMPRESSION) \+  && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+STACK_OF(SSL_COMP)* openssl_init_base::get_null_compression_methods()+{+  return instance()->get_null_compression_methods();+}+#endif // !defined(SSL_OP_NO_COMPRESSION)+       // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_IMPL_OPENSSL_INIT_IPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/io.hpp view
@@ -0,0 +1,415 @@+//+// ssl/detail/io.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_IO_HPP+#define ASIO_SSL_DETAIL_IO_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/handler_tracking.hpp"+#include "asio/ssl/detail/engine.hpp"+#include "asio/ssl/detail/stream_core.hpp"+#include "asio/write.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++template <typename Stream, typename Operation>+std::size_t io(Stream& next_layer, stream_core& core,+    const Operation& op, asio::error_code& ec)+{+  asio::error_code io_ec;+  std::size_t bytes_transferred = 0;+  do switch (op(core.engine_, ec, bytes_transferred))+  {+  case engine::want_input_and_retry:++    // If the input buffer is empty then we need to read some more data from+    // the underlying transport.+    if (core.input_.size() == 0)+    {+      core.input_ = asio::buffer(core.input_buffer_,+          next_layer.read_some(core.input_buffer_, io_ec));+      if (!ec)+        ec = io_ec;+    }++    // Pass the new input data to the engine.+    core.input_ = core.engine_.put_input(core.input_);++    // Try the operation again.+    continue;++  case engine::want_output_and_retry:++    // Get output data from the engine and write it to the underlying+    // transport.+    asio::write(next_layer,+        core.engine_.get_output(core.output_buffer_), io_ec);+    if (!ec)+      ec = io_ec;++    // Try the operation again.+    continue;++  case engine::want_output:++    // Get output data from the engine and write it to the underlying+    // transport.+    asio::write(next_layer,+        core.engine_.get_output(core.output_buffer_), io_ec);+    if (!ec)+      ec = io_ec;++    // Operation is complete. Return result to caller.+    core.engine_.map_error_code(ec);+    return bytes_transferred;++  default:++    // Operation is complete. Return result to caller.+    core.engine_.map_error_code(ec);+    return bytes_transferred;++  } while (!ec);++  // Operation failed. Return result to caller.+  core.engine_.map_error_code(ec);+  return 0;+}++template <typename Stream, typename Operation, typename Handler>+class io_op+{+public:+  io_op(Stream& next_layer, stream_core& core,+      const Operation& op, Handler& handler)+    : next_layer_(next_layer),+      core_(core),+      op_(op),+      start_(0),+      want_(engine::want_nothing),+      bytes_transferred_(0),+      handler_(ASIO_MOVE_CAST(Handler)(handler))+  {+  }++#if defined(ASIO_HAS_MOVE)+  io_op(const io_op& other)+    : next_layer_(other.next_layer_),+      core_(other.core_),+      op_(other.op_),+      start_(other.start_),+      want_(other.want_),+      ec_(other.ec_),+      bytes_transferred_(other.bytes_transferred_),+      handler_(other.handler_)+  {+  }++  io_op(io_op&& other)+    : next_layer_(other.next_layer_),+      core_(other.core_),+      op_(ASIO_MOVE_CAST(Operation)(other.op_)),+      start_(other.start_),+      want_(other.want_),+      ec_(other.ec_),+      bytes_transferred_(other.bytes_transferred_),+      handler_(ASIO_MOVE_CAST(Handler)(other.handler_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()(asio::error_code ec,+      std::size_t bytes_transferred = ~std::size_t(0), int start = 0)+  {+    switch (start_ = start)+    {+    case 1: // Called after at least one async operation.+      do+      {+        switch (want_ = op_(core_.engine_, ec_, bytes_transferred_))+        {+        case engine::want_input_and_retry:++          // If the input buffer already has data in it we can pass it to the+          // engine and then retry the operation immediately.+          if (core_.input_.size() != 0)+          {+            core_.input_ = core_.engine_.put_input(core_.input_);+            continue;+          }++          // The engine wants more data to be read from input. However, we+          // cannot allow more than one read operation at a time on the+          // underlying transport. The pending_read_ timer's expiry is set to+          // pos_infin if a read is in progress, and neg_infin otherwise.+          if (core_.expiry(core_.pending_read_) == core_.neg_infin())+          {+            // Prevent other read operations from being started.+            core_.pending_read_.expires_at(core_.pos_infin());++            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, Operation::tracking_name()));++            // Start reading some data from the underlying transport.+            next_layer_.async_read_some(+                asio::buffer(core_.input_buffer_),+                ASIO_MOVE_CAST(io_op)(*this));+          }+          else+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, Operation::tracking_name()));++            // Wait until the current read operation completes.+            core_.pending_read_.async_wait(ASIO_MOVE_CAST(io_op)(*this));+          }++          // Yield control until asynchronous operation completes. Control+          // resumes at the "default:" label below.+          return;++        case engine::want_output_and_retry:+        case engine::want_output:++          // The engine wants some data to be written to the output. However, we+          // cannot allow more than one write operation at a time on the+          // underlying transport. The pending_write_ timer's expiry is set to+          // pos_infin if a write is in progress, and neg_infin otherwise.+          if (core_.expiry(core_.pending_write_) == core_.neg_infin())+          {+            // Prevent other write operations from being started.+            core_.pending_write_.expires_at(core_.pos_infin());++            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, Operation::tracking_name()));++            // Start writing all the data to the underlying transport.+            asio::async_write(next_layer_,+                core_.engine_.get_output(core_.output_buffer_),+                ASIO_MOVE_CAST(io_op)(*this));+          }+          else+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, Operation::tracking_name()));++            // Wait until the current write operation completes.+            core_.pending_write_.async_wait(ASIO_MOVE_CAST(io_op)(*this));+          }++          // Yield control until asynchronous operation completes. Control+          // resumes at the "default:" label below.+          return;++        default:++          // The SSL operation is done and we can invoke the handler, but we+          // have to keep in mind that this function might be being called from+          // the async operation's initiating function. In this case we're not+          // allowed to call the handler directly. Instead, issue a zero-sized+          // read so the handler runs "as-if" posted using io_context::post().+          if (start)+          {+            ASIO_HANDLER_LOCATION((+                  __FILE__, __LINE__, Operation::tracking_name()));++            next_layer_.async_read_some(+                asio::buffer(core_.input_buffer_, 0),+                ASIO_MOVE_CAST(io_op)(*this));++            // Yield control until asynchronous operation completes. Control+            // resumes at the "default:" label below.+            return;+          }+          else+          {+            // Continue on to run handler directly.+            break;+          }+        }++        default:+        if (bytes_transferred == ~std::size_t(0))+          bytes_transferred = 0; // Timer cancellation, no data transferred.+        else if (!ec_)+          ec_ = ec;++        switch (want_)+        {+        case engine::want_input_and_retry:++          // Add received data to the engine's input.+          core_.input_ = asio::buffer(+              core_.input_buffer_, bytes_transferred);+          core_.input_ = core_.engine_.put_input(core_.input_);++          // Release any waiting read operations.+          core_.pending_read_.expires_at(core_.neg_infin());++          // Try the operation again.+          continue;++        case engine::want_output_and_retry:++          // Release any waiting write operations.+          core_.pending_write_.expires_at(core_.neg_infin());++          // Try the operation again.+          continue;++        case engine::want_output:++          // Release any waiting write operations.+          core_.pending_write_.expires_at(core_.neg_infin());++          // Fall through to call handler.++        default:++          // Pass the result to the handler.+          op_.call_handler(handler_,+              core_.engine_.map_error_code(ec_),+              ec_ ? 0 : bytes_transferred_);++          // Our work here is done.+          return;+        }+      } while (!ec_);++      // Operation failed. Pass the result to the handler.+      op_.call_handler(handler_, core_.engine_.map_error_code(ec_), 0);+    }+  }++//private:+  Stream& next_layer_;+  stream_core& core_;+  Operation op_;+  int start_;+  engine::want want_;+  asio::error_code ec_;+  std::size_t bytes_transferred_;+  Handler handler_;+};++template <typename Stream, typename Operation, typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    io_op<Stream, Operation, Handler>* this_handler)+{+#if defined(ASIO_NO_DEPRECATED)+  asio_handler_alloc_helpers::allocate(size, this_handler->handler_);+  return asio_handler_allocate_is_no_longer_used();+#else // defined(ASIO_NO_DEPRECATED)+  return asio_handler_alloc_helpers::allocate(+      size, this_handler->handler_);+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Stream, typename Operation, typename Handler>+inline asio_handler_deallocate_is_deprecated+asio_handler_deallocate(void* pointer, std::size_t size,+    io_op<Stream, Operation, Handler>* this_handler)+{+  asio_handler_alloc_helpers::deallocate(+      pointer, size, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_deallocate_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Stream, typename Operation, typename Handler>+inline bool asio_handler_is_continuation(+    io_op<Stream, Operation, Handler>* this_handler)+{+  return this_handler->start_ == 0 ? true+    : asio_handler_cont_helpers::is_continuation(this_handler->handler_);+}++template <typename Function, typename Stream,+    typename Operation, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(Function& function,+    io_op<Stream, Operation, Handler>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Function, typename Stream,+    typename Operation, typename Handler>+inline asio_handler_invoke_is_deprecated+asio_handler_invoke(const Function& function,+    io_op<Stream, Operation, Handler>* this_handler)+{+  asio_handler_invoke_helpers::invoke(+      function, this_handler->handler_);+#if defined(ASIO_NO_DEPRECATED)+  return asio_handler_invoke_is_no_longer_used();+#endif // defined(ASIO_NO_DEPRECATED)+}++template <typename Stream, typename Operation, typename Handler>+inline void async_io(Stream& next_layer, stream_core& core,+    const Operation& op, Handler& handler)+{+  io_op<Stream, Operation, Handler>(+    next_layer, core, op, handler)(+      asio::error_code(), 0, 1);+}++} // namespace detail+} // namespace ssl++template <typename Stream, typename Operation,+    typename Handler, typename Allocator>+struct associated_allocator<+    ssl::detail::io_op<Stream, Operation, Handler>, Allocator>+{+  typedef typename associated_allocator<Handler, Allocator>::type type;++  static type get(const ssl::detail::io_op<Stream, Operation, Handler>& h,+      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  {+    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+  }+};++template <typename Stream, typename Operation,+    typename Handler, typename Executor>+struct associated_executor<+    ssl::detail::io_op<Stream, Operation, Handler>, Executor>+{+  typedef typename associated_executor<Handler, Executor>::type type;++  static type get(const ssl::detail::io_op<Stream, Operation, Handler>& h,+      const Executor& ex = Executor()) ASIO_NOEXCEPT+  {+    return associated_executor<Handler, Executor>::get(h.handler_, ex);+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_IO_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_init.hpp view
@@ -0,0 +1,101 @@+//+// ssl/detail/openssl_init.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_OPENSSL_INIT_HPP+#define ASIO_SSL_DETAIL_OPENSSL_INIT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <cstring>+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/ssl/detail/openssl_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++class openssl_init_base+  : private noncopyable+{+protected:+  // Class that performs the actual initialisation.+  class do_init;++  // Helper function to manage a do_init singleton. The static instance of the+  // openssl_init object ensures that this function is always called before+  // main, and therefore before any other threads can get started. The do_init+  // instance must be static in this function to ensure that it gets+  // initialised before any other global objects try to use it.+  ASIO_DECL static asio::detail::shared_ptr<do_init> instance();++#if !defined(SSL_OP_NO_COMPRESSION) \+  && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+  // Get an empty stack of compression methods, to be used when disabling+  // compression.+  ASIO_DECL static STACK_OF(SSL_COMP)* get_null_compression_methods();+#endif // !defined(SSL_OP_NO_COMPRESSION)+       // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+};++template <bool Do_Init = true>+class openssl_init : private openssl_init_base+{+public:+  // Constructor.+  openssl_init()+    : ref_(instance())+  {+    using namespace std; // For memmove.++    // Ensure openssl_init::instance_ is linked in.+    openssl_init* tmp = &instance_;+    memmove(&tmp, &tmp, sizeof(openssl_init*));+  }++  // Destructor.+  ~openssl_init()+  {+  }++#if !defined(SSL_OP_NO_COMPRESSION) \+  && (OPENSSL_VERSION_NUMBER >= 0x00908000L)+  using openssl_init_base::get_null_compression_methods;+#endif // !defined(SSL_OP_NO_COMPRESSION)+       // && (OPENSSL_VERSION_NUMBER >= 0x00908000L)++private:+  // Instance to force initialisation of openssl at global scope.+  static openssl_init instance_;++  // Reference to singleton do_init object to ensure that openssl does not get+  // cleaned up until the last user has finished with it.+  asio::detail::shared_ptr<do_init> ref_;+};++template <bool Do_Init>+openssl_init<Do_Init> openssl_init<Do_Init>::instance_;++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/ssl/detail/impl/openssl_init.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_SSL_DETAIL_OPENSSL_INIT_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_types.hpp view
@@ -0,0 +1,34 @@+//+// ssl/detail/openssl_types.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_OPENSSL_TYPES_HPP+#define ASIO_SSL_DETAIL_OPENSSL_TYPES_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/socket_types.hpp"+#if defined(ASIO_USE_WOLFSSL)+# include <wolfssl/options.h>+#endif // defined(ASIO_USE_WOLFSSL)+#include <openssl/conf.h>+#include <openssl/ssl.h>+#if !defined(OPENSSL_NO_ENGINE)+# include <openssl/engine.h>+#endif // !defined(OPENSSL_NO_ENGINE)+#include <openssl/dh.h>+#include <openssl/err.h>+#include <openssl/rsa.h>+#include <openssl/x509.h>+#include <openssl/x509v3.h>++#endif // ASIO_SSL_DETAIL_OPENSSL_TYPES_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/password_callback.hpp view
@@ -0,0 +1,66 @@+//+// ssl/detail/password_callback.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_PASSWORD_CALLBACK_HPP+#define ASIO_SSL_DETAIL_PASSWORD_CALLBACK_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 <string>+#include "asio/ssl/context_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++class password_callback_base+{+public:+  virtual ~password_callback_base()+  {+  }++  virtual std::string call(std::size_t size,+      context_base::password_purpose purpose) = 0;+};++template <typename PasswordCallback>+class password_callback : public password_callback_base+{+public:+  explicit password_callback(PasswordCallback callback)+    : callback_(callback)+  {+  }++  virtual std::string call(std::size_t size,+      context_base::password_purpose purpose)+  {+    return callback_(size, purpose);+  }++private:+  PasswordCallback callback_;+};++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_PASSWORD_CALLBACK_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/read_op.hpp view
@@ -0,0 +1,72 @@+//+// ssl/detail/read_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_READ_OP_HPP+#define ASIO_SSL_DETAIL_READ_OP_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/buffer_sequence_adapter.hpp"+#include "asio/ssl/detail/engine.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++template <typename MutableBufferSequence>+class read_op+{+public:+  static ASIO_CONSTEXPR const char* tracking_name()+  {+    return "ssl::stream<>::async_read_some";+  }++  read_op(const MutableBufferSequence& buffers)+    : buffers_(buffers)+  {+  }++  engine::want operator()(engine& eng,+      asio::error_code& ec,+      std::size_t& bytes_transferred) const+  {+    asio::mutable_buffer buffer =+      asio::detail::buffer_sequence_adapter<asio::mutable_buffer,+        MutableBufferSequence>::first(buffers_);++    return eng.read(buffer, ec, bytes_transferred);+  }++  template <typename Handler>+  void call_handler(Handler& handler,+      const asio::error_code& ec,+      const std::size_t& bytes_transferred) const+  {+    handler(ec, bytes_transferred);+  }++private:+  MutableBufferSequence buffers_;+};++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_READ_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/shutdown_op.hpp view
@@ -0,0 +1,69 @@+//+// ssl/detail/shutdown_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_SHUTDOWN_OP_HPP+#define ASIO_SSL_DETAIL_SHUTDOWN_OP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/ssl/detail/engine.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++class shutdown_op+{+public:+  static ASIO_CONSTEXPR const char* tracking_name()+  {+    return "ssl::stream<>::async_shutdown";+  }++  engine::want operator()(engine& eng,+      asio::error_code& ec,+      std::size_t& bytes_transferred) const+  {+    bytes_transferred = 0;+    return eng.shutdown(ec);+  }++  template <typename Handler>+  void call_handler(Handler& handler,+      const asio::error_code& ec,+      const std::size_t&) const+  {+    if (ec == asio::error::eof)+    {+      // The engine only generates an eof when the shutdown notification has+      // been received from the peer. This indicates that the shutdown has+      // completed successfully, and thus need not be passed on to the handler.+      handler(asio::error_code());+    }+    else+    {+      handler(ec);+    }+  }+};++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_SHUTDOWN_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/stream_core.hpp view
@@ -0,0 +1,169 @@+//+// ssl/detail/stream_core.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_STREAM_CORE_HPP+#define ASIO_SSL_DETAIL_STREAM_CORE_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)+# include "asio/deadline_timer.hpp"+#else // defined(ASIO_HAS_BOOST_DATE_TIME)+# include "asio/steady_timer.hpp"+#endif // defined(ASIO_HAS_BOOST_DATE_TIME)+#include "asio/ssl/detail/engine.hpp"+#include "asio/buffer.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++struct stream_core+{+  // According to the OpenSSL documentation, this is the buffer size that is+  // sufficient to hold the largest possible TLS record.+  enum { max_tls_record_size = 17 * 1024 };++  template <typename Executor>+  stream_core(SSL_CTX* context, const Executor& ex)+    : engine_(context),+      pending_read_(ex),+      pending_write_(ex),+      output_buffer_space_(max_tls_record_size),+      output_buffer_(asio::buffer(output_buffer_space_)),+      input_buffer_space_(max_tls_record_size),+      input_buffer_(asio::buffer(input_buffer_space_))+  {+    pending_read_.expires_at(neg_infin());+    pending_write_.expires_at(neg_infin());+  }++#if defined(ASIO_HAS_MOVE)+  stream_core(stream_core&& other)+    : engine_(ASIO_MOVE_CAST(engine)(other.engine_)),+#if defined(ASIO_HAS_BOOST_DATE_TIME)+      pending_read_(+         ASIO_MOVE_CAST(asio::deadline_timer)(+           other.pending_read_)),+      pending_write_(+         ASIO_MOVE_CAST(asio::deadline_timer)(+           other.pending_write_)),+#else // defined(ASIO_HAS_BOOST_DATE_TIME)+      pending_read_(+         ASIO_MOVE_CAST(asio::steady_timer)(+           other.pending_read_)),+      pending_write_(+         ASIO_MOVE_CAST(asio::steady_timer)(+           other.pending_write_)),+#endif // defined(ASIO_HAS_BOOST_DATE_TIME)+      output_buffer_space_(+          ASIO_MOVE_CAST(std::vector<unsigned char>)(+            other.output_buffer_space_)),+      output_buffer_(other.output_buffer_),+      input_buffer_space_(+          ASIO_MOVE_CAST(std::vector<unsigned char>)(+            other.input_buffer_space_)),+      input_buffer_(other.input_buffer_),+      input_(other.input_)+  {+    other.output_buffer_ = asio::mutable_buffer(0, 0);+    other.input_buffer_ = asio::mutable_buffer(0, 0);+    other.input_ = asio::const_buffer(0, 0);+  }+#endif // defined(ASIO_HAS_MOVE)++  ~stream_core()+  {+  }++  // The SSL engine.+  engine engine_;++#if defined(ASIO_HAS_BOOST_DATE_TIME)+  // Timer used for storing queued read operations.+  asio::deadline_timer pending_read_;++  // Timer used for storing queued write operations.+  asio::deadline_timer pending_write_;++  // Helper function for obtaining a time value that always fires.+  static asio::deadline_timer::time_type neg_infin()+  {+    return boost::posix_time::neg_infin;+  }++  // Helper function for obtaining a time value that never fires.+  static asio::deadline_timer::time_type pos_infin()+  {+    return boost::posix_time::pos_infin;+  }++  // Helper function to get a timer's expiry time.+  static asio::deadline_timer::time_type expiry(+      const asio::deadline_timer& timer)+  {+    return timer.expires_at();+  }+#else // defined(ASIO_HAS_BOOST_DATE_TIME)+  // Timer used for storing queued read operations.+  asio::steady_timer pending_read_;++  // Timer used for storing queued write operations.+  asio::steady_timer pending_write_;++  // Helper function for obtaining a time value that always fires.+  static asio::steady_timer::time_point neg_infin()+  {+    return (asio::steady_timer::time_point::min)();+  }++  // Helper function for obtaining a time value that never fires.+  static asio::steady_timer::time_point pos_infin()+  {+    return (asio::steady_timer::time_point::max)();+  }++  // Helper function to get a timer's expiry time.+  static asio::steady_timer::time_point expiry(+      const asio::steady_timer& timer)+  {+    return timer.expiry();+  }+#endif // defined(ASIO_HAS_BOOST_DATE_TIME)++  // Buffer space used to prepare output intended for the transport.+  std::vector<unsigned char> output_buffer_space_;++  // A buffer that may be used to prepare output intended for the transport.+  asio::mutable_buffer output_buffer_;++  // Buffer space used to read input intended for the engine.+  std::vector<unsigned char> input_buffer_space_;++  // A buffer that may be used to read input intended for the engine.+  asio::mutable_buffer input_buffer_;++  // The buffer pointing to the engine's unconsumed input.+  asio::const_buffer input_;+};++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_STREAM_CORE_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/verify_callback.hpp view
@@ -0,0 +1,62 @@+//+// ssl/detail/verify_callback.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_VERIFY_CALLBACK_HPP+#define ASIO_SSL_DETAIL_VERIFY_CALLBACK_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/ssl/verify_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++class verify_callback_base+{+public:+  virtual ~verify_callback_base()+  {+  }++  virtual bool call(bool preverified, verify_context& ctx) = 0;+};++template <typename VerifyCallback>+class verify_callback : public verify_callback_base+{+public:+  explicit verify_callback(VerifyCallback callback)+    : callback_(callback)+  {+  }++  virtual bool call(bool preverified, verify_context& ctx)+  {+    return callback_(preverified, ctx);+  }++private:+  VerifyCallback callback_;+};++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_VERIFY_CALLBACK_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/detail/write_op.hpp view
@@ -0,0 +1,76 @@+//+// ssl/detail/write_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_DETAIL_WRITE_OP_HPP+#define ASIO_SSL_DETAIL_WRITE_OP_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/buffer_sequence_adapter.hpp"+#include "asio/ssl/detail/engine.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {+namespace detail {++template <typename ConstBufferSequence>+class write_op+{+public:+  static ASIO_CONSTEXPR const char* tracking_name()+  {+    return "ssl::stream<>::async_write_some";+  }++  write_op(const ConstBufferSequence& buffers)+    : buffers_(buffers)+  {+  }++  engine::want operator()(engine& eng,+      asio::error_code& ec,+      std::size_t& bytes_transferred) const+  {+    unsigned char storage[+      asio::detail::buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence>::linearisation_storage_size];++    asio::const_buffer buffer =+      asio::detail::buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence>::linearise(buffers_, asio::buffer(storage));++    return eng.write(buffer, ec, bytes_transferred);+  }++  template <typename Handler>+  void call_handler(Handler& handler,+      const asio::error_code& ec,+      const std::size_t& bytes_transferred) const+  {+    handler(ec, bytes_transferred);+  }++private:+  ConstBufferSequence buffers_;+};++} // namespace detail+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_DETAIL_WRITE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/error.hpp view
@@ -0,0 +1,125 @@+//+// ssl/error.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_ERROR_HPP+#define ASIO_SSL_ERROR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/error_code.hpp"+#include "asio/ssl/detail/openssl_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace error {++enum ssl_errors+{+  // Error numbers are those produced by openssl.+};++extern ASIO_DECL+const asio::error_category& get_ssl_category();++static const asio::error_category&+  ssl_category ASIO_UNUSED_VARIABLE+  = asio::error::get_ssl_category();++} // namespace error+namespace ssl {+namespace error {++enum stream_errors+{+#if defined(GENERATING_DOCUMENTATION)+  /// The underlying stream closed before the ssl stream gracefully shut down.+  stream_truncated,++  /// The underlying SSL library returned a system error without providing+  /// further information.+  unspecified_system_error,++  /// The underlying SSL library generated an unexpected result from a function+  /// call.+  unexpected_result+#else // defined(GENERATING_DOCUMENTATION)+# if (OPENSSL_VERSION_NUMBER < 0x10100000L) \+    && !defined(OPENSSL_IS_BORINGSSL) \+    && !defined(ASIO_USE_WOLFSSL)+  stream_truncated = ERR_PACK(ERR_LIB_SSL, 0, SSL_R_SHORT_READ),+# else+  stream_truncated = 1,+# endif+  unspecified_system_error = 2,+  unexpected_result = 3+#endif // defined(GENERATING_DOCUMENTATION)+};++extern ASIO_DECL+const asio::error_category& get_stream_category();++static const asio::error_category&+  stream_category ASIO_UNUSED_VARIABLE+  = asio::ssl::error::get_stream_category();++} // namespace error+} // namespace ssl+} // namespace asio++#if defined(ASIO_HAS_STD_SYSTEM_ERROR)+namespace std {++template<> struct is_error_code_enum<asio::error::ssl_errors>+{+  static const bool value = true;+};++template<> struct is_error_code_enum<asio::ssl::error::stream_errors>+{+  static const bool value = true;+};++} // namespace std+#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)++namespace asio {+namespace error {++inline asio::error_code make_error_code(ssl_errors e)+{+  return asio::error_code(+      static_cast<int>(e), get_ssl_category());+}++} // namespace error+namespace ssl {+namespace error {++inline asio::error_code make_error_code(stream_errors e)+{+  return asio::error_code(+      static_cast<int>(e), get_stream_category());+}++} // namespace error+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/ssl/impl/error.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_SSL_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/host_name_verification.hpp view
@@ -0,0 +1,90 @@+//+// ssl/host_name_verification.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_HOST_NAME_VERIFICATION_HPP+#define ASIO_SSL_HOST_NAME_VERIFICATION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <string>+#include "asio/ssl/detail/openssl_types.hpp"+#include "asio/ssl/verify_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++/// Verifies a certificate against a host_name according to the rules described+/// in RFC 6125.+/**+ * @par Example+ * The following example shows how to synchronously open a secure connection to+ * a given host name:+ * @code+ * using asio::ip::tcp;+ * namespace ssl = asio::ssl;+ * typedef ssl::stream<tcp::socket> ssl_socket;+ *+ * // Create a context that uses the default paths for finding CA certificates.+ * ssl::context ctx(ssl::context::sslv23);+ * ctx.set_default_verify_paths();+ *+ * // Open a socket and connect it to the remote host.+ * asio::io_context io_context;+ * ssl_socket sock(io_context, ctx);+ * tcp::resolver resolver(io_context);+ * tcp::resolver::query query("host.name", "https");+ * asio::connect(sock.lowest_layer(), resolver.resolve(query));+ * sock.lowest_layer().set_option(tcp::no_delay(true));+ *+ * // Perform SSL handshake and verify the remote host's certificate.+ * sock.set_verify_mode(ssl::verify_peer);+ * sock.set_verify_callback(ssl::host_name_verification("host.name"));+ * sock.handshake(ssl_socket::client);+ *+ * // ... read and write as normal ...+ * @endcode+ */+class host_name_verification+{+public:+  /// The type of the function object's result.+  typedef bool result_type;++  /// Constructor.+  explicit host_name_verification(const std::string& host)+    : host_(host)+  {+  }++  /// Perform certificate verification.+  ASIO_DECL bool operator()(bool preverified, verify_context& ctx) const;++private:+  // Helper function to check a host name against an IPv4 address+  // The host name to be checked.+  std::string host_;+};++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/ssl/impl/host_name_verification.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_SSL_HOST_NAME_VERIFICATION_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/impl/context.hpp view
@@ -0,0 +1,67 @@+//+// ssl/impl/context.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com+// Copyright (c) 2005-2020 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_SSL_IMPL_CONTEXT_HPP+#define ASIO_SSL_IMPL_CONTEXT_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/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++template <typename VerifyCallback>+void context::set_verify_callback(VerifyCallback callback)+{+  asio::error_code ec;+  this->set_verify_callback(callback, ec);+  asio::detail::throw_error(ec, "set_verify_callback");+}++template <typename VerifyCallback>+ASIO_SYNC_OP_VOID context::set_verify_callback(+    VerifyCallback callback, asio::error_code& ec)+{+  do_set_verify_callback(+      new detail::verify_callback<VerifyCallback>(callback), ec);+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++template <typename PasswordCallback>+void context::set_password_callback(PasswordCallback callback)+{+  asio::error_code ec;+  this->set_password_callback(callback, ec);+  asio::detail::throw_error(ec, "set_password_callback");+}++template <typename PasswordCallback>+ASIO_SYNC_OP_VOID context::set_password_callback(+    PasswordCallback callback, asio::error_code& ec)+{+  do_set_password_callback(+      new detail::password_callback<PasswordCallback>(callback), ec);+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_IMPL_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/impl/context.ipp view
@@ -0,0 +1,1238 @@+//+// ssl/impl/context.ipp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com+// Copyright (c) 2005-2020 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_SSL_IMPL_CONTEXT_IPP+#define ASIO_SSL_IMPL_CONTEXT_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <cstring>+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"+#include "asio/ssl/context.hpp"+#include "asio/ssl/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++struct context::bio_cleanup+{+  BIO* p;+  ~bio_cleanup() { if (p) ::BIO_free(p); }+};++struct context::x509_cleanup+{+  X509* p;+  ~x509_cleanup() { if (p) ::X509_free(p); }+};++struct context::evp_pkey_cleanup+{+  EVP_PKEY* p;+  ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); }+};++struct context::rsa_cleanup+{+  RSA* p;+  ~rsa_cleanup() { if (p) ::RSA_free(p); }+};++struct context::dh_cleanup+{+  DH* p;+  ~dh_cleanup() { if (p) ::DH_free(p); }+};++context::context(context::method m)+  : handle_(0)+{+  ::ERR_clear_error();++  switch (m)+  {+    // SSL v2.+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)+  case context::sslv2:+  case context::sslv2_client:+  case context::sslv2_server:+    asio::detail::throw_error(+        asio::error::invalid_argument, "context");+    break;+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)+  case context::sslv2:+    handle_ = ::SSL_CTX_new(::SSLv2_method());+    break;+  case context::sslv2_client:+    handle_ = ::SSL_CTX_new(::SSLv2_client_method());+    break;+  case context::sslv2_server:+    handle_ = ::SSL_CTX_new(::SSLv2_server_method());+    break;+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L) || defined(OPENSSL_NO_SSL2)++    // SSL v3.+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)+  case context::sslv3:+    handle_ = ::SSL_CTX_new(::TLS_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);+      SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);+    }+    break;+  case context::sslv3_client:+    handle_ = ::SSL_CTX_new(::TLS_client_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);+      SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);+    }+    break;+  case context::sslv3_server:+    handle_ = ::SSL_CTX_new(::TLS_server_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, SSL3_VERSION);+      SSL_CTX_set_max_proto_version(handle_, SSL3_VERSION);+    }+    break;+#elif defined(OPENSSL_NO_SSL3)+  case context::sslv3:+  case context::sslv3_client:+  case context::sslv3_server:+    asio::detail::throw_error(+        asio::error::invalid_argument, "context");+    break;+#else // defined(OPENSSL_NO_SSL3)+  case context::sslv3:+    handle_ = ::SSL_CTX_new(::SSLv3_method());+    break;+  case context::sslv3_client:+    handle_ = ::SSL_CTX_new(::SSLv3_client_method());+    break;+  case context::sslv3_server:+    handle_ = ::SSL_CTX_new(::SSLv3_server_method());+    break;+#endif // defined(OPENSSL_NO_SSL3)++    // TLS v1.0.+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)+  case context::tlsv1:+    handle_ = ::SSL_CTX_new(::TLS_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);+    }+    break;+  case context::tlsv1_client:+    handle_ = ::SSL_CTX_new(::TLS_client_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);+    }+    break;+  case context::tlsv1_server:+    handle_ = ::SSL_CTX_new(::TLS_server_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_VERSION);+    }+    break;+#elif defined(SSL_TXT_TLSV1)+  case context::tlsv1:+    handle_ = ::SSL_CTX_new(::TLSv1_method());+    break;+  case context::tlsv1_client:+    handle_ = ::SSL_CTX_new(::TLSv1_client_method());+    break;+  case context::tlsv1_server:+    handle_ = ::SSL_CTX_new(::TLSv1_server_method());+    break;+#else // defined(SSL_TXT_TLSV1)+  case context::tlsv1:+  case context::tlsv1_client:+  case context::tlsv1_server:+    asio::detail::throw_error(+        asio::error::invalid_argument, "context");+    break;+#endif // defined(SSL_TXT_TLSV1)++    // TLS v1.1.+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)+  case context::tlsv11:+    handle_ = ::SSL_CTX_new(::TLS_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);+    }+    break;+  case context::tlsv11_client:+    handle_ = ::SSL_CTX_new(::TLS_client_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);+    }+    break;+  case context::tlsv11_server:+    handle_ = ::SSL_CTX_new(::TLS_server_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_1_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_1_VERSION);+    }+    break;+#elif defined(SSL_TXT_TLSV1_1)+  case context::tlsv11:+    handle_ = ::SSL_CTX_new(::TLSv1_1_method());+    break;+  case context::tlsv11_client:+    handle_ = ::SSL_CTX_new(::TLSv1_1_client_method());+    break;+  case context::tlsv11_server:+    handle_ = ::SSL_CTX_new(::TLSv1_1_server_method());+    break;+#else // defined(SSL_TXT_TLSV1_1)+  case context::tlsv11:+  case context::tlsv11_client:+  case context::tlsv11_server:+    asio::detail::throw_error(+        asio::error::invalid_argument, "context");+    break;+#endif // defined(SSL_TXT_TLSV1_1)++    // TLS v1.2.+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)+  case context::tlsv12:+    handle_ = ::SSL_CTX_new(::TLS_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);+    }+    break;+  case context::tlsv12_client:+    handle_ = ::SSL_CTX_new(::TLS_client_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);+    }+    break;+  case context::tlsv12_server:+    handle_ = ::SSL_CTX_new(::TLS_server_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_2_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_2_VERSION);+    }+    break;+#elif defined(SSL_TXT_TLSV1_2)+  case context::tlsv12:+    handle_ = ::SSL_CTX_new(::TLSv1_2_method());+    break;+  case context::tlsv12_client:+    handle_ = ::SSL_CTX_new(::TLSv1_2_client_method());+    break;+  case context::tlsv12_server:+    handle_ = ::SSL_CTX_new(::TLSv1_2_server_method());+    break;+#else // defined(SSL_TXT_TLSV1_2)+  case context::tlsv12:+  case context::tlsv12_client:+  case context::tlsv12_server:+    asio::detail::throw_error(+        asio::error::invalid_argument, "context");+    break;+#endif // defined(SSL_TXT_TLSV1_2)++    // TLS v1.3.+#if (OPENSSL_VERSION_NUMBER >= 0x10101000L) \+    && !defined(LIBRESSL_VERSION_NUMBER)+  case context::tlsv13:+    handle_ = ::SSL_CTX_new(::TLS_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION);+    }+    break;+  case context::tlsv13_client:+    handle_ = ::SSL_CTX_new(::TLS_client_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION);+    }+    break;+  case context::tlsv13_server:+    handle_ = ::SSL_CTX_new(::TLS_server_method());+    if (handle_)+    {+      SSL_CTX_set_min_proto_version(handle_, TLS1_3_VERSION);+      SSL_CTX_set_max_proto_version(handle_, TLS1_3_VERSION);+    }+    break;+#else // (OPENSSL_VERSION_NUMBER >= 0x10101000L)+      //   && !defined(LIBRESSL_VERSION_NUMBER)+  case context::tlsv13:+  case context::tlsv13_client:+  case context::tlsv13_server:+    asio::detail::throw_error(+        asio::error::invalid_argument, "context");+    break;+#endif // (OPENSSL_VERSION_NUMBER >= 0x10101000L)+       //   && !defined(LIBRESSL_VERSION_NUMBER)++    // Any supported SSL/TLS version.+  case context::sslv23:+    handle_ = ::SSL_CTX_new(::SSLv23_method());+    break;+  case context::sslv23_client:+    handle_ = ::SSL_CTX_new(::SSLv23_client_method());+    break;+  case context::sslv23_server:+    handle_ = ::SSL_CTX_new(::SSLv23_server_method());+    break;++    // Any supported TLS version.+#if (OPENSSL_VERSION_NUMBER >= 0x10100000L) && !defined(LIBRESSL_VERSION_NUMBER)+  case context::tls:+    handle_ = ::SSL_CTX_new(::TLS_method());+    if (handle_)+      SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);+    break;+  case context::tls_client:+    handle_ = ::SSL_CTX_new(::TLS_client_method());+    if (handle_)+      SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);+    break;+  case context::tls_server:+    handle_ = ::SSL_CTX_new(::TLS_server_method());+    if (handle_)+      SSL_CTX_set_min_proto_version(handle_, TLS1_VERSION);+    break;+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+  case context::tls:+    handle_ = ::SSL_CTX_new(::SSLv23_method());+    if (handle_)+      SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);+    break;+  case context::tls_client:+    handle_ = ::SSL_CTX_new(::SSLv23_client_method());+    if (handle_)+      SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);+    break;+  case context::tls_server:+    handle_ = ::SSL_CTX_new(::SSLv23_server_method());+    if (handle_)+      SSL_CTX_set_options(handle_, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);+    break;+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)++  default:+    handle_ = ::SSL_CTX_new(0);+    break;+  }++  if (handle_ == 0)+  {+    asio::error_code ec(+        static_cast<int>(::ERR_get_error()),+        asio::error::get_ssl_category());+    asio::detail::throw_error(ec, "context");+  }++  set_options(no_compression);+}++context::context(context::native_handle_type native_handle)+  : handle_(native_handle)+{+  if (!handle_)+  {+    asio::detail::throw_error(+        asio::error::invalid_argument, "context");+  }+}++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+context::context(context&& other)+{+  handle_ = other.handle_;+  other.handle_ = 0;+}++context& context::operator=(context&& other)+{+  context tmp(ASIO_MOVE_CAST(context)(*this));+  handle_ = other.handle_;+  other.handle_ = 0;+  return *this;+}+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++context::~context()+{+  if (handle_)+  {+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \+      && !defined(LIBRESSL_VERSION_NUMBER)) \+    || defined(ASIO_USE_WOLFSSL)+    void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+    void* cb_userdata = handle_->default_passwd_callback_userdata;+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+    if (cb_userdata)+    {+      detail::password_callback_base* callback =+        static_cast<detail::password_callback_base*>(+            cb_userdata);+      delete callback;+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \+      && !defined(LIBRESSL_VERSION_NUMBER)) \+    || defined(ASIO_USE_WOLFSSL)+      ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0);+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+      handle_->default_passwd_callback_userdata = 0;+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+    }++    if (SSL_CTX_get_app_data(handle_))+    {+      detail::verify_callback_base* callback =+        static_cast<detail::verify_callback_base*>(+            SSL_CTX_get_app_data(handle_));+      delete callback;+      SSL_CTX_set_app_data(handle_, 0);+    }++    ::SSL_CTX_free(handle_);+  }+}++context::native_handle_type context::native_handle()+{+  return handle_;+}++void context::clear_options(context::options o)+{+  asio::error_code ec;+  clear_options(o, ec);+  asio::detail::throw_error(ec, "clear_options");+}++ASIO_SYNC_OP_VOID context::clear_options(+    context::options o, asio::error_code& ec)+{+#if (OPENSSL_VERSION_NUMBER >= 0x009080DFL) \+  && (OPENSSL_VERSION_NUMBER != 0x00909000L)+# if !defined(SSL_OP_NO_COMPRESSION)+  if ((o & context::no_compression) != 0)+  {+# if (OPENSSL_VERSION_NUMBER >= 0x00908000L)+    handle_->comp_methods = SSL_COMP_get_compression_methods();+# endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)+    o ^= context::no_compression;+  }+# endif // !defined(SSL_OP_NO_COMPRESSION)++  ::SSL_CTX_clear_options(handle_, o);++  ec = asio::error_code();+#else // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)+      //   && (OPENSSL_VERSION_NUMBER != 0x00909000L)+  (void)o;+  ec = asio::error::operation_not_supported;+#endif // (OPENSSL_VERSION_NUMBER >= 0x009080DFL)+       //   && (OPENSSL_VERSION_NUMBER != 0x00909000L)+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::set_options(context::options o)+{+  asio::error_code ec;+  set_options(o, ec);+  asio::detail::throw_error(ec, "set_options");+}++ASIO_SYNC_OP_VOID context::set_options(+    context::options o, asio::error_code& ec)+{+#if !defined(SSL_OP_NO_COMPRESSION)+  if ((o & context::no_compression) != 0)+  {+#if (OPENSSL_VERSION_NUMBER >= 0x00908000L)+    handle_->comp_methods =+      asio::ssl::detail::openssl_init<>::get_null_compression_methods();+#endif // (OPENSSL_VERSION_NUMBER >= 0x00908000L)+    o ^= context::no_compression;+  }+#endif // !defined(SSL_OP_NO_COMPRESSION)++  ::SSL_CTX_set_options(handle_, o);++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::set_verify_mode(verify_mode v)+{+  asio::error_code ec;+  set_verify_mode(v, ec);+  asio::detail::throw_error(ec, "set_verify_mode");+}++ASIO_SYNC_OP_VOID context::set_verify_mode(+    verify_mode v, asio::error_code& ec)+{+  ::SSL_CTX_set_verify(handle_, v, ::SSL_CTX_get_verify_callback(handle_));++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::set_verify_depth(int depth)+{+  asio::error_code ec;+  set_verify_depth(depth, ec);+  asio::detail::throw_error(ec, "set_verify_depth");+}++ASIO_SYNC_OP_VOID context::set_verify_depth(+    int depth, asio::error_code& ec)+{+  ::SSL_CTX_set_verify_depth(handle_, depth);++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::load_verify_file(const std::string& filename)+{+  asio::error_code ec;+  load_verify_file(filename, ec);+  asio::detail::throw_error(ec, "load_verify_file");+}++ASIO_SYNC_OP_VOID context::load_verify_file(+    const std::string& filename, asio::error_code& ec)+{+  ::ERR_clear_error();++  if (::SSL_CTX_load_verify_locations(handle_, filename.c_str(), 0) != 1)+  {+    ec = asio::error_code(+        static_cast<int>(::ERR_get_error()),+        asio::error::get_ssl_category());+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::add_certificate_authority(const const_buffer& ca)+{+  asio::error_code ec;+  add_certificate_authority(ca, ec);+  asio::detail::throw_error(ec, "add_certificate_authority");+}++ASIO_SYNC_OP_VOID context::add_certificate_authority(+    const const_buffer& ca, asio::error_code& ec)+{+  ::ERR_clear_error();++  bio_cleanup bio = { make_buffer_bio(ca) };+  if (bio.p)+  {+    if (X509_STORE* store = ::SSL_CTX_get_cert_store(handle_))+    {+      for (bool added = false;; added = true)+      {+        x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };+        if (!cert.p)+        {+          unsigned long err = ::ERR_get_error();+          if (added && ERR_GET_LIB(err) == ERR_LIB_PEM+              && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)+            break;++          ec = asio::error_code(+              static_cast<int>(err),+              asio::error::get_ssl_category());+          ASIO_SYNC_OP_VOID_RETURN(ec);+        }++        if (::X509_STORE_add_cert(store, cert.p) != 1)+        {+          ec = asio::error_code(+              static_cast<int>(::ERR_get_error()),+              asio::error::get_ssl_category());+          ASIO_SYNC_OP_VOID_RETURN(ec);+        }+      }+    }+  }++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::set_default_verify_paths()+{+  asio::error_code ec;+  set_default_verify_paths(ec);+  asio::detail::throw_error(ec, "set_default_verify_paths");+}++ASIO_SYNC_OP_VOID context::set_default_verify_paths(+    asio::error_code& ec)+{+  ::ERR_clear_error();++  if (::SSL_CTX_set_default_verify_paths(handle_) != 1)+  {+    ec = asio::error_code(+        static_cast<int>(::ERR_get_error()),+        asio::error::get_ssl_category());+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::add_verify_path(const std::string& path)+{+  asio::error_code ec;+  add_verify_path(path, ec);+  asio::detail::throw_error(ec, "add_verify_path");+}++ASIO_SYNC_OP_VOID context::add_verify_path(+    const std::string& path, asio::error_code& ec)+{+  ::ERR_clear_error();++  if (::SSL_CTX_load_verify_locations(handle_, 0, path.c_str()) != 1)+  {+    ec = asio::error_code(+        static_cast<int>(::ERR_get_error()),+        asio::error::get_ssl_category());+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::use_certificate(+    const const_buffer& certificate, file_format format)+{+  asio::error_code ec;+  use_certificate(certificate, format, ec);+  asio::detail::throw_error(ec, "use_certificate");+}++ASIO_SYNC_OP_VOID context::use_certificate(+    const const_buffer& certificate, file_format format,+    asio::error_code& ec)+{+  ::ERR_clear_error();++  if (format == context_base::asn1)+  {+    if (::SSL_CTX_use_certificate_ASN1(handle_,+          static_cast<int>(certificate.size()),+          static_cast<const unsigned char*>(certificate.data())) == 1)+    {+      ec = asio::error_code();+      ASIO_SYNC_OP_VOID_RETURN(ec);+    }+  }+  else if (format == context_base::pem)+  {+    bio_cleanup bio = { make_buffer_bio(certificate) };+    if (bio.p)+    {+      x509_cleanup cert = { ::PEM_read_bio_X509(bio.p, 0, 0, 0) };+      if (cert.p)+      {+        if (::SSL_CTX_use_certificate(handle_, cert.p) == 1)+        {+          ec = asio::error_code();+          ASIO_SYNC_OP_VOID_RETURN(ec);+        }+      }+    }+  }+  else+  {+    ec = asio::error::invalid_argument;+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ec = asio::error_code(+      static_cast<int>(::ERR_get_error()),+      asio::error::get_ssl_category());+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::use_certificate_file(+    const std::string& filename, file_format format)+{+  asio::error_code ec;+  use_certificate_file(filename, format, ec);+  asio::detail::throw_error(ec, "use_certificate_file");+}++ASIO_SYNC_OP_VOID context::use_certificate_file(+    const std::string& filename, file_format format,+    asio::error_code& ec)+{+  int file_type;+  switch (format)+  {+  case context_base::asn1:+    file_type = SSL_FILETYPE_ASN1;+    break;+  case context_base::pem:+    file_type = SSL_FILETYPE_PEM;+    break;+  default:+    {+      ec = asio::error::invalid_argument;+      ASIO_SYNC_OP_VOID_RETURN(ec);+    }+  }++  ::ERR_clear_error();++  if (::SSL_CTX_use_certificate_file(handle_, filename.c_str(), file_type) != 1)+  {+    ec = asio::error_code(+        static_cast<int>(::ERR_get_error()),+        asio::error::get_ssl_category());+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::use_certificate_chain(const const_buffer& chain)+{+  asio::error_code ec;+  use_certificate_chain(chain, ec);+  asio::detail::throw_error(ec, "use_certificate_chain");+}++ASIO_SYNC_OP_VOID context::use_certificate_chain(+    const const_buffer& chain, asio::error_code& ec)+{+  ::ERR_clear_error();++  bio_cleanup bio = { make_buffer_bio(chain) };+  if (bio.p)+  {+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \+      && !defined(LIBRESSL_VERSION_NUMBER)) \+    || defined(ASIO_USE_WOLFSSL)+    pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);+    void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+    pem_password_cb* callback = handle_->default_passwd_callback;+    void* cb_userdata = handle_->default_passwd_callback_userdata;+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+    x509_cleanup cert = {+      ::PEM_read_bio_X509_AUX(bio.p, 0,+          callback,+          cb_userdata) };+    if (!cert.p)+    {+      ec = asio::error_code(ERR_R_PEM_LIB,+          asio::error::get_ssl_category());+      ASIO_SYNC_OP_VOID_RETURN(ec);+    }++    int result = ::SSL_CTX_use_certificate(handle_, cert.p);+    if (result == 0 || ::ERR_peek_error() != 0)+    {+      ec = asio::error_code(+          static_cast<int>(::ERR_get_error()),+          asio::error::get_ssl_category());+      ASIO_SYNC_OP_VOID_RETURN(ec);+    }++#if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) \+      && !defined(LIBRESSL_VERSION_NUMBER)) \+    || defined(ASIO_USE_WOLFSSL)+    ::SSL_CTX_clear_chain_certs(handle_);+#else+    if (handle_->extra_certs)+    {+      ::sk_X509_pop_free(handle_->extra_certs, X509_free);+      handle_->extra_certs = 0;+    }+#endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)++    while (X509* cacert = ::PEM_read_bio_X509(bio.p, 0,+          callback,+          cb_userdata))+    {+      if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))+      {+        ec = asio::error_code(+            static_cast<int>(::ERR_get_error()),+            asio::error::get_ssl_category());+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }+    }+  +    result = ::ERR_peek_last_error();+    if ((ERR_GET_LIB(result) == ERR_LIB_PEM)+        && (ERR_GET_REASON(result) == PEM_R_NO_START_LINE))+    {+      ::ERR_clear_error();+      ec = asio::error_code();+      ASIO_SYNC_OP_VOID_RETURN(ec);+    }+  }++  ec = asio::error_code(+      static_cast<int>(::ERR_get_error()),+      asio::error::get_ssl_category());+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::use_certificate_chain_file(const std::string& filename)+{+  asio::error_code ec;+  use_certificate_chain_file(filename, ec);+  asio::detail::throw_error(ec, "use_certificate_chain_file");+}++ASIO_SYNC_OP_VOID context::use_certificate_chain_file(+    const std::string& filename, asio::error_code& ec)+{+  ::ERR_clear_error();++  if (::SSL_CTX_use_certificate_chain_file(handle_, filename.c_str()) != 1)+  {+    ec = asio::error_code(+        static_cast<int>(::ERR_get_error()),+        asio::error::get_ssl_category());+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::use_private_key(+    const const_buffer& private_key, context::file_format format)+{+  asio::error_code ec;+  use_private_key(private_key, format, ec);+  asio::detail::throw_error(ec, "use_private_key");+}++ASIO_SYNC_OP_VOID context::use_private_key(+    const const_buffer& private_key, context::file_format format,+    asio::error_code& ec)+{+  ::ERR_clear_error();++#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \+      && !defined(LIBRESSL_VERSION_NUMBER)) \+    || defined(ASIO_USE_WOLFSSL)+    pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);+    void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+    pem_password_cb* callback = handle_->default_passwd_callback;+    void* cb_userdata = handle_->default_passwd_callback_userdata;+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)++  bio_cleanup bio = { make_buffer_bio(private_key) };+  if (bio.p)+  {+    evp_pkey_cleanup evp_private_key = { 0 };+    switch (format)+    {+    case context_base::asn1:+      evp_private_key.p = ::d2i_PrivateKey_bio(bio.p, 0);+      break;+    case context_base::pem:+      evp_private_key.p = ::PEM_read_bio_PrivateKey(+          bio.p, 0, callback,+          cb_userdata);+      break;+    default:+      {+        ec = asio::error::invalid_argument;+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }+    }++    if (evp_private_key.p)+    {+      if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)+      {+        ec = asio::error_code();+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }+    }+  }++  ec = asio::error_code(+      static_cast<int>(::ERR_get_error()),+      asio::error::get_ssl_category());+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::use_private_key_file(+    const std::string& filename, context::file_format format)+{+  asio::error_code ec;+  use_private_key_file(filename, format, ec);+  asio::detail::throw_error(ec, "use_private_key_file");+}++void context::use_rsa_private_key(+    const const_buffer& private_key, context::file_format format)+{+  asio::error_code ec;+  use_rsa_private_key(private_key, format, ec);+  asio::detail::throw_error(ec, "use_rsa_private_key");+}++ASIO_SYNC_OP_VOID context::use_rsa_private_key(+    const const_buffer& private_key, context::file_format format,+    asio::error_code& ec)+{+  ::ERR_clear_error();++#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \+      && !defined(LIBRESSL_VERSION_NUMBER)) \+    || defined(ASIO_USE_WOLFSSL)+    pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);+    void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+    pem_password_cb* callback = handle_->default_passwd_callback;+    void* cb_userdata = handle_->default_passwd_callback_userdata;+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)++  bio_cleanup bio = { make_buffer_bio(private_key) };+  if (bio.p)+  {+    rsa_cleanup rsa_private_key = { 0 };+    switch (format)+    {+    case context_base::asn1:+      rsa_private_key.p = ::d2i_RSAPrivateKey_bio(bio.p, 0);+      break;+    case context_base::pem:+      rsa_private_key.p = ::PEM_read_bio_RSAPrivateKey(+          bio.p, 0, callback,+          cb_userdata);+      break;+    default:+      {+        ec = asio::error::invalid_argument;+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }+    }++    if (rsa_private_key.p)+    {+      if (::SSL_CTX_use_RSAPrivateKey(handle_, rsa_private_key.p) == 1)+      {+        ec = asio::error_code();+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }+    }+  }++  ec = asio::error_code(+      static_cast<int>(::ERR_get_error()),+      asio::error::get_ssl_category());+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++ASIO_SYNC_OP_VOID context::use_private_key_file(+    const std::string& filename, context::file_format format,+    asio::error_code& ec)+{+  int file_type;+  switch (format)+  {+  case context_base::asn1:+    file_type = SSL_FILETYPE_ASN1;+    break;+  case context_base::pem:+    file_type = SSL_FILETYPE_PEM;+    break;+  default:+    {+      ec = asio::error::invalid_argument;+      ASIO_SYNC_OP_VOID_RETURN(ec);+    }+  }++  ::ERR_clear_error();++  if (::SSL_CTX_use_PrivateKey_file(handle_, filename.c_str(), file_type) != 1)+  {+    ec = asio::error_code(+        static_cast<int>(::ERR_get_error()),+        asio::error::get_ssl_category());+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::use_rsa_private_key_file(+    const std::string& filename, context::file_format format)+{+  asio::error_code ec;+  use_rsa_private_key_file(filename, format, ec);+  asio::detail::throw_error(ec, "use_rsa_private_key_file");+}++ASIO_SYNC_OP_VOID context::use_rsa_private_key_file(+    const std::string& filename, context::file_format format,+    asio::error_code& ec)+{+  int file_type;+  switch (format)+  {+  case context_base::asn1:+    file_type = SSL_FILETYPE_ASN1;+    break;+  case context_base::pem:+    file_type = SSL_FILETYPE_PEM;+    break;+  default:+    {+      ec = asio::error::invalid_argument;+      ASIO_SYNC_OP_VOID_RETURN(ec);+    }+  }++  ::ERR_clear_error();++  if (::SSL_CTX_use_RSAPrivateKey_file(+        handle_, filename.c_str(), file_type) != 1)+  {+    ec = asio::error_code(+        static_cast<int>(::ERR_get_error()),+        asio::error::get_ssl_category());+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::use_tmp_dh(const const_buffer& dh)+{+  asio::error_code ec;+  use_tmp_dh(dh, ec);+  asio::detail::throw_error(ec, "use_tmp_dh");+}++ASIO_SYNC_OP_VOID context::use_tmp_dh(+    const const_buffer& dh, asio::error_code& ec)+{+  ::ERR_clear_error();++  bio_cleanup bio = { make_buffer_bio(dh) };+  if (bio.p)+  {+    return do_use_tmp_dh(bio.p, ec);+  }++  ec = asio::error_code(+      static_cast<int>(::ERR_get_error()),+      asio::error::get_ssl_category());+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++void context::use_tmp_dh_file(const std::string& filename)+{+  asio::error_code ec;+  use_tmp_dh_file(filename, ec);+  asio::detail::throw_error(ec, "use_tmp_dh_file");+}++ASIO_SYNC_OP_VOID context::use_tmp_dh_file(+    const std::string& filename, asio::error_code& ec)+{+  ::ERR_clear_error();++  bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };+  if (bio.p)+  {+    return do_use_tmp_dh(bio.p, ec);+  }++  ec = asio::error_code(+      static_cast<int>(::ERR_get_error()),+      asio::error::get_ssl_category());+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++ASIO_SYNC_OP_VOID context::do_use_tmp_dh(+    BIO* bio, asio::error_code& ec)+{+  ::ERR_clear_error();++  dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };+  if (dh.p)+  {+    if (::SSL_CTX_set_tmp_dh(handle_, dh.p) == 1)+    {+      ec = asio::error_code();+      ASIO_SYNC_OP_VOID_RETURN(ec);+    }+  }++  ec = asio::error_code(+      static_cast<int>(::ERR_get_error()),+      asio::error::get_ssl_category());+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++ASIO_SYNC_OP_VOID context::do_set_verify_callback(+    detail::verify_callback_base* callback, asio::error_code& ec)+{+  if (SSL_CTX_get_app_data(handle_))+  {+    delete static_cast<detail::verify_callback_base*>(+        SSL_CTX_get_app_data(handle_));+  }++  SSL_CTX_set_app_data(handle_, callback);++  ::SSL_CTX_set_verify(handle_,+      ::SSL_CTX_get_verify_mode(handle_),+      &context::verify_callback_function);++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++int context::verify_callback_function(int preverified, X509_STORE_CTX* ctx)+{+  if (ctx)+  {+    if (SSL* ssl = static_cast<SSL*>(+          ::X509_STORE_CTX_get_ex_data(+            ctx, ::SSL_get_ex_data_X509_STORE_CTX_idx())))+    {+      if (SSL_CTX* handle = ::SSL_get_SSL_CTX(ssl))+      {+        if (SSL_CTX_get_app_data(handle))+        {+          detail::verify_callback_base* callback =+            static_cast<detail::verify_callback_base*>(+                SSL_CTX_get_app_data(handle));++          verify_context verify_ctx(ctx);+          return callback->call(preverified != 0, verify_ctx) ? 1 : 0;+        }+      }+    }+  }++  return 0;+}++ASIO_SYNC_OP_VOID context::do_set_password_callback(+    detail::password_callback_base* callback, asio::error_code& ec)+{+#if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \+      && !defined(LIBRESSL_VERSION_NUMBER)) \+    || defined(ASIO_USE_WOLFSSL)+  void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);+  ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);+#else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)+  void* old_callback = handle_->default_passwd_callback_userdata;+  handle_->default_passwd_callback_userdata = callback;+#endif // (OPENSSL_VERSION_NUMBER >= 0x10100000L)++  if (old_callback)+    delete static_cast<detail::password_callback_base*>(+        old_callback);++  SSL_CTX_set_default_passwd_cb(handle_, &context::password_callback_function);++  ec = asio::error_code();+  ASIO_SYNC_OP_VOID_RETURN(ec);+}++int context::password_callback_function(+    char* buf, int size, int purpose, void* data)+{+  using namespace std; // For strncat and strlen.++  if (data)+  {+    detail::password_callback_base* callback =+      static_cast<detail::password_callback_base*>(data);++    std::string passwd = callback->call(static_cast<std::size_t>(size),+        purpose ? context_base::for_writing : context_base::for_reading);++#if defined(ASIO_HAS_SECURE_RTL)+    strcpy_s(buf, size, passwd.c_str());+#else // defined(ASIO_HAS_SECURE_RTL)+    *buf = '\0';+    if (size > 0)+      strncat(buf, passwd.c_str(), size - 1);+#endif // defined(ASIO_HAS_SECURE_RTL)++    return static_cast<int>(strlen(buf));+  }++  return 0;+}++BIO* context::make_buffer_bio(const const_buffer& b)+{+  return ::BIO_new_mem_buf(+      const_cast<void*>(b.data()),+      static_cast<int>(b.size()));+}++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_IMPL_CONTEXT_IPP
+ link/modules/asio-standalone/asio/include/asio/ssl/impl/error.ipp view
@@ -0,0 +1,102 @@+//+// ssl/impl/error.ipp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_IMPL_ERROR_IPP+#define ASIO_SSL_IMPL_ERROR_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/ssl/error.hpp"+#include "asio/ssl/detail/openssl_init.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace error {+namespace detail {++class ssl_category : public asio::error_category+{+public:+  const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT+  {+    return "asio.ssl";+  }++  std::string message(int value) const+  {+    const char* s = ::ERR_reason_error_string(value);+    return s ? s : "asio.ssl error";+  }+};++} // namespace detail++const asio::error_category& get_ssl_category()+{+  static detail::ssl_category instance;+  return instance;+}++} // namespace error+namespace ssl {+namespace error {++#if (OPENSSL_VERSION_NUMBER < 0x10100000L) && !defined(OPENSSL_IS_BORINGSSL)++const asio::error_category& get_stream_category()+{+  return asio::error::get_ssl_category();+}++#else++namespace detail {++class stream_category : public asio::error_category+{+public:+  const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT+  {+    return "asio.ssl.stream";+  }++  std::string message(int value) const+  {+    switch (value)+    {+    case stream_truncated: return "stream truncated";+    case unspecified_system_error: return "unspecified system error";+    case unexpected_result: return "unexpected result";+    default: return "asio.ssl.stream error";+    }+  }+};++} // namespace detail++const asio::error_category& get_stream_category()+{+  static detail::stream_category instance;+  return instance;+}++#endif++} // namespace error+} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_IMPL_ERROR_IPP
+ link/modules/asio-standalone/asio/include/asio/ssl/impl/host_name_verification.ipp view
@@ -0,0 +1,73 @@+//+// ssl/impl/host_name_verification.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_IMPL_HOST_NAME_VERIFICATION_IPP+#define ASIO_SSL_IMPL_HOST_NAME_VERIFICATION_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include <cctype>+#include <cstring>+#include "asio/ip/address.hpp"+#include "asio/ssl/host_name_verification.hpp"+#include "asio/ssl/detail/openssl_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++bool host_name_verification::operator()(+    bool preverified, verify_context& ctx) const+{+  using namespace std; // For memcmp.++  // Don't bother looking at certificates that have failed pre-verification.+  if (!preverified)+    return false;++  // We're only interested in checking the certificate at the end of the chain.+  int depth = X509_STORE_CTX_get_error_depth(ctx.native_handle());+  if (depth > 0)+    return true;++  // Try converting the host name to an address. If it is an address then we+  // need to look for an IP address in the certificate rather than a host name.+  asio::error_code ec;+  ip::address address = ip::make_address(host_, ec);+  const bool is_address = !ec;+  (void)address;++  X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());++  if (is_address)+  {+    return X509_check_ip_asc(cert, host_.c_str(), 0) == 1;+  }+  else+  {+    char* peername = 0;+    const int result = X509_check_host(cert,+        host_.c_str(), host_.size(), 0, &peername);+    OPENSSL_free(peername);+    return result == 1;+  }+}++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_IMPL_HOST_NAME_VERIFICATION_IPP
+ link/modules/asio-standalone/asio/include/asio/ssl/impl/rfc2818_verification.ipp view
@@ -0,0 +1,164 @@+//+// ssl/impl/rfc2818_verification.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_IMPL_RFC2818_VERIFICATION_IPP+#define ASIO_SSL_IMPL_RFC2818_VERIFICATION_IPP++#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_DEPRECATED)++#include <cctype>+#include <cstring>+#include "asio/ip/address.hpp"+#include "asio/ssl/rfc2818_verification.hpp"+#include "asio/ssl/detail/openssl_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++bool rfc2818_verification::operator()(+    bool preverified, verify_context& ctx) const+{+  using namespace std; // For memcmp.++  // Don't bother looking at certificates that have failed pre-verification.+  if (!preverified)+    return false;++  // We're only interested in checking the certificate at the end of the chain.+  int depth = X509_STORE_CTX_get_error_depth(ctx.native_handle());+  if (depth > 0)+    return true;++  // Try converting the host name to an address. If it is an address then we+  // need to look for an IP address in the certificate rather than a host name.+  asio::error_code ec;+  ip::address address = ip::make_address(host_, ec);+  bool is_address = !ec;++  X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());++  // Go through the alternate names in the certificate looking for matching DNS+  // or IP address entries.+  GENERAL_NAMES* gens = static_cast<GENERAL_NAMES*>(+      X509_get_ext_d2i(cert, NID_subject_alt_name, 0, 0));+  for (int i = 0; i < sk_GENERAL_NAME_num(gens); ++i)+  {+    GENERAL_NAME* gen = sk_GENERAL_NAME_value(gens, i);+    if (gen->type == GEN_DNS && !is_address)+    {+      ASN1_IA5STRING* domain = gen->d.dNSName;+      if (domain->type == V_ASN1_IA5STRING && domain->data && domain->length)+      {+        const char* pattern = reinterpret_cast<const char*>(domain->data);+        std::size_t pattern_length = domain->length;+        if (match_pattern(pattern, pattern_length, host_.c_str()))+        {+          GENERAL_NAMES_free(gens);+          return true;+        }+      }+    }+    else if (gen->type == GEN_IPADD && is_address)+    {+      ASN1_OCTET_STRING* ip_address = gen->d.iPAddress;+      if (ip_address->type == V_ASN1_OCTET_STRING && ip_address->data)+      {+        if (address.is_v4() && ip_address->length == 4)+        {+          ip::address_v4::bytes_type bytes = address.to_v4().to_bytes();+          if (memcmp(bytes.data(), ip_address->data, 4) == 0)+          {+            GENERAL_NAMES_free(gens);+            return true;+          }+        }+        else if (address.is_v6() && ip_address->length == 16)+        {+          ip::address_v6::bytes_type bytes = address.to_v6().to_bytes();+          if (memcmp(bytes.data(), ip_address->data, 16) == 0)+          {+            GENERAL_NAMES_free(gens);+            return true;+          }+        }+      }+    }+  }+  GENERAL_NAMES_free(gens);++  // No match in the alternate names, so try the common names. We should only+  // use the "most specific" common name, which is the last one in the list.+  X509_NAME* name = X509_get_subject_name(cert);+  int i = -1;+  ASN1_STRING* common_name = 0;+  while ((i = X509_NAME_get_index_by_NID(name, NID_commonName, i)) >= 0)+  {+    X509_NAME_ENTRY* name_entry = X509_NAME_get_entry(name, i);+    common_name = X509_NAME_ENTRY_get_data(name_entry);+  }+  if (common_name && common_name->data && common_name->length)+  {+    const char* pattern = reinterpret_cast<const char*>(common_name->data);+    std::size_t pattern_length = common_name->length;+    if (match_pattern(pattern, pattern_length, host_.c_str()))+      return true;+  }++  return false;+}++bool rfc2818_verification::match_pattern(const char* pattern,+    std::size_t pattern_length, const char* host)+{+  using namespace std; // For tolower.++  const char* p = pattern;+  const char* p_end = p + pattern_length;+  const char* h = host;++  while (p != p_end && *h)+  {+    if (*p == '*')+    {+      ++p;+      while (*h && *h != '.')+        if (match_pattern(p, p_end - p, h++))+          return true;+    }+    else if (tolower(*p) == tolower(*h))+    {+      ++p;+      ++h;+    }+    else+    {+      return false;+    }+  }++  return p == p_end && !*h;+}++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)++#endif // ASIO_SSL_IMPL_RFC2818_VERIFICATION_IPP
+ link/modules/asio-standalone/asio/include/asio/ssl/impl/src.hpp view
@@ -0,0 +1,29 @@+//+// impl/ssl/src.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_IMPL_SRC_HPP+#define ASIO_SSL_IMPL_SRC_HPP++#define ASIO_SOURCE++#include "asio/detail/config.hpp"++#if defined(ASIO_HEADER_ONLY)+# error Do not compile Asio library source with ASIO_HEADER_ONLY defined+#endif++#include "asio/ssl/impl/context.ipp"+#include "asio/ssl/impl/error.ipp"+#include "asio/ssl/detail/impl/engine.ipp"+#include "asio/ssl/detail/impl/openssl_init.ipp"+#include "asio/ssl/impl/host_name_verification.ipp"+#include "asio/ssl/impl/rfc2818_verification.ipp"++#endif // ASIO_SSL_IMPL_SRC_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/rfc2818_verification.hpp view
@@ -0,0 +1,98 @@+//+// ssl/rfc2818_verification.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_RFC2818_VERIFICATION_HPP+#define ASIO_SSL_RFC2818_VERIFICATION_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_DEPRECATED)++#include <string>+#include "asio/ssl/detail/openssl_types.hpp"+#include "asio/ssl/verify_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++/// (Deprecated. Use ssl::host_name_verification.) Verifies a certificate+/// against a hostname according to the rules described in RFC 2818.+/**+ * @par Example+ * The following example shows how to synchronously open a secure connection to+ * a given host name:+ * @code+ * using asio::ip::tcp;+ * namespace ssl = asio::ssl;+ * typedef ssl::stream<tcp::socket> ssl_socket;+ *+ * // Create a context that uses the default paths for finding CA certificates.+ * ssl::context ctx(ssl::context::sslv23);+ * ctx.set_default_verify_paths();+ *+ * // Open a socket and connect it to the remote host.+ * asio::io_context io_context;+ * ssl_socket sock(io_context, ctx);+ * tcp::resolver resolver(io_context);+ * tcp::resolver::query query("host.name", "https");+ * asio::connect(sock.lowest_layer(), resolver.resolve(query));+ * sock.lowest_layer().set_option(tcp::no_delay(true));+ *+ * // Perform SSL handshake and verify the remote host's certificate.+ * sock.set_verify_mode(ssl::verify_peer);+ * sock.set_verify_callback(ssl::rfc2818_verification("host.name"));+ * sock.handshake(ssl_socket::client);+ *+ * // ... read and write as normal ...+ * @endcode+ */+class rfc2818_verification+{+public:+  /// The type of the function object's result.+  typedef bool result_type;++  /// Constructor.+  explicit rfc2818_verification(const std::string& host)+    : host_(host)+  {+  }++  /// Perform certificate verification.+  ASIO_DECL bool operator()(bool preverified, verify_context& ctx) const;++private:+  // Helper function to check a host name against a pattern.+  ASIO_DECL static bool match_pattern(const char* pattern,+      std::size_t pattern_length, const char* host);++  // Helper function to check a host name against an IPv4 address+  // The host name to be checked.+  std::string host_;+};++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/ssl/impl/rfc2818_verification.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // !defined(ASIO_NO_DEPRECATED)++#endif // ASIO_SSL_RFC2818_VERIFICATION_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/stream.hpp view
@@ -0,0 +1,900 @@+//+// ssl/stream.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_STREAM_HPP+#define ASIO_SSL_STREAM_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/buffer_sequence_adapter.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/ssl/context.hpp"+#include "asio/ssl/detail/buffered_handshake_op.hpp"+#include "asio/ssl/detail/handshake_op.hpp"+#include "asio/ssl/detail/io.hpp"+#include "asio/ssl/detail/read_op.hpp"+#include "asio/ssl/detail/shutdown_op.hpp"+#include "asio/ssl/detail/stream_core.hpp"+#include "asio/ssl/detail/write_op.hpp"+#include "asio/ssl/stream_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++/// Provides stream-oriented functionality using SSL.+/**+ * The stream class template provides asynchronous and blocking stream-oriented+ * functionality using SSL.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe. The application must also ensure that all+ * asynchronous operations are performed within the same implicit or explicit+ * strand.+ *+ * @par Example+ * To use the SSL stream template with an ip::tcp::socket, you would write:+ * @code+ * asio::io_context my_context;+ * asio::ssl::context ctx(asio::ssl::context::sslv23);+ * asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx);+ * @endcode+ *+ * @par Concepts:+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.+ */+template <typename Stream>+class stream :+  public stream_base,+  private noncopyable+{+public:+  /// The native handle type of the SSL stream.+  typedef SSL* native_handle_type;++  /// Structure for use with deprecated impl_type.+  struct impl_struct+  {+    SSL* ssl;+  };++  /// 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(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Construct a stream.+  /**+   * This constructor creates a stream and initialises the underlying stream+   * object.+   *+   * @param arg The argument to be passed to initialise the underlying stream.+   *+   * @param ctx The SSL context to be used for the stream.+   */+  template <typename Arg>+  stream(Arg&& arg, context& ctx)+    : next_layer_(ASIO_MOVE_CAST(Arg)(arg)),+      core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor())+  {+  }+#else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  template <typename Arg>+  stream(Arg& arg, context& ctx)+    : next_layer_(arg),+      core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor())+  {+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a stream from another.+  /**+   * @param other The other stream object from which the move will occur. Must+   * have no outstanding asynchronous operations associated with it. Following+   * the move, @c other has a valid but unspecified state where the only safe+   * operation is destruction.+   */+  stream(stream&& other)+    : next_layer_(ASIO_MOVE_CAST(Stream)(other.next_layer_)),+      core_(ASIO_MOVE_CAST(detail::stream_core)(other.core_))+  {+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  /**+   * @note A @c stream object must not be destroyed while there are pending+   * asynchronous operations associated with it.+   */+  ~stream()+  {+  }++  /// Get the executor associated with the object.+  /**+   * This function may be used to obtain the executor object that the stream+   * uses to dispatch handlers for asynchronous operations.+   *+   * @return A copy of the executor that stream will use to dispatch handlers.+   */+  executor_type get_executor() ASIO_NOEXCEPT+  {+    return next_layer_.lowest_layer().get_executor();+  }++  /// Get the underlying implementation in the native type.+  /**+   * This function may be used to obtain the underlying implementation of the+   * context. This is intended to allow access to context functionality that is+   * not otherwise provided.+   *+   * @par Example+   * The native_handle() function returns a pointer of type @c SSL* that is+   * suitable for passing to functions such as @c SSL_get_verify_result and+   * @c SSL_get_peer_certificate:+   * @code+   * asio::ssl::stream<asio:ip::tcp::socket> sock(my_context, ctx);+   *+   * // ... establish connection and perform handshake ...+   *+   * if (X509* cert = SSL_get_peer_certificate(sock.native_handle()))+   * {+   *   if (SSL_get_verify_result(sock.native_handle()) == X509_V_OK)+   *   {+   *     // ...+   *   }+   * }+   * @endcode+   */+  native_handle_type native_handle()+  {+    return core_.engine_.native_handle();+  }++  /// Get a reference to the next layer.+  /**+   * This function returns a reference to the next layer in a stack of stream+   * layers.+   *+   * @return A reference to the next layer in the stack of stream layers.+   * Ownership is not transferred to the caller.+   */+  const next_layer_type& next_layer() const+  {+    return next_layer_;+  }++  /// Get a reference to the next layer.+  /**+   * This function returns a reference to the next layer in a stack of stream+   * layers.+   *+   * @return A reference to the next layer in the stack of stream layers.+   * Ownership is not transferred to the caller.+   */+  next_layer_type& next_layer()+  {+    return next_layer_;+  }++  /// Get a reference to the lowest layer.+  /**+   * This function returns a reference to the lowest layer in a stack of+   * stream layers.+   *+   * @return A reference to the lowest layer in the stack of stream layers.+   * Ownership is not transferred to the caller.+   */+  lowest_layer_type& lowest_layer()+  {+    return next_layer_.lowest_layer();+  }++  /// Get a reference to the lowest layer.+  /**+   * This function returns a reference to the lowest layer in a stack of+   * stream layers.+   *+   * @return A reference to the lowest layer in the stack of stream layers.+   * Ownership is not transferred to the caller.+   */+  const lowest_layer_type& lowest_layer() const+  {+    return next_layer_.lowest_layer();+  }++  /// Set the peer verification mode.+  /**+   * This function may be used to configure the peer verification mode used by+   * the stream. The new mode will override the mode inherited from the context.+   *+   * @param v A bitmask of peer verification modes. See @ref verify_mode for+   * available values.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_set_verify.+   */+  void set_verify_mode(verify_mode v)+  {+    asio::error_code ec;+    set_verify_mode(v, ec);+    asio::detail::throw_error(ec, "set_verify_mode");+  }++  /// Set the peer verification mode.+  /**+   * This function may be used to configure the peer verification mode used by+   * the stream. The new mode will override the mode inherited from the context.+   *+   * @param v A bitmask of peer verification modes. See @ref verify_mode for+   * available values.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_set_verify.+   */+  ASIO_SYNC_OP_VOID set_verify_mode(+      verify_mode v, asio::error_code& ec)+  {+    core_.engine_.set_verify_mode(v, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Set the peer verification depth.+  /**+   * This function may be used to configure the maximum verification depth+   * allowed by the stream.+   *+   * @param depth Maximum depth for the certificate chain verification that+   * shall be allowed.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_set_verify_depth.+   */+  void set_verify_depth(int depth)+  {+    asio::error_code ec;+    set_verify_depth(depth, ec);+    asio::detail::throw_error(ec, "set_verify_depth");+  }++  /// Set the peer verification depth.+  /**+   * This function may be used to configure the maximum verification depth+   * allowed by the stream.+   *+   * @param depth Maximum depth for the certificate chain verification that+   * shall be allowed.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_set_verify_depth.+   */+  ASIO_SYNC_OP_VOID set_verify_depth(+      int depth, asio::error_code& ec)+  {+    core_.engine_.set_verify_depth(depth, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Set the callback used to verify peer certificates.+  /**+   * This function is used to specify a callback function that will be called+   * by the implementation when it needs to verify a peer certificate.+   *+   * @param callback The function object to be used for verifying a certificate.+   * The function signature of the handler must be:+   * @code bool verify_callback(+   *   bool preverified, // True if the certificate passed pre-verification.+   *   verify_context& ctx // The peer certificate and other context.+   * ); @endcode+   * The return value of the callback is true if the certificate has passed+   * verification, false otherwise.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls @c SSL_set_verify.+   */+  template <typename VerifyCallback>+  void set_verify_callback(VerifyCallback callback)+  {+    asio::error_code ec;+    this->set_verify_callback(callback, ec);+    asio::detail::throw_error(ec, "set_verify_callback");+  }++  /// Set the callback used to verify peer certificates.+  /**+   * This function is used to specify a callback function that will be called+   * by the implementation when it needs to verify a peer certificate.+   *+   * @param callback The function object to be used for verifying a certificate.+   * The function signature of the handler must be:+   * @code bool verify_callback(+   *   bool preverified, // True if the certificate passed pre-verification.+   *   verify_context& ctx // The peer certificate and other context.+   * ); @endcode+   * The return value of the callback is true if the certificate has passed+   * verification, false otherwise.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls @c SSL_set_verify.+   */+  template <typename VerifyCallback>+  ASIO_SYNC_OP_VOID set_verify_callback(VerifyCallback callback,+      asio::error_code& ec)+  {+    core_.engine_.set_verify_callback(+        new detail::verify_callback<VerifyCallback>(callback), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Perform SSL handshaking.+  /**+   * This function is used to perform SSL handshaking on the stream. The+   * function call will block until handshaking is complete or an error occurs.+   *+   * @param type The type of handshaking to be performed, i.e. as a client or as+   * a server.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void handshake(handshake_type type)+  {+    asio::error_code ec;+    handshake(type, ec);+    asio::detail::throw_error(ec, "handshake");+  }++  /// Perform SSL handshaking.+  /**+   * This function is used to perform SSL handshaking on the stream. The+   * function call will block until handshaking is complete or an error occurs.+   *+   * @param type The type of handshaking to be performed, i.e. as a client or as+   * a server.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID handshake(handshake_type type,+      asio::error_code& ec)+  {+    detail::io(next_layer_, core_, detail::handshake_op(type), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Perform SSL handshaking.+  /**+   * This function is used to perform SSL handshaking on the stream. The+   * function call will block until handshaking is complete or an error occurs.+   *+   * @param type The type of handshaking to be performed, i.e. as a client or as+   * a server.+   *+   * @param buffers The buffered data to be reused for the handshake.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ConstBufferSequence>+  void handshake(handshake_type type, const ConstBufferSequence& buffers)+  {+    asio::error_code ec;+    handshake(type, buffers, ec);+    asio::detail::throw_error(ec, "handshake");+  }++  /// Perform SSL handshaking.+  /**+   * This function is used to perform SSL handshaking on the stream. The+   * function call will block until handshaking is complete or an error occurs.+   *+   * @param type The type of handshaking to be performed, i.e. as a client or as+   * a server.+   *+   * @param buffers The buffered data to be reused for the handshake.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  template <typename ConstBufferSequence>+  ASIO_SYNC_OP_VOID handshake(handshake_type type,+      const ConstBufferSequence& buffers, asio::error_code& ec)+  {+    detail::io(next_layer_, core_,+        detail::buffered_handshake_op<ConstBufferSequence>(type, buffers), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Start an asynchronous SSL handshake.+  /**+   * This function is used to asynchronously perform an SSL handshake on the+   * stream. This function call always returns immediately.+   *+   * @param type The type of handshaking to be performed, i.e. as a client or as+   * a server.+   *+   * @param handler The handler to be called when the handshake operation+   * completes. Copies will be made of the handler as required. The equivalent+   * function signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error // Result of operation.+   * ); @endcode+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        HandshakeHandler+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(HandshakeHandler,+      void (asio::error_code))+  async_handshake(handshake_type type,+      ASIO_MOVE_ARG(HandshakeHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<HandshakeHandler,+      void (asio::error_code)>(+        initiate_async_handshake(this), handler, type);+  }++  /// Start an asynchronous SSL handshake.+  /**+   * This function is used to asynchronously perform an SSL handshake on the+   * stream. This function call always returns immediately.+   *+   * @param type The type of handshaking to be performed, i.e. as a client or as+   * a server.+   *+   * @param buffers The buffered data to be reused for the handshake. Although+   * the buffers object may be copied as necessary, ownership of the underlying+   * buffers is retained by the caller, which must guarantee that they remain+   * valid until the handler is called.+   *+   * @param handler The handler to be called when the handshake operation+   * completes. Copies will be made of the handler as required. The equivalent+   * function signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   std::size_t bytes_transferred // Amount of buffers used in handshake.+   * ); @endcode+   */+  template <typename ConstBufferSequence,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        std::size_t)) BufferedHandshakeHandler+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(BufferedHandshakeHandler,+      void (asio::error_code, std::size_t))+  async_handshake(handshake_type type, const ConstBufferSequence& buffers,+      ASIO_MOVE_ARG(BufferedHandshakeHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<BufferedHandshakeHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_buffered_handshake(this), handler, type, buffers);+  }++  /// Shut down SSL on the stream.+  /**+   * This function is used to shut down SSL on the stream. The function call+   * will block until SSL has been shut down or an error occurs.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void shutdown()+  {+    asio::error_code ec;+    shutdown(ec);+    asio::detail::throw_error(ec, "shutdown");+  }++  /// Shut down SSL on the stream.+  /**+   * This function is used to shut down SSL on the stream. The function call+   * will block until SSL has been shut down or an error occurs.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID shutdown(asio::error_code& ec)+  {+    detail::io(next_layer_, core_, detail::shutdown_op(), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Asynchronously shut down SSL on the stream.+  /**+   * This function is used to asynchronously shut down SSL on the stream. This+   * function call always returns immediately.+   *+   * @param handler The handler to be called when the handshake operation+   * completes. Copies will be made of the handler as required. The equivalent+   * function signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error // Result of operation.+   * ); @endcode+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        ShutdownHandler+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(ShutdownHandler,+      void (asio::error_code))+  async_shutdown(+      ASIO_MOVE_ARG(ShutdownHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ShutdownHandler,+      void (asio::error_code)>(+        initiate_async_shutdown(this), handler);+  }++  /// Write some data to the stream.+  /**+   * This function is used to write data on the stream. The function call will+   * block until one or more bytes of data has been written successfully, or+   * until an error occurs.+   *+   * @param buffers The data to be written.+   *+   * @returns The number of bytes written.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @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;+    std::size_t n = write_some(buffers, ec);+    asio::detail::throw_error(ec, "write_some");+    return n;+  }++  /// Write some data to the stream.+  /**+   * This function is used to write data on the stream. The function call will+   * block until one or more bytes of data has been written successfully, or+   * until an error occurs.+   *+   * @param buffers The data to be written to the stream.+   *+   * @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 detail::io(next_layer_, core_,+        detail::write_op<ConstBufferSequence>(buffers), ec);+  }++  /// Start an asynchronous write.+  /**+   * This function is used to asynchronously write one or more bytes of data to+   * the stream. The function call always returns immediately.+   *+   * @param buffers The data to be written to the stream. Although the buffers+   * object may be copied as necessary, ownership of the underlying buffers is+   * retained by the caller, which must guarantee that they remain valid until+   * the handler is called.+   *+   * @param handler The handler to be called when the write operation completes.+   * Copies will be made of the handler as required. The equivalent function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   std::size_t bytes_transferred           // Number of bytes written.+   * ); @endcode+   *+   * @note The async_write_some 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.+   */+  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 async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_write_some(this), handler, buffers);+  }++  /// Read some data from the stream.+  /**+   * This function is used to read data from the stream. The function call will+   * block until one or more bytes of data has been read successfully, or until+   * an error occurs.+   *+   * @param buffers The buffers into which the data will be read.+   *+   * @returns The number of bytes read.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @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;+    std::size_t n = read_some(buffers, ec);+    asio::detail::throw_error(ec, "read_some");+    return n;+  }++  /// Read some data from the stream.+  /**+   * This function is used to read data from the stream. The function call will+   * block until one or more bytes of data has been read successfully, or until+   * an error occurs.+   *+   * @param buffers The 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 detail::io(next_layer_, core_,+        detail::read_op<MutableBufferSequence>(buffers), ec);+  }++  /// Start an asynchronous read.+  /**+   * This function is used to asynchronously read one or more bytes of data from+   * the stream. The function call always returns immediately.+   *+   * @param buffers The buffers into which the data will be read. Although the+   * buffers object may be copied as necessary, ownership of the underlying+   * buffers is retained by the caller, which must guarantee that they remain+   * valid until the handler is called.+   *+   * @param handler The handler to be called when the read operation completes.+   * Copies will be made of the handler as required. The equivalent function+   * signature of the handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   std::size_t bytes_transferred           // Number of bytes read.+   * ); @endcode+   *+   * @note The async_read_some 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.+   */+  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 async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_read_some(this), handler, buffers);+  }++private:+  class initiate_async_handshake+  {+  public:+    typedef typename stream::executor_type executor_type;++    explicit initiate_async_handshake(stream* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename HandshakeHandler>+    void operator()(ASIO_MOVE_ARG(HandshakeHandler) handler,+        handshake_type type) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a HandshakeHandler.+      ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check;++      asio::detail::non_const_lvalue<HandshakeHandler> handler2(handler);+      detail::async_io(self_->next_layer_, self_->core_,+          detail::handshake_op(type), handler2.value);+    }++  private:+    stream* self_;+  };++  class initiate_async_buffered_handshake+  {+  public:+    typedef typename stream::executor_type executor_type;++    explicit initiate_async_buffered_handshake(stream* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename BufferedHandshakeHandler, typename ConstBufferSequence>+    void operator()(ASIO_MOVE_ARG(BufferedHandshakeHandler) handler,+        handshake_type type, 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+      // BufferedHandshakeHandler.+      ASIO_BUFFERED_HANDSHAKE_HANDLER_CHECK(+          BufferedHandshakeHandler, handler) type_check;++      asio::detail::non_const_lvalue<+          BufferedHandshakeHandler> handler2(handler);+      detail::async_io(self_->next_layer_, self_->core_,+          detail::buffered_handshake_op<ConstBufferSequence>(type, buffers),+          handler2.value);+    }++  private:+    stream* self_;+  };++  class initiate_async_shutdown+  {+  public:+    typedef typename stream::executor_type executor_type;++    explicit initiate_async_shutdown(stream* self)+      : self_(self)+    {+    }++    executor_type get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename ShutdownHandler>+    void operator()(ASIO_MOVE_ARG(ShutdownHandler) 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 ShutdownHandler.+      ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check;++      asio::detail::non_const_lvalue<ShutdownHandler> handler2(handler);+      detail::async_io(self_->next_layer_, self_->core_,+          detail::shutdown_op(), handler2.value);+    }++  private:+    stream* self_;+  };++  class initiate_async_write_some+  {+  public:+    typedef typename stream::executor_type executor_type;++    explicit initiate_async_write_some(stream* 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;++      asio::detail::non_const_lvalue<WriteHandler> handler2(handler);+      detail::async_io(self_->next_layer_, self_->core_,+          detail::write_op<ConstBufferSequence>(buffers), handler2.value);+    }++  private:+    stream* self_;+  };++  class initiate_async_read_some+  {+  public:+    typedef typename stream::executor_type executor_type;++    explicit initiate_async_read_some(stream* 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;++      asio::detail::non_const_lvalue<ReadHandler> handler2(handler);+      detail::async_io(self_->next_layer_, self_->core_,+          detail::read_op<MutableBufferSequence>(buffers), handler2.value);+    }++  private:+    stream* self_;+  };++  Stream next_layer_;+  detail::stream_core core_;+};++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_STREAM_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/stream_base.hpp view
@@ -0,0 +1,52 @@+//+// ssl/stream_base.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_STREAM_BASE_HPP+#define ASIO_SSL_STREAM_BASE_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 {+namespace ssl {++/// The stream_base class is used as a base for the asio::ssl::stream+/// class template so that we have a common place to define various enums.+class stream_base+{+public:+  /// Different handshake types.+  enum handshake_type+  {+    /// Perform handshaking as a client.+    client,++    /// Perform handshaking as a server.+    server+  };++protected:+  /// Protected destructor to prevent deletion through this type.+  ~stream_base()+  {+  }+};++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_STREAM_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/verify_context.hpp view
@@ -0,0 +1,67 @@+//+// ssl/verify_context.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_VERIFY_CONTEXT_HPP+#define ASIO_SSL_VERIFY_CONTEXT_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/noncopyable.hpp"+#include "asio/ssl/detail/openssl_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++/// A simple wrapper around the X509_STORE_CTX type, used during verification of+/// a peer certificate.+/**+ * @note The verify_context does not own the underlying X509_STORE_CTX object.+ */+class verify_context+  : private noncopyable+{+public:+  /// The native handle type of the verification context.+  typedef X509_STORE_CTX* native_handle_type;++  /// Constructor.+  explicit verify_context(native_handle_type handle)+    : handle_(handle)+  {+  }++  /// Get the underlying implementation in the native type.+  /**+   * This function may be used to obtain the underlying implementation of the+   * context. This is intended to allow access to context functionality that is+   * not otherwise provided.+   */+  native_handle_type native_handle()+  {+    return handle_;+  }++private:+  // The underlying native implementation.+  native_handle_type handle_;+};++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_VERIFY_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/ssl/verify_mode.hpp view
@@ -0,0 +1,63 @@+//+// ssl/verify_mode.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SSL_VERIFY_MODE_HPP+#define ASIO_SSL_VERIFY_MODE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/ssl/detail/openssl_types.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace ssl {++/// Bitmask type for peer verification.+/**+ * Possible values are:+ *+ * @li @ref verify_none+ * @li @ref verify_peer+ * @li @ref verify_fail_if_no_peer_cert+ * @li @ref verify_client_once+ */+typedef int verify_mode;++#if defined(GENERATING_DOCUMENTATION)+/// No verification.+const int verify_none = implementation_defined;++/// Verify the peer.+const int verify_peer = implementation_defined;++/// Fail verification if the peer has no certificate. Ignored unless+/// @ref verify_peer is set.+const int verify_fail_if_no_peer_cert = implementation_defined;++/// Do not request client certificate on renegotiation. Ignored unless+/// @ref verify_peer is set.+const int verify_client_once = implementation_defined;+#else+const int verify_none = SSL_VERIFY_NONE;+const int verify_peer = SSL_VERIFY_PEER;+const int verify_fail_if_no_peer_cert = SSL_VERIFY_FAIL_IF_NO_PEER_CERT;+const int verify_client_once = SSL_VERIFY_CLIENT_ONCE;+#endif++} // namespace ssl+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SSL_VERIFY_MODE_HPP
+ link/modules/asio-standalone/asio/include/asio/static_thread_pool.hpp view
@@ -0,0 +1,31 @@+//+// static_thread_pool.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_STATIC_THREAD_POOL_HPP+#define ASIO_STATIC_THREAD_POOL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/thread_pool.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++typedef thread_pool static_thread_pool;++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_STATIC_THREAD_POOL_HPP
+ link/modules/asio-standalone/asio/include/asio/steady_timer.hpp view
@@ -0,0 +1,42 @@+//+// steady_timer.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_STEADY_TIMER_HPP+#define ASIO_STEADY_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_CHRONO) || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_waitable_timer.hpp"+#include "asio/detail/chrono.hpp"++namespace asio {++/// Typedef for a timer based on the steady clock.+/**+ * This typedef uses the C++11 @c &lt;chrono&gt; standard library facility, if+ * available. Otherwise, it may use the Boost.Chrono library. To explicitly+ * utilise Boost.Chrono, use the basic_waitable_timer template directly:+ * @code+ * typedef basic_waitable_timer<boost::chrono::steady_clock> timer;+ * @endcode+ */+typedef basic_waitable_timer<chrono::steady_clock> steady_timer;++} // namespace asio++#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_STEADY_TIMER_HPP
+ link/modules/asio-standalone/asio/include/asio/strand.hpp view
@@ -0,0 +1,537 @@+//+// strand.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_STRAND_HPP+#define ASIO_STRAND_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/strand_executor_service.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/executor.hpp"+#include "asio/is_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Provides serialised function invocation for any executor type.+template <typename Executor>+class strand+{+public:+  /// The type of the underlying executor.+  typedef Executor inner_executor_type;++  /// Default constructor.+  /**+   * This constructor is only valid if the underlying executor type is default+   * constructible.+   */+  strand()+    : executor_(),+      impl_(strand::create_implementation(executor_))+  {+  }++  /// Construct a strand for the specified executor.+  template <typename Executor1>+  explicit strand(const Executor1& e,+      typename enable_if<+        conditional<+          !is_same<Executor1, strand>::value,+          is_convertible<Executor1, Executor>,+          false_type+        >::type::value+      >::type* = 0)+    : executor_(e),+      impl_(strand::create_implementation(executor_))+  {+  }++  /// Copy constructor.+  strand(const strand& other) ASIO_NOEXCEPT+    : executor_(other.executor_),+      impl_(other.impl_)+  {+  }++  /// Converting constructor.+  /**+   * This constructor is only valid if the @c OtherExecutor type is convertible+   * to @c Executor.+   */+  template <class OtherExecutor>+  strand(+      const strand<OtherExecutor>& other) ASIO_NOEXCEPT+    : executor_(other.executor_),+      impl_(other.impl_)+  {+  }++  /// Assignment operator.+  strand& operator=(const strand& other) ASIO_NOEXCEPT+  {+    executor_ = other.executor_;+    impl_ = other.impl_;+    return *this;+  }++  /// Converting assignment operator.+  /**+   * This assignment operator is only valid if the @c OtherExecutor type is+   * convertible to @c Executor.+   */+  template <class OtherExecutor>+  strand& operator=(+      const strand<OtherExecutor>& other) ASIO_NOEXCEPT+  {+    executor_ = other.executor_;+    impl_ = other.impl_;+    return *this;+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  strand(strand&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(Executor)(other.executor_)),+      impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_))+  {+  }++  /// Converting move constructor.+  /**+   * This constructor is only valid if the @c OtherExecutor type is convertible+   * to @c Executor.+   */+  template <class OtherExecutor>+  strand(strand<OtherExecutor>&& other) ASIO_NOEXCEPT+    : executor_(ASIO_MOVE_CAST(OtherExecutor)(other.executor_)),+      impl_(ASIO_MOVE_CAST(implementation_type)(other.impl_))+  {+  }++  /// Move assignment operator.+  strand& operator=(strand&& other) ASIO_NOEXCEPT+  {+    executor_ = ASIO_MOVE_CAST(Executor)(other.executor_);+    impl_ = ASIO_MOVE_CAST(implementation_type)(other.impl_);+    return *this;+  }++  /// Converting move assignment operator.+  /**+   * This assignment operator is only valid if the @c OtherExecutor type is+   * convertible to @c Executor.+   */+  template <class OtherExecutor>+  strand& operator=(strand<OtherExecutor>&& other) ASIO_NOEXCEPT+  {+    executor_ = ASIO_MOVE_CAST(OtherExecutor)(other.executor_);+    impl_ = ASIO_MOVE_CAST(implementation_type)(other.impl_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  ~strand() ASIO_NOEXCEPT+  {+  }++  /// Obtain the underlying executor.+  inner_executor_type get_inner_executor() const ASIO_NOEXCEPT+  {+    return executor_;+  }++  /// Forward a query to the underlying executor.+  /**+   * Do not call this function directly. It is intended for use with the+   * execution::execute customisation point.+   *+   * For example:+   * @code asio::strand<my_executor_type> ex = ...;+   * if (asio::query(ex, asio::execution::blocking)+   *       == asio::execution::blocking.never)+   *   ... @endcode+   */+  template <typename Property>+  typename enable_if<+    can_query<const Executor&, Property>::value,+    typename query_result<const Executor&, Property>::type+  >::type query(const Property& p) const+    ASIO_NOEXCEPT_IF((+      is_nothrow_query<const Executor&, Property>::value))+  {+    return asio::query(executor_, p);+  }++  /// Forward a requirement to the underlying executor.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code asio::strand<my_executor_type> ex1 = ...;+   * auto ex2 = asio::require(ex1,+   *     asio::execution::blocking.never); @endcode+   */+  template <typename Property>+  typename enable_if<+    can_require<const Executor&, Property>::value,+    strand<typename decay<+      typename require_result<const Executor&, Property>::type+    >::type>+  >::type require(const Property& p) const+    ASIO_NOEXCEPT_IF((+      is_nothrow_require<const Executor&, Property>::value))+  {+    return strand<typename decay<+      typename require_result<const Executor&, Property>::type+        >::type>(asio::require(executor_, p), impl_);+  }++  /// Forward a preference to the underlying executor.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::prefer customisation point.+   *+   * For example:+   * @code asio::strand<my_executor_type> ex1 = ...;+   * auto ex2 = asio::prefer(ex1,+   *     asio::execution::blocking.never); @endcode+   */+  template <typename Property>+  typename enable_if<+    can_prefer<const Executor&, Property>::value,+    strand<typename decay<+      typename prefer_result<const Executor&, Property>::type+    >::type>+  >::type prefer(const Property& p) const+    ASIO_NOEXCEPT_IF((+      is_nothrow_prefer<const Executor&, Property>::value))+  {+    return strand<typename decay<+      typename prefer_result<const Executor&, Property>::type+        >::type>(asio::prefer(executor_, p), impl_);+  }++#if !defined(ASIO_NO_TS_EXECUTORS)+  /// Obtain the underlying execution context.+  execution_context& context() const ASIO_NOEXCEPT+  {+    return executor_.context();+  }++  /// Inform the strand that it has some outstanding work to do.+  /**+   * The strand delegates this call to its underlying executor.+   */+  void on_work_started() const ASIO_NOEXCEPT+  {+    executor_.on_work_started();+  }++  /// Inform the strand that some work is no longer outstanding.+  /**+   * The strand delegates this call to its underlying executor.+   */+  void on_work_finished() const ASIO_NOEXCEPT+  {+    executor_.on_work_finished();+  }+#endif // !defined(ASIO_NO_TS_EXECUTORS)++  /// Request the strand to invoke the given function object.+  /**+   * Do not call this function directly. It is intended for use with the+   * execution::execute customisation point.+   *+   * For example:+   * @code asio::strand<my_executor_type> ex = ...;+   * execution::execute(ex, my_function_object); @endcode+   *+   * This function is used to ask the strand to execute the given function+   * object on its underlying executor. The function object will be executed+   * according to the properties of the underlying executor.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   */+  template <typename Function>+  typename enable_if<+    execution::can_execute<const Executor&, Function>::value+  >::type execute(ASIO_MOVE_ARG(Function) f) const+  {+    detail::strand_executor_service::execute(impl_,+        executor_, ASIO_MOVE_CAST(Function)(f));+  }++#if !defined(ASIO_NO_TS_EXECUTORS)+  /// Request the strand to invoke the given function object.+  /**+   * This function is used to ask the strand to execute the given function+   * object on its underlying executor. The function object will be executed+   * inside this function if the strand is not otherwise busy and if the+   * underlying executor's @c dispatch() function is also able to execute the+   * function before returning.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename Allocator>+  void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const+  {+    detail::strand_executor_service::dispatch(impl_,+        executor_, ASIO_MOVE_CAST(Function)(f), a);+  }++  /// Request the strand to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object will never be executed inside this function.+   * Instead, it will be scheduled by the underlying executor's defer function.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename Allocator>+  void post(ASIO_MOVE_ARG(Function) f, const Allocator& a) const+  {+    detail::strand_executor_service::post(impl_,+        executor_, ASIO_MOVE_CAST(Function)(f), a);+  }++  /// Request the strand to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object will never be executed inside this function.+   * Instead, it will be scheduled by the underlying executor's defer function.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename Allocator>+  void defer(ASIO_MOVE_ARG(Function) f, const Allocator& a) const+  {+    detail::strand_executor_service::defer(impl_,+        executor_, ASIO_MOVE_CAST(Function)(f), a);+  }+#endif // !defined(ASIO_NO_TS_EXECUTORS)++  /// Determine whether the strand is running in the current thread.+  /**+   * @return @c true if the current thread is executing a function that was+   * submitted to the strand using post(), dispatch() or defer(). Otherwise+   * returns @c false.+   */+  bool running_in_this_thread() const ASIO_NOEXCEPT+  {+    return detail::strand_executor_service::running_in_this_thread(impl_);+  }++  /// Compare two strands for equality.+  /**+   * Two strands are equal if they refer to the same ordered, non-concurrent+   * state.+   */+  friend bool operator==(const strand& a, const strand& b) ASIO_NOEXCEPT+  {+    return a.impl_ == b.impl_;+  }++  /// Compare two strands for inequality.+  /**+   * Two strands are equal if they refer to the same ordered, non-concurrent+   * state.+   */+  friend bool operator!=(const strand& a, const strand& b) ASIO_NOEXCEPT+  {+    return a.impl_ != b.impl_;+  }++#if defined(GENERATING_DOCUMENTATION)+private:+#endif // defined(GENERATING_DOCUMENTATION)+  typedef detail::strand_executor_service::implementation_type+    implementation_type;++  template <typename InnerExecutor>+  static implementation_type create_implementation(const InnerExecutor& ex,+      typename enable_if<+        can_query<InnerExecutor, execution::context_t>::value+      >::type* = 0)+  {+    return use_service<detail::strand_executor_service>(+        asio::query(ex, execution::context)).create_implementation();+  }++  template <typename InnerExecutor>+  static implementation_type create_implementation(const InnerExecutor& ex,+      typename enable_if<+        !can_query<InnerExecutor, execution::context_t>::value+      >::type* = 0)+  {+    return use_service<detail::strand_executor_service>(+        ex.context()).create_implementation();+  }++  strand(const Executor& ex, const implementation_type& impl)+    : executor_(ex),+      impl_(impl)+  {+  }++  Executor executor_;+  implementation_type impl_;+};++/** @defgroup make_strand asio::make_strand+ *+ * @brief The asio::make_strand function creates a @ref strand object for+ * an executor or execution context.+ */+/*@{*/++/// Create a @ref strand object for an executor.+template <typename Executor>+inline strand<Executor> make_strand(const Executor& ex,+    typename enable_if<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type* = 0)+{+  return strand<Executor>(ex);+}++/// Create a @ref strand object for an execution context.+template <typename ExecutionContext>+inline strand<typename ExecutionContext::executor_type>+make_strand(ExecutionContext& ctx,+    typename enable_if<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type* = 0)+{+  return strand<typename ExecutionContext::executor_type>(ctx.get_executor());+}++/*@}*/++#if !defined(GENERATING_DOCUMENTATION)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <typename Executor>+struct equality_comparable<strand<Executor> >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename Executor, typename Function>+struct execute_member<strand<Executor>, Function>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(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 Executor, typename Property>+struct query_member<strand<Executor>, Property,+    typename enable_if<+      can_query<const Executor&, Property>::value+    >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_query<Executor, Property>::value));+  typedef typename query_result<Executor, Property>::type result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Executor, typename Property>+struct require_member<strand<Executor>, Property,+    typename enable_if<+      can_require<const Executor&, Property>::value+    >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_require<Executor, Property>::value));+  typedef strand<typename decay<+    typename require_result<Executor, Property>::type+      >::type> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++template <typename Executor, typename Property>+struct prefer_member<strand<Executor>, Property,+    typename enable_if<+      can_prefer<const Executor&, Property>::value+    >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+      (is_nothrow_prefer<Executor, Property>::value));+  typedef strand<typename decay<+    typename prefer_result<Executor, Property>::type+      >::type> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++} // namespace traits++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++// If both io_context.hpp and strand.hpp have been included, automatically+// include the header file needed for the io_context::strand class.+#if !defined(ASIO_NO_EXTENSIONS)+# if defined(ASIO_IO_CONTEXT_HPP)+#  include "asio/io_context_strand.hpp"+# endif // defined(ASIO_IO_CONTEXT_HPP)+#endif // !defined(ASIO_NO_EXTENSIONS)++#endif // ASIO_STRAND_HPP
+ link/modules/asio-standalone/asio/include/asio/streambuf.hpp view
@@ -0,0 +1,33 @@+//+// streambuf.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_STREAMBUF_HPP+#define ASIO_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 "asio/basic_streambuf.hpp"++namespace asio {++/// Typedef for the typical usage of basic_streambuf.+typedef basic_streambuf<> streambuf;++} // namespace asio++#endif // !defined(ASIO_NO_IOSTREAM)++#endif // ASIO_STREAMBUF_HPP
+ link/modules/asio-standalone/asio/include/asio/system_context.hpp view
@@ -0,0 +1,90 @@+//+// system_context.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SYSTEM_CONTEXT_HPP+#define ASIO_SYSTEM_CONTEXT_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/scheduler.hpp"+#include "asio/detail/thread_group.hpp"+#include "asio/execution.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename Blocking, typename Relationship, typename Allocator>+class basic_system_executor;++/// The executor context for the system executor.+class system_context : public execution_context+{+public:+  /// The executor type associated with the context.+  typedef basic_system_executor<+      execution::blocking_t::possibly_t,+      execution::relationship_t::fork_t,+      std::allocator<void>+    > executor_type;++  /// Destructor shuts down all threads in the system thread pool.+  ASIO_DECL ~system_context();++  /// Obtain an executor for the context.+  executor_type get_executor() ASIO_NOEXCEPT;++  /// Signal all threads in the system thread pool to stop.+  ASIO_DECL void stop();++  /// Determine whether the system thread pool has been stopped.+  ASIO_DECL bool stopped() const ASIO_NOEXCEPT;++  /// Join all threads in the system thread pool.+  ASIO_DECL void join();++#if defined(GENERATING_DOCUMENTATION)+private:+#endif // defined(GENERATING_DOCUMENTATION)+  // Constructor creates all threads in the system thread pool.+  ASIO_DECL system_context();++private:+  template <typename, typename, typename> friend class basic_system_executor;++  struct thread_function;++  // Helper function to create the underlying scheduler.+  ASIO_DECL detail::scheduler& add_scheduler(detail::scheduler* s);++  // The underlying scheduler.+  detail::scheduler& scheduler_;++  // The threads in the system thread pool.+  detail::thread_group threads_;++  // The number of threads in the pool.+  std::size_t num_threads_;+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/system_context.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/system_context.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_SYSTEM_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/system_error.hpp view
@@ -0,0 +1,131 @@+//+// system_error.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SYSTEM_ERROR_HPP+#define ASIO_SYSTEM_ERROR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_STD_SYSTEM_ERROR)+# include <system_error>+#else // defined(ASIO_HAS_STD_SYSTEM_ERROR)+# include <cerrno>+# include <exception>+# include <string>+# include "asio/error_code.hpp"+# include "asio/detail/scoped_ptr.hpp"+#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)++#include "asio/detail/push_options.hpp"++namespace asio {++#if defined(ASIO_HAS_STD_SYSTEM_ERROR)++typedef std::system_error system_error;++#else // defined(ASIO_HAS_STD_SYSTEM_ERROR)++/// The system_error class is used to represent system conditions that+/// prevent the library from operating correctly.+class system_error+  : public std::exception+{+public:+  /// Construct with an error code.+  system_error(const error_code& ec)+    : code_(ec),+      context_()+  {+  }++  /// Construct with an error code and context.+  system_error(const error_code& ec, const std::string& context)+    : code_(ec),+      context_(context)+  {+  }++  /// Copy constructor.+  system_error(const system_error& other)+    : std::exception(other),+      code_(other.code_),+      context_(other.context_),+      what_()+  {+  }++  /// Destructor.+  virtual ~system_error() throw ()+  {+  }++  /// Assignment operator.+  system_error& operator=(const system_error& e)+  {+    context_ = e.context_;+    code_ = e.code_;+    what_.reset();+    return *this;+  }++  /// Get a string representation of the exception.+  virtual const char* what() const throw ()+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+#endif // !defined(ASIO_NO_EXCEPTIONS)+    {+      if (!what_.get())+      {+        std::string tmp(context_);+        if (tmp.length())+          tmp += ": ";+        tmp += code_.message();+        what_.reset(new std::string(tmp));+      }+      return what_->c_str();+    }+#if !defined(ASIO_NO_EXCEPTIONS)+    catch (std::exception&)+    {+      return "system_error";+    }+#endif // !defined(ASIO_NO_EXCEPTIONS)+  }++  /// Get the error code associated with the exception.+  error_code code() const+  {+    return code_;+  }++private:+  // The code associated with the error.+  error_code code_;++  // The context associated with the error.+  std::string context_;++  // The string representation of the error.+  mutable asio::detail::scoped_ptr<std::string> what_;+};++#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SYSTEM_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/system_executor.hpp view
@@ -0,0 +1,662 @@+//+// system_executor.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SYSTEM_EXECUTOR_HPP+#define ASIO_SYSTEM_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/memory.hpp"+#include "asio/execution.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++class system_context;++/// An executor that uses arbitrary threads.+/**+ * The system executor represents an execution context where functions are+ * permitted to run on arbitrary threads. When the blocking.never property is+ * established, the system executor will schedule the function to run on an+ * unspecified system thread pool. When either blocking.possibly or+ * blocking.always is established, the executor invokes the function+ * immediately.+ */+template <typename Blocking, typename Relationship, typename Allocator>+class basic_system_executor+{+public:+  /// Default constructor.+  basic_system_executor() ASIO_NOEXCEPT+    : allocator_(Allocator())+  {+  }++  /// Obtain an executor with the @c blocking.possibly property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code asio::system_executor ex1;+   * auto ex2 = asio::require(ex1,+   *     asio::execution::blocking.possibly); @endcode+   */+  basic_system_executor<execution::blocking_t::possibly_t,+      Relationship, Allocator>+  require(execution::blocking_t::possibly_t) const+  {+    return basic_system_executor<execution::blocking_t::possibly_t,+        Relationship, Allocator>(allocator_);+  }++  /// Obtain an executor with the @c blocking.always property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code asio::system_executor ex1;+   * auto ex2 = asio::require(ex1,+   *     asio::execution::blocking.always); @endcode+   */+  basic_system_executor<execution::blocking_t::always_t,+      Relationship, Allocator>+  require(execution::blocking_t::always_t) const+  {+    return basic_system_executor<execution::blocking_t::always_t,+        Relationship, Allocator>(allocator_);+  }++  /// Obtain an executor with the @c blocking.never property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code asio::system_executor ex1;+   * auto ex2 = asio::require(ex1,+   *     asio::execution::blocking.never); @endcode+   */+  basic_system_executor<execution::blocking_t::never_t,+      Relationship, Allocator>+  require(execution::blocking_t::never_t) const+  {+    return basic_system_executor<execution::blocking_t::never_t,+        Relationship, Allocator>(allocator_);+  }++  /// Obtain an executor with the @c relationship.continuation property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code asio::system_executor ex1;+   * auto ex2 = asio::require(ex1,+   *     asio::execution::relationship.continuation); @endcode+   */+  basic_system_executor<Blocking,+      execution::relationship_t::continuation_t, Allocator>+  require(execution::relationship_t::continuation_t) const+  {+    return basic_system_executor<Blocking,+        execution::relationship_t::continuation_t, Allocator>(allocator_);+  }++  /// Obtain an executor with the @c relationship.fork property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code asio::system_executor ex1;+   * auto ex2 = asio::require(ex1,+   *     asio::execution::relationship.fork); @endcode+   */+  basic_system_executor<Blocking,+      execution::relationship_t::fork_t, Allocator>+  require(execution::relationship_t::fork_t) const+  {+    return basic_system_executor<Blocking,+        execution::relationship_t::fork_t, Allocator>(allocator_);+  }++  /// Obtain an executor with the specified @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code asio::system_executor ex1;+   * auto ex2 = asio::require(ex1,+   *     asio::execution::allocator(my_allocator)); @endcode+   */+  template <typename OtherAllocator>+  basic_system_executor<Blocking, Relationship, OtherAllocator>+  require(execution::allocator_t<OtherAllocator> a) const+  {+    return basic_system_executor<Blocking,+        Relationship, OtherAllocator>(a.value());+  }++  /// Obtain an executor with the default @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code asio::system_executor ex1;+   * auto ex2 = asio::require(ex1,+   *     asio::execution::allocator); @endcode+   */+  basic_system_executor<Blocking, Relationship, std::allocator<void> >+  require(execution::allocator_t<void>) const+  {+    return basic_system_executor<Blocking,+        Relationship, std::allocator<void> >();+  }++  /// Query the current value of the @c mapping property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code asio::system_executor ex;+   * if (asio::query(ex, asio::execution::mapping)+   *       == asio::execution::mapping.thread)+   *   ... @endcode+   */+  static ASIO_CONSTEXPR execution::mapping_t query(+      execution::mapping_t) ASIO_NOEXCEPT+  {+    return execution::mapping.thread;+  }++  /// Query the current value of the @c context property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code asio::system_executor ex;+   * asio::system_context& pool = asio::query(+   *     ex, asio::execution::context); @endcode+   */+  static system_context& query(execution::context_t) ASIO_NOEXCEPT;++  /// Query the current value of the @c blocking property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code asio::system_executor ex;+   * if (asio::query(ex, asio::execution::blocking)+   *       == asio::execution::blocking.always)+   *   ... @endcode+   */+  static ASIO_CONSTEXPR execution::blocking_t query(+      execution::blocking_t) ASIO_NOEXCEPT+  {+    return Blocking();+  }++  /// Query the current value of the @c relationship property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code asio::system_executor ex;+   * if (asio::query(ex, asio::execution::relationship)+   *       == asio::execution::relationship.continuation)+   *   ... @endcode+   */+  static ASIO_CONSTEXPR execution::relationship_t query(+      execution::relationship_t) ASIO_NOEXCEPT+  {+    return Relationship();+  }++  /// Query the current value of the @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code asio::system_executor ex;+   * auto alloc = asio::query(ex,+   *     asio::execution::allocator); @endcode+   */+  template <typename OtherAllocator>+  ASIO_CONSTEXPR Allocator query(+      execution::allocator_t<OtherAllocator>) const ASIO_NOEXCEPT+  {+    return allocator_;+  }++  /// Query the current value of the @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code asio::system_executor ex;+   * auto alloc = asio::query(ex,+   *     asio::execution::allocator); @endcode+   */+  ASIO_CONSTEXPR Allocator query(+      execution::allocator_t<void>) const ASIO_NOEXCEPT+  {+    return allocator_;+  }++  /// Query the occupancy (recommended number of work items) for the system+  /// context.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code asio::system_executor ex;+   * std::size_t occupancy = asio::query(+   *     ex, asio::execution::occupancy); @endcode+   */+  std::size_t query(execution::occupancy_t) const ASIO_NOEXCEPT;++  /// Compare two executors for equality.+  /**+   * Two executors are equal if they refer to the same underlying io_context.+   */+  friend bool operator==(const basic_system_executor&,+      const basic_system_executor&) ASIO_NOEXCEPT+  {+    return true;+  }++  /// Compare two executors for inequality.+  /**+   * Two executors are equal if they refer to the same underlying io_context.+   */+  friend bool operator!=(const basic_system_executor&,+      const basic_system_executor&) ASIO_NOEXCEPT+  {+    return false;+  }++  /// Execution function.+  /**+   * Do not call this function directly. It is intended for use with the+   * execution::execute customisation point.+   *+   * For example:+   * @code asio::system_executor ex;+   * execution::execute(ex, my_function_object); @endcode+   */+  template <typename Function>+  void execute(ASIO_MOVE_ARG(Function) f) const+  {+    this->do_execute(ASIO_MOVE_CAST(Function)(f), Blocking());+  }++#if !defined(ASIO_NO_TS_EXECUTORS)+  /// Obtain the underlying execution context.+  system_context& context() const ASIO_NOEXCEPT;++  /// Inform the executor that it has some outstanding work to do.+  /**+   * For the system executor, this is a no-op.+   */+  void on_work_started() const ASIO_NOEXCEPT+  {+  }++  /// Inform the executor that some work is no longer outstanding.+  /**+   * For the system executor, this is a no-op.+   */+  void on_work_finished() const ASIO_NOEXCEPT+  {+  }++  /// Request the system executor to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object will always be executed inside this function.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename OtherAllocator>+  void dispatch(ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const;++  /// Request the system executor to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object will never be executed inside this function.+   * Instead, it will be scheduled to run on an unspecified system thread pool.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename OtherAllocator>+  void post(ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const;++  /// Request the system executor to invoke the given function object.+  /**+   * This function is used to ask the executor to execute the given function+   * object. The function object will never be executed inside this function.+   * Instead, it will be scheduled to run on an unspecified system thread pool.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename OtherAllocator>+  void defer(ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const;+#endif // !defined(ASIO_NO_TS_EXECUTORS)++private:+  template <typename, typename, typename> friend class basic_system_executor;++  // Constructor used by require().+  basic_system_executor(const Allocator& a)+    : allocator_(a)+  {+  }++  /// Execution helper implementation for the possibly blocking property.+  template <typename Function>+  void do_execute(ASIO_MOVE_ARG(Function) f,+      execution::blocking_t::possibly_t) const;++  /// Execution helper implementation for the always blocking property.+  template <typename Function>+  void do_execute(ASIO_MOVE_ARG(Function) f,+      execution::blocking_t::always_t) const;++  /// Execution helper implementation for the never blocking property.+  template <typename Function>+  void do_execute(ASIO_MOVE_ARG(Function) f,+      execution::blocking_t::never_t) const;++  // The allocator used for execution functions.+  Allocator allocator_;+};++/// An executor that uses arbitrary threads.+/**+ * The system executor represents an execution context where functions are+ * permitted to run on arbitrary threads. When the blocking.never property is+ * established, the system executor will schedule the function to run on an+ * unspecified system thread pool. When either blocking.possibly or+ * blocking.always is established, the executor invokes the function+ * immediately.+ */+typedef basic_system_executor<execution::blocking_t::possibly_t,+    execution::relationship_t::fork_t, std::allocator<void> >+  system_executor;++#if !defined(GENERATING_DOCUMENTATION)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <typename Blocking, typename Relationship, typename Allocator>+struct equality_comparable<+    asio::basic_system_executor<Blocking, Relationship, Allocator>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename Blocking, typename Relationship,+    typename Allocator, typename Function>+struct execute_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    Function+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Blocking, typename Relationship, typename Allocator>+struct require_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::blocking_t::possibly_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::basic_system_executor<+      asio::execution::blocking_t::possibly_t,+      Relationship, Allocator> result_type;+};++template <typename Blocking, typename Relationship, typename Allocator>+struct require_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::blocking_t::always_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::basic_system_executor<+      asio::execution::blocking_t::always_t,+      Relationship, Allocator> result_type;+};++template <typename Blocking, typename Relationship, typename Allocator>+struct require_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::blocking_t::never_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::basic_system_executor<+      asio::execution::blocking_t::never_t,+      Relationship, Allocator> result_type;+};++template <typename Blocking, typename Relationship, typename Allocator>+struct require_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::relationship_t::fork_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::basic_system_executor<Blocking,+      asio::execution::relationship_t::fork_t,+      Allocator> result_type;+};++template <typename Blocking, typename Relationship, typename Allocator>+struct require_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::relationship_t::continuation_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::basic_system_executor<Blocking,+      asio::execution::relationship_t::continuation_t,+      Allocator> result_type;+};++template <typename Blocking, typename Relationship, typename Allocator>+struct require_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::allocator_t<void>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::basic_system_executor<Blocking,+      Relationship, std::allocator<void> > result_type;+};++template <typename Blocking, typename Relationship,+    typename Allocator, typename OtherAllocator>+struct require_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::allocator_t<OtherAllocator>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::basic_system_executor<Blocking,+      Relationship, OtherAllocator> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++template <typename Blocking, typename Relationship,+    typename Allocator, typename Property>+struct query_static_constexpr_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::mapping_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::mapping_t::thread_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename Blocking, typename Relationship,+    typename Allocator, typename Property>+struct query_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::blocking_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::blocking_t result_type;+};++template <typename Blocking, typename Relationship,+    typename Allocator, typename Property>+struct query_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::relationship_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::relationship_t result_type;+};++template <typename Blocking, typename Relationship, typename Allocator>+struct query_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::context_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::system_context& result_type;+};++template <typename Blocking, typename Relationship, typename Allocator>+struct query_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::allocator_t<void>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef Allocator result_type;+};++template <typename Blocking, typename Relationship, typename Allocator>+struct query_member<+    asio::basic_system_executor<Blocking, Relationship, Allocator>,+    asio::execution::allocator_t<Allocator>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef Allocator result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++} // namespace traits++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/system_executor.hpp"++#endif // ASIO_SYSTEM_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/system_timer.hpp view
@@ -0,0 +1,42 @@+//+// system_timer.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_SYSTEM_TIMER_HPP+#define ASIO_SYSTEM_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_CHRONO) || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_waitable_timer.hpp"+#include "asio/detail/chrono.hpp"++namespace asio {++/// Typedef for a timer based on the system clock.+/**+ * This typedef uses the C++11 @c &lt;chrono&gt; standard library facility, if+ * available. Otherwise, it may use the Boost.Chrono library. To explicitly+ * utilise Boost.Chrono, use the basic_waitable_timer template directly:+ * @code+ * typedef basic_waitable_timer<boost::chrono::system_clock> timer;+ * @endcode+ */+typedef basic_waitable_timer<chrono::system_clock> system_timer;++} // namespace asio++#endif // defined(ASIO_HAS_CHRONO) || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_SYSTEM_TIMER_HPP
+ link/modules/asio-standalone/asio/include/asio/this_coro.hpp view
@@ -0,0 +1,45 @@+//+// this_coro.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_THIS_CORO_HPP+#define ASIO_THIS_CORO_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 {+namespace this_coro {++/// Awaitable type that returns the executor of the current coroutine.+struct executor_t+{+  ASIO_CONSTEXPR executor_t()+  {+  }+};++/// Awaitable object that returns the executor of the current coroutine.+#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr executor_t executor;+#elif defined(ASIO_MSVC)+__declspec(selectany) executor_t executor;+#endif++} // namespace this_coro+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_THIS_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/thread.hpp view
@@ -0,0 +1,92 @@+//+// thread.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_THREAD_HPP+#define ASIO_THREAD_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/noncopyable.hpp"+#include "asio/detail/thread.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// A simple abstraction for starting threads.+/**+ * The asio::thread class implements the smallest possible subset of the+ * functionality of boost::thread. It is intended to be used only for starting+ * a thread and waiting for it to exit. If more extensive threading+ * capabilities are required, you are strongly advised to use something else.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * @par Example+ * A typical use of asio::thread would be to launch a thread to run an+ * io_context's event processing loop:+ *+ * @par+ * @code asio::io_context io_context;+ * // ...+ * asio::thread t(boost::bind(&asio::io_context::run, &io_context));+ * // ...+ * t.join(); @endcode+ */+class thread+  : private noncopyable+{+public:+  /// Start a new thread that executes the supplied function.+  /**+   * This constructor creates a new thread that will execute the given function+   * or function object.+   *+   * @param f The function or function object to be run in the thread. The+   * function signature must be: @code void f(); @endcode+   */+  template <typename Function>+  explicit thread(Function f)+    : impl_(f)+  {+  }++  /// Destructor.+  ~thread()+  {+  }++  /// Wait for the thread to exit.+  /**+   * This function will block until the thread has exited.+   *+   * If this function is not called before the thread object is destroyed, the+   * thread itself will continue to run until completion. You will, however,+   * no longer have the ability to wait for it to exit.+   */+  void join()+  {+    impl_.join();+  }++private:+  detail::thread impl_;+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_THREAD_HPP
+ link/modules/asio-standalone/asio/include/asio/thread_pool.hpp view
@@ -0,0 +1,1111 @@+//+// thread_pool.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_THREAD_POOL_HPP+#define ASIO_THREAD_POOL_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/atomic_count.hpp"+#include "asio/detail/scheduler.hpp"+#include "asio/detail/thread_group.hpp"+#include "asio/execution.hpp"+#include "asio/execution_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {+  struct thread_pool_bits+  {+    ASIO_STATIC_CONSTEXPR(unsigned int, blocking_never = 1);+    ASIO_STATIC_CONSTEXPR(unsigned int, blocking_always = 2);+    ASIO_STATIC_CONSTEXPR(unsigned int, blocking_mask = 3);+    ASIO_STATIC_CONSTEXPR(unsigned int, relationship_continuation = 4);+    ASIO_STATIC_CONSTEXPR(unsigned int, outstanding_work_tracked = 8);+  };+} // namespace detail++/// A simple fixed-size thread pool.+/**+ * The thread pool class is an execution context where functions are permitted+ * to run on one of a fixed number of threads.+ *+ * @par Submitting tasks to the pool+ *+ * To submit functions to the thread pool, use the @ref asio::dispatch,+ * @ref asio::post or @ref asio::defer free functions.+ *+ * For example:+ *+ * @code void my_task()+ * {+ *   ...+ * }+ *+ * ...+ *+ * // Launch the pool with four threads.+ * asio::thread_pool pool(4);+ *+ * // Submit a function to the pool.+ * asio::post(pool, my_task);+ *+ * // Submit a lambda object to the pool.+ * asio::post(pool,+ *     []()+ *     {+ *       ...+ *     });+ *+ * // Wait for all tasks in the pool to complete.+ * pool.join(); @endcode+ */+class thread_pool+  : public execution_context+{+public:+  template <typename Allocator, unsigned int Bits>+  class basic_executor_type;++  template <typename Allocator, unsigned int Bits>+  friend class basic_executor_type;++  /// Executor used to submit functions to a thread pool.+  typedef basic_executor_type<std::allocator<void>, 0> executor_type;++  /// Scheduler used to schedule receivers on a thread pool.+  typedef basic_executor_type<std::allocator<void>, 0> scheduler_type;++#if !defined(ASIO_NO_TS_EXECUTORS)+  /// Constructs a pool with an automatically determined number of threads.+  ASIO_DECL thread_pool();+#endif // !defined(ASIO_NO_TS_EXECUTORS)++  /// Constructs a pool with a specified number of threads.+  ASIO_DECL thread_pool(std::size_t num_threads);++  /// Destructor.+  /**+   * Automatically stops and joins the pool, if not explicitly done beforehand.+   */+  ASIO_DECL ~thread_pool();++  /// Obtains the executor associated with the pool.+  executor_type get_executor() ASIO_NOEXCEPT;++  /// Obtains the executor associated with the pool.+  executor_type executor() ASIO_NOEXCEPT;++  /// Obtains the scheduler associated with the pool.+  scheduler_type scheduler() ASIO_NOEXCEPT;++  /// Stops the threads.+  /**+   * This function stops the threads as soon as possible. As a result of calling+   * @c stop(), pending function objects may be never be invoked.+   */+  ASIO_DECL void stop();++  /// Attaches the current thread to the pool.+  /**+   * This function attaches the current thread to the pool so that it may be+   * used for executing submitted function objects. Blocks the calling thread+   * until the pool is stopped or joined and has no outstanding work.+   */+  ASIO_DECL void attach();++  /// Joins the threads.+  /**+   * This function blocks until the threads in the pool have completed. If @c+   * stop() is not called prior to @c join(), the @c join() call will wait+   * until the pool has no more outstanding work.+   */+  ASIO_DECL void join();++  /// Waits for threads to complete.+  /**+   * This function blocks until the threads in the pool have completed. If @c+   * stop() is not called prior to @c wait(), the @c wait() call will wait+   * until the pool has no more outstanding work.+   */+  ASIO_DECL void wait();++private:+  thread_pool(const thread_pool&) ASIO_DELETED;+  thread_pool& operator=(const thread_pool&) ASIO_DELETED;++  struct thread_function;++  // Helper function to create the underlying scheduler.+  ASIO_DECL detail::scheduler& add_scheduler(detail::scheduler* s);++  // The underlying scheduler.+  detail::scheduler& scheduler_;++  // The threads in the pool.+  detail::thread_group threads_;++  // The current number of threads in the pool.+  detail::atomic_count num_threads_;+};++/// Executor implementation type used to submit functions to a thread pool.+template <typename Allocator, unsigned int Bits>+class thread_pool::basic_executor_type : detail::thread_pool_bits+{+public:+  /// The sender type, when this type is used as a scheduler.+  typedef basic_executor_type sender_type;++  /// The bulk execution shape type.+  typedef std::size_t shape_type;++  /// The bulk execution index type.+  typedef std::size_t index_type;++#if defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT) \+  && defined(ASIO_HAS_STD_EXCEPTION_PTR)+  template <+      template <typename...> class Tuple,+      template <typename...> class Variant>+  using value_types = Variant<Tuple<>>;++  template <template <typename...> class Variant>+  using error_types = Variant<std::exception_ptr>;++  ASIO_STATIC_CONSTEXPR(bool, sends_done = true);+#endif // defined(ASIO_HAS_DEDUCED_EXECUTION_IS_TYPED_SENDER_TRAIT)+       //   && defined(ASIO_HAS_STD_EXCEPTION_PTR)++  /// Copy constructor.+  basic_executor_type(+      const basic_executor_type& other) ASIO_NOEXCEPT+    : pool_(other.pool_),+      allocator_(other.allocator_),+      bits_(other.bits_)+  {+    if (Bits & outstanding_work_tracked)+      if (pool_)+        pool_->scheduler_.work_started();+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  basic_executor_type(basic_executor_type&& other) ASIO_NOEXCEPT+    : pool_(other.pool_),+      allocator_(ASIO_MOVE_CAST(Allocator)(other.allocator_)),+      bits_(other.bits_)+  {+    if (Bits & outstanding_work_tracked)+      other.pool_ = 0;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  ~basic_executor_type() ASIO_NOEXCEPT+  {+    if (Bits & outstanding_work_tracked)+      if (pool_)+        pool_->scheduler_.work_finished();+  }++  /// Assignment operator.+  basic_executor_type& operator=(+      const basic_executor_type& other) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move assignment operator.+  basic_executor_type& operator=(+      basic_executor_type&& other) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Obtain an executor with the @c blocking.possibly property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_thread_pool.executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::blocking.possibly); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type<Allocator,+      ASIO_UNSPECIFIED(Bits & ~blocking_mask)>+  require(execution::blocking_t::possibly_t) const+  {+    return basic_executor_type<Allocator, Bits & ~blocking_mask>(+        pool_, allocator_, bits_ & ~blocking_mask);+  }++  /// Obtain an executor with the @c blocking.always property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_thread_pool.executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::blocking.always); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type<Allocator,+      ASIO_UNSPECIFIED((Bits & ~blocking_mask) | blocking_always)>+  require(execution::blocking_t::always_t) const+  {+    return basic_executor_type<Allocator,+        ASIO_UNSPECIFIED((Bits & ~blocking_mask) | blocking_always)>(+          pool_, allocator_, bits_ & ~blocking_mask);+  }++  /// Obtain an executor with the @c blocking.never property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_thread_pool.executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::blocking.never); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type<Allocator,+      ASIO_UNSPECIFIED(Bits & ~blocking_mask)>+  require(execution::blocking_t::never_t) const+  {+    return basic_executor_type<Allocator, Bits & ~blocking_mask>(+        pool_, allocator_, (bits_ & ~blocking_mask) | blocking_never);+  }++  /// Obtain an executor with the @c relationship.fork property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_thread_pool.executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::relationship.fork); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type require(+      execution::relationship_t::fork_t) const+  {+    return basic_executor_type(pool_,+        allocator_, bits_ & ~relationship_continuation);+  }++  /// Obtain an executor with the @c relationship.continuation property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_thread_pool.executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::relationship.continuation); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type require(+      execution::relationship_t::continuation_t) const+  {+    return basic_executor_type(pool_,+        allocator_, bits_ | relationship_continuation);+  }++  /// Obtain an executor with the @c outstanding_work.tracked property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_thread_pool.executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::outstanding_work.tracked); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type<Allocator,+      ASIO_UNSPECIFIED(Bits | outstanding_work_tracked)>+  require(execution::outstanding_work_t::tracked_t) const+  {+    return basic_executor_type<Allocator, Bits | outstanding_work_tracked>(+        pool_, allocator_, bits_);+  }++  /// Obtain an executor with the @c outstanding_work.untracked property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_thread_pool.executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::outstanding_work.untracked); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type<Allocator,+      ASIO_UNSPECIFIED(Bits & ~outstanding_work_tracked)>+  require(execution::outstanding_work_t::untracked_t) const+  {+    return basic_executor_type<Allocator, Bits & ~outstanding_work_tracked>(+        pool_, allocator_, bits_);+  }++  /// Obtain an executor with the specified @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_thread_pool.executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::allocator(my_allocator)); @endcode+   */+  template <typename OtherAllocator>+  ASIO_CONSTEXPR basic_executor_type<OtherAllocator, Bits>+  require(execution::allocator_t<OtherAllocator> a) const+  {+    return basic_executor_type<OtherAllocator, Bits>(+        pool_, a.value(), bits_);+  }++  /// Obtain an executor with the default @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require customisation point.+   *+   * For example:+   * @code auto ex1 = my_thread_pool.executor();+   * auto ex2 = asio::require(ex1,+   *     asio::execution::allocator); @endcode+   */+  ASIO_CONSTEXPR basic_executor_type<std::allocator<void>, Bits>+  require(execution::allocator_t<void>) const+  {+    return basic_executor_type<std::allocator<void>, Bits>(+        pool_, std::allocator<void>(), bits_);+  }++  /// Query the current value of the @c bulk_guarantee property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * if (asio::query(ex, asio::execution::bulk_guarantee)+   *       == asio::execution::bulk_guarantee.parallel)+   *   ... @endcode+   */+  static ASIO_CONSTEXPR execution::bulk_guarantee_t query(+      execution::bulk_guarantee_t) ASIO_NOEXCEPT+  {+    return execution::bulk_guarantee.parallel;+  }++  /// Query the current value of the @c mapping property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * if (asio::query(ex, asio::execution::mapping)+   *       == asio::execution::mapping.thread)+   *   ... @endcode+   */+  static ASIO_CONSTEXPR execution::mapping_t query(+      execution::mapping_t) ASIO_NOEXCEPT+  {+    return execution::mapping.thread;+  }++  /// Query the current value of the @c context property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * asio::thread_pool& pool = asio::query(+   *     ex, asio::execution::context); @endcode+   */+  thread_pool& query(execution::context_t) const ASIO_NOEXCEPT+  {+    return *pool_;+  }++  /// Query the current value of the @c blocking property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * if (asio::query(ex, asio::execution::blocking)+   *       == asio::execution::blocking.always)+   *   ... @endcode+   */+  ASIO_CONSTEXPR execution::blocking_t query(+      execution::blocking_t) const ASIO_NOEXCEPT+  {+    return (bits_ & blocking_never)+      ? execution::blocking_t(execution::blocking.never)+      : ((Bits & blocking_always)+          ? execution::blocking_t(execution::blocking.always)+          : execution::blocking_t(execution::blocking.possibly));+  }++  /// Query the current value of the @c relationship property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * if (asio::query(ex, asio::execution::relationship)+   *       == asio::execution::relationship.continuation)+   *   ... @endcode+   */+  ASIO_CONSTEXPR execution::relationship_t query(+      execution::relationship_t) const ASIO_NOEXCEPT+  {+    return (bits_ & relationship_continuation)+      ? execution::relationship_t(execution::relationship.continuation)+      : execution::relationship_t(execution::relationship.fork);+  }++  /// Query the current value of the @c outstanding_work property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * if (asio::query(ex, asio::execution::outstanding_work)+   *       == asio::execution::outstanding_work.tracked)+   *   ... @endcode+   */+  static ASIO_CONSTEXPR execution::outstanding_work_t query(+      execution::outstanding_work_t) ASIO_NOEXCEPT+  {+    return (Bits & outstanding_work_tracked)+      ? execution::outstanding_work_t(execution::outstanding_work.tracked)+      : execution::outstanding_work_t(execution::outstanding_work.untracked);+  }++  /// Query the current value of the @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * auto alloc = asio::query(ex,+   *     asio::execution::allocator); @endcode+   */+  template <typename OtherAllocator>+  ASIO_CONSTEXPR Allocator query(+      execution::allocator_t<OtherAllocator>) const ASIO_NOEXCEPT+  {+    return allocator_;+  }++  /// Query the current value of the @c allocator property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * auto alloc = asio::query(ex,+   *     asio::execution::allocator); @endcode+   */+  ASIO_CONSTEXPR Allocator query(+      execution::allocator_t<void>) const ASIO_NOEXCEPT+  {+    return allocator_;+  }++  /// Query the occupancy (recommended number of work items) for the pool.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::query customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * std::size_t occupancy = asio::query(+   *     ex, asio::execution::occupancy); @endcode+   */+  std::size_t query(execution::occupancy_t) const ASIO_NOEXCEPT+  {+    return static_cast<std::size_t>(pool_->num_threads_);+  }++  /// Determine whether the thread pool is running in the current thread.+  /**+   * @return @c true if the current thread is running the thread pool. Otherwise+   * returns @c false.+   */+  bool running_in_this_thread() const ASIO_NOEXCEPT;++  /// Compare two executors for equality.+  /**+   * Two executors are equal if they refer to the same underlying thread pool.+   */+  friend bool operator==(const basic_executor_type& a,+      const basic_executor_type& b) ASIO_NOEXCEPT+  {+    return a.pool_ == b.pool_+      && a.allocator_ == b.allocator_+      && a.bits_ == b.bits_;+  }++  /// Compare two executors for inequality.+  /**+   * Two executors are equal if they refer to the same underlying thread pool.+   */+  friend bool operator!=(const basic_executor_type& a,+      const basic_executor_type& b) ASIO_NOEXCEPT+  {+    return a.pool_ != b.pool_+      || a.allocator_ != b.allocator_+      || a.bits_ != b.bits_;+  }++  /// Execution function.+  /**+   * Do not call this function directly. It is intended for use with the+   * execution::execute customisation point.+   *+   * For example:+   * @code auto ex = my_thread_pool.executor();+   * execution::execute(ex, my_function_object); @endcode+   */+  template <typename Function>+  void execute(ASIO_MOVE_ARG(Function) f) const+  {+    this->do_execute(ASIO_MOVE_CAST(Function)(f),+        integral_constant<bool, (Bits & blocking_always) != 0>());+  }++  /// Bulk execution function.+  template <typename Function>+  void bulk_execute(ASIO_MOVE_ARG(Function) f, std::size_t n) const+  {+    this->do_bulk_execute(ASIO_MOVE_CAST(Function)(f), n,+        integral_constant<bool, (Bits & blocking_always) != 0>());+  }++  /// Schedule function.+  /**+   * Do not call this function directly. It is intended for use with the+   * execution::schedule customisation point.+   *+   * @return An object that satisfies the sender concept.+   */+  sender_type schedule() const ASIO_NOEXCEPT+  {+    return *this;+  }++  /// Connect function.+  /**+   * Do not call this function directly. It is intended for use with the+   * execution::connect customisation point.+   *+   * @return An object of an unspecified type that satisfies the @c+   * operation_state concept.+   */+  template <ASIO_EXECUTION_RECEIVER_OF_0 Receiver>+#if defined(GENERATING_DOCUMENTATION)+  unspecified+#else // defined(GENERATING_DOCUMENTATION)+  execution::detail::as_operation<basic_executor_type, Receiver>+#endif // defined(GENERATING_DOCUMENTATION)+  connect(ASIO_MOVE_ARG(Receiver) r) const+  {+    return execution::detail::as_operation<basic_executor_type, Receiver>(+        *this, ASIO_MOVE_CAST(Receiver)(r));+  }++#if !defined(ASIO_NO_TS_EXECUTORS)+  /// Obtain the underlying execution context.+  thread_pool& context() const ASIO_NOEXCEPT;++  /// Inform the thread pool that it has some outstanding work to do.+  /**+   * This function is used to inform the thread pool that some work has begun.+   * This ensures that the thread pool's join() function will not return while+   * the work is underway.+   */+  void on_work_started() const ASIO_NOEXCEPT;++  /// Inform the thread pool that some work is no longer outstanding.+  /**+   * This function is used to inform the thread pool that some work has+   * finished. Once the count of unfinished work reaches zero, the thread+   * pool's join() function is permitted to exit.+   */+  void on_work_finished() const ASIO_NOEXCEPT;++  /// Request the thread pool to invoke the given function object.+  /**+   * This function is used to ask the thread pool to execute the given function+   * object. If the current thread belongs to the pool, @c dispatch() executes+   * the function before returning. Otherwise, the function will be scheduled+   * to run on the thread pool.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename OtherAllocator>+  void dispatch(ASIO_MOVE_ARG(Function) f,+      const OtherAllocator& a) const;++  /// Request the thread pool to invoke the given function object.+  /**+   * This function is used to ask the thread pool to execute the given function+   * object. The function object will never be executed inside @c post().+   * Instead, it will be scheduled to run on the thread pool.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename OtherAllocator>+  void post(ASIO_MOVE_ARG(Function) f,+      const OtherAllocator& a) const;++  /// Request the thread pool to invoke the given function object.+  /**+   * This function is used to ask the thread pool to execute the given function+   * object. The function object will never be executed inside @c defer().+   * Instead, it will be scheduled to run on the thread pool.+   *+   * If the current thread belongs to the thread pool, @c defer() will delay+   * scheduling the function object until the current thread returns control to+   * the pool.+   *+   * @param f The function object to be called. The executor will make+   * a copy of the handler object as required. The function signature of the+   * function object must be: @code void function(); @endcode+   *+   * @param a An allocator that may be used by the executor to allocate the+   * internal storage needed for function invocation.+   */+  template <typename Function, typename OtherAllocator>+  void defer(ASIO_MOVE_ARG(Function) f,+      const OtherAllocator& a) const;+#endif // !defined(ASIO_NO_TS_EXECUTORS)++private:+  friend class thread_pool;+  template <typename, unsigned int> friend class basic_executor_type;++  // Constructor used by thread_pool::get_executor().+  explicit basic_executor_type(thread_pool& p) ASIO_NOEXCEPT+    : pool_(&p),+      allocator_(),+      bits_(0)+  {+    if (Bits & outstanding_work_tracked)+      pool_->scheduler_.work_started();+  }++  // Constructor used by require().+  basic_executor_type(thread_pool* p,+      const Allocator& a, unsigned int bits) ASIO_NOEXCEPT+    : pool_(p),+      allocator_(a),+      bits_(bits)+  {+    if (Bits & outstanding_work_tracked)+      if (pool_)+        pool_->scheduler_.work_started();+  }++  /// Execution helper implementation for possibly and never blocking.+  template <typename Function>+  void do_execute(ASIO_MOVE_ARG(Function) f, false_type) const;++  /// Execution helper implementation for always blocking.+  template <typename Function>+  void do_execute(ASIO_MOVE_ARG(Function) f, true_type) const;++  /// Bulk execution helper implementation for possibly and never blocking.+  template <typename Function>+  void do_bulk_execute(ASIO_MOVE_ARG(Function) f,+      std::size_t n, false_type) const;++  /// Bulk execution helper implementation for always blocking.+  template <typename Function>+  void do_bulk_execute(ASIO_MOVE_ARG(Function) f,+      std::size_t n, true_type) const;++  // The underlying thread pool.+  thread_pool* pool_;++  // The allocator used for execution functions.+  Allocator allocator_;++  // The runtime-switched properties of the thread pool executor.+  unsigned int bits_;+};++#if !defined(GENERATING_DOCUMENTATION)++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <typename Allocator, unsigned int Bits>+struct equality_comparable<+    asio::thread_pool::basic_executor_type<Allocator, Bits>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits, typename Function>+struct execute_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    Function+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits>+struct schedule_member<+    const asio::thread_pool::basic_executor_type<Allocator, Bits>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::thread_pool::basic_executor_type<+      Allocator, Bits> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits, typename Receiver>+struct connect_member<+    const asio::thread_pool::basic_executor_type<Allocator, Bits>,+    Receiver+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::execution::detail::as_operation<+      asio::thread_pool::basic_executor_type<Allocator, Bits>,+      Receiver> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::blocking_t::possibly_t+  > : asio::detail::thread_pool_bits+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::thread_pool::basic_executor_type<+      Allocator, Bits & ~blocking_mask> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::blocking_t::always_t+  > : asio::detail::thread_pool_bits+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::thread_pool::basic_executor_type<Allocator,+      (Bits & ~blocking_mask) | blocking_always> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::blocking_t::never_t+  > : asio::detail::thread_pool_bits+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::thread_pool::basic_executor_type<+      Allocator, Bits & ~blocking_mask> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::relationship_t::fork_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::thread_pool::basic_executor_type<+      Allocator, Bits> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::relationship_t::continuation_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::thread_pool::basic_executor_type<+      Allocator, Bits> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::outstanding_work_t::tracked_t+  > : asio::detail::thread_pool_bits+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::thread_pool::basic_executor_type<+      Allocator, Bits | outstanding_work_tracked> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::outstanding_work_t::untracked_t+  > : asio::detail::thread_pool_bits+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::thread_pool::basic_executor_type<+      Allocator, Bits & ~outstanding_work_tracked> result_type;+};++template <typename Allocator, unsigned int Bits>+struct require_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::allocator_t<void>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::thread_pool::basic_executor_type<+      std::allocator<void>, Bits> result_type;+};++template <unsigned int Bits,+    typename Allocator, typename OtherAllocator>+struct require_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::allocator_t<OtherAllocator>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+  typedef asio::thread_pool::basic_executor_type<+      OtherAllocator, Bits> result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits, typename Property>+struct query_static_constexpr_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::bulk_guarantee_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::bulk_guarantee_t::parallel_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++template <typename Allocator, unsigned int Bits, typename Property>+struct query_static_constexpr_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::outstanding_work_t+      >::value+    >::type+  > : asio::detail::thread_pool_bits+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::outstanding_work_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return (Bits & outstanding_work_tracked)+      ? execution::outstanding_work_t(execution::outstanding_work.tracked)+      : execution::outstanding_work_t(execution::outstanding_work.untracked);+  }+};++template <typename Allocator, unsigned int Bits, typename Property>+struct query_static_constexpr_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::mapping_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::mapping_t::thread_t result_type;++  static ASIO_CONSTEXPR result_type value() ASIO_NOEXCEPT+  {+    return result_type();+  }+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename Allocator, unsigned int Bits, typename Property>+struct query_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::blocking_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::blocking_t result_type;+};++template <typename Allocator, unsigned int Bits, typename Property>+struct query_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    Property,+    typename asio::enable_if<+      asio::is_convertible<+        Property,+        asio::execution::relationship_t+      >::value+    >::type+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::execution::relationship_t result_type;+};++template <typename Allocator, unsigned int Bits>+struct query_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::occupancy_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef std::size_t result_type;+};++template <typename Allocator, unsigned int Bits>+struct query_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::context_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::thread_pool& result_type;+};++template <typename Allocator, unsigned int Bits>+struct query_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::allocator_t<void>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef Allocator result_type;+};++template <typename Allocator, unsigned int Bits, typename OtherAllocator>+struct query_member<+    asio::thread_pool::basic_executor_type<Allocator, Bits>,+    asio::execution::allocator_t<OtherAllocator>+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef Allocator result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++} // namespace traits++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/thread_pool.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/thread_pool.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_THREAD_POOL_HPP
+ link/modules/asio-standalone/asio/include/asio/time_traits.hpp view
@@ -0,0 +1,86 @@+//+// time_traits.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TIME_TRAITS_HPP+#define ASIO_TIME_TRAITS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/socket_types.hpp" // Must come before posix_time.++#if defined(ASIO_HAS_BOOST_DATE_TIME) \+  || defined(GENERATING_DOCUMENTATION)++#include <boost/date_time/posix_time/posix_time_types.hpp>++#include "asio/detail/push_options.hpp"++namespace asio {++/// Time traits suitable for use with the deadline timer.+template <typename Time>+struct time_traits;++/// Time traits specialised for posix_time.+template <>+struct time_traits<boost::posix_time::ptime>+{+  /// The time type.+  typedef boost::posix_time::ptime time_type;++  /// The duration type.+  typedef boost::posix_time::time_duration duration_type;++  /// Get the current time.+  static time_type now()+  {+#if defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)+    return boost::posix_time::microsec_clock::universal_time();+#else // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)+    return boost::posix_time::second_clock::universal_time();+#endif // defined(BOOST_DATE_TIME_HAS_HIGH_PRECISION_CLOCK)+  }++  /// Add a duration to a time.+  static time_type add(const time_type& t, const duration_type& d)+  {+    return t + d;+  }++  /// Subtract one time from another.+  static duration_type subtract(const time_type& t1, const time_type& t2)+  {+    return t1 - t2;+  }++  /// Test whether one time is less than another.+  static bool less_than(const time_type& t1, const time_type& t2)+  {+    return t1 < t2;+  }++  /// Convert to POSIX duration type.+  static boost::posix_time::time_duration to_posix_duration(+      const duration_type& d)+  {+    return d;+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_BOOST_DATE_TIME)+       // || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_TIME_TRAITS_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_free.hpp view
@@ -0,0 +1,114 @@+//+// traits/bulk_execute_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_BULK_EXECUTE_FREE_HPP+#define ASIO_TRAITS_BULK_EXECUTE_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_BULK_EXECUTE_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename F, typename N, typename = void>+struct bulk_execute_free_default;++template <typename T, typename F, typename N, typename = void>+struct bulk_execute_free;++} // namespace traits+namespace detail {++struct no_bulk_execute_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_FREE_TRAIT)++template <typename T, typename F, typename N, typename = void>+struct bulk_execute_free_trait : no_bulk_execute_free+{+};++template <typename T, typename F, typename N>+struct bulk_execute_free_trait<T, F, N,+  typename void_type<+    decltype(bulk_execute(declval<T>(), declval<F>(), declval<N>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    bulk_execute(declval<T>(), declval<F>(), declval<N>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    bulk_execute(declval<T>(), declval<F>(), declval<N>())));+};++#else // defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_FREE_TRAIT)++template <typename T, typename F, typename N, typename = void>+struct bulk_execute_free_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value+      && is_same<F, typename decay<F>::type>::value+      && is_same<N, typename decay<N>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_bulk_execute_free,+      traits::bulk_execute_free<typename add_const<T>::type, F, N>+    >::type,+    traits::bulk_execute_free<+      typename remove_reference<T>::type,+      typename decay<F>::type,+      typename decay<N>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename F, typename N, typename>+struct bulk_execute_free_default :+  detail::bulk_execute_free_trait<T, F, N>+{+};++template <typename T, typename F, typename N, typename>+struct bulk_execute_free :+  bulk_execute_free_default<T, F, N>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_BULK_EXECUTE_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_member.hpp view
@@ -0,0 +1,114 @@+//+// traits/bulk_execute_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_BULK_EXECUTE_MEMBER_HPP+#define ASIO_TRAITS_BULK_EXECUTE_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_BULK_EXECUTE_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename F, typename N, typename = void>+struct bulk_execute_member_default;++template <typename T, typename F, typename N, typename = void>+struct bulk_execute_member;++} // namespace traits+namespace detail {++struct no_bulk_execute_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_MEMBER_TRAIT)++template <typename T, typename F, typename N, typename = void>+struct bulk_execute_member_trait : no_bulk_execute_member+{+};++template <typename T, typename F, typename N>+struct bulk_execute_member_trait<T, F, N,+  typename void_type<+    decltype(declval<T>().bulk_execute(declval<F>(), declval<N>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<T>().bulk_execute(declval<F>(), declval<N>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<T>().bulk_execute(declval<F>(), declval<N>())));+};++#else // defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_MEMBER_TRAIT)++template <typename T, typename F, typename N, typename = void>+struct bulk_execute_member_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value+      && is_same<F, typename decay<F>::type>::value+      && is_same<N, typename decay<N>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_bulk_execute_member,+      traits::bulk_execute_member<typename add_const<T>::type, F, N>+    >::type,+    traits::bulk_execute_member<+      typename remove_reference<T>::type,+      typename decay<F>::type,+      typename decay<N>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_BULK_EXECUTE_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename F, typename N, typename>+struct bulk_execute_member_default :+  detail::bulk_execute_member_trait<T, F, N>+{+};++template <typename T, typename F, typename N, typename>+struct bulk_execute_member :+  bulk_execute_member_default<T, F, N>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_BULK_EXECUTE_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/connect_free.hpp view
@@ -0,0 +1,112 @@+//+// traits/connect_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_CONNECT_FREE_HPP+#define ASIO_TRAITS_CONNECT_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename S, typename R, typename = void>+struct connect_free_default;++template <typename S, typename R, typename = void>+struct connect_free;++} // namespace traits+namespace detail {++struct no_connect_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT)++template <typename S, typename R, typename = void>+struct connect_free_trait : no_connect_free+{+};++template <typename S, typename R>+struct connect_free_trait<S, R,+  typename void_type<+    decltype(connect(declval<S>(), declval<R>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    connect(declval<S>(), declval<R>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    connect(declval<S>(), declval<R>())));+};++#else // defined(ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT)++template <typename S, typename R, typename = void>+struct connect_free_trait :+  conditional<+    is_same<S, typename remove_reference<S>::type>::value+      && is_same<R, typename decay<R>::type>::value,+    typename conditional<+      is_same<S, typename add_const<S>::type>::value,+      no_connect_free,+      traits::connect_free<typename add_const<S>::type, R>+    >::type,+    traits::connect_free<+      typename remove_reference<S>::type,+      typename decay<R>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_CONNECT_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename S, typename R, typename>+struct connect_free_default :+  detail::connect_free_trait<S, R>+{+};++template <typename S, typename R, typename>+struct connect_free :+  connect_free_default<S, R>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_CONNECT_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/connect_member.hpp view
@@ -0,0 +1,112 @@+//+// traits/connect_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_CONNECT_MEMBER_HPP+#define ASIO_TRAITS_CONNECT_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename S, typename R, typename = void>+struct connect_member_default;++template <typename S, typename R, typename = void>+struct connect_member;++} // namespace traits+namespace detail {++struct no_connect_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)++template <typename S, typename R, typename = void>+struct connect_member_trait : no_connect_member+{+};++template <typename S, typename R>+struct connect_member_trait<S, R,+  typename void_type<+    decltype(declval<S>().connect(declval<R>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<S>().connect(declval<R>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<S>().connect(declval<R>())));+};++#else // defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)++template <typename S, typename R, typename = void>+struct connect_member_trait :+  conditional<+    is_same<S, typename remove_reference<S>::type>::value+      && is_same<R, typename decay<R>::type>::value,+    typename conditional<+      is_same<S, typename add_const<S>::type>::value,+      no_connect_member,+      traits::connect_member<typename add_const<S>::type, R>+    >::type,+    traits::connect_member<+      typename remove_reference<S>::type,+      typename decay<R>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename S, typename R, typename>+struct connect_member_default :+  detail::connect_member_trait<S, R>+{+};++template <typename S, typename R, typename>+struct connect_member :+  connect_member_default<S, R>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_CONNECT_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/equality_comparable.hpp view
@@ -0,0 +1,100 @@+//+// traits/equality_comparable.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_EQUALITY_COMPARABLE_HPP+#define ASIO_TRAITS_EQUALITY_COMPARABLE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++namespace asio {+namespace traits {++template <typename T, typename = void>+struct equality_comparable_default;++template <typename T, typename = void>+struct equality_comparable;++} // namespace traits+namespace detail {++struct no_equality_comparable+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <typename T, typename = void>+struct equality_comparable_trait : no_equality_comparable+{+};++template <typename T>+struct equality_comparable_trait<T,+  typename void_type<+    decltype(+      static_cast<bool>(declval<const T>() == declval<const T>()),+      static_cast<bool>(declval<const T>() != declval<const T>())+    )+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    noexcept(declval<const T>() == declval<const T>())+      && noexcept(declval<const T>() != declval<const T>()));+};++#else // defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <typename T, typename = void>+struct equality_comparable_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value,+    no_equality_comparable,+    traits::equality_comparable<typename decay<T>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename>+struct equality_comparable_default : detail::equality_comparable_trait<T>+{+};++template <typename T, typename>+struct equality_comparable : equality_comparable_default<T>+{+};++} // namespace traits+} // namespace asio++#endif // ASIO_TRAITS_EQUALITY_COMPARABLE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/execute_free.hpp view
@@ -0,0 +1,108 @@+//+// traits/execute_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_EXECUTE_FREE_HPP+#define ASIO_TRAITS_EXECUTE_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename F, typename = void>+struct execute_free_default;++template <typename T, typename F, typename = void>+struct execute_free;++} // namespace traits+namespace detail {++struct no_execute_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT)++template <typename T, typename F, typename = void>+struct execute_free_trait : no_execute_free+{+};++template <typename T, typename F>+struct execute_free_trait<T, F,+  typename void_type<+    decltype(execute(declval<T>(), declval<F>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    execute(declval<T>(), declval<F>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    execute(declval<T>(), declval<F>())));+};++#else // defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT)++template <typename T, typename F, typename = void>+struct execute_free_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<F, typename decay<F>::type>::value,+    no_execute_free,+    traits::execute_free<+      typename decay<T>::type,+      typename decay<F>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename F, typename>+struct execute_free_default :+  detail::execute_free_trait<T, F>+{+};++template <typename T, typename F, typename>+struct execute_free :+  execute_free_default<T, F>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_EXECUTE_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/execute_member.hpp view
@@ -0,0 +1,108 @@+//+// traits/execute_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_EXECUTE_MEMBER_HPP+#define ASIO_TRAITS_EXECUTE_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename F, typename = void>+struct execute_member_default;++template <typename T, typename F, typename = void>+struct execute_member;++} // namespace traits+namespace detail {++struct no_execute_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename T, typename F, typename = void>+struct execute_member_trait : no_execute_member+{+};++template <typename T, typename F>+struct execute_member_trait<T, F,+  typename void_type<+    decltype(declval<T>().execute(declval<F>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<T>().execute(declval<F>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<T>().execute(declval<F>())));+};++#else // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename T, typename F, typename = void>+struct execute_member_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<F, typename decay<F>::type>::value,+    no_execute_member,+    traits::execute_member<+      typename decay<T>::type,+      typename decay<F>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename F, typename>+struct execute_member_default :+  detail::execute_member_trait<T, F>+{+};++template <typename T, typename F, typename>+struct execute_member :+  execute_member_default<T, F>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_EXECUTE_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/prefer_free.hpp view
@@ -0,0 +1,108 @@+//+// traits/prefer_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_PREFER_FREE_HPP+#define ASIO_TRAITS_PREFER_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct prefer_free_default;++template <typename T, typename Property, typename = void>+struct prefer_free;++} // namespace traits+namespace detail {++struct no_prefer_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)++template <typename T, typename Property, typename = void>+struct prefer_free_trait : no_prefer_free+{+};++template <typename T, typename Property>+struct prefer_free_trait<T, Property,+  typename void_type<+    decltype(prefer(declval<T>(), declval<Property>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    prefer(declval<T>(), declval<Property>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    prefer(declval<T>(), declval<Property>())));+};++#else // defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)++template <typename T, typename Property, typename = void>+struct prefer_free_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_prefer_free,+    traits::prefer_free<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_PREFER_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct prefer_free_default :+  detail::prefer_free_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct prefer_free :+  prefer_free_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_PREFER_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/prefer_member.hpp view
@@ -0,0 +1,108 @@+//+// traits/prefer_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_PREFER_MEMBER_HPP+#define ASIO_TRAITS_PREFER_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct prefer_member_default;++template <typename T, typename Property, typename = void>+struct prefer_member;++} // namespace traits+namespace detail {++struct no_prefer_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++template <typename T, typename Property, typename = void>+struct prefer_member_trait : no_prefer_member+{+};++template <typename T, typename Property>+struct prefer_member_trait<T, Property,+  typename void_type<+    decltype(declval<T>().prefer(declval<Property>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<T>().prefer(declval<Property>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<T>().prefer(declval<Property>())));+};++#else // defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++template <typename T, typename Property, typename = void>+struct prefer_member_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_prefer_member,+    traits::prefer_member<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct prefer_member_default :+  detail::prefer_member_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct prefer_member :+  prefer_member_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_PREFER_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/query_free.hpp view
@@ -0,0 +1,108 @@+//+// traits/query_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_QUERY_FREE_HPP+#define ASIO_TRAITS_QUERY_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct query_free_default;++template <typename T, typename Property, typename = void>+struct query_free;++} // namespace traits+namespace detail {++struct no_query_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T, typename Property, typename = void>+struct query_free_trait : no_query_free+{+};++template <typename T, typename Property>+struct query_free_trait<T, Property,+  typename void_type<+    decltype(query(declval<T>(), declval<Property>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    query(declval<T>(), declval<Property>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    query(declval<T>(), declval<Property>())));+};++#else // defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++template <typename T, typename Property, typename = void>+struct query_free_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_query_free,+    traits::query_free<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_QUERY_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct query_free_default :+  detail::query_free_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct query_free :+  query_free_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_QUERY_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/query_member.hpp view
@@ -0,0 +1,108 @@+//+// traits/query_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_QUERY_MEMBER_HPP+#define ASIO_TRAITS_QUERY_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct query_member_default;++template <typename T, typename Property, typename = void>+struct query_member;++} // namespace traits+namespace detail {++struct no_query_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename T, typename Property, typename = void>+struct query_member_trait : no_query_member+{+};++template <typename T, typename Property>+struct query_member_trait<T, Property,+  typename void_type<+    decltype(declval<T>().query(declval<Property>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<T>().query(declval<Property>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<T>().query(declval<Property>())));+};++#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename T, typename Property, typename = void>+struct query_member_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_query_member,+    traits::query_member<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct query_member_default :+  detail::query_member_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct query_member :+  query_member_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_QUERY_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/query_static_constexpr_member.hpp view
@@ -0,0 +1,108 @@+//+// traits/query_static_constexpr_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_QUERY_STATIC_CONSTEXPR_MEMBER_HPP+#define ASIO_TRAITS_QUERY_STATIC_CONSTEXPR_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_CONSTEXPR) \+  && defined(ASIO_HAS_CONSTANT_EXPRESSION_SFINAE) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_CONSTEXPR)+       //   && defined(ASIO_HAS_CONSTANT_EXPRESSION_SFINAE)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct query_static_constexpr_member_default;++template <typename T, typename Property, typename = void>+struct query_static_constexpr_member;++} // namespace traits+namespace detail {++struct no_query_static_constexpr_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+};++template <typename T, typename Property, typename = void>+struct query_static_constexpr_member_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_query_static_constexpr_member,+    traits::query_static_constexpr_member<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++template <typename T, typename Property>+struct query_static_constexpr_member_trait<T, Property,+  typename enable_if<+    (static_cast<void>(T::query(Property{})), true)+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(T::query(Property{}));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    noexcept(T::query(Property{})));++  static ASIO_CONSTEXPR result_type value() noexcept(is_noexcept)+  {+    return T::query(Property{});+  }+};++#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct query_static_constexpr_member_default :+  detail::query_static_constexpr_member_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct query_static_constexpr_member :+  query_static_constexpr_member_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_QUERY_STATIC_CONSTEXPR_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/require_concept_free.hpp view
@@ -0,0 +1,108 @@+//+// traits/require_concept_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_REQUIRE_CONCEPT_FREE_HPP+#define ASIO_TRAITS_REQUIRE_CONCEPT_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct require_concept_free_default;++template <typename T, typename Property, typename = void>+struct require_concept_free;++} // namespace traits+namespace detail {++struct no_require_concept_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_FREE_TRAIT)++template <typename T, typename Property, typename = void>+struct require_concept_free_trait : no_require_concept_free+{+};++template <typename T, typename Property>+struct require_concept_free_trait<T, Property,+  typename void_type<+    decltype(require_concept(declval<T>(), declval<Property>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    require_concept(declval<T>(), declval<Property>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    require_concept(declval<T>(), declval<Property>())));+};++#else // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_FREE_TRAIT)++template <typename T, typename Property, typename = void>+struct require_concept_free_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_require_concept_free,+    traits::require_concept_free<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct require_concept_free_default :+  detail::require_concept_free_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct require_concept_free :+  require_concept_free_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_REQUIRE_CONCEPT_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/require_concept_member.hpp view
@@ -0,0 +1,108 @@+//+// traits/require_concept_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_REQUIRE_CONCEPT_MEMBER_HPP+#define ASIO_TRAITS_REQUIRE_CONCEPT_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct require_concept_member_default;++template <typename T, typename Property, typename = void>+struct require_concept_member;++} // namespace traits+namespace detail {++struct no_require_concept_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)++template <typename T, typename Property, typename = void>+struct require_concept_member_trait : no_require_concept_member+{+};++template <typename T, typename Property>+struct require_concept_member_trait<T, Property,+  typename void_type<+    decltype(declval<T>().require_concept(declval<Property>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<T>().require_concept(declval<Property>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<T>().require_concept(declval<Property>())));+};++#else // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)++template <typename T, typename Property, typename = void>+struct require_concept_member_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_require_concept_member,+    traits::require_concept_member<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct require_concept_member_default :+  detail::require_concept_member_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct require_concept_member :+  require_concept_member_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_REQUIRE_CONCEPT_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/require_free.hpp view
@@ -0,0 +1,108 @@+//+// traits/require_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_REQUIRE_FREE_HPP+#define ASIO_TRAITS_REQUIRE_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct require_free_default;++template <typename T, typename Property, typename = void>+struct require_free;++} // namespace traits+namespace detail {++struct no_require_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)++template <typename T, typename Property, typename = void>+struct require_free_trait : no_require_free+{+};++template <typename T, typename Property>+struct require_free_trait<T, Property,+  typename void_type<+    decltype(require(declval<T>(), declval<Property>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    require(declval<T>(), declval<Property>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    require(declval<T>(), declval<Property>())));+};++#else // defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)++template <typename T, typename Property, typename = void>+struct require_free_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_require_free,+    traits::require_free<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct require_free_default :+  detail::require_free_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct require_free :+  require_free_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_REQUIRE_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/require_member.hpp view
@@ -0,0 +1,108 @@+//+// traits/require_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_REQUIRE_MEMBER_HPP+#define ASIO_TRAITS_REQUIRE_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct require_member_default;++template <typename T, typename Property, typename = void>+struct require_member;++} // namespace traits+namespace detail {++struct no_require_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename T, typename Property, typename = void>+struct require_member_trait : no_require_member+{+};++template <typename T, typename Property>+struct require_member_trait<T, Property,+  typename void_type<+    decltype(declval<T>().require(declval<Property>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<T>().require(declval<Property>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<T>().require(declval<Property>())));+};++#else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename T, typename Property, typename = void>+struct require_member_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_require_member,+    traits::require_member<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct require_member_default :+  detail::require_member_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct require_member :+  require_member_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_REQUIRE_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/schedule_free.hpp view
@@ -0,0 +1,108 @@+//+// traits/schedule_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SCHEDULE_FREE_HPP+#define ASIO_TRAITS_SCHEDULE_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename = void>+struct schedule_free_default;++template <typename T, typename = void>+struct schedule_free;++} // namespace traits+namespace detail {++struct no_schedule_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT)++template <typename T, typename = void>+struct schedule_free_trait : no_schedule_free+{+};++template <typename T>+struct schedule_free_trait<T,+  typename void_type<+    decltype(schedule(declval<T>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(schedule(declval<T>()));++  ASIO_STATIC_CONSTEXPR(bool,+    is_noexcept = noexcept(schedule(declval<T>())));+};++#else // defined(ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT)++template <typename T, typename = void>+struct schedule_free_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_schedule_free,+      traits::schedule_free<typename add_const<T>::type>+    >::type,+    traits::schedule_free<typename remove_reference<T>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_SCHEDULE_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename>+struct schedule_free_default :+  detail::schedule_free_trait<T>+{+};++template <typename T, typename>+struct schedule_free :+  schedule_free_default<T>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SCHEDULE_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/schedule_member.hpp view
@@ -0,0 +1,108 @@+//+// traits/schedule_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SCHEDULE_MEMBER_HPP+#define ASIO_TRAITS_SCHEDULE_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename = void>+struct schedule_member_default;++template <typename T, typename = void>+struct schedule_member;++} // namespace traits+namespace detail {++struct no_schedule_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT)++template <typename T, typename = void>+struct schedule_member_trait : no_schedule_member+{+};++template <typename T>+struct schedule_member_trait<T,+  typename void_type<+    decltype(declval<T>().schedule())+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(declval<T>().schedule());++  ASIO_STATIC_CONSTEXPR(bool,+    is_noexcept = noexcept(declval<T>().schedule()));+};++#else // defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT)++template <typename T, typename = void>+struct schedule_member_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_schedule_member,+      traits::schedule_member<typename add_const<T>::type>+    >::type,+    traits::schedule_member<typename remove_reference<T>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename>+struct schedule_member_default :+  detail::schedule_member_trait<T>+{+};++template <typename T, typename>+struct schedule_member :+  schedule_member_default<T>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SCHEDULE_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/set_done_free.hpp view
@@ -0,0 +1,108 @@+//+// traits/set_done_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SET_DONE_FREE_HPP+#define ASIO_TRAITS_SET_DONE_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename = void>+struct set_done_free_default;++template <typename T, typename = void>+struct set_done_free;++} // namespace traits+namespace detail {++struct no_set_done_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT)++template <typename T, typename = void>+struct set_done_free_trait : no_set_done_free+{+};++template <typename T>+struct set_done_free_trait<T,+  typename void_type<+    decltype(set_done(declval<T>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(set_done(declval<T>()));++  ASIO_STATIC_CONSTEXPR(bool,+    is_noexcept = noexcept(set_done(declval<T>())));+};++#else // defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT)++template <typename T, typename = void>+struct set_done_free_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_set_done_free,+      traits::set_done_free<typename add_const<T>::type>+    >::type,+    traits::set_done_free<typename remove_reference<T>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_SET_DONE_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename>+struct set_done_free_default :+  detail::set_done_free_trait<T>+{+};++template <typename T, typename>+struct set_done_free :+  set_done_free_default<T>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SET_DONE_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/set_done_member.hpp view
@@ -0,0 +1,108 @@+//+// traits/set_done_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SET_DONE_MEMBER_HPP+#define ASIO_TRAITS_SET_DONE_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename = void>+struct set_done_member_default;++template <typename T, typename = void>+struct set_done_member;++} // namespace traits+namespace detail {++struct no_set_done_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++template <typename T, typename = void>+struct set_done_member_trait : no_set_done_member+{+};++template <typename T>+struct set_done_member_trait<T,+  typename void_type<+    decltype(declval<T>().set_done())+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(declval<T>().set_done());++  ASIO_STATIC_CONSTEXPR(bool,+    is_noexcept = noexcept(declval<T>().set_done()));+};++#else // defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++template <typename T, typename = void>+struct set_done_member_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_set_done_member,+      traits::set_done_member<typename add_const<T>::type>+    >::type,+    traits::set_done_member<typename remove_reference<T>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_SET_DONE_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename>+struct set_done_member_default :+  detail::set_done_member_trait<T>+{+};++template <typename T, typename>+struct set_done_member :+  set_done_member_default<T>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SET_DONE_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/set_error_free.hpp view
@@ -0,0 +1,112 @@+//+// traits/set_error_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SET_ERROR_FREE_HPP+#define ASIO_TRAITS_SET_ERROR_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename E, typename = void>+struct set_error_free_default;++template <typename T, typename E, typename = void>+struct set_error_free;++} // namespace traits+namespace detail {++struct no_set_error_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT)++template <typename T, typename E, typename = void>+struct set_error_free_trait : no_set_error_free+{+};++template <typename T, typename E>+struct set_error_free_trait<T, E,+  typename void_type<+    decltype(set_error(declval<T>(), declval<E>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    set_error(declval<T>(), declval<E>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    set_error(declval<T>(), declval<E>())));+};++#else // defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT)++template <typename T, typename E, typename = void>+struct set_error_free_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value+      && is_same<E, typename decay<E>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_set_error_free,+      traits::set_error_free<typename add_const<T>::type, E>+    >::type,+    traits::set_error_free<+      typename remove_reference<T>::type,+      typename decay<E>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_SET_ERROR_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename E, typename>+struct set_error_free_default :+  detail::set_error_free_trait<T, E>+{+};++template <typename T, typename E, typename>+struct set_error_free :+  set_error_free_default<T, E>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SET_ERROR_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/set_error_member.hpp view
@@ -0,0 +1,112 @@+//+// traits/set_error_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SET_ERROR_MEMBER_HPP+#define ASIO_TRAITS_SET_ERROR_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename E, typename = void>+struct set_error_member_default;++template <typename T, typename E, typename = void>+struct set_error_member;++} // namespace traits+namespace detail {++struct no_set_error_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++template <typename T, typename E, typename = void>+struct set_error_member_trait : no_set_error_member+{+};++template <typename T, typename E>+struct set_error_member_trait<T, E,+  typename void_type<+    decltype(declval<T>().set_error(declval<E>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<T>().set_error(declval<E>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<T>().set_error(declval<E>())));+};++#else // defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++template <typename T, typename E, typename = void>+struct set_error_member_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value+      && is_same<E, typename decay<E>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_set_error_member,+      traits::set_error_member<typename add_const<T>::type, E>+    >::type,+    traits::set_error_member<+      typename remove_reference<T>::type,+      typename decay<E>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_SET_ERROR_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename E, typename>+struct set_error_member_default :+  detail::set_error_member_trait<T, E>+{+};++template <typename T, typename E, typename>+struct set_error_member :+  set_error_member_default<T, E>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SET_ERROR_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/set_value_free.hpp view
@@ -0,0 +1,234 @@+//+// traits/set_value_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SET_VALUE_FREE_HPP+#define ASIO_TRAITS_SET_VALUE_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Vs, typename = void>+struct set_value_free_default;++template <typename T, typename Vs, typename = void>+struct set_value_free;++} // namespace traits+namespace detail {++struct no_set_value_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT)++template <typename T, typename Vs, typename = void>+struct set_value_free_trait : no_set_value_free+{+};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Vs>+struct set_value_free_trait<T, void(Vs...),+  typename void_type<+    decltype(set_value(declval<T>(), declval<Vs>()...))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    set_value(declval<T>(), declval<Vs>()...));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    set_value(declval<T>(), declval<Vs>()...)));+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T>+struct set_value_free_trait<T, void(),+  typename void_type<+    decltype(set_value(declval<T>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(set_value(declval<T>()));++  ASIO_STATIC_CONSTEXPR(bool,+    is_noexcept = noexcept(set_value(declval<T>())));+};++#define ASIO_PRIVATE_SET_VALUE_FREE_TRAIT_DEF(n) \+  template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+  struct set_value_free_trait<T, void(ASIO_VARIADIC_TARGS(n)), \+    typename void_type< \+      decltype(set_value(declval<T>(), ASIO_VARIADIC_DECLVAL(n))) \+    >::type> \+  { \+    ASIO_STATIC_CONSTEXPR(bool, is_valid = true); \+  \+    using result_type = decltype( \+      set_value(declval<T>(), ASIO_VARIADIC_DECLVAL(n))); \+  \+    ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( \+      set_value(declval<T>(), ASIO_VARIADIC_DECLVAL(n)))); \+  }; \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_FREE_TRAIT_DEF)+#undef ASIO_PRIVATE_SET_VALUE_FREE_TRAIT_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#else // defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT)++template <typename T, typename Vs, typename = void>+struct set_value_free_trait;++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Vs>+struct set_value_free_trait<T, void(Vs...)> :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value+      && conjunction<is_same<Vs, typename decay<Vs>::type>...>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_set_value_free,+      traits::set_value_free<typename add_const<T>::type, void(Vs...)>+    >::type,+    traits::set_value_free<+      typename remove_reference<T>::type,+      void(typename decay<Vs>::type...)>+  >::type+{+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T>+struct set_value_free_trait<T, void()> :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_set_value_free,+      traits::set_value_free<typename add_const<T>::type, void()>+    >::type,+    traits::set_value_free<typename remove_reference<T>::type, void()>+  >::type+{+};++#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME(n) \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_##n++#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 \+  && is_same<T1, typename decay<T1>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 \+  && is_same<T2, typename decay<T2>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 \+  && is_same<T3, typename decay<T3>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 \+  && is_same<T4, typename decay<T4>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 \+  && is_same<T5, typename decay<T5>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 \+  && is_same<T6, typename decay<T6>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 \+  && is_same<T7, typename decay<T7>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_8 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 \+  && is_same<T8, typename decay<T8>::type>::value++#define ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF(n) \+  template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+  struct set_value_free_trait<T, void(ASIO_VARIADIC_TARGS(n))> : \+    conditional< \+      is_same<T, typename remove_reference<T>::type>::value \+        ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME(n), \+      typename conditional< \+        is_same<T, typename add_const<T>::type>::value, \+        no_set_value_free, \+        traits::set_value_free< \+          typename add_const<T>::type, \+          void(ASIO_VARIADIC_TARGS(n))> \+      >::type, \+      traits::set_value_free< \+        typename remove_reference<T>::type, \+        void(ASIO_VARIADIC_DECAY(n))> \+    >::type \+  { \+  }; \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF)+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_8++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#endif // defined(ASIO_HAS_DEDUCED_SET_VALUE_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Vs, typename>+struct set_value_free_default :+  detail::set_value_free_trait<T, Vs>+{+};++template <typename T, typename Vs, typename>+struct set_value_free :+  set_value_free_default<T, Vs>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SET_VALUE_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/set_value_member.hpp view
@@ -0,0 +1,234 @@+//+// traits/set_value_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SET_VALUE_MEMBER_HPP+#define ASIO_TRAITS_SET_VALUE_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Vs, typename = void>+struct set_value_member_default;++template <typename T, typename Vs, typename = void>+struct set_value_member;++} // namespace traits+namespace detail {++struct no_set_value_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++template <typename T, typename Vs, typename = void>+struct set_value_member_trait : no_set_value_member+{+};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Vs>+struct set_value_member_trait<T, void(Vs...),+  typename void_type<+    decltype(declval<T>().set_value(declval<Vs>()...))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<T>().set_value(declval<Vs>()...));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<T>().set_value(declval<Vs>()...)));+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T>+struct set_value_member_trait<T, void(),+  typename void_type<+    decltype(declval<T>().set_value())+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(declval<T>().set_value());++  ASIO_STATIC_CONSTEXPR(bool,+    is_noexcept = noexcept(declval<T>().set_value()));+};++#define ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF(n) \+  template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+  struct set_value_member_trait<T, void(ASIO_VARIADIC_TARGS(n)), \+    typename void_type< \+      decltype(declval<T>().set_value(ASIO_VARIADIC_DECLVAL(n))) \+    >::type> \+  { \+    ASIO_STATIC_CONSTEXPR(bool, is_valid = true); \+  \+    using result_type = decltype( \+      declval<T>().set_value(ASIO_VARIADIC_DECLVAL(n))); \+  \+    ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept( \+      declval<T>().set_value(ASIO_VARIADIC_DECLVAL(n)))); \+  }; \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF)+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#else // defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++template <typename T, typename Vs, typename = void>+struct set_value_member_trait;++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Vs>+struct set_value_member_trait<T, void(Vs...)> :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value+      && conjunction<is_same<Vs, typename decay<Vs>::type>...>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_set_value_member,+      traits::set_value_member<typename add_const<T>::type, void(Vs...)>+    >::type,+    traits::set_value_member<+      typename remove_reference<T>::type,+      void(typename decay<Vs>::type...)>+  >::type+{+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T>+struct set_value_member_trait<T, void()> :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_set_value_member,+      traits::set_value_member<typename add_const<T>::type, void()>+    >::type,+    traits::set_value_member<typename remove_reference<T>::type, void()>+  >::type+{+};++#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME(n) \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_##n++#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 \+  && is_same<T1, typename decay<T1>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1 \+  && is_same<T2, typename decay<T2>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2 \+  && is_same<T3, typename decay<T3>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3 \+  && is_same<T4, typename decay<T4>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4 \+  && is_same<T5, typename decay<T5>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5 \+  && is_same<T6, typename decay<T6>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6 \+  && is_same<T7, typename decay<T7>::type>::value+#define ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_8 \+  ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7 \+  && is_same<T8, typename decay<T8>::type>::value++#define ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF(n) \+  template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+  struct set_value_member_trait<T, void(ASIO_VARIADIC_TARGS(n))> : \+    conditional< \+      is_same<T, typename remove_reference<T>::type>::value \+        ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME(n), \+      typename conditional< \+        is_same<T, typename add_const<T>::type>::value, \+        no_set_value_member, \+        traits::set_value_member< \+          typename add_const<T>::type, \+          void(ASIO_VARIADIC_TARGS(n))> \+      >::type, \+      traits::set_value_member< \+        typename remove_reference<T>::type, \+        void(ASIO_VARIADIC_DECAY(n))> \+    >::type \+  { \+  }; \+  /**/+ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF)+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_TRAIT_DEF+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_1+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_2+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_3+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_4+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_5+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_6+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_7+#undef ASIO_PRIVATE_SET_VALUE_MEMBER_IS_SAME_8++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#endif // defined(ASIO_HAS_DEDUCED_SET_VALUE_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Vs, typename>+struct set_value_member_default :+  detail::set_value_member_trait<T, Vs>+{+};++template <typename T, typename Vs, typename>+struct set_value_member :+  set_value_member_default<T, Vs>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SET_VALUE_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/start_free.hpp view
@@ -0,0 +1,108 @@+//+// traits/start_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_START_FREE_HPP+#define ASIO_TRAITS_START_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_START_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename = void>+struct start_free_default;++template <typename T, typename = void>+struct start_free;++} // namespace traits+namespace detail {++struct no_start_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT)++template <typename T, typename = void>+struct start_free_trait : no_start_free+{+};++template <typename T>+struct start_free_trait<T,+  typename void_type<+    decltype(start(declval<T>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(start(declval<T>()));++  ASIO_STATIC_CONSTEXPR(bool,+    is_noexcept = noexcept(start(declval<T>())));+};++#else // defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT)++template <typename T, typename = void>+struct start_free_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_start_free,+      traits::start_free<typename add_const<T>::type>+    >::type,+    traits::start_free<typename remove_reference<T>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_START_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename>+struct start_free_default :+  detail::start_free_trait<T>+{+};++template <typename T, typename>+struct start_free :+  start_free_default<T>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_START_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/start_member.hpp view
@@ -0,0 +1,108 @@+//+// traits/start_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_START_MEMBER_HPP+#define ASIO_TRAITS_START_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_START_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename = void>+struct start_member_default;++template <typename T, typename = void>+struct start_member;++} // namespace traits+namespace detail {++struct no_start_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT)++template <typename T, typename = void>+struct start_member_trait : no_start_member+{+};++template <typename T>+struct start_member_trait<T,+  typename void_type<+    decltype(declval<T>().start())+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(declval<T>().start());++  ASIO_STATIC_CONSTEXPR(bool,+    is_noexcept = noexcept(declval<T>().start()));+};++#else // defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT)++template <typename T, typename = void>+struct start_member_trait :+  conditional<+    is_same<T, typename remove_reference<T>::type>::value,+    typename conditional<+      is_same<T, typename add_const<T>::type>::value,+      no_start_member,+      traits::start_member<typename add_const<T>::type>+    >::type,+    traits::start_member<typename remove_reference<T>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_START_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename>+struct start_member_default :+  detail::start_member_trait<T>+{+};++template <typename T, typename>+struct start_member :+  start_member_default<T>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_START_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/static_query.hpp view
@@ -0,0 +1,108 @@+//+// traits/static_query.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_STATIC_QUERY_HPP+#define ASIO_TRAITS_STATIC_QUERY_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_CONSTEXPR) \+  && defined(ASIO_HAS_VARIABLE_TEMPLATES) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_CONSTEXPR)+       //   && defined(ASIO_HAS_VARIABLE_TEMPLATES)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct static_query_default;++template <typename T, typename Property, typename = void>+struct static_query;++} // namespace traits+namespace detail {++struct no_static_query+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++template <typename T, typename Property, typename = void>+struct static_query_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_static_query,+    traits::static_query<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#if defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)++template <typename T, typename Property>+struct static_query_trait<T, Property,+  typename void_type<+    decltype(decay<Property>::type::template static_query_v<T>)+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+      decay<Property>::type::template static_query_v<T>);++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept =+    noexcept(decay<Property>::type::template static_query_v<T>));++  static ASIO_CONSTEXPR result_type value() noexcept(is_noexcept)+  {+    return decay<Property>::type::template static_query_v<T>;+  }+};++#endif // defined(ASIO_HAS_DEDUCED_STATIC_QUERY_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct static_query_default : detail::static_query_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct static_query : static_query_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_STATIC_QUERY_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/static_require.hpp view
@@ -0,0 +1,123 @@+//+// traits/static_require.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_STATIC_REQUIRE_HPP+#define ASIO_TRAITS_STATIC_REQUIRE_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/traits/static_query.hpp"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT)+# define ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct static_require_default;++template <typename T, typename Property, typename = void>+struct static_require;++} // namespace traits+namespace detail {++struct no_static_require+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+};++template <typename T, typename Property, typename = void>+struct static_require_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_static_require,+    traits::static_require<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#if defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++template <typename T, typename Property>+struct static_require_trait<T, Property,+  typename enable_if<+    decay<Property>::type::value() == traits::static_query<T, Property>::value()+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+};++#else // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++false_type static_require_test(...);++template <typename T, typename Property>+true_type static_require_test(T*, Property*,+    typename enable_if<+      Property::value() == traits::static_query<T, Property>::value()+    >::type* = 0);++template <typename T, typename Property>+struct has_static_require+{+  ASIO_STATIC_CONSTEXPR(bool, value =+    decltype((static_require_test)(+      static_cast<T*>(0), static_cast<Property*>(0)))::value);+};++template <typename T, typename Property>+struct static_require_trait<T, Property,+  typename enable_if<+    has_static_require<typename decay<T>::type,+      typename decay<Property>::type>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+};++#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#endif // defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct static_require_default : detail::static_require_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct static_require : static_require_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_STATIC_REQUIRE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/static_require_concept.hpp view
@@ -0,0 +1,123 @@+//+// traits/static_require_concept.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_STATIC_REQUIRE_CONCEPT_HPP+#define ASIO_TRAITS_STATIC_REQUIRE_CONCEPT_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/traits/static_query.hpp"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT)+# define ASIO_HAS_DEDUCED_STATIC_REQUIRE_CONCEPT_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename T, typename Property, typename = void>+struct static_require_concept_default;++template <typename T, typename Property, typename = void>+struct static_require_concept;++} // namespace traits+namespace detail {++struct no_static_require_concept+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+};++template <typename T, typename Property, typename = void>+struct static_require_concept_trait :+  conditional<+    is_same<T, typename decay<T>::type>::value+      && is_same<Property, typename decay<Property>::type>::value,+    no_static_require_concept,+    traits::static_require_concept<+      typename decay<T>::type,+      typename decay<Property>::type>+  >::type+{+};++#if defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_CONCEPT_TRAIT)++#if defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++template <typename T, typename Property>+struct static_require_concept_trait<T, Property,+  typename enable_if<+    decay<Property>::type::value() == traits::static_query<T, Property>::value()+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+};++#else // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++false_type static_require_concept_test(...);++template <typename T, typename Property>+true_type static_require_concept_test(T*, Property*,+    typename enable_if<+      Property::value() == traits::static_query<T, Property>::value()+    >::type* = 0);++template <typename T, typename Property>+struct has_static_require_concept+{+  ASIO_STATIC_CONSTEXPR(bool, value =+    decltype((static_require_concept_test)(+      static_cast<T*>(0), static_cast<Property*>(0)))::value);+};++template <typename T, typename Property>+struct static_require_concept_trait<T, Property,+  typename enable_if<+    has_static_require_concept<T, typename decay<Property>::type>::value+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+};++#endif // defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#endif // defined(ASIO_HAS_DEDUCED_STATIC_REQUIRE_CONCEPT_TRAIT)++} // namespace detail+namespace traits {++template <typename T, typename Property, typename>+struct static_require_concept_default :+  detail::static_require_concept_trait<T, Property>+{+};++template <typename T, typename Property, typename>+struct static_require_concept : static_require_concept_default<T, Property>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_STATIC_REQUIRE_CONCEPT_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/submit_free.hpp view
@@ -0,0 +1,112 @@+//+// traits/submit_free.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SUBMIT_FREE_HPP+#define ASIO_TRAITS_SUBMIT_FREE_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SUBMIT_FREE_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename S, typename R, typename = void>+struct submit_free_default;++template <typename S, typename R, typename = void>+struct submit_free;++} // namespace traits+namespace detail {++struct no_submit_free+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SUBMIT_FREE_TRAIT)++template <typename S, typename R, typename = void>+struct submit_free_trait : no_submit_free+{+};++template <typename S, typename R>+struct submit_free_trait<S, R,+  typename void_type<+    decltype(submit(declval<S>(), declval<R>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    submit(declval<S>(), declval<R>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    submit(declval<S>(), declval<R>())));+};++#else // defined(ASIO_HAS_DEDUCED_SUBMIT_FREE_TRAIT)++template <typename S, typename R, typename = void>+struct submit_free_trait :+  conditional<+    is_same<S, typename remove_reference<S>::type>::value+      && is_same<R, typename decay<R>::type>::value,+    typename conditional<+      is_same<S, typename add_const<S>::type>::value,+      no_submit_free,+      traits::submit_free<typename add_const<S>::type, R>+    >::type,+    traits::submit_free<+      typename remove_reference<S>::type,+      typename decay<R>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_SUBMIT_FREE_TRAIT)++} // namespace detail+namespace traits {++template <typename S, typename R, typename>+struct submit_free_default :+  detail::submit_free_trait<S, R>+{+};++template <typename S, typename R, typename>+struct submit_free :+  submit_free_default<S, R>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SUBMIT_FREE_HPP
+ link/modules/asio-standalone/asio/include/asio/traits/submit_member.hpp view
@@ -0,0 +1,112 @@+//+// traits/submit_member.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TRAITS_SUBMIT_MEMBER_HPP+#define ASIO_TRAITS_SUBMIT_MEMBER_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"++#if defined(ASIO_HAS_DECLTYPE) \+  && defined(ASIO_HAS_NOEXCEPT) \+  && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)+# define ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT 1+#endif // defined(ASIO_HAS_DECLTYPE)+       //   && defined(ASIO_HAS_NOEXCEPT)+       //   && defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace traits {++template <typename S, typename R, typename = void>+struct submit_member_default;++template <typename S, typename R, typename = void>+struct submit_member;++} // namespace traits+namespace detail {++struct no_submit_member+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = false);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);+};++#if defined(ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT)++template <typename S, typename R, typename = void>+struct submit_member_trait : no_submit_member+{+};++template <typename S, typename R>+struct submit_member_trait<S, R,+  typename void_type<+    decltype(declval<S>().submit(declval<R>()))+  >::type>+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);++  using result_type = decltype(+    declval<S>().submit(declval<R>()));++  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = noexcept(+    declval<S>().submit(declval<R>())));+};++#else // defined(ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT)++template <typename S, typename R, typename = void>+struct submit_member_trait :+  conditional<+    is_same<S, typename remove_reference<S>::type>::value+      && is_same<R, typename decay<R>::type>::value,+    typename conditional<+      is_same<S, typename add_const<S>::type>::value,+      no_submit_member,+      traits::submit_member<typename add_const<S>::type, R>+    >::type,+    traits::submit_member<+      typename remove_reference<S>::type,+      typename decay<R>::type>+  >::type+{+};++#endif // defined(ASIO_HAS_DEDUCED_SUBMIT_MEMBER_TRAIT)++} // namespace detail+namespace traits {++template <typename S, typename R, typename>+struct submit_member_default :+  detail::submit_member_trait<S, R>+{+};++template <typename S, typename R, typename>+struct submit_member :+  submit_member_default<S, R>+{+};++} // namespace traits+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_TRAITS_SUBMIT_MEMBER_HPP
+ link/modules/asio-standalone/asio/include/asio/ts/buffer.hpp view
@@ -0,0 +1,24 @@+//+// ts/buffer.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TS_BUFFER_HPP+#define ASIO_TS_BUFFER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/buffer.hpp"+#include "asio/completion_condition.hpp"+#include "asio/read.hpp"+#include "asio/write.hpp"+#include "asio/read_until.hpp"++#endif // ASIO_TS_BUFFER_HPP
+ link/modules/asio-standalone/asio/include/asio/ts/executor.hpp view
@@ -0,0 +1,35 @@+//+// ts/executor.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TS_EXECUTOR_HPP+#define ASIO_TS_EXECUTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/async_result.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/execution_context.hpp"+#include "asio/is_executor.hpp"+#include "asio/associated_executor.hpp"+#include "asio/bind_executor.hpp"+#include "asio/executor_work_guard.hpp"+#include "asio/system_executor.hpp"+#include "asio/executor.hpp"+#include "asio/any_io_executor.hpp"+#include "asio/dispatch.hpp"+#include "asio/post.hpp"+#include "asio/defer.hpp"+#include "asio/strand.hpp"+#include "asio/packaged_task.hpp"+#include "asio/use_future.hpp"++#endif // ASIO_TS_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/ts/internet.hpp view
@@ -0,0 +1,40 @@+//+// ts/internet.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TS_INTERNET_HPP+#define ASIO_TS_INTERNET_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#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/bad_address_cast.hpp"+#include "asio/ip/basic_endpoint.hpp"+#include "asio/ip/basic_resolver_query.hpp"+#include "asio/ip/basic_resolver_entry.hpp"+#include "asio/ip/basic_resolver_iterator.hpp"+#include "asio/ip/basic_resolver.hpp"+#include "asio/ip/host_name.hpp"+#include "asio/ip/network_v4.hpp"+#include "asio/ip/network_v6.hpp"+#include "asio/ip/tcp.hpp"+#include "asio/ip/udp.hpp"+#include "asio/ip/v6_only.hpp"+#include "asio/ip/unicast.hpp"+#include "asio/ip/multicast.hpp"++#endif // ASIO_TS_INTERNET_HPP
+ link/modules/asio-standalone/asio/include/asio/ts/io_context.hpp view
@@ -0,0 +1,20 @@+//+// ts/io_context.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TS_IO_CONTEXT_HPP+#define ASIO_TS_IO_CONTEXT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/io_context.hpp"++#endif // ASIO_TS_IO_CONTEXT_HPP
+ link/modules/asio-standalone/asio/include/asio/ts/net.hpp view
@@ -0,0 +1,26 @@+//+// ts/net.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TS_NET_HPP+#define ASIO_TS_NET_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/ts/netfwd.hpp"+#include "asio/ts/executor.hpp"+#include "asio/ts/io_context.hpp"+#include "asio/ts/timer.hpp"+#include "asio/ts/buffer.hpp"+#include "asio/ts/socket.hpp"+#include "asio/ts/internet.hpp"++#endif // ASIO_TS_NET_HPP
+ link/modules/asio-standalone/asio/include/asio/ts/netfwd.hpp view
@@ -0,0 +1,262 @@+//+// ts/netfwd.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TS_NETFWD_HPP+#define ASIO_TS_NETFWD_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_CHRONO)+# include "asio/detail/chrono.hpp"+#endif // defined(ASIO_HAS_CHRONO)++#if defined(ASIO_HAS_BOOST_DATE_TIME)+# include "asio/detail/date_time_fwd.hpp"+#endif // defined(ASIO_HAS_BOOST_DATE_TIME)++#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+#include "asio/execution/blocking.hpp"+#include "asio/execution/outstanding_work.hpp"+#include "asio/execution/relationship.hpp"+#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#if !defined(GENERATING_DOCUMENTATION)++#include "asio/detail/push_options.hpp"++namespace asio {++class execution_context;++template <typename T, typename Executor>+class executor_binder;++#if !defined(ASIO_EXECUTOR_WORK_GUARD_DECL)+#define ASIO_EXECUTOR_WORK_GUARD_DECL++template <typename Executor, typename = void>+class executor_work_guard;++#endif // !defined(ASIO_EXECUTOR_WORK_GUARD_DECL)++template <typename Blocking, typename Relationship, typename Allocator>+class basic_system_executor;++#if defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++class executor;++typedef executor any_io_executor;++#else // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++namespace execution {++#if !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)+#define ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... SupportableProperties>+class any_executor;++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void>+class any_executor;++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#endif // !defined(ASIO_EXECUTION_ANY_EXECUTOR_FWD_DECL)++template <typename U>+struct context_as_t;++template <typename Property>+struct prefer_only;++} // namespace execution++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>+  > any_io_executor;++#endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++template <typename Executor>+class strand;++class io_context;++template <typename Clock>+struct wait_traits;++#if defined(ASIO_HAS_BOOST_DATE_TIME)++template <typename Time>+struct time_traits;++#endif // defined(ASIO_HAS_BOOST_DATE_TIME)++#if !defined(ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)+#define ASIO_BASIC_WAITABLE_TIMER_FWD_DECL++template <typename Clock,+    typename WaitTraits = wait_traits<Clock>,+    typename Executor = any_io_executor>+class basic_waitable_timer;++#endif // !defined(ASIO_BASIC_WAITABLE_TIMER_FWD_DECL)++#if defined(ASIO_HAS_CHRONO)++typedef basic_waitable_timer<chrono::system_clock> system_timer;++typedef basic_waitable_timer<chrono::steady_clock> steady_timer;++typedef basic_waitable_timer<chrono::high_resolution_clock>+  high_resolution_timer;++#endif // defined(ASIO_HAS_CHRONO)++#if !defined(ASIO_BASIC_SOCKET_FWD_DECL)+#define ASIO_BASIC_SOCKET_FWD_DECL++template <typename Protocol, typename Executor = any_io_executor>+class basic_socket;++#endif // !defined(ASIO_BASIC_SOCKET_FWD_DECL)++#if !defined(ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)+#define ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL++template <typename Protocol, typename Executor = any_io_executor>+class basic_datagram_socket;++#endif // !defined(ASIO_BASIC_DATAGRAM_SOCKET_FWD_DECL)++#if !defined(ASIO_BASIC_STREAM_SOCKET_FWD_DECL)+#define ASIO_BASIC_STREAM_SOCKET_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Protocol, typename Executor = any_io_executor>+class basic_stream_socket;++#endif // !defined(ASIO_BASIC_STREAM_SOCKET_FWD_DECL)++#if !defined(ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL)+#define ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL++template <typename Protocol, typename Executor = any_io_executor>+class basic_socket_acceptor;++#endif // !defined(ASIO_BASIC_SOCKET_ACCEPTOR_FWD_DECL)++#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(GENERATING_DOCUMENTATION)+    typename Clock = boost::posix_time::ptime,+    typename WaitTraits = time_traits<Clock> >+#else+    typename Clock = chrono::steady_clock,+    typename WaitTraits = wait_traits<Clock> >+#endif+class basic_socket_streambuf;++#endif // !defined(ASIO_BASIC_SOCKET_STREAMBUF_FWD_DECL)++#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(GENERATING_DOCUMENTATION)+    typename Clock = boost::posix_time::ptime,+    typename WaitTraits = time_traits<Clock> >+#else+    typename Clock = chrono::steady_clock,+    typename WaitTraits = wait_traits<Clock> >+#endif+class basic_socket_iostream;++#endif // !defined(ASIO_BASIC_SOCKET_IOSTREAM_FWD_DECL)++namespace ip {++class address;++class address_v4;++class address_v6;++template <typename Address>+class basic_address_iterator;++typedef basic_address_iterator<address_v4> address_v4_iterator;++typedef basic_address_iterator<address_v6> address_v6_iterator;++template <typename Address>+class basic_address_range;++typedef basic_address_range<address_v4> address_v4_range;++typedef basic_address_range<address_v6> address_v6_range;++class network_v4;++class network_v6;++template <typename InternetProtocol>+class basic_endpoint;++template <typename InternetProtocol>+class basic_resolver_entry;++template <typename InternetProtocol>+class basic_resolver_results;++#if !defined(ASIO_IP_BASIC_RESOLVER_FWD_DECL)+#define ASIO_IP_BASIC_RESOLVER_FWD_DECL++template <typename InternetProtocol, typename Executor = any_io_executor>+class basic_resolver;++#endif // !defined(ASIO_IP_BASIC_RESOLVER_FWD_DECL)++class tcp;++class udp;++} // namespace ip+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(GENERATING_DOCUMENTATION)++#endif // ASIO_TS_NETFWD_HPP
+ link/modules/asio-standalone/asio/include/asio/ts/socket.hpp view
@@ -0,0 +1,27 @@+//+// ts/socket.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TS_SOCKET_HPP+#define ASIO_TS_SOCKET_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/socket_base.hpp"+#include "asio/basic_socket.hpp"+#include "asio/basic_datagram_socket.hpp"+#include "asio/basic_stream_socket.hpp"+#include "asio/basic_socket_acceptor.hpp"+#include "asio/basic_socket_streambuf.hpp"+#include "asio/basic_socket_iostream.hpp"+#include "asio/connect.hpp"++#endif // ASIO_TS_SOCKET_HPP
+ link/modules/asio-standalone/asio/include/asio/ts/timer.hpp view
@@ -0,0 +1,26 @@+//+// ts/timer.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_TS_TIMER_HPP+#define ASIO_TS_TIMER_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/chrono.hpp"++#include "asio/wait_traits.hpp"+#include "asio/basic_waitable_timer.hpp"+#include "asio/system_timer.hpp"+#include "asio/steady_timer.hpp"+#include "asio/high_resolution_timer.hpp"++#endif // ASIO_TS_TIMER_HPP
+ link/modules/asio-standalone/asio/include/asio/unyield.hpp view
@@ -0,0 +1,21 @@+//+// unyield.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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)+//++#ifdef reenter+# undef reenter+#endif++#ifdef yield+# undef yield+#endif++#ifdef fork+# undef fork+#endif
+ link/modules/asio-standalone/asio/include/asio/use_awaitable.hpp view
@@ -0,0 +1,169 @@+//+// use_awaitable.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_USE_AWAITABLE_HPP+#define ASIO_USE_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)++#include "asio/awaitable.hpp"+#include "asio/detail/handler_tracking.hpp"++#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+#  include "asio/detail/source_location.hpp"+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)++#include "asio/detail/push_options.hpp"++namespace asio {++/// A completion token that represents the currently executing coroutine.+/**+ * The @c use_awaitable_t class, with its value @c use_awaitable, is used to+ * represent the currently executing coroutine. This completion token may be+ * passed as a handler to an asynchronous operation. For example:+ *+ * @code awaitable<void> my_coroutine()+ * {+ *   std::size_t n = co_await my_socket.async_read_some(buffer, use_awaitable);+ *   ...+ * } @endcode+ *+ * When used with co_await, the initiating function (@c async_read_some in the+ * above example) suspends the current coroutine. The coroutine is resumed when+ * the asynchronous operation completes, and the result of the operation is+ * returned.+ */+template <typename Executor = any_io_executor>+struct use_awaitable_t+{+  /// Default constructor.+  ASIO_CONSTEXPR use_awaitable_t(+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+      detail::source_location location = detail::source_location::current()+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+    )+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+    : file_name_(location.file_name()),+      line_(location.line()),+      function_name_(location.function_name())+# else // defined(ASIO_HAS_SOURCE_LOCATION)+    : file_name_(0),+      line_(0),+      function_name_(0)+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+  {+  }++  /// Constructor used to specify file name, line, and function name.+  ASIO_CONSTEXPR use_awaitable_t(const char* file_name,+      int line, const char* function_name)+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+    : file_name_(file_name),+      line_(line),+      function_name_(function_name)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+  {+#if !defined(ASIO_ENABLE_HANDLER_TRACKING)+    (void)file_name;+    (void)line;+    (void)function_name;+#endif // !defined(ASIO_ENABLE_HANDLER_TRACKING)+  }++  /// Adapts an executor to add the @c use_awaitable_t completion token as the+  /// default.+  template <typename InnerExecutor>+  struct executor_with_default : InnerExecutor+  {+    /// Specify @c use_awaitable_t as the default completion token type.+    typedef use_awaitable_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 enable_if<+          is_convertible<OtherExecutor, InnerExecutor>::value+        >::type* = 0) ASIO_NOEXCEPT+      : InnerExecutor(ex)+    {+    }+  };++  /// Type alias to adapt an I/O object to use @c use_awaitable_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 use_awaitable_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));+  }++#if defined(ASIO_ENABLE_HANDLER_TRACKING)+  const char* file_name_;+  int line_;+  const char* function_name_;+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+};++/// A completion token object that represents the currently executing coroutine.+/**+ * See the documentation for asio::use_awaitable_t for a usage example.+ */+#if defined(GENERATING_DOCUMENTATION)+constexpr use_awaitable_t<> use_awaitable;+#elif defined(ASIO_HAS_CONSTEXPR)+constexpr use_awaitable_t<> use_awaitable(0, 0, 0);+#elif defined(ASIO_MSVC)+__declspec(selectany) use_awaitable_t<> use_awaitable(0, 0, 0);+#endif++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/use_awaitable.hpp"++#endif // defined(ASIO_HAS_CO_AWAIT) || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_USE_AWAITABLE_HPP
+ link/modules/asio-standalone/asio/include/asio/use_future.hpp view
@@ -0,0 +1,160 @@+//+// use_future.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_USE_FUTURE_HPP+#define ASIO_USE_FUTURE_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/future.hpp"++#if defined(ASIO_HAS_STD_FUTURE_CLASS) \+  || defined(GENERATING_DOCUMENTATION)++#include <memory>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Function, typename Allocator>+class packaged_token;++template <typename Function, typename Allocator, typename Result>+class packaged_handler;++} // namespace detail++/// Class used to specify that an asynchronous operation should return a future.+/**+ * The use_future_t class is used to indicate that an asynchronous operation+ * should return a std::future object. A use_future_t object may be passed as a+ * handler to an asynchronous operation, typically using the special value @c+ * asio::use_future. For example:+ *+ * @code std::future<std::size_t> my_future+ *   = my_socket.async_read_some(my_buffer, asio::use_future); @endcode+ *+ * The initiating function (async_read_some in the above example) returns a+ * future that will receive the result of the operation. If the operation+ * completes with an error_code indicating failure, it is converted into a+ * system_error and passed back to the caller via the future.+ */+template <typename Allocator = std::allocator<void> >+class use_future_t+{+public:+  /// The allocator type. The allocator is used when constructing the+  /// @c std::promise object for a given asynchronous operation.+  typedef Allocator allocator_type;++  /// Construct using default-constructed allocator.+  ASIO_CONSTEXPR use_future_t()+  {+  }++  /// Construct using specified allocator.+  explicit use_future_t(const Allocator& allocator)+    : allocator_(allocator)+  {+  }++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated: Use rebind().) Specify an alternate allocator.+  template <typename OtherAllocator>+  use_future_t<OtherAllocator> operator[](const OtherAllocator& allocator) const+  {+    return use_future_t<OtherAllocator>(allocator);+  }+#endif // !defined(ASIO_NO_DEPRECATED)++  /// Specify an alternate allocator.+  template <typename OtherAllocator>+  use_future_t<OtherAllocator> rebind(const OtherAllocator& allocator) const+  {+    return use_future_t<OtherAllocator>(allocator);+  }++  /// Obtain allocator.+  allocator_type get_allocator() const+  {+    return allocator_;+  }++  /// Wrap a function object in a packaged task.+  /**+   * The @c package function is used to adapt a function object as a packaged+   * task. When this adapter is passed as a completion token to an asynchronous+   * operation, the result of the function object is retuned via a std::future.+   *+   * @par Example+   *+   * @code std::future<std::size_t> fut =+   *   my_socket.async_read_some(buffer,+   *     use_future([](asio::error_code ec, std::size_t n)+   *       {+   *         return ec ? 0 : n;+   *       }));+   * ...+   * std::size_t n = fut.get(); @endcode+   */+  template <typename Function>+#if defined(GENERATING_DOCUMENTATION)+  unspecified+#else // defined(GENERATING_DOCUMENTATION)+  detail::packaged_token<typename decay<Function>::type, Allocator>+#endif // defined(GENERATING_DOCUMENTATION)+  operator()(ASIO_MOVE_ARG(Function) f) const;++private:+  // Helper type to ensure that use_future can be constexpr default-constructed+  // even when std::allocator<void> can't be.+  struct std_allocator_void+  {+    ASIO_CONSTEXPR std_allocator_void()+    {+    }++    operator std::allocator<void>() const+    {+      return std::allocator<void>();+    }+  };++  typename conditional<+    is_same<std::allocator<void>, Allocator>::value,+    std_allocator_void, Allocator>::type allocator_;+};++/// A special value, similar to std::nothrow.+/**+ * See the documentation for asio::use_future_t for a usage example.+ */+#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr use_future_t<> use_future;+#elif defined(ASIO_MSVC)+__declspec(selectany) use_future_t<> use_future;+#endif++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/use_future.hpp"++#endif // defined(ASIO_HAS_STD_FUTURE_CLASS)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_USE_FUTURE_HPP
+ link/modules/asio-standalone/asio/include/asio/uses_executor.hpp view
@@ -0,0 +1,71 @@+//+// uses_executor.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_USES_EXECUTOR_HPP+#define ASIO_USES_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/push_options.hpp"++namespace asio {++/// A special type, similar to std::nothrow_t, used to disambiguate+/// constructors that accept executor arguments.+/**+ * The executor_arg_t struct is an empty structure type used as a unique type+ * to disambiguate constructor and function overloading. Specifically, some+ * types have constructors with executor_arg_t as the first argument,+ * immediately followed by an argument of a type that satisfies the Executor+ * type requirements.+ */+struct executor_arg_t+{+  /// Constructor.+  ASIO_CONSTEXPR executor_arg_t() ASIO_NOEXCEPT+  {+  }+};++/// A special value, similar to std::nothrow, used to disambiguate constructors+/// that accept executor arguments.+/**+ * See asio::executor_arg_t and asio::uses_executor+ * for more information.+ */+#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr executor_arg_t executor_arg;+#elif defined(ASIO_MSVC)+__declspec(selectany) executor_arg_t executor_arg;+#endif++/// The uses_executor trait detects whether a type T has an associated executor+/// that is convertible from type Executor.+/**+ * Meets the BinaryTypeTrait requirements. The Asio library provides a+ * definition that is derived from false_type. A program may specialize this+ * template to derive from true_type for a user-defined type T that can be+ * constructed with an executor, where the first argument of a constructor has+ * type executor_arg_t and the second argument is convertible from type+ * Executor.+ */+template <typename T, typename Executor>+struct uses_executor : false_type {};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_USES_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/version.hpp view
@@ -0,0 +1,23 @@+//+// version.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_VERSION_HPP+#define ASIO_VERSION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++// ASIO_VERSION % 100 is the sub-minor version+// ASIO_VERSION / 100 % 1000 is the minor version+// ASIO_VERSION / 100000 is the major version+#define ASIO_VERSION 101700 // 1.17.0++#endif // ASIO_VERSION_HPP
+ link/modules/asio-standalone/asio/include/asio/wait_traits.hpp view
@@ -0,0 +1,56 @@+//+// wait_traits.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WAIT_TRAITS_HPP+#define ASIO_WAIT_TRAITS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/push_options.hpp"++namespace asio {++/// Wait traits suitable for use with the basic_waitable_timer class template.+template <typename Clock>+struct wait_traits+{+  /// Convert a clock duration into a duration used for waiting.+  /**+   * @returns @c d.+   */+  static typename Clock::duration to_wait_duration(+      const typename Clock::duration& d)+  {+    return d;+  }++  /// Convert a clock duration into a duration used for waiting.+  /**+   * @returns @c d.+   */+  static typename Clock::duration to_wait_duration(+      const typename Clock::time_point& t)+  {+    typename Clock::time_point now = Clock::now();+    if (now + (Clock::duration::max)() < t)+      return (Clock::duration::max)();+    if (now + (Clock::duration::min)() > t)+      return (Clock::duration::min)();+    return t - now;+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_WAIT_TRAITS_HPP
+ link/modules/asio-standalone/asio/include/asio/windows/basic_object_handle.hpp view
@@ -0,0 +1,435 @@+//+// windows/basic_object_handle.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2011 Boris Schaeling (boris@highscore.de)+//+// 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_WINDOWS_BASIC_OBJECT_HANDLE_HPP+#define ASIO_WINDOWS_BASIC_OBJECT_HANDLE_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_WINDOWS_OBJECT_HANDLE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/any_io_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/io_object_impl.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/win_object_handle_service.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace windows {++/// Provides object-oriented handle functionality.+/**+ * The windows::basic_object_handle class provides asynchronous and blocking+ * object-oriented handle functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor = any_io_executor>+class basic_object_handle+{+public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the handle type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The handle type when rebound to the specified executor.+    typedef basic_object_handle<Executor1> other;+  };++  /// The native representation of a handle.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#else+  typedef asio::detail::win_object_handle_service::native_handle_type+    native_handle_type;+#endif++  /// An object handle is always the lowest layer.+  typedef basic_object_handle lowest_layer_type;++  /// Construct an object handle without opening it.+  /**+   * This constructor creates an object handle without opening it.+   *+   * @param ex The I/O executor that the object handle will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * object handle.+   */+  explicit basic_object_handle(const executor_type& ex)+    : impl_(ex)+  {+  }++  /// Construct an object handle without opening it.+  /**+   * This constructor creates an object handle without opening it.+   *+   * @param context An execution context which provides the I/O executor that+   * the object handle will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the object handle.+   */+  template <typename ExecutionContext>+  explicit basic_object_handle(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value,+        basic_object_handle+      >::type* = 0)+    : impl_(context)+  {+  }++  /// Construct an object handle on an existing native handle.+  /**+   * This constructor creates an object handle object to hold an existing native+   * handle.+   *+   * @param ex The I/O executor that the object handle will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * object handle.+   *+   * @param native_handle The new underlying handle implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_object_handle(const executor_type& ex,+      const native_handle_type& native_handle)+    : impl_(ex)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Construct an object handle on an existing native handle.+  /**+   * This constructor creates an object handle object to hold an existing native+   * handle.+   *+   * @param context An execution context which provides the I/O executor that+   * the object handle will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the object handle.+   *+   * @param native_handle The new underlying handle implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_object_handle(ExecutionContext& context,+      const native_handle_type& native_handle,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);+    asio::detail::throw_error(ec, "assign");+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct an object handle from another.+  /**+   * This constructor moves an object handle from one object to another.+   *+   * @param other The other object handle 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_object_handle(const executor_type&)+   * constructor.+   */+  basic_object_handle(basic_object_handle&& other)+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign an object handle from another.+  /**+   * This assignment operator moves an object handle from one object to another.+   *+   * @param other The other object handle 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_object_handle(const executor_type&)+   * constructor.+   */+  basic_object_handle& operator=(basic_object_handle&& other)+  {+    impl_ = std::move(other.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();+  }++  /// Get a reference to the lowest layer.+  /**+   * This function returns a reference to the lowest layer in a stack of+   * layers. Since an object handle 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 an object handle 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 handle to the handle.+  /*+   * This function opens the handle to hold an existing native handle.+   *+   * @param handle A native handle.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void assign(const native_handle_type& handle)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(), handle, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Assign an existing native handle to the handle.+  /*+   * This function opens the handle to hold an existing native handle.+   *+   * @param handle A native handle.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,+      asio::error_code& ec)+  {+    impl_.get_service().assign(impl_.get_implementation(), handle, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Determine whether the handle is open.+  bool is_open() const+  {+    return impl_.get_service().is_open(impl_.get_implementation());+  }++  /// Close the handle.+  /**+   * This function is used to close the handle. 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 handle.+  /**+   * This function is used to close the handle. 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 handle representation.+  /**+   * This function may be used to obtain the underlying representation of the+   * handle. This is intended to allow access to native handle 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 handle.+  /**+   * 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 handle.+  /**+   * 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);+  }++  /// Perform a blocking wait on the object handle.+  /**+   * This function is used to wait for the object handle to be set to the+   * signalled state. This function blocks and does not return until the object+   * handle has been set to the signalled state.+   *+   * @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 object handle.+  /**+   * This function is used to wait for the object handle to be set to the+   * signalled state. This function blocks and does not return until the object+   * handle has been set to the signalled state.+   *+   * @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 object handle.+  /**+   * This function is be used to initiate an asynchronous wait against the+   * object handle. It always returns immediately.+   *+   * @param handler The handler to be called when the object handle is set to+   * the signalled state. Copies will be made of the handler as required. The+   * function signature of the 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 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().+   */+  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+      void (asio::error_code))+  async_wait(+      ASIO_MOVE_ARG(WaitHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WaitHandler, void (asio::error_code)>(+        initiate_async_wait(this), handler);+  }++private:+  // Disallow copying and assignment.+  basic_object_handle(const basic_object_handle&) ASIO_DELETED;+  basic_object_handle& operator=(const basic_object_handle&) ASIO_DELETED;++  class initiate_async_wait+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_wait(basic_object_handle* 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_object_handle* self_;+  };++  asio::detail::io_object_impl<+    asio::detail::win_object_handle_service, Executor> impl_;+};++} // namespace windows+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WINDOWS_BASIC_OBJECT_HANDLE_HPP
+ link/modules/asio-standalone/asio/include/asio/windows/basic_overlapped_handle.hpp view
@@ -0,0 +1,361 @@+//+// windows/basic_overlapped_handle.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WINDOWS_BASIC_OVERLAPPED_HANDLE_HPP+#define ASIO_WINDOWS_BASIC_OVERLAPPED_HANDLE_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_WINDOWS_RANDOM_ACCESS_HANDLE) \+  || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \+  || defined(GENERATING_DOCUMENTATION)++#include <cstddef>+#include "asio/any_io_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/io_object_impl.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/win_iocp_handle_service.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace windows {++/// Provides Windows handle functionality for objects that support+/// overlapped I/O.+/**+ * The windows::overlapped_handle class provides the ability to wrap a Windows+ * handle. The underlying object referred to by the handle must support+ * overlapped I/O.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor = any_io_executor>+class basic_overlapped_handle+{+public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the handle type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The handle type when rebound to the specified executor.+    typedef basic_overlapped_handle<Executor1> other;+  };++  /// The native representation of a handle.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#else+  typedef asio::detail::win_iocp_handle_service::native_handle_type+    native_handle_type;+#endif++  /// An overlapped_handle is always the lowest layer.+  typedef basic_overlapped_handle lowest_layer_type;++  /// Construct an overlapped handle without opening it.+  /**+   * This constructor creates an overlapped handle without opening it.+   *+   * @param ex The I/O executor that the overlapped handle will use, by default,+   * to dispatch handlers for any asynchronous operations performed on the+   * overlapped handle.+   */+  explicit basic_overlapped_handle(const executor_type& ex)+    : impl_(ex)+  {+  }++  /// Construct an overlapped handle without opening it.+  /**+   * This constructor creates an overlapped handle without opening it.+   *+   * @param context An execution context which provides the I/O executor that+   * the overlapped handle will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the overlapped handle.+   */+  template <typename ExecutionContext>+  explicit basic_overlapped_handle(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value,+        basic_overlapped_handle+      >::type* = 0)+    : impl_(context)+  {+  }++  /// Construct an overlapped handle on an existing native handle.+  /**+   * This constructor creates an overlapped handle object to hold an existing+   * native handle.+   *+   * @param ex The I/O executor that the overlapped handle will use, by default,+   * to dispatch handlers for any asynchronous operations performed on the+   * overlapped handle.+   *+   * @param native_handle The new underlying handle implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_overlapped_handle(const executor_type& ex,+      const native_handle_type& native_handle)+    : impl_(ex)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Construct an overlapped handle on an existing native handle.+  /**+   * This constructor creates an overlapped handle object to hold an existing+   * native handle.+   *+   * @param context An execution context which provides the I/O executor that+   * the overlapped handle will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the overlapped handle.+   *+   * @param native_handle The new underlying handle implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_overlapped_handle(ExecutionContext& context,+      const native_handle_type& native_handle,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);+    asio::detail::throw_error(ec, "assign");+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct an overlapped handle from another.+  /**+   * This constructor moves a handle from one object to another.+   *+   * @param other The other overlapped handle 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 overlapped_handle(const executor_type&)+   * constructor.+   */+  basic_overlapped_handle(basic_overlapped_handle&& other)+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign an overlapped handle from another.+  /**+   * This assignment operator moves a handle from one object to another.+   *+   * @param other The other overlapped handle 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 overlapped_handle(const executor_type&)+   * constructor.+   */+  basic_overlapped_handle& operator=(basic_overlapped_handle&& other)+  {+    impl_ = std::move(other.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();+  }++  /// Get a reference to the lowest layer.+  /**+   * This function returns a reference to the lowest layer in a stack of+   * layers. Since an overlapped_handle 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 an overlapped_handle 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 handle to the handle.+  /*+   * This function opens the handle to hold an existing native handle.+   *+   * @param handle A native handle.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void assign(const native_handle_type& handle)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(), handle, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Assign an existing native handle to the handle.+  /*+   * This function opens the handle to hold an existing native handle.+   *+   * @param handle A native handle.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID assign(const native_handle_type& handle,+      asio::error_code& ec)+  {+    impl_.get_service().assign(impl_.get_implementation(), handle, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Determine whether the handle is open.+  bool is_open() const+  {+    return impl_.get_service().is_open(impl_.get_implementation());+  }++  /// Close the handle.+  /**+   * This function is used to close the handle. 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 handle.+  /**+   * This function is used to close the handle. 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 handle representation.+  /**+   * This function may be used to obtain the underlying representation of the+   * handle. This is intended to allow access to native handle 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 handle.+  /**+   * 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 handle.+  /**+   * 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);+  }++protected:+  /// Protected destructor to prevent deletion through this type.+  /**+   * This function destroys the handle, cancelling any outstanding asynchronous+   * wait operations associated with the handle as if by calling @c cancel.+   */+  ~basic_overlapped_handle()+  {+  }++  asio::detail::io_object_impl<+    asio::detail::win_iocp_handle_service, Executor> impl_;++private:+  // Disallow copying and assignment.+  basic_overlapped_handle(const basic_overlapped_handle&) ASIO_DELETED;+  basic_overlapped_handle& operator=(+      const basic_overlapped_handle&) ASIO_DELETED;+};++} // namespace windows+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)+       //   || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WINDOWS_BASIC_OVERLAPPED_HANDLE_HPP
+ link/modules/asio-standalone/asio/include/asio/windows/basic_random_access_handle.hpp view
@@ -0,0 +1,490 @@+//+// windows/basic_random_access_handle.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP+#define ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/windows/basic_overlapped_handle.hpp"++#if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace windows {++/// Provides random-access handle functionality.+/**+ * The windows::basic_random_access_handle class provides asynchronous and+ * blocking random-access handle functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor = any_io_executor>+class basic_random_access_handle+  : public basic_overlapped_handle<Executor>+{+public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the handle type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The handle type when rebound to the specified executor.+    typedef basic_random_access_handle<Executor1> other;+  };++  /// The native representation of a handle.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#else+  typedef asio::detail::win_iocp_handle_service::native_handle_type+    native_handle_type;+#endif++  /// Construct a random-access handle without opening it.+  /**+   * This constructor creates a random-access handle without opening it.+   *+   * @param ex The I/O executor that the random-access handle will use, by+   * default, to dispatch handlers for any asynchronous operations performed on+   * the random-access handle.+   */+  explicit basic_random_access_handle(const executor_type& ex)+    : basic_overlapped_handle<Executor>(ex)+  {+  }++  /// Construct a random-access handle without opening it.+  /**+   * This constructor creates a random-access handle without opening it. The+   * handle needs to be opened or assigned before data can be sent or received+   * on it.+   *+   * @param context An execution context which provides the I/O executor that+   * the random-access handle will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the random-access handle.+   */+  template <typename ExecutionContext>+  explicit basic_random_access_handle(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value,+        basic_random_access_handle+      >::type* = 0)+    : basic_overlapped_handle<Executor>(context)+  {+  }++  /// Construct a random-access handle on an existing native handle.+  /**+   * This constructor creates a random-access handle object to hold an existing+   * native handle.+   *+   * @param ex The I/O executor that the random-access handle will use, by+   * default, to dispatch handlers for any asynchronous operations performed on+   * the random-access handle.+   *+   * @param handle The new underlying handle implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_random_access_handle(const executor_type& ex,+      const native_handle_type& handle)+    : basic_overlapped_handle<Executor>(ex, handle)+  {+  }++  /// Construct a random-access handle on an existing native handle.+  /**+   * This constructor creates a random-access handle object to hold an existing+   * native handle.+   *+   * @param context An execution context which provides the I/O executor that+   * the random-access handle will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the random-access handle.+   *+   * @param handle The new underlying handle implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_random_access_handle(ExecutionContext& context,+      const native_handle_type& handle,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_overlapped_handle<Executor>(context, handle)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a random-access handle from another.+  /**+   * This constructor moves a random-access handle from one object to another.+   *+   * @param other The other random-access handle 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_handle(const executor_type&)+   * constructor.+   */+  basic_random_access_handle(basic_random_access_handle&& other)+    : basic_overlapped_handle<Executor>(std::move(other))+  {+  }++  /// Move-assign a random-access handle from another.+  /**+   * This assignment operator moves a random-access handle from one object to+   * another.+   *+   * @param other The other random-access handle 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_handle(const executor_type&)+   * constructor.+   */+  basic_random_access_handle& operator=(basic_random_access_handle&& other)+  {+    basic_overlapped_handle<Executor>::operator=(std::move(other));+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// 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 connection was closed by the+   * peer.+   *+   * @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 transmit all of the data to the+   * peer. 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. The function call 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 handler is called.+   *+   * @param handler The handler to be called when the write operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @note The write operation may not transmit all of the data to the peer.+   * 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.+   */+  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_at(uint64_t offset,+      const ConstBufferSequence& buffers,+      ASIO_MOVE_ARG(WriteHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_write_some_at(this), handler, 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 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_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. The function call 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 handler is called.+   *+   * @param handler The handler to be called when the read operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @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.+   */+  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_at(uint64_t offset,+      const MutableBufferSequence& buffers,+      ASIO_MOVE_ARG(ReadHandler) handler+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+  {+    return async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_read_some_at(this), handler, offset, buffers);+  }++private:+  class initiate_async_write_some_at+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_write_some_at(basic_random_access_handle* 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_handle* self_;+  };++  class initiate_async_read_some_at+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_read_some_at(basic_random_access_handle* 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_handle* self_;+  };+};++} // namespace windows+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WINDOWS_BASIC_RANDOM_ACCESS_HANDLE_HPP
+ link/modules/asio-standalone/asio/include/asio/windows/basic_stream_handle.hpp view
@@ -0,0 +1,474 @@+//+// windows/basic_stream_handle.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WINDOWS_BASIC_STREAM_HANDLE_HPP+#define ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/windows/basic_overlapped_handle.hpp"++#if defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace windows {++/// Provides stream-oriented handle functionality.+/**+ * The windows::basic_stream_handle class provides asynchronous and blocking+ * stream-oriented handle 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 = any_io_executor>+class basic_stream_handle+  : public basic_overlapped_handle<Executor>+{+public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the handle type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The handle type when rebound to the specified executor.+    typedef basic_stream_handle<Executor1> other;+  };++  /// The native representation of a handle.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#else+  typedef asio::detail::win_iocp_handle_service::native_handle_type+    native_handle_type;+#endif++  /// Construct a stream handle without opening it.+  /**+   * This constructor creates a stream handle without opening it.+   *+   * @param ex The I/O executor that the stream handle will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the stream+   * handle.+   */+  explicit basic_stream_handle(const executor_type& ex)+    : basic_overlapped_handle<Executor>(ex)+  {+  }++  /// Construct a stream handle without opening it.+  /**+   * This constructor creates a stream handle without opening it. The handle+   * needs to be opened or assigned before data can be sent or received on it.+   *+   * @param context An execution context which provides the I/O executor that+   * the stream handle will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the stream handle.+   */+  template <typename ExecutionContext>+  explicit basic_stream_handle(ExecutionContext& context,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value,+        basic_stream_handle+      >::type* = 0)+    : basic_overlapped_handle<Executor>(context)+  {+  }++  /// Construct a stream handle on an existing native handle.+  /**+   * This constructor creates a stream handle object to hold an existing native+   * handle.+   *+   * @param ex The I/O executor that the stream handle will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the stream+   * handle.+   *+   * @param handle The new underlying handle implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_stream_handle(const executor_type& ex, const native_handle_type& handle)+    : basic_overlapped_handle<Executor>(ex, handle)+  {+  }++  /// Construct a stream handle on an existing native handle.+  /**+   * This constructor creates a stream handle object to hold an existing native+   * handle.+   *+   * @param context An execution context which provides the I/O executor that+   * the stream handle will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the stream handle.+   *+   * @param handle The new underlying handle implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_stream_handle(ExecutionContext& context,+      const native_handle_type& handle,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : basic_overlapped_handle<Executor>(context, handle)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a stream handle from another.+  /**+   * This constructor moves a stream handle from one object to another.+   *+   * @param other The other stream handle 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_handle(const executor_type&)+   * constructor.+   */+  basic_stream_handle(basic_stream_handle&& other)+    : basic_overlapped_handle<Executor>(std::move(other))+  {+  }++  /// Move-assign a stream handle from another.+  /**+   * This assignment operator moves a stream handle from one object to+   * another.+   *+   * @param other The other stream handle 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_handle(const executor_type&)+   * constructor.+   */+  basic_stream_handle& operator=(basic_stream_handle&& other)+  {+    basic_overlapped_handle<Executor>::operator=(std::move(other));+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Write some data to the handle.+  /**+   * This function is used to write data to the stream handle. 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 handle.+   *+   * @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+   * handle.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 handle.+  /**+   * This function is used to write data to the stream handle. 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 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 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 handle.+   * The function call always returns immediately.+   *+   * @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 handler is called.+   *+   * @param handler The handler to be called when the write operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @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+   * handle.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)) 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 async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_write_some(this), handler, buffers);+  }++  /// Read some data from the handle.+  /**+   * This function is used to read data from the stream handle. 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+   * handle.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 handle.+  /**+   * This function is used to read data from the stream handle. 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 handle.+   * The function call 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 handler is called.+   *+   * @param handler The handler to be called when the read operation completes.+   * Copies will be made of the handler as required. The function signature of+   * the 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 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().+   *+   * @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+   * handle.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)) 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 async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        initiate_async_read_some(this), handler, buffers);+  }++private:+  class initiate_async_write_some+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_write_some(basic_stream_handle* 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_handle* self_;+  };++  class initiate_async_read_some+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_read_some(basic_stream_handle* 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_handle* self_;+  };+};++} // namespace windows+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WINDOWS_BASIC_STREAM_HANDLE_HPP
+ link/modules/asio-standalone/asio/include/asio/windows/object_handle.hpp view
@@ -0,0 +1,38 @@+//+// windows/object_handle.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2011 Boris Schaeling (boris@highscore.de)+//+// 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_WINDOWS_OBJECT_HANDLE_HPP+#define ASIO_WINDOWS_OBJECT_HANDLE_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_WINDOWS_OBJECT_HANDLE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/windows/basic_object_handle.hpp"++namespace asio {+namespace windows {++/// Typedef for the typical usage of an object handle.+typedef basic_object_handle<> object_handle;++} // namespace windows+} // namespace asio++#endif // defined(ASIO_HAS_WINDOWS_OBJECT_HANDLE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WINDOWS_OBJECT_HANDLE_HPP
+ link/modules/asio-standalone/asio/include/asio/windows/overlapped_handle.hpp view
@@ -0,0 +1,39 @@+//+// windows/overlapped_handle.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WINDOWS_OVERLAPPED_HANDLE_HPP+#define ASIO_WINDOWS_OVERLAPPED_HANDLE_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_WINDOWS_RANDOM_ACCESS_HANDLE) \+  || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/windows/basic_overlapped_handle.hpp"++namespace asio {+namespace windows {++/// Typedef for the typical usage of an overlapped handle.+typedef basic_overlapped_handle<> overlapped_handle;++} // namespace windows+} // namespace asio++#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)+       //   || defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WINDOWS_OVERLAPPED_HANDLE_HPP
+ link/modules/asio-standalone/asio/include/asio/windows/overlapped_ptr.hpp view
@@ -0,0 +1,145 @@+//+// windows/overlapped_ptr.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WINDOWS_OVERLAPPED_PTR_HPP+#define ASIO_WINDOWS_OVERLAPPED_PTR_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_WINDOWS_OVERLAPPED_PTR) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/detail/noncopyable.hpp"+#include "asio/detail/win_iocp_overlapped_ptr.hpp"+#include "asio/io_context.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace windows {++/// Wraps a handler to create an OVERLAPPED object for use with overlapped I/O.+/**+ * A special-purpose smart pointer used to wrap an application handler so that+ * it can be passed as the LPOVERLAPPED argument to overlapped I/O functions.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+class overlapped_ptr+  : private noncopyable+{+public:+  /// Construct an empty overlapped_ptr.+  overlapped_ptr()+    : impl_()+  {+  }++  /// Construct an overlapped_ptr to contain the specified handler.+  template <typename ExecutionContext, typename Handler>+  explicit overlapped_ptr(ExecutionContext& context,+      ASIO_MOVE_ARG(Handler) handler,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+    : impl_(context.get_executor(), ASIO_MOVE_CAST(Handler)(handler))+  {+  }++  /// Construct an overlapped_ptr to contain the specified handler.+  template <typename Executor, typename Handler>+  explicit overlapped_ptr(const Executor& ex,+      ASIO_MOVE_ARG(Handler) handler,+      typename enable_if<+        execution::is_executor<Executor>::value+          || is_executor<Executor>::value+      >::type* = 0)+    : impl_(ex, ASIO_MOVE_CAST(Handler)(handler))+  {+  }++  /// Destructor automatically frees the OVERLAPPED object unless released.+  ~overlapped_ptr()+  {+  }++  /// Reset to empty.+  void reset()+  {+    impl_.reset();+  }++  /// Reset to contain the specified handler, freeing any current OVERLAPPED+  /// object.+  template <typename ExecutionContext, typename Handler>+  void reset(ExecutionContext& context, ASIO_MOVE_ARG(Handler) handler,+      typename enable_if<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type* = 0)+  {+    impl_.reset(context.get_executor(), ASIO_MOVE_CAST(Handler)(handler));+  }++  /// Reset to contain the specified handler, freeing any current OVERLAPPED+  /// object.+  template <typename Executor, typename Handler>+  void reset(const Executor& ex, ASIO_MOVE_ARG(Handler) handler,+      typename enable_if<+        execution::is_executor<Executor>::value+          || is_executor<Executor>::value+      >::type* = 0)+  {+    impl_.reset(ex, ASIO_MOVE_CAST(Handler)(handler));+  }++  /// Get the contained OVERLAPPED object.+  OVERLAPPED* get()+  {+    return impl_.get();+  }++  /// Get the contained OVERLAPPED object.+  const OVERLAPPED* get() const+  {+    return impl_.get();+  }++  /// Release ownership of the OVERLAPPED object.+  OVERLAPPED* release()+  {+    return impl_.release();+  }++  /// Post completion notification for overlapped operation. Releases ownership.+  void complete(const asio::error_code& ec,+      std::size_t bytes_transferred)+  {+    impl_.complete(ec, bytes_transferred);+  }++private:+  detail::win_iocp_overlapped_ptr impl_;+};++} // namespace windows+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_WINDOWS_OVERLAPPED_PTR)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WINDOWS_OVERLAPPED_PTR_HPP
+ link/modules/asio-standalone/asio/include/asio/windows/random_access_handle.hpp view
@@ -0,0 +1,37 @@+//+// windows/random_access_handle.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WINDOWS_RANDOM_ACCESS_HANDLE_HPP+#define ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_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_WINDOWS_RANDOM_ACCESS_HANDLE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/windows/basic_random_access_handle.hpp"++namespace asio {+namespace windows {++/// Typedef for the typical usage of a random-access handle.+typedef basic_random_access_handle<> random_access_handle;++} // namespace windows+} // namespace asio++#endif // defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WINDOWS_RANDOM_ACCESS_HANDLE_HPP
+ link/modules/asio-standalone/asio/include/asio/windows/stream_handle.hpp view
@@ -0,0 +1,37 @@+//+// windows/stream_handle.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WINDOWS_STREAM_HANDLE_HPP+#define ASIO_WINDOWS_STREAM_HANDLE_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_WINDOWS_STREAM_HANDLE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/windows/basic_stream_handle.hpp"++namespace asio {+namespace windows {++/// Typedef for the typical usage of a stream-oriented handle.+typedef basic_stream_handle<> stream_handle;++} // namespace windows+} // namespace asio++#endif // defined(ASIO_HAS_WINDOWS_STREAM_HANDLE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WINDOWS_STREAM_HANDLE_HPP
+ link/modules/asio-standalone/asio/include/asio/write.hpp view
@@ -0,0 +1,1246 @@+//+// write.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WRITE_HPP+#define ASIO_WRITE_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/buffer.hpp"+#include "asio/error.hpp"++#if !defined(ASIO_NO_EXTENSIONS)+# include "asio/basic_streambuf_fwd.hpp"+#endif // !defined(ASIO_NO_EXTENSIONS)++#include "asio/detail/push_options.hpp"++namespace asio {++/**+ * @defgroup write asio::write+ *+ * @brief The @c write function is a composed operation that writes a certain+ * amount of data to a stream before returning.+ */+/*@{*/++/// Write all of the supplied data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers One or more buffers containing the data to be written. The sum+ * of the buffer sizes indicates the maximum number of bytes to write to the+ * stream.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code asio::write(s, 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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write(+ *     s, buffers,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncWriteStream, typename ConstBufferSequence>+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type* = 0);++/// Write all of the supplied data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers One or more buffers containing the data to be written. The sum+ * of the buffer sizes indicates the maximum number of bytes to write to the+ * stream.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code asio::write(s, asio::buffer(data, size), ec); @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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write(+ *     s, buffers,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncWriteStream, typename ConstBufferSequence>+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,+    asio::error_code& ec,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type* = 0);++/// Write a certain amount of data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers One or more buffers containing the data to be written. The sum+ * of the buffer sizes indicates the maximum number of bytes to write to the+ * stream.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's write_some function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code asio::write(s, asio::buffer(data, size),+ *     asio::transfer_at_least(32)); @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 SyncWriteStream, typename ConstBufferSequence,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type* = 0);++/// Write a certain amount of data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers One or more buffers containing the data to be written. The sum+ * of the buffer sizes indicates the maximum number of bytes to write to the+ * stream.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's write_some function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes written. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncWriteStream, typename ConstBufferSequence,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type* = 0);++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Write all of the supplied data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * Successfully written data is automatically consumed from the buffers.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write(+ *     s, buffers,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncWriteStream, typename DynamicBuffer_v1>+std::size_t write(SyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Write all of the supplied data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * Successfully written data is automatically consumed from the buffers.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write(+ *     s, buffers,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncWriteStream, typename DynamicBuffer_v1>+std::size_t write(SyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Write a certain amount of data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * Successfully written data is automatically consumed from the buffers.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's write_some function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename SyncWriteStream, typename DynamicBuffer_v1,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Write a certain amount of data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * Successfully written data is automatically consumed from the buffers.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's write_some function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes written. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncWriteStream, typename DynamicBuffer_v1,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++/// Write all of the supplied data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param b The basic_streambuf object from which data will be written.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write(+ *     s, b,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncWriteStream, typename Allocator>+std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b);++/// Write all of the supplied data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param b The basic_streambuf object from which data will be written.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write(+ *     s, b,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncWriteStream, typename Allocator>+std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,+    asio::error_code& ec);++/// Write a certain amount of data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param b The basic_streambuf object from which data will be written.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's write_some function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename SyncWriteStream, typename Allocator,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition);++/// Write a certain amount of data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param b The basic_streambuf object from which data will be written.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's write_some function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes written. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncWriteStream, typename Allocator,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition, asio::error_code& ec);++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Write all of the supplied data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * Successfully written data is automatically consumed from the buffers.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write(+ *     s, buffers,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncWriteStream, typename DynamicBuffer_v2>+std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Write all of the supplied data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * Successfully written data is automatically consumed from the buffers.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write(+ *     s, buffers,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncWriteStream, typename DynamicBuffer_v2>+std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,+    asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Write a certain amount of data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * Successfully written data is automatically consumed from the buffers.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's write_some function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename SyncWriteStream, typename DynamicBuffer_v2,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Write a certain amount of data to a stream before returning.+/**+ * This function is used to write a certain number of bytes of data to a stream.+ * The call will block until one of the following conditions is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * write_some function.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the SyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * Successfully written data is automatically consumed from the buffers.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's write_some function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes written. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncWriteStream, typename DynamicBuffer_v2,+    typename CompletionCondition>+std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition, asio::error_code& ec,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/*@}*/+/**+ * @defgroup async_write asio::async_write+ *+ * @brief The @c async_write function is a composed asynchronous operation that+ * writes a certain amount of data to a stream before completion.+ */+/*@{*/++/// Start an asynchronous operation to write all of the supplied data to a+/// stream.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_write_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other write operations (such+ * as async_write, the stream's async_write_some function, or any other composed+ * operations that perform writes) until this operation completes.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the AsyncWriteStream concept.+ *+ * @param buffers One or more buffers containing the data to be written.+ * 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 handler is called.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of+ * the handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes written from the+ *                                           // buffers. If an error occurred,+ *                                           // this will be less than the sum+ *                                           // of the buffer sizes.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code+ * asio::async_write(s, 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 AsyncWriteStream, typename ConstBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncWriteStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,+    ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncWriteStream::executor_type),+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type* = 0);++/// Start an asynchronous operation to write a certain amount of data to a+/// stream.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_write_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other write operations (such+ * as async_write, the stream's async_write_some function, or any other composed+ * operations that perform writes) until this operation completes.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the AsyncWriteStream concept.+ *+ * @param buffers One or more buffers containing the data to be written.+ * 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 handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's async_write_some function.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes written from the+ *                                           // buffers. If an error occurred,+ *                                           // this will be less than the sum+ *                                           // of the buffer sizes.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code asio::async_write(s,+ *     asio::buffer(data, size),+ *     asio::transfer_at_least(32),+ *     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 AsyncWriteStream,+    typename ConstBufferSequence, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler,+    typename enable_if<+      is_const_buffer_sequence<ConstBufferSequence>::value+    >::type* = 0);++#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Start an asynchronous operation to write all of the supplied data to a+/// stream.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_write_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other write operations (such+ * as async_write, the stream's async_write_some function, or any other composed+ * operations that perform writes) until this operation completes.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the AsyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * 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 handler is called. Successfully written+ * data is automatically consumed from the buffers.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes written from the+ *                                           // buffers. If an error occurred,+ *                                           // this will be less than the sum+ *                                           // of the buffer sizes.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncWriteStream, typename DynamicBuffer_v1,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncWriteStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncWriteStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++/// Start an asynchronous operation to write a certain amount of data to a+/// stream.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_write_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other write operations (such+ * as async_write, the stream's async_write_some function, or any other composed+ * operations that perform writes) until this operation completes.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the AsyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * 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 handler is called. Successfully written+ * data is automatically consumed from the buffers.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's async_write_some function.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes written from the+ *                                           // buffers. If an error occurred,+ *                                           // this will be less than the sum+ *                                           // of the buffer sizes.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncWriteStream,+    typename DynamicBuffer_v1, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s,+    ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type* = 0);++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++/// Start an asynchronous operation to write all of the supplied data to a+/// stream.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_write_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other write operations (such+ * as async_write, the stream's async_write_some function, or any other composed+ * operations that perform writes) until this operation completes.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the AsyncWriteStream concept.+ *+ * @param b A basic_streambuf object from which data will be written. Ownership+ * of the streambuf is retained by the caller, which must guarantee that it+ * remains valid until the handler is called.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes written from the+ *                                           // buffers. If an error occurred,+ *                                           // this will be less than the sum+ *                                           // of the buffer sizes.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncWriteStream, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncWriteStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,+    ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncWriteStream::executor_type));++/// Start an asynchronous operation to write a certain amount of data to a+/// stream.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_write_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other write operations (such+ * as async_write, the stream's async_write_some function, or any other composed+ * operations that perform writes) until this operation completes.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the AsyncWriteStream concept.+ *+ * @param b A basic_streambuf object from which data will be written. Ownership+ * of the streambuf is retained by the caller, which must guarantee that it+ * remains valid until the handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's async_write_some function.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes written from the+ *                                           // buffers. If an error occurred,+ *                                           // this will be less than the sum+ *                                           // of the buffer sizes.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncWriteStream,+    typename Allocator, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler);++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)++/// Start an asynchronous operation to write all of the supplied data to a+/// stream.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_write_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other write operations (such+ * as async_write, the stream's async_write_some function, or any other composed+ * operations that perform writes) until this operation completes.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the AsyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * 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 handler is called. Successfully written+ * data is automatically consumed from the buffers.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes written from the+ *                                           // buffers. If an error occurred,+ *                                           // this will be less than the sum+ *                                           // of the buffer sizes.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncWriteStream, typename DynamicBuffer_v2,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncWriteStream::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,+    ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncWriteStream::executor_type),+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/// Start an asynchronous operation to write a certain amount of data to a+/// stream.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a stream. The function call always returns immediately. The+ * asynchronous operation will continue until one of the following conditions+ * is true:+ *+ * @li All of the data in the supplied dynamic buffer sequence has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the stream's+ * async_write_some function, and is known as a <em>composed operation</em>. The+ * program must ensure that the stream performs no other write operations (such+ * as async_write, the stream's async_write_some function, or any other composed+ * operations that perform writes) until this operation completes.+ *+ * @param s The stream to which the data is to be written. The type must support+ * the AsyncWriteStream concept.+ *+ * @param buffers The dynamic buffer sequence from which data will be written.+ * 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 handler is called. Successfully written+ * data is automatically consumed from the buffers.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_write_some operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the stream's async_write_some function.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   const asio::error_code& error, // Result of operation.+ *+ *   std::size_t bytes_transferred           // Number of bytes written from the+ *                                           // buffers. If an error occurred,+ *                                           // this will be less than the sum+ *                                           // of the buffer sizes.+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncWriteStream,+    typename DynamicBuffer_v2, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler,+    typename enable_if<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type* = 0);++/*@}*/++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/write.hpp"++#endif // ASIO_WRITE_HPP
+ link/modules/asio-standalone/asio/include/asio/write_at.hpp view
@@ -0,0 +1,702 @@+//+// write_at.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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_WRITE_AT_HPP+#define ASIO_WRITE_AT_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/detail/cstdint.hpp"+#include "asio/error.hpp"++#if !defined(ASIO_NO_EXTENSIONS)+# include "asio/basic_streambuf_fwd.hpp"+#endif // !defined(ASIO_NO_EXTENSIONS)++#include "asio/detail/push_options.hpp"++namespace asio {++/**+ * @defgroup write_at asio::write_at+ *+ * @brief The @c write_at function is a composed operation that writes a+ * certain amount of data at a specified offset before returning.+ */+/*@{*/++/// Write all of the supplied data at the specified offset before returning.+/**+ * This function is used to write a certain number of bytes of data to a random+ * access device at a specified offset. The call will block until one of the+ * following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * write_some_at function.+ *+ * @param d The device to which the data is to be written. The type must support+ * the SyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param buffers One or more buffers containing the data to be written. The sum+ * of the buffer sizes indicates the maximum number of bytes to write to the+ * device.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code asio::write_at(d, 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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write_at(+ *     d, offset, buffers,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>+std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers);++/// Write all of the supplied data at the specified offset before returning.+/**+ * This function is used to write a certain number of bytes of data to a random+ * access device at a specified offset. The call will block until one of the+ * following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * write_some_at function.+ *+ * @param d The device to which the data is to be written. The type must support+ * the SyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param buffers One or more buffers containing the data to be written. The sum+ * of the buffer sizes indicates the maximum number of bytes to write to the+ * device.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code asio::write_at(d, 42,+ *     asio::buffer(data, size), ec); @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.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write_at(+ *     d, offset, buffers,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence>+std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers,+    asio::error_code& ec);++/// Write a certain amount of data at a specified offset before returning.+/**+ * This function is used to write a certain number of bytes of data to a random+ * access device at a specified offset. The call will block until one of the+ * following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * write_some_at function.+ *+ * @param d The device to which the data is to be written. The type must support+ * the SyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param buffers One or more buffers containing the data to be written. The sum+ * of the buffer sizes indicates the maximum number of bytes to write to the+ * device.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the device's write_some_at function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @par Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code asio::write_at(d, 42, asio::buffer(data, size),+ *     asio::transfer_at_least(32)); @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 SyncRandomAccessWriteDevice, typename ConstBufferSequence,+    typename CompletionCondition>+std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition);++/// Write a certain amount of data at a specified offset before returning.+/**+ * This function is used to write a certain number of bytes of data to a random+ * access device at a specified offset. The call will block until one of the+ * following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * write_some_at function.+ *+ * @param d The device to which the data is to be written. The type must support+ * the SyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param buffers One or more buffers containing the data to be written. The sum+ * of the buffer sizes indicates the maximum number of bytes to write to the+ * device.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the device's write_some_at function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes written. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncRandomAccessWriteDevice, typename ConstBufferSequence,+    typename CompletionCondition>+std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition, asio::error_code& ec);++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++/// Write all of the supplied data at the specified offset before returning.+/**+ * This function is used to write a certain number of bytes of data to a random+ * access device at a specified offset. The call will block until one of the+ * following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * write_some_at function.+ *+ * @param d The device to which the data is to be written. The type must support+ * the SyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param b The basic_streambuf object from which data will be written.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write_at(+ *     d, 42, b,+ *     asio::transfer_all()); @endcode+ */+template <typename SyncRandomAccessWriteDevice, typename Allocator>+std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, basic_streambuf<Allocator>& b);++/// Write all of the supplied data at the specified offset before returning.+/**+ * This function is used to write a certain number of bytes of data to a random+ * access device at a specified offset. The call will block until one of the+ * following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * write_some_at function.+ *+ * @param d The device to which the data is to be written. The type must support+ * the SyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param b The basic_streambuf object from which data will be written.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes transferred.+ *+ * @note This overload is equivalent to calling:+ * @code asio::write_at(+ *     d, 42, b,+ *     asio::transfer_all(), ec); @endcode+ */+template <typename SyncRandomAccessWriteDevice, typename Allocator>+std::size_t write_at(SyncRandomAccessWriteDevice& d,+    uint64_t offset, basic_streambuf<Allocator>& b,+    asio::error_code& ec);++/// Write a certain amount of data at a specified offset before returning.+/**+ * This function is used to write a certain number of bytes of data to a random+ * access device at a specified offset. The call will block until one of the+ * following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * write_some_at function.+ *+ * @param d The device to which the data is to be written. The type must support+ * the SyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param b The basic_streambuf object from which data will be written.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the device's write_some_at function.+ *+ * @returns The number of bytes transferred.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename SyncRandomAccessWriteDevice, typename Allocator,+    typename CompletionCondition>+std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset,+    basic_streambuf<Allocator>& b, CompletionCondition completion_condition);++/// Write a certain amount of data at a specified offset before returning.+/**+ * This function is used to write a certain number of bytes of data to a random+ * access device at a specified offset. The call will block until one of the+ * following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * write_some_at function.+ *+ * @param d The device to which the data is to be written. The type must support+ * the SyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param b The basic_streambuf object from which data will be written.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest write_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the device's write_some_at function.+ *+ * @param ec Set to indicate what error occurred, if any.+ *+ * @returns The number of bytes written. If an error occurs, returns the total+ * number of bytes successfully transferred prior to the error.+ */+template <typename SyncRandomAccessWriteDevice, typename Allocator,+    typename CompletionCondition>+std::size_t write_at(SyncRandomAccessWriteDevice& d, uint64_t offset,+    basic_streambuf<Allocator>& b, CompletionCondition completion_condition,+    asio::error_code& ec);++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)++/*@}*/+/**+ * @defgroup async_write_at asio::async_write_at+ *+ * @brief The @c async_write_at function is a composed asynchronous operation+ * that writes a certain amount of data at the specified offset before+ * completion.+ */+/*@{*/++/// Start an asynchronous operation to write all of the supplied data at the+/// specified offset.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a random access device at a specified offset. The function call+ * always returns immediately. The asynchronous operation will continue until+ * one of the following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * async_write_some_at function, and is known as a <em>composed operation</em>.+ * The program must ensure that the device performs no <em>overlapping</em>+ * write operations (such as async_write_at, the device's async_write_some_at+ * function, or any other composed operations that perform writes) until this+ * operation completes. Operations are overlapping if the regions defined by+ * their offsets, and the numbers of bytes to write, intersect.+ *+ * @param d The device to which the data is to be written. The type must support+ * the AsyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param buffers One or more buffers containing the data to be written.+ * 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 handler is called.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of+ * the handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes written from the buffers. If an error+ *   // occurred, this will be less than the sum of the buffer sizes.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code+ * asio::async_write_at(d, 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.+ */+template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncRandomAccessWriteDevice::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset,+    const ConstBufferSequence& buffers,+    ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncRandomAccessWriteDevice::executor_type));++/// Start an asynchronous operation to write a certain amount of data at the+/// specified offset.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a random access device at a specified offset. The function call+ * always returns immediately. The asynchronous operation will continue until+ * one of the following conditions is true:+ *+ * @li All of the data in the supplied buffers has been written. That is, the+ * bytes transferred is equal to the sum of the buffer sizes.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * async_write_some_at function, and is known as a <em>composed operation</em>.+ * The program must ensure that the device performs no <em>overlapping</em>+ * write operations (such as async_write_at, the device's async_write_some_at+ * function, or any other composed operations that perform writes) until this+ * operation completes. Operations are overlapping if the regions defined by+ * their offsets, and the numbers of bytes to write, intersect.+ *+ * @param d The device to which the data is to be written. The type must support+ * the AsyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param buffers One or more buffers containing the data to be written.+ * 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 handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_write_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the device's async_write_some_at function.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes written from the buffers. If an error+ *   // occurred, this will be less than the sum of the buffer sizes.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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 Example+ * To write a single data buffer use the @ref buffer function as follows:+ * @code asio::async_write_at(d, 42,+ *     asio::buffer(data, size),+ *     asio::transfer_at_least(32),+ *     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 AsyncRandomAccessWriteDevice,+    typename ConstBufferSequence, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncRandomAccessWriteDevice::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write_at(AsyncRandomAccessWriteDevice& d,+    uint64_t offset, const ConstBufferSequence& buffers,+    CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncRandomAccessWriteDevice::executor_type));++#if !defined(ASIO_NO_EXTENSIONS)+#if !defined(ASIO_NO_IOSTREAM)++/// Start an asynchronous operation to write all of the supplied data at the+/// specified offset.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a random access device at a specified offset. The function call+ * always returns immediately. The asynchronous operation will continue until+ * one of the following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li An error occurred.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * async_write_some_at function, and is known as a <em>composed operation</em>.+ * The program must ensure that the device performs no <em>overlapping</em>+ * write operations (such as async_write_at, the device's async_write_some_at+ * function, or any other composed operations that perform writes) until this+ * operation completes. Operations are overlapping if the regions defined by+ * their offsets, and the numbers of bytes to write, intersect.+ *+ * @param d The device to which the data is to be written. The type must support+ * the AsyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param b A basic_streambuf object from which data will be written. Ownership+ * of the streambuf is retained by the caller, which must guarantee that it+ * remains valid until the handler is called.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes written from the buffers. If an error+ *   // occurred, this will be less than the sum of the buffer sizes.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncRandomAccessWriteDevice, typename Allocator,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncRandomAccessWriteDevice::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write_at(AsyncRandomAccessWriteDevice& d,+    uint64_t offset, basic_streambuf<Allocator>& b,+    ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncRandomAccessWriteDevice::executor_type));++/// Start an asynchronous operation to write a certain amount of data at the+/// specified offset.+/**+ * This function is used to asynchronously write a certain number of bytes of+ * data to a random access device at a specified offset. The function call+ * always returns immediately. The asynchronous operation will continue until+ * one of the following conditions is true:+ *+ * @li All of the data in the supplied basic_streambuf has been written.+ *+ * @li The completion_condition function object returns 0.+ *+ * This operation is implemented in terms of zero or more calls to the device's+ * async_write_some_at function, and is known as a <em>composed operation</em>.+ * The program must ensure that the device performs no <em>overlapping</em>+ * write operations (such as async_write_at, the device's async_write_some_at+ * function, or any other composed operations that perform writes) until this+ * operation completes. Operations are overlapping if the regions defined by+ * their offsets, and the numbers of bytes to write, intersect.+ *+ * @param d The device to which the data is to be written. The type must support+ * the AsyncRandomAccessWriteDevice concept.+ *+ * @param offset The offset at which the data will be written.+ *+ * @param b A basic_streambuf object from which data will be written. Ownership+ * of the streambuf is retained by the caller, which must guarantee that it+ * remains valid until the handler is called.+ *+ * @param completion_condition The function object to be called to determine+ * whether the write operation is complete. The signature of the function object+ * must be:+ * @code std::size_t completion_condition(+ *   // Result of latest async_write_some_at operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes transferred so far.+ *   std::size_t bytes_transferred+ * ); @endcode+ * A return value of 0 indicates that the write operation is complete. A+ * non-zero return value indicates the maximum number of bytes to be written on+ * the next call to the device's async_write_some_at function.+ *+ * @param handler The handler to be called when the write operation completes.+ * Copies will be made of the handler as required. The function signature of the+ * handler must be:+ * @code void handler(+ *   // Result of operation.+ *   const asio::error_code& error,+ *+ *   // Number of bytes written from the buffers. If an error+ *   // occurred, this will be less than the sum of the buffer sizes.+ *   std::size_t bytes_transferred+ * ); @endcode+ * Regardless of whether the asynchronous operation completes immediately or+ * not, the 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().+ */+template <typename AsyncRandomAccessWriteDevice,+    typename Allocator, typename CompletionCondition,+    ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+      std::size_t)) WriteHandler+        ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+          typename AsyncRandomAccessWriteDevice::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+    void (asio::error_code, std::size_t))+async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset,+    basic_streambuf<Allocator>& b, CompletionCondition completion_condition,+    ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename AsyncRandomAccessWriteDevice::executor_type));++#endif // !defined(ASIO_NO_IOSTREAM)+#endif // !defined(ASIO_NO_EXTENSIONS)++/*@}*/++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/write_at.hpp"++#endif // ASIO_WRITE_AT_HPP
+ link/modules/asio-standalone/asio/include/asio/yield.hpp view
@@ -0,0 +1,23 @@+//+// yield.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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)+//++#include "coroutine.hpp"++#ifndef reenter+# define reenter(c) ASIO_CORO_REENTER(c)+#endif++#ifndef yield+# define yield ASIO_CORO_YIELD+#endif++#ifndef fork+# define fork ASIO_CORO_FORK+#endif
+ link/modules/asio-standalone/asio/src/examples/cpp03/chat/chat_message.hpp view
@@ -0,0 +1,93 @@+//+// chat_message.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 CHAT_MESSAGE_HPP+#define CHAT_MESSAGE_HPP++#include <cstdio>+#include <cstdlib>+#include <cstring>++class chat_message+{+public:+  enum { header_length = 4 };+  enum { max_body_length = 512 };++  chat_message()+    : body_length_(0)+  {+  }++  const char* data() const+  {+    return data_;+  }++  char* data()+  {+    return data_;+  }++  size_t length() const+  {+    return header_length + body_length_;+  }++  const char* body() const+  {+    return data_ + header_length;+  }++  char* body()+  {+    return data_ + header_length;+  }++  size_t body_length() const+  {+    return body_length_;+  }++  void body_length(size_t new_length)+  {+    body_length_ = new_length;+    if (body_length_ > max_body_length)+      body_length_ = max_body_length;+  }++  bool decode_header()+  {+    using namespace std; // For strncat and atoi.+    char header[header_length + 1] = "";+    strncat(header, data_, header_length);+    body_length_ = atoi(header);+    if (body_length_ > max_body_length)+    {+      body_length_ = 0;+      return false;+    }+    return true;+  }++  void encode_header()+  {+    using namespace std; // For sprintf and memcpy.+    char header[header_length + 1] = "";+    sprintf(header, "%4d", static_cast<int>(body_length_));+    memcpy(data_, header, header_length);+  }++private:+  char data_[header_length + max_body_length];+  size_t body_length_;+};++#endif // CHAT_MESSAGE_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection.hpp view
@@ -0,0 +1,83 @@+//+// connection.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_CONNECTION_HPP+#define HTTP_CONNECTION_HPP++#include <asio.hpp>+#include <boost/array.hpp>+#include <boost/noncopyable.hpp>+#include <boost/shared_ptr.hpp>+#include <boost/enable_shared_from_this.hpp>+#include "reply.hpp"+#include "request.hpp"+#include "request_handler.hpp"+#include "request_parser.hpp"++namespace http {+namespace server {++class connection_manager;++/// Represents a single connection from a client.+class connection+  : public boost::enable_shared_from_this<connection>,+    private boost::noncopyable+{+public:+  /// Construct a connection with the given io_context.+  explicit connection(asio::io_context& io_context,+      connection_manager& manager, request_handler& handler);++  /// Get the socket associated with the connection.+  asio::ip::tcp::socket& socket();++  /// Start the first asynchronous operation for the connection.+  void start();++  /// Stop all asynchronous operations associated with the connection.+  void stop();++private:+  /// Handle completion of a read operation.+  void handle_read(const asio::error_code& e,+      std::size_t bytes_transferred);++  /// Handle completion of a write operation.+  void handle_write(const asio::error_code& e);++  /// Socket for the connection.+  asio::ip::tcp::socket socket_;++  /// The manager for this connection.+  connection_manager& connection_manager_;++  /// The handler used to process the incoming request.+  request_handler& request_handler_;++  /// Buffer for incoming data.+  boost::array<char, 8192> buffer_;++  /// The incoming request.+  request request_;++  /// The parser for the incoming request.+  request_parser request_parser_;++  /// The reply to be sent back to the client.+  reply reply_;+};++typedef boost::shared_ptr<connection> connection_ptr;++} // namespace server+} // namespace http++#endif // HTTP_CONNECTION_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection_manager.hpp view
@@ -0,0 +1,44 @@+//+// connection_manager.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_CONNECTION_MANAGER_HPP+#define HTTP_CONNECTION_MANAGER_HPP++#include <set>+#include <boost/noncopyable.hpp>+#include "connection.hpp"++namespace http {+namespace server {++/// Manages open connections so that they may be cleanly stopped when the server+/// needs to shut down.+class connection_manager+  : private boost::noncopyable+{+public:+  /// Add the specified connection to the manager and start it.+  void start(connection_ptr c);++  /// Stop the specified connection.+  void stop(connection_ptr c);++  /// Stop all connections.+  void stop_all();++private:+  /// The managed connections.+  std::set<connection_ptr> connections_;+};++} // namespace server+} // namespace http++#endif // HTTP_CONNECTION_MANAGER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server/header.hpp view
@@ -0,0 +1,28 @@+//+// header.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_HEADER_HPP+#define HTTP_HEADER_HPP++#include <string>++namespace http {+namespace server {++struct header+{+  std::string name;+  std::string value;+};++} // namespace server+} // namespace http++#endif // HTTP_HEADER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server/mime_types.hpp view
@@ -0,0 +1,27 @@+//+// mime_types.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_MIME_TYPES_HPP+#define HTTP_MIME_TYPES_HPP++#include <string>++namespace http {+namespace server {+namespace mime_types {++/// Convert a file extension into a MIME type.+std::string extension_to_type(const std::string& extension);++} // namespace mime_types+} // namespace server+} // namespace http++#endif // HTTP_MIME_TYPES_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server/reply.hpp view
@@ -0,0 +1,64 @@+//+// reply.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_REPLY_HPP+#define HTTP_REPLY_HPP++#include <string>+#include <vector>+#include <asio.hpp>+#include "header.hpp"++namespace http {+namespace server {++/// A reply to be sent to a client.+struct reply+{+  /// The status of the reply.+  enum status_type+  {+    ok = 200,+    created = 201,+    accepted = 202,+    no_content = 204,+    multiple_choices = 300,+    moved_permanently = 301,+    moved_temporarily = 302,+    not_modified = 304,+    bad_request = 400,+    unauthorized = 401,+    forbidden = 403,+    not_found = 404,+    internal_server_error = 500,+    not_implemented = 501,+    bad_gateway = 502,+    service_unavailable = 503+  } status;++  /// The headers to be included in the reply.+  std::vector<header> headers;++  /// The content to be sent in the reply.+  std::string content;++  /// Convert the reply into a vector of buffers. The buffers do not own the+  /// underlying memory blocks, therefore the reply object must remain valid and+  /// not be changed until the write operation has completed.+  std::vector<asio::const_buffer> to_buffers();++  /// Get a stock reply.+  static reply stock_reply(status_type status);+};++} // namespace server+} // namespace http++#endif // HTTP_REPLY_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request.hpp view
@@ -0,0 +1,34 @@+//+// request.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_REQUEST_HPP+#define HTTP_REQUEST_HPP++#include <string>+#include <vector>+#include "header.hpp"++namespace http {+namespace server {++/// A request received from a client.+struct request+{+  std::string method;+  std::string uri;+  int http_version_major;+  int http_version_minor;+  std::vector<header> headers;+};++} // namespace server+} // namespace http++#endif // HTTP_REQUEST_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_handler.hpp view
@@ -0,0 +1,46 @@+//+// request_handler.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_REQUEST_HANDLER_HPP+#define HTTP_REQUEST_HANDLER_HPP++#include <string>+#include <boost/noncopyable.hpp>++namespace http {+namespace server {++struct reply;+struct request;++/// The common handler for all incoming requests.+class request_handler+  : private boost::noncopyable+{+public:+  /// Construct with a directory containing files to be served.+  explicit request_handler(const std::string& doc_root);++  /// Handle a request and produce a reply.+  void handle_request(const request& req, reply& rep);++private:+  /// The directory containing the files to be served.+  std::string doc_root_;++  /// Perform URL-decoding on a string. Returns false if the encoding was+  /// invalid.+  static bool url_decode(const std::string& in, std::string& out);+};++} // namespace server+} // namespace http++#endif // HTTP_REQUEST_HANDLER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_parser.hpp view
@@ -0,0 +1,95 @@+//+// request_parser.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_REQUEST_PARSER_HPP+#define HTTP_REQUEST_PARSER_HPP++#include <boost/logic/tribool.hpp>+#include <boost/tuple/tuple.hpp>++namespace http {+namespace server {++struct request;++/// Parser for incoming requests.+class request_parser+{+public:+  /// Construct ready to parse the request method.+  request_parser();++  /// Reset to initial parser state.+  void reset();++  /// Parse some data. The tribool return value is true when a complete request+  /// has been parsed, false if the data is invalid, indeterminate when more+  /// data is required. The InputIterator return value indicates how much of the+  /// input has been consumed.+  template <typename InputIterator>+  boost::tuple<boost::tribool, InputIterator> parse(request& req,+      InputIterator begin, InputIterator end)+  {+    while (begin != end)+    {+      boost::tribool result = consume(req, *begin++);+      if (result || !result)+        return boost::make_tuple(result, begin);+    }+    boost::tribool result = boost::indeterminate;+    return boost::make_tuple(result, begin);+  }++private:+  /// Handle the next character of input.+  boost::tribool consume(request& req, char input);++  /// Check if a byte is an HTTP character.+  static bool is_char(int c);++  /// Check if a byte is an HTTP control character.+  static bool is_ctl(int c);++  /// Check if a byte is defined as an HTTP tspecial character.+  static bool is_tspecial(int c);++  /// Check if a byte is a digit.+  static bool is_digit(int c);++  /// The current state of the parser.+  enum state+  {+    method_start,+    method,+    uri,+    http_version_h,+    http_version_t_1,+    http_version_t_2,+    http_version_p,+    http_version_slash,+    http_version_major_start,+    http_version_major,+    http_version_minor_start,+    http_version_minor,+    expecting_newline_1,+    header_line_start,+    header_lws,+    header_name,+    space_before_header_value,+    header_value,+    expecting_newline_2,+    expecting_newline_3+  } state_;+};++} // namespace server+} // namespace http++#endif // HTTP_REQUEST_PARSER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server/server.hpp view
@@ -0,0 +1,69 @@+//+// server.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER_HPP+#define HTTP_SERVER_HPP++#include <asio.hpp>+#include <string>+#include <boost/noncopyable.hpp>+#include "connection.hpp"+#include "connection_manager.hpp"+#include "request_handler.hpp"++namespace http {+namespace server {++/// The top-level class of the HTTP server.+class server+  : private boost::noncopyable+{+public:+  /// Construct the server to listen on the specified TCP address and port, and+  /// serve up files from the given directory.+  explicit server(const std::string& address, const std::string& port,+      const std::string& doc_root);++  /// Run the server's io_context loop.+  void run();++private:+  /// Initiate an asynchronous accept operation.+  void start_accept();++  /// Handle completion of an asynchronous accept operation.+  void handle_accept(const asio::error_code& e);++  /// Handle a request to stop the server.+  void handle_stop();++  /// The io_context used to perform asynchronous operations.+  asio::io_context io_context_;++  /// The signal_set is used to register for process termination notifications.+  asio::signal_set signals_;++  /// Acceptor used to listen for incoming connections.+  asio::ip::tcp::acceptor acceptor_;++  /// The connection manager which owns all live connections.+  connection_manager connection_manager_;++  /// The next connection to be accepted.+  connection_ptr new_connection_;++  /// The handler for all incoming requests.+  request_handler request_handler_;+};++} // namespace server+} // namespace http++#endif // HTTP_SERVER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/connection.hpp view
@@ -0,0 +1,75 @@+//+// connection.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER2_CONNECTION_HPP+#define HTTP_SERVER2_CONNECTION_HPP++#include <asio.hpp>+#include <boost/array.hpp>+#include <boost/noncopyable.hpp>+#include <boost/shared_ptr.hpp>+#include <boost/enable_shared_from_this.hpp>+#include "reply.hpp"+#include "request.hpp"+#include "request_handler.hpp"+#include "request_parser.hpp"++namespace http {+namespace server2 {++/// Represents a single connection from a client.+class connection+  : public boost::enable_shared_from_this<connection>,+    private boost::noncopyable+{+public:+  /// Construct a connection with the given io_context.+  explicit connection(asio::io_context& io_context,+      request_handler& handler);++  /// Get the socket associated with the connection.+  asio::ip::tcp::socket& socket();++  /// Start the first asynchronous operation for the connection.+  void start();++private:+  /// Handle completion of a read operation.+  void handle_read(const asio::error_code& e,+      std::size_t bytes_transferred);++  /// Handle completion of a write operation.+  void handle_write(const asio::error_code& e);++  /// Socket for the connection.+  asio::ip::tcp::socket socket_;++  /// The handler used to process the incoming request.+  request_handler& request_handler_;++  /// Buffer for incoming data.+  boost::array<char, 8192> buffer_;++  /// The incoming request.+  request request_;++  /// The parser for the incoming request.+  request_parser request_parser_;++  /// The reply to be sent back to the client.+  reply reply_;+};++typedef boost::shared_ptr<connection> connection_ptr;++} // namespace server2+} // namespace http++#endif // HTTP_SERVER2_CONNECTION_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/header.hpp view
@@ -0,0 +1,28 @@+//+// header.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER2_HEADER_HPP+#define HTTP_SERVER2_HEADER_HPP++#include <string>++namespace http {+namespace server2 {++struct header+{+  std::string name;+  std::string value;+};++} // namespace server2+} // namespace http++#endif // HTTP_SERVER2_HEADER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/io_context_pool.hpp view
@@ -0,0 +1,56 @@+//+// io_context_pool.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER2_IO_SERVICE_POOL_HPP+#define HTTP_SERVER2_IO_SERVICE_POOL_HPP++#include <asio.hpp>+#include <list>+#include <vector>+#include <boost/noncopyable.hpp>+#include <boost/shared_ptr.hpp>++namespace http {+namespace server2 {++/// A pool of io_context objects.+class io_context_pool+  : private boost::noncopyable+{+public:+  /// Construct the io_context pool.+  explicit io_context_pool(std::size_t pool_size);++  /// Run all io_context objects in the pool.+  void run();++  /// Stop all io_context objects in the pool.+  void stop();++  /// Get an io_context to use.+  asio::io_context& get_io_context();++private:+  typedef boost::shared_ptr<asio::io_context> io_context_ptr;++  /// The pool of io_contexts.+  std::vector<io_context_ptr> io_contexts_;++  /// The work-tracking executors that keep the io_contexts running.+  std::list<asio::any_io_executor> work_;++  /// The next io_context to use for a connection.+  std::size_t next_io_context_;+};++} // namespace server2+} // namespace http++#endif // HTTP_SERVER2_IO_SERVICE_POOL_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/mime_types.hpp view
@@ -0,0 +1,27 @@+//+// mime_types.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER2_MIME_TYPES_HPP+#define HTTP_SERVER2_MIME_TYPES_HPP++#include <string>++namespace http {+namespace server2 {+namespace mime_types {++/// Convert a file extension into a MIME type.+std::string extension_to_type(const std::string& extension);++} // namespace mime_types+} // namespace server2+} // namespace http++#endif // HTTP_SERVER2_MIME_TYPES_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/reply.hpp view
@@ -0,0 +1,64 @@+//+// reply.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER2_REPLY_HPP+#define HTTP_SERVER2_REPLY_HPP++#include <string>+#include <vector>+#include <asio.hpp>+#include "header.hpp"++namespace http {+namespace server2 {++/// A reply to be sent to a client.+struct reply+{+  /// The status of the reply.+  enum status_type+  {+    ok = 200,+    created = 201,+    accepted = 202,+    no_content = 204,+    multiple_choices = 300,+    moved_permanently = 301,+    moved_temporarily = 302,+    not_modified = 304,+    bad_request = 400,+    unauthorized = 401,+    forbidden = 403,+    not_found = 404,+    internal_server_error = 500,+    not_implemented = 501,+    bad_gateway = 502,+    service_unavailable = 503+  } status;++  /// The headers to be included in the reply.+  std::vector<header> headers;++  /// The content to be sent in the reply.+  std::string content;++  /// Convert the reply into a vector of buffers. The buffers do not own the+  /// underlying memory blocks, therefore the reply object must remain valid and+  /// not be changed until the write operation has completed.+  std::vector<asio::const_buffer> to_buffers();++  /// Get a stock reply.+  static reply stock_reply(status_type status);+};++} // namespace server2+} // namespace http++#endif // HTTP_SERVER2_REPLY_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request.hpp view
@@ -0,0 +1,34 @@+//+// request.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER2_REQUEST_HPP+#define HTTP_SERVER2_REQUEST_HPP++#include <string>+#include <vector>+#include "header.hpp"++namespace http {+namespace server2 {++/// A request received from a client.+struct request+{+  std::string method;+  std::string uri;+  int http_version_major;+  int http_version_minor;+  std::vector<header> headers;+};++} // namespace server2+} // namespace http++#endif // HTTP_SERVER2_REQUEST_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_handler.hpp view
@@ -0,0 +1,46 @@+//+// request_handler.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER2_REQUEST_HANDLER_HPP+#define HTTP_SERVER2_REQUEST_HANDLER_HPP++#include <string>+#include <boost/noncopyable.hpp>++namespace http {+namespace server2 {++struct reply;+struct request;++/// The common handler for all incoming requests.+class request_handler+  : private boost::noncopyable+{+public:+  /// Construct with a directory containing files to be served.+  explicit request_handler(const std::string& doc_root);++  /// Handle a request and produce a reply.+  void handle_request(const request& req, reply& rep);++private:+  /// The directory containing the files to be served.+  std::string doc_root_;++  /// Perform URL-decoding on a string. Returns false if the encoding was+  /// invalid.+  static bool url_decode(const std::string& in, std::string& out);+};++} // namespace server2+} // namespace http++#endif // HTTP_SERVER2_REQUEST_HANDLER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_parser.hpp view
@@ -0,0 +1,95 @@+//+// request_parser.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER2_REQUEST_PARSER_HPP+#define HTTP_SERVER2_REQUEST_PARSER_HPP++#include <boost/logic/tribool.hpp>+#include <boost/tuple/tuple.hpp>++namespace http {+namespace server2 {++struct request;++/// Parser for incoming requests.+class request_parser+{+public:+  /// Construct ready to parse the request method.+  request_parser();++  /// Reset to initial parser state.+  void reset();++  /// Parse some data. The tribool return value is true when a complete request+  /// has been parsed, false if the data is invalid, indeterminate when more+  /// data is required. The InputIterator return value indicates how much of the+  /// input has been consumed.+  template <typename InputIterator>+  boost::tuple<boost::tribool, InputIterator> parse(request& req,+      InputIterator begin, InputIterator end)+  {+    while (begin != end)+    {+      boost::tribool result = consume(req, *begin++);+      if (result || !result)+        return boost::make_tuple(result, begin);+    }+    boost::tribool result = boost::indeterminate;+    return boost::make_tuple(result, begin);+  }++private:+  /// Handle the next character of input.+  boost::tribool consume(request& req, char input);++  /// Check if a byte is an HTTP character.+  static bool is_char(int c);++  /// Check if a byte is an HTTP control character.+  static bool is_ctl(int c);++  /// Check if a byte is defined as an HTTP tspecial character.+  static bool is_tspecial(int c);++  /// Check if a byte is a digit.+  static bool is_digit(int c);++  /// The current state of the parser.+  enum state+  {+    method_start,+    method,+    uri,+    http_version_h,+    http_version_t_1,+    http_version_t_2,+    http_version_p,+    http_version_slash,+    http_version_major_start,+    http_version_major,+    http_version_minor_start,+    http_version_minor,+    expecting_newline_1,+    header_line_start,+    header_lws,+    header_name,+    space_before_header_value,+    header_value,+    expecting_newline_2,+    expecting_newline_3+  } state_;+};++} // namespace server2+} // namespace http++#endif // HTTP_SERVER2_REQUEST_PARSER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/server.hpp view
@@ -0,0 +1,68 @@+//+// server.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER2_SERVER_HPP+#define HTTP_SERVER2_SERVER_HPP++#include <asio.hpp>+#include <string>+#include <vector>+#include <boost/noncopyable.hpp>+#include <boost/shared_ptr.hpp>+#include "connection.hpp"+#include "io_context_pool.hpp"+#include "request_handler.hpp"++namespace http {+namespace server2 {++/// The top-level class of the HTTP server.+class server+  : private boost::noncopyable+{+public:+  /// Construct the server to listen on the specified TCP address and port, and+  /// serve up files from the given directory.+  explicit server(const std::string& address, const std::string& port,+      const std::string& doc_root, std::size_t io_context_pool_size);++  /// Run the server's io_context loop.+  void run();++private:+  /// Initiate an asynchronous accept operation.+  void start_accept();++  /// Handle completion of an asynchronous accept operation.+  void handle_accept(const asio::error_code& e);++  /// Handle a request to stop the server.+  void handle_stop();++  /// The pool of io_context objects used to perform asynchronous operations.+  io_context_pool io_context_pool_;++  /// The signal_set is used to register for process termination notifications.+  asio::signal_set signals_;++  /// Acceptor used to listen for incoming connections.+  asio::ip::tcp::acceptor acceptor_;++  /// The next connection to be accepted.+  connection_ptr new_connection_;++  /// The handler for all incoming requests.+  request_handler request_handler_;+};++} // namespace server2+} // namespace http++#endif // HTTP_SERVER2_SERVER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/connection.hpp view
@@ -0,0 +1,78 @@+//+// connection.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER3_CONNECTION_HPP+#define HTTP_SERVER3_CONNECTION_HPP++#include <asio.hpp>+#include <boost/array.hpp>+#include <boost/noncopyable.hpp>+#include <boost/shared_ptr.hpp>+#include <boost/enable_shared_from_this.hpp>+#include "reply.hpp"+#include "request.hpp"+#include "request_handler.hpp"+#include "request_parser.hpp"++namespace http {+namespace server3 {++/// Represents a single connection from a client.+class connection+  : public boost::enable_shared_from_this<connection>,+    private boost::noncopyable+{+public:+  /// Construct a connection with the given io_context.+  explicit connection(asio::io_context& io_context,+      request_handler& handler);++  /// Get the socket associated with the connection.+  asio::ip::tcp::socket& socket();++  /// Start the first asynchronous operation for the connection.+  void start();++private:+  /// Handle completion of a read operation.+  void handle_read(const asio::error_code& e,+      std::size_t bytes_transferred);++  /// Handle completion of a write operation.+  void handle_write(const asio::error_code& e);++  /// Strand to ensure the connection's handlers are not called concurrently.+  asio::strand<asio::io_context::executor_type> strand_;++  /// Socket for the connection.+  asio::ip::tcp::socket socket_;++  /// The handler used to process the incoming request.+  request_handler& request_handler_;++  /// Buffer for incoming data.+  boost::array<char, 8192> buffer_;++  /// The incoming request.+  request request_;++  /// The parser for the incoming request.+  request_parser request_parser_;++  /// The reply to be sent back to the client.+  reply reply_;+};++typedef boost::shared_ptr<connection> connection_ptr;++} // namespace server3+} // namespace http++#endif // HTTP_SERVER3_CONNECTION_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/header.hpp view
@@ -0,0 +1,28 @@+//+// header.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER3_HEADER_HPP+#define HTTP_SERVER3_HEADER_HPP++#include <string>++namespace http {+namespace server3 {++struct header+{+  std::string name;+  std::string value;+};++} // namespace server3+} // namespace http++#endif // HTTP_SERVER3_HEADER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/mime_types.hpp view
@@ -0,0 +1,27 @@+//+// mime_types.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER3_MIME_TYPES_HPP+#define HTTP_SERVER3_MIME_TYPES_HPP++#include <string>++namespace http {+namespace server3 {+namespace mime_types {++/// Convert a file extension into a MIME type.+std::string extension_to_type(const std::string& extension);++} // namespace mime_types+} // namespace server3+} // namespace http++#endif // HTTP_SERVER3_MIME_TYPES_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/reply.hpp view
@@ -0,0 +1,64 @@+//+// reply.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER3_REPLY_HPP+#define HTTP_SERVER3_REPLY_HPP++#include <string>+#include <vector>+#include <asio.hpp>+#include "header.hpp"++namespace http {+namespace server3 {++/// A reply to be sent to a client.+struct reply+{+  /// The status of the reply.+  enum status_type+  {+    ok = 200,+    created = 201,+    accepted = 202,+    no_content = 204,+    multiple_choices = 300,+    moved_permanently = 301,+    moved_temporarily = 302,+    not_modified = 304,+    bad_request = 400,+    unauthorized = 401,+    forbidden = 403,+    not_found = 404,+    internal_server_error = 500,+    not_implemented = 501,+    bad_gateway = 502,+    service_unavailable = 503+  } status;++  /// The headers to be included in the reply.+  std::vector<header> headers;++  /// The content to be sent in the reply.+  std::string content;++  /// Convert the reply into a vector of buffers. The buffers do not own the+  /// underlying memory blocks, therefore the reply object must remain valid and+  /// not be changed until the write operation has completed.+  std::vector<asio::const_buffer> to_buffers();++  /// Get a stock reply.+  static reply stock_reply(status_type status);+};++} // namespace server3+} // namespace http++#endif // HTTP_SERVER3_REPLY_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request.hpp view
@@ -0,0 +1,34 @@+//+// request.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER3_REQUEST_HPP+#define HTTP_SERVER3_REQUEST_HPP++#include <string>+#include <vector>+#include "header.hpp"++namespace http {+namespace server3 {++/// A request received from a client.+struct request+{+  std::string method;+  std::string uri;+  int http_version_major;+  int http_version_minor;+  std::vector<header> headers;+};++} // namespace server3+} // namespace http++#endif // HTTP_SERVER3_REQUEST_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_handler.hpp view
@@ -0,0 +1,46 @@+//+// request_handler.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER3_REQUEST_HANDLER_HPP+#define HTTP_SERVER3_REQUEST_HANDLER_HPP++#include <string>+#include <boost/noncopyable.hpp>++namespace http {+namespace server3 {++struct reply;+struct request;++/// The common handler for all incoming requests.+class request_handler+  : private boost::noncopyable+{+public:+  /// Construct with a directory containing files to be served.+  explicit request_handler(const std::string& doc_root);++  /// Handle a request and produce a reply.+  void handle_request(const request& req, reply& rep);++private:+  /// The directory containing the files to be served.+  std::string doc_root_;++  /// Perform URL-decoding on a string. Returns false if the encoding was+  /// invalid.+  static bool url_decode(const std::string& in, std::string& out);+};++} // namespace server3+} // namespace http++#endif // HTTP_SERVER3_REQUEST_HANDLER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_parser.hpp view
@@ -0,0 +1,95 @@+//+// request_parser.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER3_REQUEST_PARSER_HPP+#define HTTP_SERVER3_REQUEST_PARSER_HPP++#include <boost/logic/tribool.hpp>+#include <boost/tuple/tuple.hpp>++namespace http {+namespace server3 {++struct request;++/// Parser for incoming requests.+class request_parser+{+public:+  /// Construct ready to parse the request method.+  request_parser();++  /// Reset to initial parser state.+  void reset();++  /// Parse some data. The tribool return value is true when a complete request+  /// has been parsed, false if the data is invalid, indeterminate when more+  /// data is required. The InputIterator return value indicates how much of the+  /// input has been consumed.+  template <typename InputIterator>+  boost::tuple<boost::tribool, InputIterator> parse(request& req,+      InputIterator begin, InputIterator end)+  {+    while (begin != end)+    {+      boost::tribool result = consume(req, *begin++);+      if (result || !result)+        return boost::make_tuple(result, begin);+    }+    boost::tribool result = boost::indeterminate;+    return boost::make_tuple(result, begin);+  }++private:+  /// Handle the next character of input.+  boost::tribool consume(request& req, char input);++  /// Check if a byte is an HTTP character.+  static bool is_char(int c);++  /// Check if a byte is an HTTP control character.+  static bool is_ctl(int c);++  /// Check if a byte is defined as an HTTP tspecial character.+  static bool is_tspecial(int c);++  /// Check if a byte is a digit.+  static bool is_digit(int c);++  /// The current state of the parser.+  enum state+  {+    method_start,+    method,+    uri,+    http_version_h,+    http_version_t_1,+    http_version_t_2,+    http_version_p,+    http_version_slash,+    http_version_major_start,+    http_version_major,+    http_version_minor_start,+    http_version_minor,+    expecting_newline_1,+    header_line_start,+    header_lws,+    header_name,+    space_before_header_value,+    header_value,+    expecting_newline_2,+    expecting_newline_3+  } state_;+};++} // namespace server3+} // namespace http++#endif // HTTP_SERVER3_REQUEST_PARSER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/server.hpp view
@@ -0,0 +1,70 @@+//+// server.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER3_SERVER_HPP+#define HTTP_SERVER3_SERVER_HPP++#include <asio.hpp>+#include <string>+#include <vector>+#include <boost/noncopyable.hpp>+#include <boost/shared_ptr.hpp>+#include "connection.hpp"+#include "request_handler.hpp"++namespace http {+namespace server3 {++/// The top-level class of the HTTP server.+class server+  : private boost::noncopyable+{+public:+  /// Construct the server to listen on the specified TCP address and port, and+  /// serve up files from the given directory.+  explicit server(const std::string& address, const std::string& port,+      const std::string& doc_root, std::size_t thread_pool_size);++  /// Run the server's io_context loop.+  void run();++private:+  /// Initiate an asynchronous accept operation.+  void start_accept();++  /// Handle completion of an asynchronous accept operation.+  void handle_accept(const asio::error_code& e);++  /// Handle a request to stop the server.+  void handle_stop();++  /// The number of threads that will call io_context::run().+  std::size_t thread_pool_size_;++  /// The io_context used to perform asynchronous operations.+  asio::io_context io_context_;++  /// The signal_set is used to register for process termination notifications.+  asio::signal_set signals_;++  /// Acceptor used to listen for incoming connections.+  asio::ip::tcp::acceptor acceptor_;++  /// The next connection to be accepted.+  connection_ptr new_connection_;++  /// The handler for all incoming requests.+  request_handler request_handler_;+};++} // namespace server3+} // namespace http++#endif // HTTP_SERVER3_SERVER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/file_handler.hpp view
@@ -0,0 +1,44 @@+//+// file_handler.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER4_FILE_HANDLER_HPP+#define HTTP_SERVER4_FILE_HANDLER_HPP++#include <string>++namespace http {+namespace server4 {++struct reply;+struct request;++/// The common handler for all incoming requests.+class file_handler+{+public:+  /// Construct with a directory containing files to be served.+  explicit file_handler(const std::string& doc_root);++  /// Handle a request and produce a reply.+  void operator()(const request& req, reply& rep);++private:+  /// The directory containing the files to be served.+  std::string doc_root_;++  /// Perform URL-decoding on a string. Returns false if the encoding was+  /// invalid.+  static bool url_decode(const std::string& in, std::string& out);+};++} // namespace server4+} // namespace http++#endif // HTTP_SERVER4_FILE_HANDLER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/header.hpp view
@@ -0,0 +1,28 @@+//+// header.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER4_HEADER_HPP+#define HTTP_SERVER4_HEADER_HPP++#include <string>++namespace http {+namespace server4 {++struct header+{+  std::string name;+  std::string value;+};++} // namespace server4+} // namespace http++#endif // HTTP_SERVER4_HEADER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/mime_types.hpp view
@@ -0,0 +1,27 @@+//+// mime_types.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER4_MIME_TYPES_HPP+#define HTTP_SERVER4_MIME_TYPES_HPP++#include <string>++namespace http {+namespace server4 {+namespace mime_types {++/// Convert a file extension into a MIME type.+std::string extension_to_type(const std::string& extension);++} // namespace mime_types+} // namespace server4+} // namespace http++#endif // HTTP_SERVER4_MIME_TYPES_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/reply.hpp view
@@ -0,0 +1,64 @@+//+// reply.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER4_REPLY_HPP+#define HTTP_SERVER4_REPLY_HPP++#include <string>+#include <vector>+#include <asio.hpp>+#include "header.hpp"++namespace http {+namespace server4 {++/// A reply to be sent to a client.+struct reply+{+  /// The status of the reply.+  enum status_type+  {+    ok = 200,+    created = 201,+    accepted = 202,+    no_content = 204,+    multiple_choices = 300,+    moved_permanently = 301,+    moved_temporarily = 302,+    not_modified = 304,+    bad_request = 400,+    unauthorized = 401,+    forbidden = 403,+    not_found = 404,+    internal_server_error = 500,+    not_implemented = 501,+    bad_gateway = 502,+    service_unavailable = 503+  } status;++  /// The headers to be included in the reply.+  std::vector<header> headers;++  /// The content to be sent in the reply.+  std::string content;++  /// Convert the reply into a vector of buffers. The buffers do not own the+  /// underlying memory blocks, therefore the reply object must remain valid and+  /// not be changed until the write operation has completed.+  std::vector<asio::const_buffer> to_buffers();++  /// Get a stock reply.+  static reply stock_reply(status_type status);+};++} // namespace server4+} // namespace http++#endif // HTTP_SERVER4_REPLY_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request.hpp view
@@ -0,0 +1,46 @@+//+// request.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER4_REQUEST_HPP+#define HTTP_SERVER4_REQUEST_HPP++#include <string>+#include <vector>+#include "header.hpp"++namespace http {+namespace server4 {++/// A request received from a client.+struct request+{+  /// The request method, e.g. "GET", "POST".+  std::string method;++  /// The requested URI, such as a path to a file.+  std::string uri;++  /// Major version number, usually 1.+  int http_version_major;++  /// Minor version number, usually 0 or 1.+  int http_version_minor;++  /// The headers included with the request.+  std::vector<header> headers;++  /// The optional content sent with the request.+  std::string content;+};++} // namespace server4+} // namespace http++#endif // HTTP_SERVER4_REQUEST_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request_parser.hpp view
@@ -0,0 +1,78 @@+//+// request_parser.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER4_REQUEST_PARSER_HPP+#define HTTP_SERVER4_REQUEST_PARSER_HPP++#include <string>+#include <boost/logic/tribool.hpp>+#include <boost/tuple/tuple.hpp>+#include <asio/coroutine.hpp>++namespace http {+namespace server4 {++struct request;++/// Parser for incoming requests.+class request_parser : asio::coroutine+{+public:+  /// Parse some data. The tribool return value is true when a complete request+  /// has been parsed, false if the data is invalid, indeterminate when more+  /// data is required. The InputIterator return value indicates how much of the+  /// input has been consumed.+  template <typename InputIterator>+  boost::tuple<boost::tribool, InputIterator> parse(request& req,+      InputIterator begin, InputIterator end)+  {+    while (begin != end)+    {+      boost::tribool result = consume(req, *begin++);+      if (result || !result)+        return boost::make_tuple(result, begin);+    }+    boost::tribool result = boost::indeterminate;+    return boost::make_tuple(result, begin);+  }++private:+  /// The name of the content length header.+  static std::string content_length_name_;++  /// Content length as decoded from headers. Defaults to 0.+  std::size_t content_length_;++  /// Handle the next character of input.+  boost::tribool consume(request& req, char input);++  /// Check if a byte is an HTTP character.+  static bool is_char(int c);++  /// Check if a byte is an HTTP control character.+  static bool is_ctl(int c);++  /// Check if a byte is defined as an HTTP tspecial character.+  static bool is_tspecial(int c);++  /// Check if a byte is a digit.+  static bool is_digit(int c);++  /// Check if two characters are equal, without regard to case.+  static bool tolower_compare(char a, char b);++  /// Check whether the two request header names match.+  bool headers_equal(const std::string& a, const std::string& b);+};++} // namespace server4+} // namespace http++#endif // HTTP_SERVER4_REQUEST_PARSER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/server.hpp view
@@ -0,0 +1,73 @@+//+// server.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER4_SERVER_HPP+#define HTTP_SERVER4_SERVER_HPP++#include <asio.hpp>+#include <string>+#include <boost/array.hpp>+#include <boost/function.hpp>+#include <boost/shared_ptr.hpp>+#include "request_parser.hpp"++namespace http {+namespace server4 {++struct request;+struct reply;++/// The top-level coroutine of the HTTP server.+class server : asio::coroutine+{+public:+  /// Construct the server to listen on the specified TCP address and port, and+  /// serve up files from the given directory.+  explicit server(asio::io_context& io_context,+      const std::string& address, const std::string& port,+      boost::function<void(const request&, reply&)> request_handler);++  /// Perform work associated with the server.+  void operator()(+      asio::error_code ec = asio::error_code(),+      std::size_t length = 0);++private:+  typedef asio::ip::tcp tcp;++  /// The user-supplied handler for all incoming requests.+  boost::function<void(const request&, reply&)> request_handler_;++  /// Acceptor used to listen for incoming connections.+  boost::shared_ptr<tcp::acceptor> acceptor_;++  /// The current connection from a client.+  boost::shared_ptr<tcp::socket> socket_;++  /// Buffer for incoming data.+  boost::shared_ptr<boost::array<char, 8192> > buffer_;++  /// The incoming request.+  boost::shared_ptr<request> request_;++  /// Whether the request is valid or not.+  boost::tribool valid_request_;++  /// The parser for the incoming request.+  request_parser request_parser_;++  /// The reply to be sent back to the client.+  boost::shared_ptr<reply> reply_;+};++} // namespace server4+} // namespace http++#endif // HTTP_SERVER4_SERVER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/icmp/icmp_header.hpp view
@@ -0,0 +1,94 @@+//+// icmp_header.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 ICMP_HEADER_HPP+#define ICMP_HEADER_HPP++#include <istream>+#include <ostream>+#include <algorithm>++// ICMP header for both IPv4 and IPv6.+//+// The wire format of an ICMP header is:+// +// 0               8               16                             31+// +---------------+---------------+------------------------------+      ---+// |               |               |                              |       ^+// |     type      |     code      |          checksum            |       |+// |               |               |                              |       |+// +---------------+---------------+------------------------------+    8 bytes+// |                               |                              |       |+// |          identifier           |       sequence number        |       |+// |                               |                              |       v+// +-------------------------------+------------------------------+      ---++class icmp_header+{+public:+  enum { echo_reply = 0, destination_unreachable = 3, source_quench = 4,+    redirect = 5, echo_request = 8, time_exceeded = 11, parameter_problem = 12,+    timestamp_request = 13, timestamp_reply = 14, info_request = 15,+    info_reply = 16, address_request = 17, address_reply = 18 };++  icmp_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); }++  unsigned char type() const { return rep_[0]; }+  unsigned char code() const { return rep_[1]; }+  unsigned short checksum() const { return decode(2, 3); }+  unsigned short identifier() const { return decode(4, 5); }+  unsigned short sequence_number() const { return decode(6, 7); }++  void type(unsigned char n) { rep_[0] = n; }+  void code(unsigned char n) { rep_[1] = n; }+  void checksum(unsigned short n) { encode(2, 3, n); }+  void identifier(unsigned short n) { encode(4, 5, n); }+  void sequence_number(unsigned short n) { encode(6, 7, n); }++  friend std::istream& operator>>(std::istream& is, icmp_header& header)+    { return is.read(reinterpret_cast<char*>(header.rep_), 8); }++  friend std::ostream& operator<<(std::ostream& os, const icmp_header& header)+    { return os.write(reinterpret_cast<const char*>(header.rep_), 8); }++private:+  unsigned short decode(int a, int b) const+    { return (rep_[a] << 8) + rep_[b]; }++  void encode(int a, int b, unsigned short n)+  {+    rep_[a] = static_cast<unsigned char>(n >> 8);+    rep_[b] = static_cast<unsigned char>(n & 0xFF);+  }++  unsigned char rep_[8];+};++template <typename Iterator>+void compute_checksum(icmp_header& header,+    Iterator body_begin, Iterator body_end)+{+  unsigned int sum = (header.type() << 8) + header.code()+    + header.identifier() + header.sequence_number();++  Iterator body_iter = body_begin;+  while (body_iter != body_end)+  {+    sum += (static_cast<unsigned char>(*body_iter++) << 8);+    if (body_iter != body_end)+      sum += static_cast<unsigned char>(*body_iter++);+  }++  sum = (sum >> 16) + (sum & 0xFFFF);+  sum += (sum >> 16);+  header.checksum(static_cast<unsigned short>(~sum));+}++#endif // ICMP_HEADER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/icmp/ipv4_header.hpp view
@@ -0,0 +1,102 @@+//+// ipv4_header.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 IPV4_HEADER_HPP+#define IPV4_HEADER_HPP++#include <algorithm>+#include <asio/ip/address_v4.hpp>++// Packet header for IPv4.+//+// The wire format of an IPv4 header is:+// +// 0               8               16                             31+// +-------+-------+---------------+------------------------------+      ---+// |       |       |               |                              |       ^+// |version|header |    type of    |    total length in bytes     |       |+// |  (4)  | length|    service    |                              |       |+// +-------+-------+---------------+-+-+-+------------------------+       |+// |                               | | | |                        |       |+// |        identification         |0|D|M|    fragment offset     |       |+// |                               | |F|F|                        |       |+// +---------------+---------------+-+-+-+------------------------+       |+// |               |               |                              |       |+// | time to live  |   protocol    |       header checksum        |   20 bytes+// |               |               |                              |       |+// +---------------+---------------+------------------------------+       |+// |                                                              |       |+// |                      source IPv4 address                     |       |+// |                                                              |       |+// +--------------------------------------------------------------+       |+// |                                                              |       |+// |                   destination IPv4 address                   |       |+// |                                                              |       v+// +--------------------------------------------------------------+      ---+// |                                                              |       ^+// |                                                              |       |+// /                        options (if any)                      /    0 - 40+// /                                                              /     bytes+// |                                                              |       |+// |                                                              |       v+// +--------------------------------------------------------------+      ---++class ipv4_header+{+public:+  ipv4_header() { std::fill(rep_, rep_ + sizeof(rep_), 0); }++  unsigned char version() const { return (rep_[0] >> 4) & 0xF; }+  unsigned short header_length() const { return (rep_[0] & 0xF) * 4; }+  unsigned char type_of_service() const { return rep_[1]; }+  unsigned short total_length() const { return decode(2, 3); }+  unsigned short identification() const { return decode(4, 5); }+  bool dont_fragment() const { return (rep_[6] & 0x40) != 0; }+  bool more_fragments() const { return (rep_[6] & 0x20) != 0; }+  unsigned short fragment_offset() const { return decode(6, 7) & 0x1FFF; }+  unsigned int time_to_live() const { return rep_[8]; }+  unsigned char protocol() const { return rep_[9]; }+  unsigned short header_checksum() const { return decode(10, 11); }++  asio::ip::address_v4 source_address() const+  {+    asio::ip::address_v4::bytes_type bytes+      = { { rep_[12], rep_[13], rep_[14], rep_[15] } };+    return asio::ip::address_v4(bytes);+  }++  asio::ip::address_v4 destination_address() const+  {+    asio::ip::address_v4::bytes_type bytes+      = { { rep_[16], rep_[17], rep_[18], rep_[19] } };+    return asio::ip::address_v4(bytes);+  }++  friend std::istream& operator>>(std::istream& is, ipv4_header& header)+  {+    is.read(reinterpret_cast<char*>(header.rep_), 20);+    if (header.version() != 4)+      is.setstate(std::ios::failbit);+    std::streamsize options_length = header.header_length() - 20;+    if (options_length < 0 || options_length > 40)+      is.setstate(std::ios::failbit);+    else+      is.read(reinterpret_cast<char*>(header.rep_) + 20, options_length);+    return is;+  }++private:+  unsigned short decode(int a, int b) const+    { return (rep_[a] << 8) + rep_[b]; }++  unsigned char rep_[60];+};++#endif // IPV4_HEADER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/porthopper/protocol.hpp view
@@ -0,0 +1,156 @@+//+// protocol.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 PORTHOPPER_PROTOCOL_HPP+#define PORTHOPPER_PROTOCOL_HPP++#include <boost/array.hpp>+#include <asio.hpp>+#include <cstring>+#include <iomanip>+#include <string>+#include <strstream>++// This request is sent by the client to the server over a TCP connection.+// The client uses it to perform three functions:+// - To request that data start being sent to a given port.+// - To request that data is no longer sent to a given port.+// - To change the target port to another.+class control_request+{+public:+  // Construct an empty request. Used when receiving.+  control_request()+  {+  }++  // Create a request to start sending data to a given port.+  static const control_request start(unsigned short port)+  {+    return control_request(0, port);+  }++  // Create a request to stop sending data to a given port.+  static const control_request stop(unsigned short port)+  {+    return control_request(port, 0);+  }++  // Create a request to change the port that data is sent to.+  static const control_request change(+      unsigned short old_port, unsigned short new_port)+  {+    return control_request(old_port, new_port);+  }++  // Get the old port. Returns 0 for start requests.+  unsigned short old_port() const+  {+    std::istrstream is(data_, encoded_port_size);+    unsigned short port = 0;+    is >> std::setw(encoded_port_size) >> std::hex >> port;+    return port;+  }++  // Get the new port. Returns 0 for stop requests.+  unsigned short new_port() const+  {+    std::istrstream is(data_ + encoded_port_size, encoded_port_size);+    unsigned short port = 0;+    is >> std::setw(encoded_port_size) >> std::hex >> port;+    return port;+  }++  // Obtain buffers for reading from or writing to a socket.+  boost::array<asio::mutable_buffer, 1> to_buffers()+  {+    boost::array<asio::mutable_buffer, 1> buffers+      = { { asio::buffer(data_) } };+    return buffers;+  }++private:+  // Construct with specified old and new ports.+  control_request(unsigned short old_port_number,+      unsigned short new_port_number)+  {+    std::ostrstream os(data_, control_request_size);+    os << std::setw(encoded_port_size) << std::hex << old_port_number;+    os << std::setw(encoded_port_size) << std::hex << new_port_number;+  }++  // The length in bytes of a control_request and its components.+  enum+  {+    encoded_port_size = 4, // 16-bit port in hex.+    control_request_size = encoded_port_size * 2+  };++  // The encoded request data.+  char data_[control_request_size];+};++// This frame is sent from the server to subscribed clients over UDP.+class frame+{+public:+  // The maximum allowable length of the payload.+  enum { payload_size = 32 };++  // Construct an empty frame. Used when receiving.+  frame()+  {+  }++  // Construct a frame with specified frame number and payload.+  frame(unsigned long frame_number, const std::string& payload_data)+  {+    std::ostrstream os(data_, frame_size);+    os << std::setw(encoded_number_size) << std::hex << frame_number;+    os << std::setw(payload_size)+      << std::setfill(' ') << payload_data.substr(0, payload_size);+  }++  // Get the frame number.+  unsigned long number() const+  {+    std::istrstream is(data_, encoded_number_size);+    unsigned long frame_number = 0;+    is >> std::setw(encoded_number_size) >> std::hex >> frame_number;+    return frame_number;+  }++  // Get the payload data.+  const std::string payload() const+  {+    return std::string(data_ + encoded_number_size, payload_size);+  }++  // Obtain buffers for reading from or writing to a socket.+  boost::array<asio::mutable_buffer, 1> to_buffers()+  {+    boost::array<asio::mutable_buffer, 1> buffers+      = { { asio::buffer(data_) } };+    return buffers;+  }++private:+  // The length in bytes of a frame and its components.+  enum+  {+    encoded_number_size = 8, // Frame number in hex.+    frame_size = encoded_number_size + payload_size+  };++  // The encoded frame data.+  char data_[frame_size];+};++#endif // PORTHOPPER_PROTOCOL_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/serialization/connection.hpp view
@@ -0,0 +1,188 @@+//+// connection.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 SERIALIZATION_CONNECTION_HPP+#define SERIALIZATION_CONNECTION_HPP++#include <asio.hpp>+#include <boost/archive/text_iarchive.hpp>+#include <boost/archive/text_oarchive.hpp>+#include <boost/bind/bind.hpp>+#include <boost/shared_ptr.hpp>+#include <boost/tuple/tuple.hpp>+#include <iomanip>+#include <string>+#include <sstream>+#include <vector>++namespace s11n_example {++/// The connection class provides serialization primitives on top of a socket.+/**+ * Each message sent using this class consists of:+ * @li An 8-byte header containing the length of the serialized data in+ * hexadecimal.+ * @li The serialized data.+ */+class connection+{+public:+  /// Constructor.+  connection(const asio::executor& ex)+    : socket_(ex)+  {+  }++  /// Get the underlying socket. Used for making a connection or for accepting+  /// an incoming connection.+  asio::ip::tcp::socket& socket()+  {+    return socket_;+  }++  /// Asynchronously write a data structure to the socket.+  template <typename T, typename Handler>+  void async_write(const T& t, Handler handler)+  {+    // Serialize the data first so we know how large it is.+    std::ostringstream archive_stream;+    boost::archive::text_oarchive archive(archive_stream);+    archive << t;+    outbound_data_ = archive_stream.str();++    // Format the header.+    std::ostringstream header_stream;+    header_stream << std::setw(header_length)+      << std::hex << outbound_data_.size();+    if (!header_stream || header_stream.str().size() != header_length)+    {+      // Something went wrong, inform the caller.+      asio::error_code error(asio::error::invalid_argument);+      asio::post(socket_.get_executor(), boost::bind(handler, error));+      return;+    }+    outbound_header_ = header_stream.str();++    // Write the serialized data to the socket. We use "gather-write" to send+    // both the header and the data in a single write operation.+    std::vector<asio::const_buffer> buffers;+    buffers.push_back(asio::buffer(outbound_header_));+    buffers.push_back(asio::buffer(outbound_data_));+    asio::async_write(socket_, buffers, handler);+  }++  /// Asynchronously read a data structure from the socket.+  template <typename T, typename Handler>+  void async_read(T& t, Handler handler)+  {+    // Issue a read operation to read exactly the number of bytes in a header.+    void (connection::*f)(+        const asio::error_code&,+        T&, boost::tuple<Handler>)+      = &connection::handle_read_header<T, Handler>;+    asio::async_read(socket_, asio::buffer(inbound_header_),+        boost::bind(f,+          this, asio::placeholders::error, boost::ref(t),+          boost::make_tuple(handler)));+  }++  /// Handle a completed read of a message header. The handler is passed using+  /// a tuple since boost::bind seems to have trouble binding a function object+  /// created using boost::bind as a parameter.+  template <typename T, typename Handler>+  void handle_read_header(const asio::error_code& e,+      T& t, boost::tuple<Handler> handler)+  {+    if (e)+    {+      boost::get<0>(handler)(e);+    }+    else+    {+      // Determine the length of the serialized data.+      std::istringstream is(std::string(inbound_header_, header_length));+      std::size_t inbound_data_size = 0;+      if (!(is >> std::hex >> inbound_data_size))+      {+        // Header doesn't seem to be valid. Inform the caller.+        asio::error_code error(asio::error::invalid_argument);+        boost::get<0>(handler)(error);+        return;+      }++      // Start an asynchronous call to receive the data.+      inbound_data_.resize(inbound_data_size);+      void (connection::*f)(+          const asio::error_code&,+          T&, boost::tuple<Handler>)+        = &connection::handle_read_data<T, Handler>;+      asio::async_read(socket_, asio::buffer(inbound_data_),+        boost::bind(f, this,+          asio::placeholders::error, boost::ref(t), handler));+    }+  }++  /// Handle a completed read of message data.+  template <typename T, typename Handler>+  void handle_read_data(const asio::error_code& e,+      T& t, boost::tuple<Handler> handler)+  {+    if (e)+    {+      boost::get<0>(handler)(e);+    }+    else+    {+      // Extract the data structure from the data just received.+      try+      {+        std::string archive_data(&inbound_data_[0], inbound_data_.size());+        std::istringstream archive_stream(archive_data);+        boost::archive::text_iarchive archive(archive_stream);+        archive >> t;+      }+      catch (std::exception& e)+      {+        // Unable to decode data.+        asio::error_code error(asio::error::invalid_argument);+        boost::get<0>(handler)(error);+        return;+      }++      // Inform caller that data has been received ok.+      boost::get<0>(handler)(e);+    }+  }++private:+  /// The underlying socket.+  asio::ip::tcp::socket socket_;++  /// The size of a fixed length header.+  enum { header_length = 8 };++  /// Holds an outbound header.+  std::string outbound_header_;++  /// Holds the outbound data.+  std::string outbound_data_;++  /// Holds an inbound header.+  char inbound_header_[header_length];++  /// Holds the inbound data.+  std::vector<char> inbound_data_;+};++typedef boost::shared_ptr<connection> connection_ptr;++} // namespace s11n_example++#endif // SERIALIZATION_CONNECTION_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/serialization/stock.hpp view
@@ -0,0 +1,50 @@+//+// stock.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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 SERIALIZATION_STOCK_HPP+#define SERIALIZATION_STOCK_HPP++#include <string>++namespace s11n_example {++/// Structure to hold information about a single stock.+struct stock+{+  std::string code;+  std::string name;+  double open_price;+  double high_price;+  double low_price;+  double last_price;+  double buy_price;+  int buy_quantity;+  double sell_price;+  int sell_quantity;++  template <typename Archive>+  void serialize(Archive& ar, const unsigned int version)+  {+    ar & code;+    ar & name;+    ar & open_price;+    ar & high_price;+    ar & low_price;+    ar & last_price;+    ar & buy_price;+    ar & buy_quantity;+    ar & sell_price;+    ar & sell_quantity;+  }+};++} // namespace s11n_example++#endif // SERIALIZATION_STOCK_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/services/basic_logger.hpp view
@@ -0,0 +1,77 @@+//+// basic_logger.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 SERVICES_BASIC_LOGGER_HPP+#define SERVICES_BASIC_LOGGER_HPP++#include <asio.hpp>+#include <boost/noncopyable.hpp>+#include <string>++namespace services {++/// Class to provide simple logging functionality. Use the services::logger+/// typedef.+template <typename Service>+class basic_logger+  : private boost::noncopyable+{+public:+  /// The type of the service that will be used to provide timer operations.+  typedef Service service_type;++  /// The native implementation type of the timer.+  typedef typename service_type::impl_type impl_type;++  /// Constructor.+  /**+   * This constructor creates a logger.+   *+   * @param context The execution context used to locate the logger service.+   *+   * @param identifier An identifier for this logger.+   */+  explicit basic_logger(asio::execution_context& context,+      const std::string& identifier)+    : service_(asio::use_service<Service>(context)),+      impl_(service_.null())+  {+    service_.create(impl_, identifier);+  }++  /// Destructor.+  ~basic_logger()+  {+    service_.destroy(impl_);+  }++  /// Set the output file for all logger instances.+  void use_file(const std::string& file)+  {+    service_.use_file(impl_, file);+  }++  /// Log a message.+  void log(const std::string& message)+  {+    service_.log(impl_, message);+  }++private:+  /// The backend service implementation.+  service_type& service_;++  /// The underlying native implementation.+  impl_type impl_;+};++} // namespace services++#endif // SERVICES_BASIC_LOGGER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/services/logger.hpp view
@@ -0,0 +1,24 @@+//+// logger.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 SERVICES_LOGGER_HPP+#define SERVICES_LOGGER_HPP++#include "basic_logger.hpp"+#include "logger_service.hpp"++namespace services {++/// Typedef for typical logger usage.+typedef basic_logger<logger_service> logger;++} // namespace services++#endif // SERVICES_LOGGER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/services/logger_service.hpp view
@@ -0,0 +1,145 @@+//+// logger_service.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 SERVICES_LOGGER_SERVICE_HPP+#define SERVICES_LOGGER_SERVICE_HPP++#include <asio.hpp>+#include <boost/bind/bind.hpp>+#include <boost/date_time/posix_time/posix_time.hpp>+#include <boost/noncopyable.hpp>+#include <boost/scoped_ptr.hpp>+#include <fstream>+#include <sstream>+#include <string>++namespace services {++/// Service implementation for the logger.+class logger_service+  : public asio::execution_context::service+{+public:+  /// The type used to identify this service in the execution context.+  typedef logger_service key_type;++  /// The backend implementation of a logger.+  struct logger_impl+  {+    explicit logger_impl(const std::string& ident) : identifier(ident) {}+    std::string identifier;+  };++  /// The type for an implementation of the logger.+  typedef logger_impl* impl_type;++  /// Constructor creates a thread to run a private io_context.+  logger_service(asio::execution_context& context)+    : asio::execution_context::service(context),+      work_io_context_(),+      work_(asio::require(work_io_context_.get_executor(),+            asio::execution::outstanding_work.tracked)),+      work_thread_(new asio::thread(+            boost::bind(&asio::io_context::run, &work_io_context_)))+  {+  }++  /// Destructor shuts down the private io_context.+  ~logger_service()+  {+    /// Indicate that we have finished with the private io_context. Its+    /// io_context::run() function will exit once all other work has completed.+    work_ = asio::any_io_executor();+    if (work_thread_)+      work_thread_->join();+  }++  /// Destroy all user-defined handler objects owned by the service.+  void shutdown()+  {+  }++  /// Return a null logger implementation.+  impl_type null() const+  {+    return 0;+  }++  /// Create a new logger implementation.+  void create(impl_type& impl, const std::string& identifier)+  {+    impl = new logger_impl(identifier);+  }++  /// Destroy a logger implementation.+  void destroy(impl_type& impl)+  {+    delete impl;+    impl = null();+  }++  /// Set the output file for the logger. The current implementation sets the+  /// output file for all logger instances, and so the impl parameter is not+  /// actually needed. It is retained here to illustrate how service functions+  /// are typically defined.+  void use_file(impl_type& /*impl*/, const std::string& file)+  {+    // Pass the work of opening the file to the background thread.+    asio::post(work_io_context_, boost::bind(+          &logger_service::use_file_impl, this, file));+  }++  /// Log a message.+  void log(impl_type& impl, const std::string& message)+  {+    // Format the text to be logged.+    std::ostringstream os;+    os << impl->identifier << ": " << message;++    // Pass the work of writing to the file to the background thread.+    asio::post(work_io_context_, boost::bind(+          &logger_service::log_impl, this, os.str()));+  }++private:+  /// Helper function used to open the output file from within the private+  /// io_context's thread.+  void use_file_impl(const std::string& file)+  {+    ofstream_.close();+    ofstream_.clear();+    ofstream_.open(file.c_str());+  }++  /// Helper function used to log a message from within the private io_context's+  /// thread.+  void log_impl(const std::string& text)+  {+    ofstream_ << text << std::endl;+  }++  /// Private io_context used for performing logging operations.+  asio::io_context work_io_context_;++  /// A work-tracking executor giving work for the private io_context to+  /// perform. If we do not give the io_context some work to do then the+  /// io_context::run() function will exit immediately.+  asio::any_io_executor work_;++  /// Thread used for running the work io_context's run loop.+  boost::scoped_ptr<asio::thread> work_thread_;++  /// The file to which log messages will be written.+  std::ofstream ofstream_;+};++} // namespace services++#endif // SERVICES_LOGGER_SERVICE_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp03/socks4/socks4.hpp view
@@ -0,0 +1,144 @@+//+// socks4.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 SOCKS4_HPP+#define SOCKS4_HPP++#include <string>+#include <asio.hpp>+#include <boost/array.hpp>++namespace socks4 {++const unsigned char version = 0x04;++class request+{+public:+  enum command_type+  {+    connect = 0x01,+    bind = 0x02+  };++  request(command_type cmd, const asio::ip::tcp::endpoint& endpoint,+      const std::string& user_id)+    : version_(version),+      command_(cmd),+      user_id_(user_id),+      null_byte_(0)+  {+    // Only IPv4 is supported by the SOCKS 4 protocol.+    if (endpoint.protocol() != asio::ip::tcp::v4())+    {+      throw asio::system_error(+          asio::error::address_family_not_supported);+    }++    // Convert port number to network byte order.+    unsigned short port = endpoint.port();+    port_high_byte_ = (port >> 8) & 0xff;+    port_low_byte_ = port & 0xff;++    // Save IP address in network byte order.+    address_ = endpoint.address().to_v4().to_bytes();+  }++  boost::array<asio::const_buffer, 7> buffers() const+  {+    boost::array<asio::const_buffer, 7> bufs =+    {+      {+        asio::buffer(&version_, 1),+        asio::buffer(&command_, 1),+        asio::buffer(&port_high_byte_, 1),+        asio::buffer(&port_low_byte_, 1),+        asio::buffer(address_),+        asio::buffer(user_id_),+        asio::buffer(&null_byte_, 1)+      }+    };+    return bufs;+  }++private:+  unsigned char version_;+  unsigned char command_;+  unsigned char port_high_byte_;+  unsigned char port_low_byte_;+  asio::ip::address_v4::bytes_type address_;+  std::string user_id_;+  unsigned char null_byte_;+};++class reply+{+public:+  enum status_type+  {+    request_granted = 0x5a,+    request_failed = 0x5b,+    request_failed_no_identd = 0x5c,+    request_failed_bad_user_id = 0x5d+  };++  reply()+    : null_byte_(0),+      status_()+  {+  }++  boost::array<asio::mutable_buffer, 5> buffers()+  {+    boost::array<asio::mutable_buffer, 5> bufs =+    {+      {+        asio::buffer(&null_byte_, 1),+        asio::buffer(&status_, 1),+        asio::buffer(&port_high_byte_, 1),+        asio::buffer(&port_low_byte_, 1),+        asio::buffer(address_)+      }+    };+    return bufs;+  }++  bool success() const+  {+    return null_byte_ == 0 && status_ == request_granted;+  }++  unsigned char status() const+  {+    return status_;+  }++  asio::ip::tcp::endpoint endpoint() const+  {+    unsigned short port = port_high_byte_;+    port = (port << 8) & 0xff00;+    port = port | port_low_byte_;++    asio::ip::address_v4 address(address_);++    return asio::ip::tcp::endpoint(address, port);+  }++private:+  unsigned char null_byte_;+  unsigned char status_;+  unsigned char port_high_byte_;+  unsigned char port_low_byte_;+  asio::ip::address_v4::bytes_type address_;+};++} // namespace socks4++#endif // SOCKS4_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/chat/chat_message.hpp view
@@ -0,0 +1,91 @@+//+// chat_message.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 CHAT_MESSAGE_HPP+#define CHAT_MESSAGE_HPP++#include <cstdio>+#include <cstdlib>+#include <cstring>++class chat_message+{+public:+  enum { header_length = 4 };+  enum { max_body_length = 512 };++  chat_message()+    : body_length_(0)+  {+  }++  const char* data() const+  {+    return data_;+  }++  char* data()+  {+    return data_;+  }++  std::size_t length() const+  {+    return header_length + body_length_;+  }++  const char* body() const+  {+    return data_ + header_length;+  }++  char* body()+  {+    return data_ + header_length;+  }++  std::size_t body_length() const+  {+    return body_length_;+  }++  void body_length(std::size_t new_length)+  {+    body_length_ = new_length;+    if (body_length_ > max_body_length)+      body_length_ = max_body_length;+  }++  bool decode_header()+  {+    char header[header_length + 1] = "";+    std::strncat(header, data_, header_length);+    body_length_ = std::atoi(header);+    if (body_length_ > max_body_length)+    {+      body_length_ = 0;+      return false;+    }+    return true;+  }++  void encode_header()+  {+    char header[header_length + 1] = "";+    std::sprintf(header, "%4d", static_cast<int>(body_length_));+    std::memcpy(data_, header, header_length);+  }++private:+  char data_[header_length + max_body_length];+  std::size_t body_length_;+};++#endif // CHAT_MESSAGE_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp view
@@ -0,0 +1,211 @@+//+// custom_tracking.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 CUSTOM_TRACKING_HPP+#define CUSTOM_TRACKING_HPP++#include <cinttypes>+#include <cstdint>+#include <cstdio>++# define ASIO_INHERIT_TRACKED_HANDLER \+  : public ::custom_tracking::tracked_handler++# define ASIO_ALSO_INHERIT_TRACKED_HANDLER \+  , public ::custom_tracking::tracked_handler++# define ASIO_HANDLER_TRACKING_INIT \+  ::custom_tracking::init()++# define ASIO_HANDLER_LOCATION(args) \+  ::custom_tracking::location args++# define ASIO_HANDLER_CREATION(args) \+  ::custom_tracking::creation args++# define ASIO_HANDLER_COMPLETION(args) \+  ::custom_tracking::completion tracked_completion args++# define ASIO_HANDLER_INVOCATION_BEGIN(args) \+  tracked_completion.invocation_begin args++# define ASIO_HANDLER_INVOCATION_END \+  tracked_completion.invocation_end()++# define ASIO_HANDLER_OPERATION(args) \+  ::custom_tracking::operation args++# define ASIO_HANDLER_REACTOR_REGISTRATION(args) \+  ::custom_tracking::reactor_registration args++# define ASIO_HANDLER_REACTOR_DEREGISTRATION(args) \+  ::custom_tracking::reactor_deregistration args++# define ASIO_HANDLER_REACTOR_READ_EVENT 1+# define ASIO_HANDLER_REACTOR_WRITE_EVENT 2+# define ASIO_HANDLER_REACTOR_ERROR_EVENT 4++# define ASIO_HANDLER_REACTOR_EVENTS(args) \+  ::custom_tracking::reactor_events args++# define ASIO_HANDLER_REACTOR_OPERATION(args) \+  ::custom_tracking::reactor_operation args++struct custom_tracking+{+  // Base class for objects containing tracked handlers.+  struct tracked_handler+  {+    std::uintmax_t handler_id_ = 0; // To uniquely identify a handler.+    std::uintmax_t tree_id_ = 0; // To identify related handlers.+    const char* object_type_; // The object type associated with the handler.+    std::uintmax_t native_handle_; // Native handle, if any.+  };++  // Initialise the tracking system.+  static void init()+  {+  }++  // Record a source location.+  static void location(const char* file_name,+      int line, const char* function_name)+  {+    std::printf("At location %s:%d in %s\n", file_name, line, function_name);+  }++  // Record the creation of a tracked handler.+  static void creation(asio::execution_context& /*ctx*/,+      tracked_handler& h, const char* object_type, void* /*object*/,+      std::uintmax_t native_handle, const char* op_name)+  {+    // Generate a unique id for the new handler.+    static std::atomic<std::uintmax_t> next_handler_id{1};+    h.handler_id_ = next_handler_id++;++    // Copy the tree identifier forward from the current handler.+    if (*current_completion())+      h.tree_id_ = (*current_completion())->handler_.tree_id_;++    // Store various attributes of the operation to use in later output.+    h.object_type_ = object_type;+    h.native_handle_ = native_handle;++    std::printf(+        "Starting operation %s.%s for native_handle = %" PRIuMAX+        ", handler = %" PRIuMAX ", tree = %" PRIuMAX "\n",+        object_type, op_name, h.native_handle_, h.handler_id_, h.tree_id_);+  }++  struct completion+  {+    explicit completion(const tracked_handler& h)+      : handler_(h),+        next_(*current_completion())+    {+      *current_completion() = this;+    }++    completion(const completion&) = delete;+    completion& operator=(const completion&) = delete;++    // Destructor records only when an exception is thrown from the handler, or+    // if the memory is being freed without the handler having been invoked.+    ~completion()+    {+      *current_completion() = next_;+    }++    // Records that handler is to be invoked with the specified arguments.+    template <class... Args>+    void invocation_begin(Args&&... /*args*/)+    {+      std::printf("Entering handler %" PRIuMAX " in tree %" PRIuMAX "\n",+          handler_.handler_id_, handler_.tree_id_);+    }++    // Record that handler invocation has ended.+    void invocation_end()+    {+      std::printf("Leaving handler %" PRIuMAX " in tree %" PRIuMAX "\n",+          handler_.handler_id_, handler_.tree_id_);+    }++    tracked_handler handler_;++    // Completions may nest. Here we stash a pointer to the outer completion.+    completion* next_;+  };++  static completion** current_completion()+  {+    static ASIO_THREAD_KEYWORD completion* current = nullptr;+    return &current;+  }++  // Record an operation that is not directly associated with a handler.+  static void operation(asio::execution_context& /*ctx*/,+      const char* /*object_type*/, void* /*object*/,+      std::uintmax_t /*native_handle*/, const char* /*op_name*/)+  {+  }++  // Record that a descriptor has been registered with the reactor.+  static void reactor_registration(asio::execution_context& context,+      uintmax_t native_handle, uintmax_t registration)+  {+    std::printf("Adding to reactor native_handle = %" PRIuMAX+        ", registration = %" PRIuMAX "\n", native_handle, registration);+  }++  // Record that a descriptor has been deregistered from the reactor.+  static void reactor_deregistration(asio::execution_context& context,+      uintmax_t native_handle, uintmax_t registration)+  {+    std::printf("Removing from reactor native_handle = %" PRIuMAX+        ", registration = %" PRIuMAX "\n", native_handle, registration);+  }++  // Record reactor-based readiness events associated with a descriptor.+  static void reactor_events(asio::execution_context& context,+      uintmax_t registration, unsigned events)+  {+    std::printf(+        "Reactor readiness for registration = %" PRIuMAX ", events =%s%s%s\n",+        registration,+        (events & ASIO_HANDLER_REACTOR_READ_EVENT) ? " read" : "",+        (events & ASIO_HANDLER_REACTOR_WRITE_EVENT) ? " write" : "",+        (events & ASIO_HANDLER_REACTOR_ERROR_EVENT) ? " error" : "");+  }++  // Record a reactor-based operation that is associated with a handler.+  static void reactor_operation(const tracked_handler& h,+      const char* op_name, const asio::error_code& ec)+  {+    std::printf(+        "Performed operation %s.%s for native_handle = %" PRIuMAX+        ", ec = %s:%d\n", h.object_type_, op_name, h.native_handle_,+        ec.category().name(), ec.value());+  }++  // Record a reactor-based operation that is associated with a handler.+  static void reactor_operation(const tracked_handler& h,+      const char* op_name, const asio::error_code& ec,+      std::size_t bytes_transferred)+  {+    std::printf(+        "Performed operation %s.%s for native_handle = %" PRIuMAX+        ", ec = %s:%d, n = %" PRIuMAX "\n", h.object_type_, op_name,+        h.native_handle_, ec.category().name(), ec.value(),+        static_cast<uintmax_t>(bytes_transferred));+  }+};++#endif // CUSTOM_TRACKING_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection.hpp view
@@ -0,0 +1,79 @@+//+// connection.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_CONNECTION_HPP+#define HTTP_CONNECTION_HPP++#include <array>+#include <memory>+#include <asio.hpp>+#include "reply.hpp"+#include "request.hpp"+#include "request_handler.hpp"+#include "request_parser.hpp"++namespace http {+namespace server {++class connection_manager;++/// Represents a single connection from a client.+class connection+  : public std::enable_shared_from_this<connection>+{+public:+  connection(const connection&) = delete;+  connection& operator=(const connection&) = delete;++  /// Construct a connection with the given socket.+  explicit connection(asio::ip::tcp::socket socket,+      connection_manager& manager, request_handler& handler);++  /// Start the first asynchronous operation for the connection.+  void start();++  /// Stop all asynchronous operations associated with the connection.+  void stop();++private:+  /// Perform an asynchronous read operation.+  void do_read();++  /// Perform an asynchronous write operation.+  void do_write();++  /// Socket for the connection.+  asio::ip::tcp::socket socket_;++  /// The manager for this connection.+  connection_manager& connection_manager_;++  /// The handler used to process the incoming request.+  request_handler& request_handler_;++  /// Buffer for incoming data.+  std::array<char, 8192> buffer_;++  /// The incoming request.+  request request_;++  /// The parser for the incoming request.+  request_parser request_parser_;++  /// The reply to be sent back to the client.+  reply reply_;+};++typedef std::shared_ptr<connection> connection_ptr;++} // namespace server+} // namespace http++#endif // HTTP_CONNECTION_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection_manager.hpp view
@@ -0,0 +1,48 @@+//+// connection_manager.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_CONNECTION_MANAGER_HPP+#define HTTP_CONNECTION_MANAGER_HPP++#include <set>+#include "connection.hpp"++namespace http {+namespace server {++/// Manages open connections so that they may be cleanly stopped when the server+/// needs to shut down.+class connection_manager+{+public:+  connection_manager(const connection_manager&) = delete;+  connection_manager& operator=(const connection_manager&) = delete;++  /// Construct a connection manager.+  connection_manager();++  /// Add the specified connection to the manager and start it.+  void start(connection_ptr c);++  /// Stop the specified connection.+  void stop(connection_ptr c);++  /// Stop all connections.+  void stop_all();++private:+  /// The managed connections.+  std::set<connection_ptr> connections_;+};++} // namespace server+} // namespace http++#endif // HTTP_CONNECTION_MANAGER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/http/server/header.hpp view
@@ -0,0 +1,28 @@+//+// header.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_HEADER_HPP+#define HTTP_HEADER_HPP++#include <string>++namespace http {+namespace server {++struct header+{+  std::string name;+  std::string value;+};++} // namespace server+} // namespace http++#endif // HTTP_HEADER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/http/server/mime_types.hpp view
@@ -0,0 +1,27 @@+//+// mime_types.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_MIME_TYPES_HPP+#define HTTP_MIME_TYPES_HPP++#include <string>++namespace http {+namespace server {+namespace mime_types {++/// Convert a file extension into a MIME type.+std::string extension_to_type(const std::string& extension);++} // namespace mime_types+} // namespace server+} // namespace http++#endif // HTTP_MIME_TYPES_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/http/server/reply.hpp view
@@ -0,0 +1,64 @@+//+// reply.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_REPLY_HPP+#define HTTP_REPLY_HPP++#include <string>+#include <vector>+#include <asio.hpp>+#include "header.hpp"++namespace http {+namespace server {++/// A reply to be sent to a client.+struct reply+{+  /// The status of the reply.+  enum status_type+  {+    ok = 200,+    created = 201,+    accepted = 202,+    no_content = 204,+    multiple_choices = 300,+    moved_permanently = 301,+    moved_temporarily = 302,+    not_modified = 304,+    bad_request = 400,+    unauthorized = 401,+    forbidden = 403,+    not_found = 404,+    internal_server_error = 500,+    not_implemented = 501,+    bad_gateway = 502,+    service_unavailable = 503+  } status;++  /// The headers to be included in the reply.+  std::vector<header> headers;++  /// The content to be sent in the reply.+  std::string content;++  /// Convert the reply into a vector of buffers. The buffers do not own the+  /// underlying memory blocks, therefore the reply object must remain valid and+  /// not be changed until the write operation has completed.+  std::vector<asio::const_buffer> to_buffers();++  /// Get a stock reply.+  static reply stock_reply(status_type status);+};++} // namespace server+} // namespace http++#endif // HTTP_REPLY_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request.hpp view
@@ -0,0 +1,34 @@+//+// request.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_REQUEST_HPP+#define HTTP_REQUEST_HPP++#include <string>+#include <vector>+#include "header.hpp"++namespace http {+namespace server {++/// A request received from a client.+struct request+{+  std::string method;+  std::string uri;+  int http_version_major;+  int http_version_minor;+  std::vector<header> headers;+};++} // namespace server+} // namespace http++#endif // HTTP_REQUEST_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_handler.hpp view
@@ -0,0 +1,47 @@+//+// request_handler.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_REQUEST_HANDLER_HPP+#define HTTP_REQUEST_HANDLER_HPP++#include <string>++namespace http {+namespace server {++struct reply;+struct request;++/// The common handler for all incoming requests.+class request_handler+{+public:+  request_handler(const request_handler&) = delete;+  request_handler& operator=(const request_handler&) = delete;++  /// Construct with a directory containing files to be served.+  explicit request_handler(const std::string& doc_root);++  /// Handle a request and produce a reply.+  void handle_request(const request& req, reply& rep);++private:+  /// The directory containing the files to be served.+  std::string doc_root_;++  /// Perform URL-decoding on a string. Returns false if the encoding was+  /// invalid.+  static bool url_decode(const std::string& in, std::string& out);+};++} // namespace server+} // namespace http++#endif // HTTP_REQUEST_HANDLER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_parser.hpp view
@@ -0,0 +1,96 @@+//+// request_parser.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_REQUEST_PARSER_HPP+#define HTTP_REQUEST_PARSER_HPP++#include <tuple>++namespace http {+namespace server {++struct request;++/// Parser for incoming requests.+class request_parser+{+public:+  /// Construct ready to parse the request method.+  request_parser();++  /// Reset to initial parser state.+  void reset();++  /// Result of parse.+  enum result_type { good, bad, indeterminate };++  /// Parse some data. The enum return value is good when a complete request has+  /// been parsed, bad if the data is invalid, indeterminate when more data is+  /// required. The InputIterator return value indicates how much of the input+  /// has been consumed.+  template <typename InputIterator>+  std::tuple<result_type, InputIterator> parse(request& req,+      InputIterator begin, InputIterator end)+  {+    while (begin != end)+    {+      result_type result = consume(req, *begin++);+      if (result == good || result == bad)+        return std::make_tuple(result, begin);+    }+    return std::make_tuple(indeterminate, begin);+  }++private:+  /// Handle the next character of input.+  result_type consume(request& req, char input);++  /// Check if a byte is an HTTP character.+  static bool is_char(int c);++  /// Check if a byte is an HTTP control character.+  static bool is_ctl(int c);++  /// Check if a byte is defined as an HTTP tspecial character.+  static bool is_tspecial(int c);++  /// Check if a byte is a digit.+  static bool is_digit(int c);++  /// The current state of the parser.+  enum state+  {+    method_start,+    method,+    uri,+    http_version_h,+    http_version_t_1,+    http_version_t_2,+    http_version_p,+    http_version_slash,+    http_version_major_start,+    http_version_major,+    http_version_minor_start,+    http_version_minor,+    expecting_newline_1,+    header_line_start,+    header_lws,+    header_name,+    space_before_header_value,+    header_value,+    expecting_newline_2,+    expecting_newline_3+  } state_;+};++} // namespace server+} // namespace http++#endif // HTTP_REQUEST_PARSER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/http/server/server.hpp view
@@ -0,0 +1,64 @@+//+// server.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HTTP_SERVER_HPP+#define HTTP_SERVER_HPP++#include <asio.hpp>+#include <string>+#include "connection.hpp"+#include "connection_manager.hpp"+#include "request_handler.hpp"++namespace http {+namespace server {++/// The top-level class of the HTTP server.+class server+{+public:+  server(const server&) = delete;+  server& operator=(const server&) = delete;++  /// Construct the server to listen on the specified TCP address and port, and+  /// serve up files from the given directory.+  explicit server(const std::string& address, const std::string& port,+      const std::string& doc_root);++  /// Run the server's io_context loop.+  void run();++private:+  /// Perform an asynchronous accept operation.+  void do_accept();++  /// Wait for a request to stop the server.+  void do_await_stop();++  /// The io_context used to perform asynchronous operations.+  asio::io_context io_context_;++  /// The signal_set is used to register for process termination notifications.+  asio::signal_set signals_;++  /// Acceptor used to listen for incoming connections.+  asio::ip::tcp::acceptor acceptor_;++  /// The connection manager which owns all live connections.+  connection_manager connection_manager_;++  /// The handler for all incoming requests.+  request_handler request_handler_;+};++} // namespace server+} // namespace http++#endif // HTTP_SERVER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/socks4/socks4.hpp view
@@ -0,0 +1,143 @@+//+// socks4.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 SOCKS4_HPP+#define SOCKS4_HPP++#include <array>+#include <string>+#include <asio/buffer.hpp>+#include <asio/ip/tcp.hpp>++namespace socks4 {++const unsigned char version = 0x04;++class request+{+public:+  enum command_type+  {+    connect = 0x01,+    bind = 0x02+  };++  request(command_type cmd, const asio::ip::tcp::endpoint& endpoint,+      const std::string& user_id)+    : version_(version),+      command_(cmd),+      user_id_(user_id),+      null_byte_(0)+  {+    // Only IPv4 is supported by the SOCKS 4 protocol.+    if (endpoint.protocol() != asio::ip::tcp::v4())+    {+      throw asio::system_error(+          asio::error::address_family_not_supported);+    }++    // Convert port number to network byte order.+    unsigned short port = endpoint.port();+    port_high_byte_ = (port >> 8) & 0xff;+    port_low_byte_ = port & 0xff;++    // Save IP address in network byte order.+    address_ = endpoint.address().to_v4().to_bytes();+  }++  std::array<asio::const_buffer, 7> buffers() const+  {+    return+    {+      {+        asio::buffer(&version_, 1),+        asio::buffer(&command_, 1),+        asio::buffer(&port_high_byte_, 1),+        asio::buffer(&port_low_byte_, 1),+        asio::buffer(address_),+        asio::buffer(user_id_),+        asio::buffer(&null_byte_, 1)+      }+    };+  }++private:+  unsigned char version_;+  unsigned char command_;+  unsigned char port_high_byte_;+  unsigned char port_low_byte_;+  asio::ip::address_v4::bytes_type address_;+  std::string user_id_;+  unsigned char null_byte_;+};++class reply+{+public:+  enum status_type+  {+    request_granted = 0x5a,+    request_failed = 0x5b,+    request_failed_no_identd = 0x5c,+    request_failed_bad_user_id = 0x5d+  };++  reply()+    : null_byte_(0),+      status_()+  {+  }++  std::array<asio::mutable_buffer, 5> buffers()+  {+    return+    {+      {+        asio::buffer(&null_byte_, 1),+        asio::buffer(&status_, 1),+        asio::buffer(&port_high_byte_, 1),+        asio::buffer(&port_low_byte_, 1),+        asio::buffer(address_)+      }+    };+  }++  bool success() const+  {+    return null_byte_ == 0 && status_ == request_granted;+  }++  unsigned char status() const+  {+    return status_;+  }++  asio::ip::tcp::endpoint endpoint() const+  {+    unsigned short port = port_high_byte_;+    port = (port << 8) & 0xff00;+    port = port | port_low_byte_;++    asio::ip::address_v4 address(address_);++    return asio::ip::tcp::endpoint(address, port);+  }++private:+  unsigned char null_byte_;+  unsigned char status_;+  unsigned char port_high_byte_;+  unsigned char port_low_byte_;+  asio::ip::address_v4::bytes_type address_;+};++} // namespace socks4++#endif // SOCKS4_HPP
+ link/modules/asio-standalone/asio/src/tests/latency/allocator.hpp view
@@ -0,0 +1,52 @@+//+// allocator.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 ALLOCATOR_HPP+#define ALLOCATOR_HPP++#include <boost/aligned_storage.hpp>++// Represents a single connection from a client.+class allocator+{+public:+  allocator()+    : in_use_(false)+  {+  }++  void* allocate(std::size_t n)+  {+    if (in_use_ || n >= 1024)+      return ::operator new(n);+    in_use_ = true;+    return static_cast<void*>(&space_);+  }++  void deallocate(void* p)+  {+    if (p != static_cast<void*>(&space_))+      ::operator delete(p);+    else+      in_use_ = false;+  }++private:+  allocator(const allocator&);+  allocator& operator=(const allocator&);++  // Whether the reusable memory space is currently in use.+  bool in_use_;++  // The reusable memory space made available by the allocator.+  boost::aligned_storage<1024>::type space_;+};++#endif // ALLOCATOR_HPP
+ link/modules/asio-standalone/asio/src/tests/latency/high_res_clock.hpp view
@@ -0,0 +1,53 @@+//+// high_res_clock.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HIGH_RES_CLOCK_HPP+#define HIGH_RES_CLOCK_HPP++#include <boost/config.hpp>+#include <boost/cstdint.hpp>++#if defined(ASIO_WINDOWS)++inline boost::uint64_t high_res_clock()+{+  LARGE_INTEGER i;+  QueryPerformanceCounter(&i);+  return i.QuadPart;+}++#elif defined(__GNUC__) && defined(__x86_64__)++inline boost::uint64_t high_res_clock()+{+  unsigned long low, high;+  __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high));+  return (((boost::uint64_t)high) << 32) | low;+}++#else++#include <boost/date_time/posix_time/posix_time_types.hpp>++inline boost::uint64_t high_res_clock()+{+  boost::posix_time::ptime now =+    boost::posix_time::microsec_clock::universal_time();++  boost::posix_time::ptime epoch(+      boost::gregorian::date(1970, 1, 1),+      boost::posix_time::seconds(0));++  return (now - epoch).total_microseconds();+}++#endif++#endif // HIGH_RES_CLOCK_HPP
+ link/modules/asio-standalone/asio/src/tests/performance/handler_allocator.hpp view
@@ -0,0 +1,112 @@+//+// handler_allocator.cpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 HANDLER_ALLOCATOR_HPP+#define HANDLER_ALLOCATOR_HPP++#include "asio.hpp"+#include <boost/aligned_storage.hpp>+#include <boost/noncopyable.hpp>++// Class to manage the memory to be used for handler-based custom allocation.+// It contains a single block of memory which may be returned for allocation+// requests. If the memory is in use when an allocation request is made, the+// allocator delegates allocation to the global heap.+class handler_allocator+  : private boost::noncopyable+{+public:+  handler_allocator()+    : in_use_(false)+  {+  }++  void* allocate(std::size_t size)+  {+    if (!in_use_ && size < storage_.size)+    {+      in_use_ = true;+      return storage_.address();+    }++    return ::operator new(size);+  }++  void deallocate(void* pointer)+  {+    if (pointer == storage_.address())+    {+      in_use_ = false;+    }+    else+    {+      ::operator delete(pointer);+    }+  }++private:+  // Storage space used for handler-based custom memory allocation.+  boost::aligned_storage<1024> storage_;++  // Whether the handler-based custom allocation storage has been used.+  bool in_use_;+};++// Wrapper class template for handler objects to allow handler memory+// allocation to be customised. Calls to operator() are forwarded to the+// encapsulated handler.+template <typename Handler>+class custom_alloc_handler+{+public:+  custom_alloc_handler(handler_allocator& a, Handler h)+    : allocator_(a),+      handler_(h)+  {+  }++  template <typename Arg1>+  void operator()(Arg1 arg1)+  {+    handler_(arg1);+  }++  template <typename Arg1, typename Arg2>+  void operator()(Arg1 arg1, Arg2 arg2)+  {+    handler_(arg1, arg2);+  }++  friend void* asio_handler_allocate(std::size_t size,+      custom_alloc_handler<Handler>* this_handler)+  {+    return this_handler->allocator_.allocate(size);+  }++  friend void asio_handler_deallocate(void* pointer, std::size_t /*size*/,+      custom_alloc_handler<Handler>* this_handler)+  {+    this_handler->allocator_.deallocate(pointer);+  }++private:+  handler_allocator& allocator_;+  Handler handler_;+};++// Helper function to wrap a handler object to add custom allocation.+template <typename Handler>+inline custom_alloc_handler<Handler> make_custom_alloc_handler(+    handler_allocator& a, Handler h)+{+  return custom_alloc_handler<Handler>(a, h);+}++#endif // HANDLER_ALLOCATOR_HPP
+ link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_ops.hpp view
@@ -0,0 +1,415 @@+//+// async_ops.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 ARCHETYPES_ASYNC_OPS_HPP+#define ARCHETYPES_ASYNC_OPS_HPP++#include <asio/associated_allocator.hpp>+#include <asio/associated_executor.hpp>+#include <asio/async_result.hpp>+#include <asio/error.hpp>++#if defined(ASIO_HAS_BOOST_BIND)+# include <boost/bind/bind.hpp>+#else // defined(ASIO_HAS_BOOST_BIND)+# include <functional>+#endif // defined(ASIO_HAS_BOOST_BIND)++namespace archetypes {++#if defined(ASIO_HAS_BOOST_BIND)+namespace bindns = boost;+#else // defined(ASIO_HAS_BOOST_BIND)+namespace bindns = std;+#endif // defined(ASIO_HAS_BOOST_BIND)++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken, void())+async_op_0(ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void()>::completion_handler_type handler_type;++  asio::async_completion<CompletionToken,+    void()> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  ex.post(ASIO_MOVE_CAST(handler_type)(completion.completion_handler), a);++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken, void(asio::error_code))+async_op_ec_0(bool ok, ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(asio::error_code)>::completion_handler_type handler_type;++  asio::async_completion<CompletionToken,+    void(asio::error_code)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  if (ok)+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          asio::error_code()), a);+  }+  else+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          asio::error_code(asio::error::operation_aborted)), a);+  }++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken, void(std::exception_ptr))+async_op_ex_0(bool ok, ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(std::exception_ptr)>::completion_handler_type handler_type;++  asio::async_completion<CompletionToken,+    void(std::exception_ptr)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  if (ok)+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          std::exception_ptr()), a);+  }+  else+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          std::make_exception_ptr(std::runtime_error("blah"))), a);+  }++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int))+async_op_1(ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(int)>::completion_handler_type handler_type;++  asio::async_completion<CompletionToken,+    void(int)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  ex.post(+      bindns::bind(+        ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+        42), a);++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken,+    void(asio::error_code, int))+async_op_ec_1(bool ok, ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(asio::error_code, int)>::completion_handler_type+      handler_type;++  asio::async_completion<CompletionToken,+    void(asio::error_code, int)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  if (ok)+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          asio::error_code(), 42), a);+  }+  else+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          asio::error_code(asio::error::operation_aborted),+          0), a);+  }++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken, void(std::exception_ptr, int))+async_op_ex_1(bool ok, ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(std::exception_ptr, int)>::completion_handler_type+      handler_type;++  asio::async_completion<CompletionToken,+    void(std::exception_ptr, int)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  if (ok)+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          std::exception_ptr(), 42), a);+  }+  else+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          std::make_exception_ptr(std::runtime_error("blah")), 0), a);+  }++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int, double))+async_op_2(ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(int, double)>::completion_handler_type handler_type;++  asio::async_completion<CompletionToken,+    void(int, double)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  ex.post(+      bindns::bind(+        ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+        42, 2.0), a);++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken,+    void(asio::error_code, int, double))+async_op_ec_2(bool ok, ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(asio::error_code, int, double)>::completion_handler_type+      handler_type;++  asio::async_completion<CompletionToken,+    void(asio::error_code, int, double)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  if (ok)+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          asio::error_code(), 42, 2.0), a);+  }+  else+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          asio::error_code(asio::error::operation_aborted),+          0, 0.0), a);+  }++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken,+    void(std::exception_ptr, int, double))+async_op_ex_2(bool ok, ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(std::exception_ptr, int, double)>::completion_handler_type+      handler_type;++  asio::async_completion<CompletionToken,+    void(std::exception_ptr, int, double)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  if (ok)+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          std::exception_ptr(), 42, 2.0), a);+  }+  else+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          std::make_exception_ptr(std::runtime_error("blah")), 0, 0.0), a);+  }++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken, void(int, double, char))+async_op_3(ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(int, double, char)>::completion_handler_type handler_type;++  asio::async_completion<CompletionToken,+    void(int, double, char)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  ex.post(+      bindns::bind(+        ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+        42, 2.0, 'a'), a);++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken,+    void(asio::error_code, int, double, char))+async_op_ec_3(bool ok, ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(asio::error_code, int, double, char)>::completion_handler_type+      handler_type;++  asio::async_completion<CompletionToken,+    void(asio::error_code, int, double, char)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  if (ok)+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          asio::error_code(), 42, 2.0, 'a'), a);+  }+  else+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          asio::error_code(asio::error::operation_aborted),+          0, 0.0, 'z'), a);+  }++  return completion.result.get();+}++template <typename CompletionToken>+ASIO_INITFN_RESULT_TYPE(CompletionToken,+    void(std::exception_ptr, int, double, char))+async_op_ex_3(bool ok, ASIO_MOVE_ARG(CompletionToken) token)+{+  typedef typename asio::async_completion<CompletionToken,+    void(std::exception_ptr, int, double, char)>::completion_handler_type+      handler_type;++  asio::async_completion<CompletionToken,+    void(std::exception_ptr, int, double, char)> completion(token);++  typename asio::associated_allocator<handler_type>::type a+    = asio::get_associated_allocator(completion.completion_handler);++  typename asio::associated_executor<handler_type>::type ex+    = asio::get_associated_executor(completion.completion_handler);++  if (ok)+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          std::exception_ptr(), 42, 2.0, 'a'), a);+  }+  else+  {+    ex.post(+        bindns::bind(+          ASIO_MOVE_CAST(handler_type)(completion.completion_handler),+          std::make_exception_ptr(std::runtime_error("blah")),+          0, 0.0, 'z'), a);+  }++  return completion.result.get();+}++} // namespace archetypes++#endif // ARCHETYPES_ASYNC_OPS_HPP
+ link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_result.hpp view
@@ -0,0 +1,94 @@+//+// async_result.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 ARCHETYPES_ASYNC_RESULT_HPP+#define ARCHETYPES_ASYNC_RESULT_HPP++#include <asio/async_result.hpp>++namespace archetypes {++struct lazy_handler+{+};++template <typename Signature>+struct concrete_handler;++template <typename R, typename Arg1>+struct concrete_handler<R(Arg1)>+{+  concrete_handler(lazy_handler)+  {+  }++  void operator()(typename asio::decay<Arg1>::type)+  {+  }++#if defined(ASIO_HAS_MOVE)+  concrete_handler(concrete_handler&&) {}+private:+  concrete_handler(const concrete_handler&);+#endif // defined(ASIO_HAS_MOVE)+};++template <typename R, typename Arg1, typename Arg2>+struct concrete_handler<R(Arg1, Arg2)>+{+  concrete_handler(lazy_handler)+  {+  }++  void operator()(typename asio::decay<Arg1>::type, typename asio::decay<Arg2>::type)+  {+  }++#if defined(ASIO_HAS_MOVE)+  concrete_handler(concrete_handler&&) {}+private:+  concrete_handler(const concrete_handler&);+#endif // defined(ASIO_HAS_MOVE)+};++} // namespace archetypes++namespace asio {++template <typename Signature>+class async_result<archetypes::lazy_handler, Signature>+{+public:+  // The concrete completion handler type.+  typedef archetypes::concrete_handler<Signature> completion_handler_type;++  // The return type of the initiating function.+  typedef int return_type;++  // Construct an async_result from a given handler.+  explicit async_result(completion_handler_type&)+  {+  }++  // Obtain the value to be returned from the initiating function.+  return_type get()+  {+    return 42;+  }++private:+  // Disallow copying and assignment.+  async_result(const async_result&) ASIO_DELETED;+  async_result& operator=(const async_result&) ASIO_DELETED;+};++} // namespace asio++#endif // ARCHETYPES_ASYNC_RESULT_HPP
+ link/modules/asio-standalone/asio/src/tests/unit/archetypes/gettable_socket_option.hpp view
@@ -0,0 +1,54 @@+//+// gettable_socket_option.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 ARCHETYPES_GETTABLE_SOCKET_OPTION_HPP+#define ARCHETYPES_GETTABLE_SOCKET_OPTION_HPP++#include <cstddef>++namespace archetypes {++template <typename PointerType>+class gettable_socket_option+{+public:+  template <typename Protocol>+  int level(const Protocol&) const+  {+    return 0;+  }++  template <typename Protocol>+  int name(const Protocol&) const+  {+    return 0;+  }++  template <typename Protocol>+  PointerType* data(const Protocol&)+  {+    return 0;+  }++  template <typename Protocol>+  std::size_t size(const Protocol&) const+  {+    return 0;+  }++  template <typename Protocol>+  void resize(const Protocol&, std::size_t)+  {+  }+};++} // namespace archetypes++#endif // ARCHETYPES_GETTABLE_SOCKET_OPTION_HPP
+ link/modules/asio-standalone/asio/src/tests/unit/archetypes/io_control_command.hpp view
@@ -0,0 +1,32 @@+//+// io_control_command.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 ARCHETYPES_IO_CONTROL_COMMAND_HPP+#define ARCHETYPES_IO_CONTROL_COMMAND_HPP++namespace archetypes {++class io_control_command+{+public:+  int name() const+  {+    return 0;+  }++  void* data()+  {+    return 0;+  }+};++} // namespace archetypes++#endif // ARCHETYPES_IO_CONTROL_COMMAND_HPP
+ link/modules/asio-standalone/asio/src/tests/unit/archetypes/settable_socket_option.hpp view
@@ -0,0 +1,49 @@+//+// settable_socket_option.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 ARCHETYPES_SETTABLE_SOCKET_OPTION_HPP+#define ARCHETYPES_SETTABLE_SOCKET_OPTION_HPP++#include <cstddef>++namespace archetypes {++template <typename PointerType>+class settable_socket_option+{+public:+  template <typename Protocol>+  int level(const Protocol&) const+  {+    return 0;+  }++  template <typename Protocol>+  int name(const Protocol&) const+  {+    return 0;+  }++  template <typename Protocol>+  const PointerType* data(const Protocol&) const+  {+    return 0;+  }++  template <typename Protocol>+  std::size_t size(const Protocol&) const+  {+    return 0;+  }+};++} // namespace archetypes++#endif // ARCHETYPES_SETTABLE_SOCKET_OPTION_HPP
+ link/modules/asio-standalone/asio/src/tests/unit/unit_test.hpp view
@@ -0,0 +1,190 @@+//+// unit_test.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2020 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 UNIT_TEST_HPP+#define UNIT_TEST_HPP++#include "asio/detail/config.hpp"+#include <iostream>+#include "asio/detail/atomic_count.hpp"++#if defined(__sun)+# include <stdlib.h> // Needed for lrand48.+#endif // defined(__sun)++#if defined(__BORLANDC__) && !defined(__clang__)++// Prevent use of intrinsic for strcmp.+# include <cstring>+# undef strcmp+ +// Suppress error about condition always being true.+# pragma option -w-ccc++#endif // defined(__BORLANDC__) && !defined(__clang__)++#if defined(ASIO_MSVC)+# pragma warning (disable:4127)+# pragma warning (push)+# pragma warning (disable:4244)+# pragma warning (disable:4702)+#endif // defined(ASIO_MSVC)++#if !defined(ASIO_TEST_IOSTREAM)+# define ASIO_TEST_IOSTREAM std::cerr+#endif // !defined(ASIO_TEST_IOSTREAM)++namespace asio {+namespace detail {++inline const char*& test_name()+{+  static const char* name = 0;+  return name;+}++inline atomic_count& test_errors()+{+  static atomic_count errors(0);+  return errors;+}++inline void begin_test_suite(const char* name)+{+  asio::detail::test_name();+  asio::detail::test_errors();+  ASIO_TEST_IOSTREAM << name << " test suite begins" << std::endl;+}++inline int end_test_suite(const char* name)+{+  ASIO_TEST_IOSTREAM << name << " test suite ends" << std::endl;+  ASIO_TEST_IOSTREAM << "\n*** ";+  long errors = asio::detail::test_errors();+  if (errors == 0)+    ASIO_TEST_IOSTREAM << "No errors detected.";+  else if (errors == 1)+    ASIO_TEST_IOSTREAM << "1 error detected.";+  else+    ASIO_TEST_IOSTREAM << errors << " errors detected." << std::endl;+  ASIO_TEST_IOSTREAM << std::endl;+  return errors == 0 ? 0 : 1;+}++template <void (*Test)()>+inline void run_test(const char* name)+{+  test_name() = name;+  long errors_before = asio::detail::test_errors();+  Test();+  if (test_errors() == errors_before)+    ASIO_TEST_IOSTREAM << name << " passed" << std::endl;+  else+    ASIO_TEST_IOSTREAM << name << " failed" << std::endl;+}++template <void (*)()>+inline void compile_test(const char* name)+{+  ASIO_TEST_IOSTREAM << name << " passed" << std::endl;+}++#if defined(ASIO_NO_EXCEPTIONS)++template <typename T>+void throw_exception(const T& t)+{+  ASIO_TEST_IOSTREAM << "Exception: " << t.what() << std::endl;+  std::abort();+}++#endif // defined(ASIO_NO_EXCEPTIONS)++} // namespace detail+} // namespace asio++#define ASIO_CHECK(expr) \+  do { if (!(expr)) { \+    ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \+      << asio::detail::test_name() << ": " \+      << "check '" << #expr << "' failed" << std::endl; \+    ++asio::detail::test_errors(); \+  } } while (0)++#define ASIO_CHECK_MESSAGE(expr, msg) \+  do { if (!(expr)) { \+    ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \+      << asio::detail::test_name() << ": " \+      << msg << std::endl; \+    ++asio::detail::test_errors(); \+  } } while (0)++#define ASIO_WARN_MESSAGE(expr, msg) \+  do { if (!(expr)) { \+    ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \+      << asio::detail::test_name() << ": " \+      << msg << std::endl; \+  } } while (0)++#define ASIO_ERROR(msg) \+  do { \+    ASIO_TEST_IOSTREAM << __FILE__ << "(" << __LINE__ << "): " \+      << asio::detail::test_name() << ": " \+      << msg << std::endl; \+    ++asio::detail::test_errors(); \+  } while (0)++#define ASIO_TEST_SUITE(name, tests) \+  int main() \+  { \+    asio::detail::begin_test_suite(name); \+    tests \+    return asio::detail::end_test_suite(name); \+  }++#define ASIO_TEST_CASE(test) \+  asio::detail::run_test<&test>(#test);++#define ASIO_TEST_CASE2(test1, test2) \+  asio::detail::run_test<&test1, test2>(#test1 "," #test2);++#define ASIO_TEST_CASE3(test1, test2, test3) \+  asio::detail::run_test<&test1, test2, test3>( \+    #test1 "," #test2 "," #test3);++#define ASIO_TEST_CASE4(test1, test2, test3, test4) \+  asio::detail::run_test<&test1, test2, test3, test4>( \+    #test1 "," #test2 "," #test3 "," #test4);++#define ASIO_TEST_CASE5(test1, test2, test3, test4, test5) \+  asio::detail::run_test<&test1, test2, test3, test4, test5>( \+    #test1 "," #test2 "," #test3 "," #test4 "," #test5);++#define ASIO_COMPILE_TEST_CASE(test) \+  asio::detail::compile_test<&test>(#test);++inline void null_test()+{+}++#if defined(__GNUC__) && defined(_AIX)++// AIX needs this symbol defined in asio, even if it doesn't do anything.+int test_main(int, char**)+{+}++#endif // defined(__GNUC__) && defined(_AIX)++#if defined(ASIO_MSVC)+# pragma warning (pop)+#endif // defined(ASIO_MSVC)++#endif // UNIT_TEST_HPP
+ link/third_party/catch/catch.hpp view
@@ -0,0 +1,17959 @@+/*+ *  Catch v2.13.7+ *  Generated: 2021-07-28 20:29:27.753164+ *  ----------------------------------------------------------+ *  This file has been merged from multiple headers. Please don't edit it directly+ *  Copyright (c) 2021 Two Blue Cubes Ltd. All rights reserved.+ *+ *  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 TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED+#define TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED+// start catch.hpp+++#define CATCH_VERSION_MAJOR 2+#define CATCH_VERSION_MINOR 13+#define CATCH_VERSION_PATCH 7++#ifdef __clang__+#    pragma clang system_header+#elif defined __GNUC__+#    pragma GCC system_header+#endif++// start catch_suppress_warnings.h++#ifdef __clang__+#   ifdef __ICC // icpc defines the __clang__ macro+#       pragma warning(push)+#       pragma warning(disable: 161 1682)+#   else // __ICC+#       pragma clang diagnostic push+#       pragma clang diagnostic ignored "-Wpadded"+#       pragma clang diagnostic ignored "-Wswitch-enum"+#       pragma clang diagnostic ignored "-Wcovered-switch-default"+#    endif+#elif defined __GNUC__+     // Because REQUIREs trigger GCC's -Wparentheses, and because still+     // supported version of g++ have only buggy support for _Pragmas,+     // Wparentheses have to be suppressed globally.+#    pragma GCC diagnostic ignored "-Wparentheses" // See #674 for details++#    pragma GCC diagnostic push+#    pragma GCC diagnostic ignored "-Wunused-variable"+#    pragma GCC diagnostic ignored "-Wpadded"+#endif+// end catch_suppress_warnings.h+#if defined(CATCH_CONFIG_MAIN) || defined(CATCH_CONFIG_RUNNER)+#  define CATCH_IMPL+#  define CATCH_CONFIG_ALL_PARTS+#endif++// In the impl file, we want to have access to all parts of the headers+// Can also be used to sanely support PCHs+#if defined(CATCH_CONFIG_ALL_PARTS)+#  define CATCH_CONFIG_EXTERNAL_INTERFACES+#  if defined(CATCH_CONFIG_DISABLE_MATCHERS)+#    undef CATCH_CONFIG_DISABLE_MATCHERS+#  endif+#  if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)+#    define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER+#  endif+#endif++#if !defined(CATCH_CONFIG_IMPL_ONLY)+// start catch_platform.h++// See e.g.:+// https://opensource.apple.com/source/CarbonHeaders/CarbonHeaders-18.1/TargetConditionals.h.auto.html+#ifdef __APPLE__+#  include <TargetConditionals.h>+#  if (defined(TARGET_OS_OSX) && TARGET_OS_OSX == 1) || \+      (defined(TARGET_OS_MAC) && TARGET_OS_MAC == 1)+#    define CATCH_PLATFORM_MAC+#  elif (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE == 1)+#    define CATCH_PLATFORM_IPHONE+#  endif++#elif defined(linux) || defined(__linux) || defined(__linux__)+#  define CATCH_PLATFORM_LINUX++#elif defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) || defined(__MINGW32__)+#  define CATCH_PLATFORM_WINDOWS+#endif++// end catch_platform.h++#ifdef CATCH_IMPL+#  ifndef CLARA_CONFIG_MAIN+#    define CLARA_CONFIG_MAIN_NOT_DEFINED+#    define CLARA_CONFIG_MAIN+#  endif+#endif++// start catch_user_interfaces.h++namespace Catch {+    unsigned int rngSeed();+}++// end catch_user_interfaces.h+// start catch_tag_alias_autoregistrar.h++// start catch_common.h++// start catch_compiler_capabilities.h++// Detect a number of compiler features - by compiler+// The following features are defined:+//+// CATCH_CONFIG_COUNTER : is the __COUNTER__ macro supported?+// CATCH_CONFIG_WINDOWS_SEH : is Windows SEH supported?+// CATCH_CONFIG_POSIX_SIGNALS : are POSIX signals supported?+// CATCH_CONFIG_DISABLE_EXCEPTIONS : Are exceptions enabled?+// ****************+// Note to maintainers: if new toggles are added please document them+// in configuration.md, too+// ****************++// In general each macro has a _NO_<feature name> form+// (e.g. CATCH_CONFIG_NO_POSIX_SIGNALS) which disables the feature.+// Many features, at point of detection, define an _INTERNAL_ macro, so they+// can be combined, en-mass, with the _NO_ forms later.++#ifdef __cplusplus++#  if (__cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L)+#    define CATCH_CPP14_OR_GREATER+#  endif++#  if (__cplusplus >= 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)+#    define CATCH_CPP17_OR_GREATER+#  endif++#endif++// Only GCC compiler should be used in this block, so other compilers trying to+// mask themselves as GCC should be ignored.+#if defined(__GNUC__) && !defined(__clang__) && !defined(__ICC) && !defined(__CUDACC__) && !defined(__LCC__)+#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "GCC diagnostic push" )+#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "GCC diagnostic pop" )++#    define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__)++#endif++#if defined(__clang__)++#    define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION _Pragma( "clang diagnostic push" )+#    define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  _Pragma( "clang diagnostic pop" )++// As of this writing, IBM XL's implementation of __builtin_constant_p has a bug+// which results in calls to destructors being emitted for each temporary,+// without a matching initialization. In practice, this can result in something+// like `std::string::~string` being called on an uninitialized value.+//+// For example, this code will likely segfault under IBM XL:+// ```+// REQUIRE(std::string("12") + "34" == "1234")+// ```+//+// Therefore, `CATCH_INTERNAL_IGNORE_BUT_WARN` is not implemented.+#  if !defined(__ibmxl__) && !defined(__CUDACC__)+#    define CATCH_INTERNAL_IGNORE_BUT_WARN(...) (void)__builtin_constant_p(__VA_ARGS__) /* NOLINT(cppcoreguidelines-pro-type-vararg, hicpp-vararg) */+#  endif++#    define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+         _Pragma( "clang diagnostic ignored \"-Wexit-time-destructors\"" ) \+         _Pragma( "clang diagnostic ignored \"-Wglobal-constructors\"")++#    define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \+         _Pragma( "clang diagnostic ignored \"-Wparentheses\"" )++#    define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \+         _Pragma( "clang diagnostic ignored \"-Wunused-variable\"" )++#    define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \+         _Pragma( "clang diagnostic ignored \"-Wgnu-zero-variadic-macro-arguments\"" )++#    define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \+         _Pragma( "clang diagnostic ignored \"-Wunused-template\"" )++#endif // __clang__++////////////////////////////////////////////////////////////////////////////////+// Assume that non-Windows platforms support posix signals by default+#if !defined(CATCH_PLATFORM_WINDOWS)+    #define CATCH_INTERNAL_CONFIG_POSIX_SIGNALS+#endif++////////////////////////////////////////////////////////////////////////////////+// We know some environments not to support full POSIX signals+#if defined(__CYGWIN__) || defined(__QNX__) || defined(__EMSCRIPTEN__) || defined(__DJGPP__)+    #define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS+#endif++#ifdef __OS400__+#       define CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS+#       define CATCH_CONFIG_COLOUR_NONE+#endif++////////////////////////////////////////////////////////////////////////////////+// Android somehow still does not support std::to_string+#if defined(__ANDROID__)+#    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING+#    define CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE+#endif++////////////////////////////////////////////////////////////////////////////////+// Not all Windows environments support SEH properly+#if defined(__MINGW32__)+#    define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH+#endif++////////////////////////////////////////////////////////////////////////////////+// PS4+#if defined(__ORBIS__)+#    define CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE+#endif++////////////////////////////////////////////////////////////////////////////////+// Cygwin+#ifdef __CYGWIN__++// Required for some versions of Cygwin to declare gettimeofday+// see: http://stackoverflow.com/questions/36901803/gettimeofday-not-declared-in-this-scope-cygwin+#   define _BSD_SOURCE+// some versions of cygwin (most) do not support std::to_string. Use the libstd check.+// https://gcc.gnu.org/onlinedocs/gcc-4.8.2/libstdc++/api/a01053_source.html line 2812-2813+# if !((__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99) \+           && !defined(_GLIBCXX_HAVE_BROKEN_VSWPRINTF))++#    define CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING++# endif+#endif // __CYGWIN__++////////////////////////////////////////////////////////////////////////////////+// Visual C+++#if defined(_MSC_VER)++#  define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION __pragma( warning(push) )+#  define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION  __pragma( warning(pop) )++// Universal Windows platform does not support SEH+// Or console colours (or console at all...)+#  if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_APP)+#    define CATCH_CONFIG_COLOUR_NONE+#  else+#    define CATCH_INTERNAL_CONFIG_WINDOWS_SEH+#  endif++// MSVC traditional preprocessor needs some workaround for __VA_ARGS__+// _MSVC_TRADITIONAL == 0 means new conformant preprocessor+// _MSVC_TRADITIONAL == 1 means old traditional non-conformant preprocessor+#  if !defined(__clang__) // Handle Clang masquerading for msvc+#    if !defined(_MSVC_TRADITIONAL) || (defined(_MSVC_TRADITIONAL) && _MSVC_TRADITIONAL)+#      define CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#    endif // MSVC_TRADITIONAL+#  endif // __clang__++#endif // _MSC_VER++#if defined(_REENTRANT) || defined(_MSC_VER)+// Enable async processing, as -pthread is specified or no additional linking is required+# define CATCH_INTERNAL_CONFIG_USE_ASYNC+#endif // _MSC_VER++////////////////////////////////////////////////////////////////////////////////+// Check if we are compiled with -fno-exceptions or equivalent+#if defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)+#  define CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED+#endif++////////////////////////////////////////////////////////////////////////////////+// DJGPP+#ifdef __DJGPP__+#  define CATCH_INTERNAL_CONFIG_NO_WCHAR+#endif // __DJGPP__++////////////////////////////////////////////////////////////////////////////////+// Embarcadero C++Build+#if defined(__BORLANDC__)+    #define CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN+#endif++////////////////////////////////////////////////////////////////////////////////++// Use of __COUNTER__ is suppressed during code analysis in+// CLion/AppCode 2017.2.x and former, because __COUNTER__ is not properly+// handled by it.+// Otherwise all supported compilers support COUNTER macro,+// but user still might want to turn it off+#if ( !defined(__JETBRAINS_IDE__) || __JETBRAINS_IDE__ >= 20170300L )+    #define CATCH_INTERNAL_CONFIG_COUNTER+#endif++////////////////////////////////////////////////////////////////////////////////++// RTX is a special version of Windows that is real time.+// This means that it is detected as Windows, but does not provide+// the same set of capabilities as real Windows does.+#if defined(UNDER_RTSS) || defined(RTX64_BUILD)+    #define CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH+    #define CATCH_INTERNAL_CONFIG_NO_ASYNC+    #define CATCH_CONFIG_COLOUR_NONE+#endif++#if !defined(_GLIBCXX_USE_C99_MATH_TR1)+#define CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER+#endif++// Various stdlib support checks that require __has_include+#if defined(__has_include)+  // Check if string_view is available and usable+  #if __has_include(<string_view>) && defined(CATCH_CPP17_OR_GREATER)+  #    define CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW+  #endif++  // Check if optional is available and usable+  #  if __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)+  #    define CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL+  #  endif // __has_include(<optional>) && defined(CATCH_CPP17_OR_GREATER)++  // Check if byte is available and usable+  #  if __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)+  #    include <cstddef>+  #    if defined(__cpp_lib_byte) && (__cpp_lib_byte > 0)+  #      define CATCH_INTERNAL_CONFIG_CPP17_BYTE+  #    endif+  #  endif // __has_include(<cstddef>) && defined(CATCH_CPP17_OR_GREATER)++  // Check if variant is available and usable+  #  if __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)+  #    if defined(__clang__) && (__clang_major__ < 8)+         // work around clang bug with libstdc++ https://bugs.llvm.org/show_bug.cgi?id=31852+         // fix should be in clang 8, workaround in libstdc++ 8.2+  #      include <ciso646>+  #      if defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)+  #        define CATCH_CONFIG_NO_CPP17_VARIANT+  #      else+  #        define CATCH_INTERNAL_CONFIG_CPP17_VARIANT+  #      endif // defined(__GLIBCXX__) && defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE < 9)+  #    else+  #      define CATCH_INTERNAL_CONFIG_CPP17_VARIANT+  #    endif // defined(__clang__) && (__clang_major__ < 8)+  #  endif // __has_include(<variant>) && defined(CATCH_CPP17_OR_GREATER)+#endif // defined(__has_include)++#if defined(CATCH_INTERNAL_CONFIG_COUNTER) && !defined(CATCH_CONFIG_NO_COUNTER) && !defined(CATCH_CONFIG_COUNTER)+#   define CATCH_CONFIG_COUNTER+#endif+#if defined(CATCH_INTERNAL_CONFIG_WINDOWS_SEH) && !defined(CATCH_CONFIG_NO_WINDOWS_SEH) && !defined(CATCH_CONFIG_WINDOWS_SEH) && !defined(CATCH_INTERNAL_CONFIG_NO_WINDOWS_SEH)+#   define CATCH_CONFIG_WINDOWS_SEH+#endif+// This is set by default, because we assume that unix compilers are posix-signal-compatible by default.+#if defined(CATCH_INTERNAL_CONFIG_POSIX_SIGNALS) && !defined(CATCH_INTERNAL_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_NO_POSIX_SIGNALS) && !defined(CATCH_CONFIG_POSIX_SIGNALS)+#   define CATCH_CONFIG_POSIX_SIGNALS+#endif+// This is set by default, because we assume that compilers with no wchar_t support are just rare exceptions.+#if !defined(CATCH_INTERNAL_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_NO_WCHAR) && !defined(CATCH_CONFIG_WCHAR)+#   define CATCH_CONFIG_WCHAR+#endif++#if !defined(CATCH_INTERNAL_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_NO_CPP11_TO_STRING) && !defined(CATCH_CONFIG_CPP11_TO_STRING)+#    define CATCH_CONFIG_CPP11_TO_STRING+#endif++#if defined(CATCH_INTERNAL_CONFIG_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_NO_CPP17_OPTIONAL) && !defined(CATCH_CONFIG_CPP17_OPTIONAL)+#  define CATCH_CONFIG_CPP17_OPTIONAL+#endif++#if defined(CATCH_INTERNAL_CONFIG_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_NO_CPP17_STRING_VIEW) && !defined(CATCH_CONFIG_CPP17_STRING_VIEW)+#  define CATCH_CONFIG_CPP17_STRING_VIEW+#endif++#if defined(CATCH_INTERNAL_CONFIG_CPP17_VARIANT) && !defined(CATCH_CONFIG_NO_CPP17_VARIANT) && !defined(CATCH_CONFIG_CPP17_VARIANT)+#  define CATCH_CONFIG_CPP17_VARIANT+#endif++#if defined(CATCH_INTERNAL_CONFIG_CPP17_BYTE) && !defined(CATCH_CONFIG_NO_CPP17_BYTE) && !defined(CATCH_CONFIG_CPP17_BYTE)+#  define CATCH_CONFIG_CPP17_BYTE+#endif++#if defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)+#  define CATCH_INTERNAL_CONFIG_NEW_CAPTURE+#endif++#if defined(CATCH_INTERNAL_CONFIG_NEW_CAPTURE) && !defined(CATCH_INTERNAL_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NO_NEW_CAPTURE) && !defined(CATCH_CONFIG_NEW_CAPTURE)+#  define CATCH_CONFIG_NEW_CAPTURE+#endif++#if !defined(CATCH_INTERNAL_CONFIG_EXCEPTIONS_ENABLED) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+#  define CATCH_CONFIG_DISABLE_EXCEPTIONS+#endif++#if defined(CATCH_INTERNAL_CONFIG_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_NO_POLYFILL_ISNAN) && !defined(CATCH_CONFIG_POLYFILL_ISNAN)+#  define CATCH_CONFIG_POLYFILL_ISNAN+#endif++#if defined(CATCH_INTERNAL_CONFIG_USE_ASYNC)  && !defined(CATCH_INTERNAL_CONFIG_NO_ASYNC) && !defined(CATCH_CONFIG_NO_USE_ASYNC) && !defined(CATCH_CONFIG_USE_ASYNC)+#  define CATCH_CONFIG_USE_ASYNC+#endif++#if defined(CATCH_INTERNAL_CONFIG_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_NO_ANDROID_LOGWRITE) && !defined(CATCH_CONFIG_ANDROID_LOGWRITE)+#  define CATCH_CONFIG_ANDROID_LOGWRITE+#endif++#if defined(CATCH_INTERNAL_CONFIG_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_NO_GLOBAL_NEXTAFTER) && !defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)+#  define CATCH_CONFIG_GLOBAL_NEXTAFTER+#endif++// Even if we do not think the compiler has that warning, we still have+// to provide a macro that can be used by the code.+#if !defined(CATCH_INTERNAL_START_WARNINGS_SUPPRESSION)+#   define CATCH_INTERNAL_START_WARNINGS_SUPPRESSION+#endif+#if !defined(CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION)+#   define CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION+#endif+#if !defined(CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS)+#   define CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS+#endif+#if !defined(CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS)+#   define CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS+#endif+#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS)+#   define CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS+#endif+#if !defined(CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS)+#   define CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS+#endif++// The goal of this macro is to avoid evaluation of the arguments, but+// still have the compiler warn on problems inside...+#if !defined(CATCH_INTERNAL_IGNORE_BUT_WARN)+#   define CATCH_INTERNAL_IGNORE_BUT_WARN(...)+#endif++#if defined(__APPLE__) && defined(__apple_build_version__) && (__clang_major__ < 10)+#   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS+#elif defined(__clang__) && (__clang_major__ < 5)+#   undef CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS+#endif++#if !defined(CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS)+#   define CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS+#endif++#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+#define CATCH_TRY if ((true))+#define CATCH_CATCH_ALL if ((false))+#define CATCH_CATCH_ANON(type) if ((false))+#else+#define CATCH_TRY try+#define CATCH_CATCH_ALL catch (...)+#define CATCH_CATCH_ANON(type) catch (type)+#endif++#if defined(CATCH_INTERNAL_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_NO_TRADITIONAL_MSVC_PREPROCESSOR) && !defined(CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR)+#define CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#endif++// end catch_compiler_capabilities.h+#define INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line ) name##line+#define INTERNAL_CATCH_UNIQUE_NAME_LINE( name, line ) INTERNAL_CATCH_UNIQUE_NAME_LINE2( name, line )+#ifdef CATCH_CONFIG_COUNTER+#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __COUNTER__ )+#else+#  define INTERNAL_CATCH_UNIQUE_NAME( name ) INTERNAL_CATCH_UNIQUE_NAME_LINE( name, __LINE__ )+#endif++#include <iosfwd>+#include <string>+#include <cstdint>++// We need a dummy global operator<< so we can bring it into Catch namespace later+struct Catch_global_namespace_dummy {};+std::ostream& operator<<(std::ostream&, Catch_global_namespace_dummy);++namespace Catch {++    struct CaseSensitive { enum Choice {+        Yes,+        No+    }; };++    class NonCopyable {+        NonCopyable( NonCopyable const& )              = delete;+        NonCopyable( NonCopyable && )                  = delete;+        NonCopyable& operator = ( NonCopyable const& ) = delete;+        NonCopyable& operator = ( NonCopyable && )     = delete;++    protected:+        NonCopyable();+        virtual ~NonCopyable();+    };++    struct SourceLineInfo {++        SourceLineInfo() = delete;+        SourceLineInfo( char const* _file, std::size_t _line ) noexcept+        :   file( _file ),+            line( _line )+        {}++        SourceLineInfo( SourceLineInfo const& other )            = default;+        SourceLineInfo& operator = ( SourceLineInfo const& )     = default;+        SourceLineInfo( SourceLineInfo&& )              noexcept = default;+        SourceLineInfo& operator = ( SourceLineInfo&& ) noexcept = default;++        bool empty() const noexcept { return file[0] == '\0'; }+        bool operator == ( SourceLineInfo const& other ) const noexcept;+        bool operator < ( SourceLineInfo const& other ) const noexcept;++        char const* file;+        std::size_t line;+    };++    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info );++    // Bring in operator<< from global namespace into Catch namespace+    // This is necessary because the overload of operator<< above makes+    // lookup stop at namespace Catch+    using ::operator<<;++    // Use this in variadic streaming macros to allow+    //    >> +StreamEndStop+    // as well as+    //    >> stuff +StreamEndStop+    struct StreamEndStop {+        std::string operator+() const;+    };+    template<typename T>+    T const& operator + ( T const& value, StreamEndStop ) {+        return value;+    }+}++#define CATCH_INTERNAL_LINEINFO \+    ::Catch::SourceLineInfo( __FILE__, static_cast<std::size_t>( __LINE__ ) )++// end catch_common.h+namespace Catch {++    struct RegistrarForTagAliases {+        RegistrarForTagAliases( char const* alias, char const* tag, SourceLineInfo const& lineInfo );+    };++} // end namespace Catch++#define CATCH_REGISTER_TAG_ALIAS( alias, spec ) \+    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+    namespace{ Catch::RegistrarForTagAliases INTERNAL_CATCH_UNIQUE_NAME( AutoRegisterTagAlias )( alias, spec, CATCH_INTERNAL_LINEINFO ); } \+    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION++// end catch_tag_alias_autoregistrar.h+// start catch_test_registry.h++// start catch_interfaces_testcase.h++#include <vector>++namespace Catch {++    class TestSpec;++    struct ITestInvoker {+        virtual void invoke () const = 0;+        virtual ~ITestInvoker();+    };++    class TestCase;+    struct IConfig;++    struct ITestCaseRegistry {+        virtual ~ITestCaseRegistry();+        virtual std::vector<TestCase> const& getAllTests() const = 0;+        virtual std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const = 0;+    };++    bool isThrowSafe( TestCase const& testCase, IConfig const& config );+    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );+    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );++}++// end catch_interfaces_testcase.h+// start catch_stringref.h++#include <cstddef>+#include <string>+#include <iosfwd>+#include <cassert>++namespace Catch {++    /// A non-owning string class (similar to the forthcoming std::string_view)+    /// Note that, because a StringRef may be a substring of another string,+    /// it may not be null terminated.+    class StringRef {+    public:+        using size_type = std::size_t;+        using const_iterator = const char*;++    private:+        static constexpr char const* const s_empty = "";++        char const* m_start = s_empty;+        size_type m_size = 0;++    public: // construction+        constexpr StringRef() noexcept = default;++        StringRef( char const* rawChars ) noexcept;++        constexpr StringRef( char const* rawChars, size_type size ) noexcept+        :   m_start( rawChars ),+            m_size( size )+        {}++        StringRef( std::string const& stdString ) noexcept+        :   m_start( stdString.c_str() ),+            m_size( stdString.size() )+        {}++        explicit operator std::string() const {+            return std::string(m_start, m_size);+        }++    public: // operators+        auto operator == ( StringRef const& other ) const noexcept -> bool;+        auto operator != (StringRef const& other) const noexcept -> bool {+            return !(*this == other);+        }++        auto operator[] ( size_type index ) const noexcept -> char {+            assert(index < m_size);+            return m_start[index];+        }++    public: // named queries+        constexpr auto empty() const noexcept -> bool {+            return m_size == 0;+        }+        constexpr auto size() const noexcept -> size_type {+            return m_size;+        }++        // Returns the current start pointer. If the StringRef is not+        // null-terminated, throws std::domain_exception+        auto c_str() const -> char const*;++    public: // substrings and searches+        // Returns a substring of [start, start + length).+        // If start + length > size(), then the substring is [start, size()).+        // If start > size(), then the substring is empty.+        auto substr( size_type start, size_type length ) const noexcept -> StringRef;++        // Returns the current start pointer. May not be null-terminated.+        auto data() const noexcept -> char const*;++        constexpr auto isNullTerminated() const noexcept -> bool {+            return m_start[m_size] == '\0';+        }++    public: // iterators+        constexpr const_iterator begin() const { return m_start; }+        constexpr const_iterator end() const { return m_start + m_size; }+    };++    auto operator += ( std::string& lhs, StringRef const& sr ) -> std::string&;+    auto operator << ( std::ostream& os, StringRef const& sr ) -> std::ostream&;++    constexpr auto operator "" _sr( char const* rawChars, std::size_t size ) noexcept -> StringRef {+        return StringRef( rawChars, size );+    }+} // namespace Catch++constexpr auto operator "" _catch_sr( char const* rawChars, std::size_t size ) noexcept -> Catch::StringRef {+    return Catch::StringRef( rawChars, size );+}++// end catch_stringref.h+// start catch_preprocessor.hpp+++#define CATCH_RECURSION_LEVEL0(...) __VA_ARGS__+#define CATCH_RECURSION_LEVEL1(...) CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(CATCH_RECURSION_LEVEL0(__VA_ARGS__)))+#define CATCH_RECURSION_LEVEL2(...) CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(CATCH_RECURSION_LEVEL1(__VA_ARGS__)))+#define CATCH_RECURSION_LEVEL3(...) CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(CATCH_RECURSION_LEVEL2(__VA_ARGS__)))+#define CATCH_RECURSION_LEVEL4(...) CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(CATCH_RECURSION_LEVEL3(__VA_ARGS__)))+#define CATCH_RECURSION_LEVEL5(...) CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(CATCH_RECURSION_LEVEL4(__VA_ARGS__)))++#ifdef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#define INTERNAL_CATCH_EXPAND_VARGS(...) __VA_ARGS__+// MSVC needs more evaluations+#define CATCH_RECURSION_LEVEL6(...) CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(CATCH_RECURSION_LEVEL5(__VA_ARGS__)))+#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL6(CATCH_RECURSION_LEVEL6(__VA_ARGS__))+#else+#define CATCH_RECURSE(...)  CATCH_RECURSION_LEVEL5(__VA_ARGS__)+#endif++#define CATCH_REC_END(...)+#define CATCH_REC_OUT++#define CATCH_EMPTY()+#define CATCH_DEFER(id) id CATCH_EMPTY()++#define CATCH_REC_GET_END2() 0, CATCH_REC_END+#define CATCH_REC_GET_END1(...) CATCH_REC_GET_END2+#define CATCH_REC_GET_END(...) CATCH_REC_GET_END1+#define CATCH_REC_NEXT0(test, next, ...) next CATCH_REC_OUT+#define CATCH_REC_NEXT1(test, next) CATCH_DEFER ( CATCH_REC_NEXT0 ) ( test, next, 0)+#define CATCH_REC_NEXT(test, next)  CATCH_REC_NEXT1(CATCH_REC_GET_END test, next)++#define CATCH_REC_LIST0(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )+#define CATCH_REC_LIST1(f, x, peek, ...) , f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0) ) ( f, peek, __VA_ARGS__ )+#define CATCH_REC_LIST2(f, x, peek, ...)   f(x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1) ) ( f, peek, __VA_ARGS__ )++#define CATCH_REC_LIST0_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )+#define CATCH_REC_LIST1_UD(f, userdata, x, peek, ...) , f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST0_UD) ) ( f, userdata, peek, __VA_ARGS__ )+#define CATCH_REC_LIST2_UD(f, userdata, x, peek, ...)   f(userdata, x) CATCH_DEFER ( CATCH_REC_NEXT(peek, CATCH_REC_LIST1_UD) ) ( f, userdata, peek, __VA_ARGS__ )++// Applies the function macro `f` to each of the remaining parameters, inserts commas between the results,+// and passes userdata as the first parameter to each invocation,+// e.g. CATCH_REC_LIST_UD(f, x, a, b, c) evaluates to f(x, a), f(x, b), f(x, c)+#define CATCH_REC_LIST_UD(f, userdata, ...) CATCH_RECURSE(CATCH_REC_LIST2_UD(f, userdata, __VA_ARGS__, ()()(), ()()(), ()()(), 0))++#define CATCH_REC_LIST(f, ...) CATCH_RECURSE(CATCH_REC_LIST2(f, __VA_ARGS__, ()()(), ()()(), ()()(), 0))++#define INTERNAL_CATCH_EXPAND1(param) INTERNAL_CATCH_EXPAND2(param)+#define INTERNAL_CATCH_EXPAND2(...) INTERNAL_CATCH_NO## __VA_ARGS__+#define INTERNAL_CATCH_DEF(...) INTERNAL_CATCH_DEF __VA_ARGS__+#define INTERNAL_CATCH_NOINTERNAL_CATCH_DEF+#define INTERNAL_CATCH_STRINGIZE(...) INTERNAL_CATCH_STRINGIZE2(__VA_ARGS__)+#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#define INTERNAL_CATCH_STRINGIZE2(...) #__VA_ARGS__+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param))+#else+// MSVC is adding extra space and needs another indirection to expand INTERNAL_CATCH_NOINTERNAL_CATCH_DEF+#define INTERNAL_CATCH_STRINGIZE2(...) INTERNAL_CATCH_STRINGIZE3(__VA_ARGS__)+#define INTERNAL_CATCH_STRINGIZE3(...) #__VA_ARGS__+#define INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS(param) (INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_REMOVE_PARENS(param)) + 1)+#endif++#define INTERNAL_CATCH_MAKE_NAMESPACE2(...) ns_##__VA_ARGS__+#define INTERNAL_CATCH_MAKE_NAMESPACE(name) INTERNAL_CATCH_MAKE_NAMESPACE2(name)++#define INTERNAL_CATCH_REMOVE_PARENS(...) INTERNAL_CATCH_EXPAND1(INTERNAL_CATCH_DEF __VA_ARGS__)++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>())+#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__))+#else+#define INTERNAL_CATCH_MAKE_TYPE_LIST2(...) INTERNAL_CATCH_EXPAND_VARGS(decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS_GEN(__VA_ARGS__)>()))+#define INTERNAL_CATCH_MAKE_TYPE_LIST(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_MAKE_TYPE_LIST2(INTERNAL_CATCH_REMOVE_PARENS(__VA_ARGS__)))+#endif++#define INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(...)\+    CATCH_REC_LIST(INTERNAL_CATCH_MAKE_TYPE_LIST,__VA_ARGS__)++#define INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_0) INTERNAL_CATCH_REMOVE_PARENS(_0)+#define INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_0, _1) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_1_ARG(_1)+#define INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_0, _1, _2) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_2_ARG(_1, _2)+#define INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_0, _1, _2, _3) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_3_ARG(_1, _2, _3)+#define INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_0, _1, _2, _3, _4) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_4_ARG(_1, _2, _3, _4)+#define INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_0, _1, _2, _3, _4, _5) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_5_ARG(_1, _2, _3, _4, _5)+#define INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_0, _1, _2, _3, _4, _5, _6) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_6_ARG(_1, _2, _3, _4, _5, _6)+#define INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_0, _1, _2, _3, _4, _5, _6, _7) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_7_ARG(_1, _2, _3, _4, _5, _6, _7)+#define INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_8_ARG(_1, _2, _3, _4, _5, _6, _7, _8)+#define INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_9_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9)+#define INTERNAL_CATCH_REMOVE_PARENS_11_ARG(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10) INTERNAL_CATCH_REMOVE_PARENS(_0), INTERNAL_CATCH_REMOVE_PARENS_10_ARG(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10)++#define INTERNAL_CATCH_VA_NARGS_IMPL(_0, _1, _2, _3, _4, _5, _6, _7, _8, _9, _10, N, ...) N++#define INTERNAL_CATCH_TYPE_GEN\+    template<typename...> struct TypeList {};\+    template<typename...Ts>\+    constexpr auto get_wrapper() noexcept -> TypeList<Ts...> { return {}; }\+    template<template<typename...> class...> struct TemplateTypeList{};\+    template<template<typename...> class...Cs>\+    constexpr auto get_wrapper() noexcept -> TemplateTypeList<Cs...> { return {}; }\+    template<typename...>\+    struct append;\+    template<typename...>\+    struct rewrap;\+    template<template<typename...> class, typename...>\+    struct create;\+    template<template<typename...> class, typename>\+    struct convert;\+    \+    template<typename T> \+    struct append<T> { using type = T; };\+    template< template<typename...> class L1, typename...E1, template<typename...> class L2, typename...E2, typename...Rest>\+    struct append<L1<E1...>, L2<E2...>, Rest...> { using type = typename append<L1<E1...,E2...>, Rest...>::type; };\+    template< template<typename...> class L1, typename...E1, typename...Rest>\+    struct append<L1<E1...>, TypeList<mpl_::na>, Rest...> { using type = L1<E1...>; };\+    \+    template< template<typename...> class Container, template<typename...> class List, typename...elems>\+    struct rewrap<TemplateTypeList<Container>, List<elems...>> { using type = TypeList<Container<elems...>>; };\+    template< template<typename...> class Container, template<typename...> class List, class...Elems, typename...Elements>\+    struct rewrap<TemplateTypeList<Container>, List<Elems...>, Elements...> { using type = typename append<TypeList<Container<Elems...>>, typename rewrap<TemplateTypeList<Container>, Elements...>::type>::type; };\+    \+    template<template <typename...> class Final, template< typename...> class...Containers, typename...Types>\+    struct create<Final, TemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<TemplateTypeList<Containers>, Types...>::type...>::type; };\+    template<template <typename...> class Final, template <typename...> class List, typename...Ts>\+    struct convert<Final, List<Ts...>> { using type = typename append<Final<>,TypeList<Ts>...>::type; };++#define INTERNAL_CATCH_NTTP_1(signature, ...)\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)> struct Nttp{};\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\+    constexpr auto get_wrapper() noexcept -> Nttp<__VA_ARGS__> { return {}; } \+    template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...> struct NttpTemplateTypeList{};\+    template<template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Cs>\+    constexpr auto get_wrapper() noexcept -> NttpTemplateTypeList<Cs...> { return {}; } \+    \+    template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature)>\+    struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>> { using type = TypeList<Container<__VA_ARGS__>>; };\+    template< template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class Container, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class List, INTERNAL_CATCH_REMOVE_PARENS(signature), typename...Elements>\+    struct rewrap<NttpTemplateTypeList<Container>, List<__VA_ARGS__>, Elements...> { using type = typename append<TypeList<Container<__VA_ARGS__>>, typename rewrap<NttpTemplateTypeList<Container>, Elements...>::type>::type; };\+    template<template <typename...> class Final, template<INTERNAL_CATCH_REMOVE_PARENS(signature)> class...Containers, typename...Types>\+    struct create<Final, NttpTemplateTypeList<Containers...>, TypeList<Types...>> { using type = typename append<Final<>, typename rewrap<NttpTemplateTypeList<Containers>, Types...>::type...>::type; };++#define INTERNAL_CATCH_DECLARE_SIG_TEST0(TestName)+#define INTERNAL_CATCH_DECLARE_SIG_TEST1(TestName, signature)\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\+    static void TestName()+#define INTERNAL_CATCH_DECLARE_SIG_TEST_X(TestName, signature, ...)\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\+    static void TestName()++#define INTERNAL_CATCH_DEFINE_SIG_TEST0(TestName)+#define INTERNAL_CATCH_DEFINE_SIG_TEST1(TestName, signature)\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\+    static void TestName()+#define INTERNAL_CATCH_DEFINE_SIG_TEST_X(TestName, signature,...)\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\+    static void TestName()++#define INTERNAL_CATCH_NTTP_REGISTER0(TestFunc, signature)\+    template<typename Type>\+    void reg_test(TypeList<Type>, Catch::NameAndTags nameAndTags)\+    {\+        Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<Type>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\+    }++#define INTERNAL_CATCH_NTTP_REGISTER(TestFunc, signature, ...)\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\+    void reg_test(Nttp<__VA_ARGS__>, Catch::NameAndTags nameAndTags)\+    {\+        Catch::AutoReg( Catch::makeTestInvoker(&TestFunc<__VA_ARGS__>), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), nameAndTags);\+    }++#define INTERNAL_CATCH_NTTP_REGISTER_METHOD0(TestName, signature, ...)\+    template<typename Type>\+    void reg_test(TypeList<Type>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\+    {\+        Catch::AutoReg( Catch::makeTestInvoker(&TestName<Type>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\+    }++#define INTERNAL_CATCH_NTTP_REGISTER_METHOD(TestName, signature, ...)\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)>\+    void reg_test(Nttp<__VA_ARGS__>, Catch::StringRef className, Catch::NameAndTags nameAndTags)\+    {\+        Catch::AutoReg( Catch::makeTestInvoker(&TestName<__VA_ARGS__>::test), CATCH_INTERNAL_LINEINFO, className, nameAndTags);\+    }++#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0(TestName, ClassName)+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1(TestName, ClassName, signature)\+    template<typename TestType> \+    struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<TestType> { \+        void test();\+    }++#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X(TestName, ClassName, signature, ...)\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \+    struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName)<__VA_ARGS__> { \+        void test();\+    }++#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0(TestName)+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1(TestName, signature)\+    template<typename TestType> \+    void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<TestType>::test()+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X(TestName, signature, ...)\+    template<INTERNAL_CATCH_REMOVE_PARENS(signature)> \+    void INTERNAL_CATCH_MAKE_NAMESPACE(TestName)::TestName<__VA_ARGS__>::test()++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#define INTERNAL_CATCH_NTTP_0+#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1(__VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_1( __VA_ARGS__),INTERNAL_CATCH_NTTP_1( __VA_ARGS__), INTERNAL_CATCH_NTTP_0)+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__)+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__)+#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__)+#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__)+#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__)+#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__)+#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__)+#else+#define INTERNAL_CATCH_NTTP_0(signature)+#define INTERNAL_CATCH_NTTP_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_1,INTERNAL_CATCH_NTTP_1, INTERNAL_CATCH_NTTP_0)( __VA_ARGS__))+#define INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD1, INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD0)(TestName, __VA_ARGS__))+#define INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X,INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD_X, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD1, INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD0)(TestName, ClassName, __VA_ARGS__))+#define INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD, INTERNAL_CATCH_NTTP_REGISTER_METHOD0, INTERNAL_CATCH_NTTP_REGISTER_METHOD0)(TestName, __VA_ARGS__))+#define INTERNAL_CATCH_NTTP_REG_GEN(TestFunc, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER, INTERNAL_CATCH_NTTP_REGISTER0, INTERNAL_CATCH_NTTP_REGISTER0)(TestFunc, __VA_ARGS__))+#define INTERNAL_CATCH_DEFINE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DEFINE_SIG_TEST1, INTERNAL_CATCH_DEFINE_SIG_TEST0)(TestName, __VA_ARGS__))+#define INTERNAL_CATCH_DECLARE_SIG_TEST(TestName, ...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL( "dummy", __VA_ARGS__, INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DEFINE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X,INTERNAL_CATCH_DECLARE_SIG_TEST_X, INTERNAL_CATCH_DECLARE_SIG_TEST1, INTERNAL_CATCH_DECLARE_SIG_TEST0)(TestName, __VA_ARGS__))+#define INTERNAL_CATCH_REMOVE_PARENS_GEN(...) INTERNAL_CATCH_EXPAND_VARGS(INTERNAL_CATCH_VA_NARGS_IMPL(__VA_ARGS__, INTERNAL_CATCH_REMOVE_PARENS_11_ARG,INTERNAL_CATCH_REMOVE_PARENS_10_ARG,INTERNAL_CATCH_REMOVE_PARENS_9_ARG,INTERNAL_CATCH_REMOVE_PARENS_8_ARG,INTERNAL_CATCH_REMOVE_PARENS_7_ARG,INTERNAL_CATCH_REMOVE_PARENS_6_ARG,INTERNAL_CATCH_REMOVE_PARENS_5_ARG,INTERNAL_CATCH_REMOVE_PARENS_4_ARG,INTERNAL_CATCH_REMOVE_PARENS_3_ARG,INTERNAL_CATCH_REMOVE_PARENS_2_ARG,INTERNAL_CATCH_REMOVE_PARENS_1_ARG)(__VA_ARGS__))+#endif++// end catch_preprocessor.hpp+// start catch_meta.hpp+++#include <type_traits>++namespace Catch {+    template<typename T>+    struct always_false : std::false_type {};++    template <typename> struct true_given : std::true_type {};+    struct is_callable_tester {+        template <typename Fun, typename... Args>+        true_given<decltype(std::declval<Fun>()(std::declval<Args>()...))> static test(int);+        template <typename...>+        std::false_type static test(...);+    };++    template <typename T>+    struct is_callable;++    template <typename Fun, typename... Args>+    struct is_callable<Fun(Args...)> : decltype(is_callable_tester::test<Fun, Args...>(0)) {};++#if defined(__cpp_lib_is_invocable) && __cpp_lib_is_invocable >= 201703+    // std::result_of is deprecated in C++17 and removed in C++20. Hence, it is+    // replaced with std::invoke_result here.+    template <typename Func, typename... U>+    using FunctionReturnType = std::remove_reference_t<std::remove_cv_t<std::invoke_result_t<Func, U...>>>;+#else+    // Keep ::type here because we still support C++11+    template <typename Func, typename... U>+    using FunctionReturnType = typename std::remove_reference<typename std::remove_cv<typename std::result_of<Func(U...)>::type>::type>::type;+#endif++} // namespace Catch++namespace mpl_{+    struct na;+}++// end catch_meta.hpp+namespace Catch {++template<typename C>+class TestInvokerAsMethod : public ITestInvoker {+    void (C::*m_testAsMethod)();+public:+    TestInvokerAsMethod( void (C::*testAsMethod)() ) noexcept : m_testAsMethod( testAsMethod ) {}++    void invoke() const override {+        C obj;+        (obj.*m_testAsMethod)();+    }+};++auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker*;++template<typename C>+auto makeTestInvoker( void (C::*testAsMethod)() ) noexcept -> ITestInvoker* {+    return new(std::nothrow) TestInvokerAsMethod<C>( testAsMethod );+}++struct NameAndTags {+    NameAndTags( StringRef const& name_ = StringRef(), StringRef const& tags_ = StringRef() ) noexcept;+    StringRef name;+    StringRef tags;+};++struct AutoReg : NonCopyable {+    AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept;+    ~AutoReg();+};++} // end namespace Catch++#if defined(CATCH_CONFIG_DISABLE)+    #define INTERNAL_CATCH_TESTCASE_NO_REGISTRATION( TestName, ... ) \+        static void TestName()+    #define INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION( TestName, ClassName, ... ) \+        namespace{                        \+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \+                void test();              \+            };                            \+        }                                 \+        void TestName::test()+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( TestName, TestFunc, Name, Tags, Signature, ... )  \+        INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature))+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... )    \+        namespace{                                                                                  \+            namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                      \+            INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\+        }                                                                                           \+        }                                                                                           \+        INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))++    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \+            INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ )+    #else+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(Name, Tags, ...) \+            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) )+    #endif++    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \+            INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ )+    #else+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(Name, Tags, Signature, ...) \+            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )+    #endif++    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \+            INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )+    #else+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION( ClassName, Name, Tags,... ) \+            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )+    #endif++    #ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \+            INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )+    #else+        #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION( ClassName, Name, Tags, Signature, ... ) \+            INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )+    #endif+#endif++    ///////////////////////////////////////////////////////////////////////////////+    #define INTERNAL_CATCH_TESTCASE2( TestName, ... ) \+        static void TestName(); \+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &TestName ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \+        static void TestName()+    #define INTERNAL_CATCH_TESTCASE( ... ) \+        INTERNAL_CATCH_TESTCASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), __VA_ARGS__ )++    ///////////////////////////////////////////////////////////////////////////////+    #define INTERNAL_CATCH_METHOD_AS_TEST_CASE( QualifiedMethod, ... ) \+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+        namespace{ Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( &QualifiedMethod ), CATCH_INTERNAL_LINEINFO, "&" #QualifiedMethod, Catch::NameAndTags{ __VA_ARGS__ } ); } /* NOLINT */ \+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION++    ///////////////////////////////////////////////////////////////////////////////+    #define INTERNAL_CATCH_TEST_CASE_METHOD2( TestName, ClassName, ... )\+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+        namespace{ \+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName) { \+                void test(); \+            }; \+            Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar ) ( Catch::makeTestInvoker( &TestName::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \+        } \+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \+        void TestName::test()+    #define INTERNAL_CATCH_TEST_CASE_METHOD( ClassName, ... ) \+        INTERNAL_CATCH_TEST_CASE_METHOD2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), ClassName, __VA_ARGS__ )++    ///////////////////////////////////////////////////////////////////////////////+    #define INTERNAL_CATCH_REGISTER_TESTCASE( Function, ... ) \+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+        Catch::AutoReg INTERNAL_CATCH_UNIQUE_NAME( autoRegistrar )( Catch::makeTestInvoker( Function ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ __VA_ARGS__ } ); /* NOLINT */ \+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION++    ///////////////////////////////////////////////////////////////////////////////+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_2(TestName, TestFunc, Name, Tags, Signature, ... )\+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \+        INTERNAL_CATCH_DECLARE_SIG_TEST(TestFunc, INTERNAL_CATCH_REMOVE_PARENS(Signature));\+        namespace {\+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\+            INTERNAL_CATCH_TYPE_GEN\+            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\+            INTERNAL_CATCH_NTTP_REG_GEN(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))\+            template<typename...Types> \+            struct TestName{\+                TestName(){\+                    int index = 0;                                    \+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\+                    using expander = int[];\+                    (void)expander{(reg_test(Types{}, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \+                }\+            };\+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\+            TestName<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\+            return 0;\+        }();\+        }\+        }\+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \+        INTERNAL_CATCH_DEFINE_SIG_TEST(TestFunc,INTERNAL_CATCH_REMOVE_PARENS(Signature))++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ )+#else+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE(Name, Tags, ...) \+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename TestType, __VA_ARGS__ ) )+#endif++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ )+#else+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG(Name, Tags, Signature, ...) \+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )+#endif++    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(TestName, TestFuncName, Name, Tags, Signature, TmplTypes, TypesList) \+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION                      \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS                      \+        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS                \+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS              \+        template<typename TestType> static void TestFuncName();       \+        namespace {\+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName) {                                     \+            INTERNAL_CATCH_TYPE_GEN                                                  \+            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))         \+            template<typename... Types>                               \+            struct TestName {                                         \+                void reg_tests() {                                          \+                    int index = 0;                                    \+                    using expander = int[];                           \+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\+                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\+                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFuncName<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */\+                }                                                     \+            };                                                        \+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \+                using TestInit = typename create<TestName, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type; \+                TestInit t;                                           \+                t.reg_tests();                                        \+                return 0;                                             \+            }();                                                      \+        }                                                             \+        }                                                             \+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \+        template<typename TestType>                                   \+        static void TestFuncName()++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T,__VA_ARGS__)+#else+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE(Name, Tags, ...)\+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, typename T, __VA_ARGS__ ) )+#endif++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__)+#else+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG(Name, Tags, Signature, ...)\+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, Signature, __VA_ARGS__ ) )+#endif++    #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2(TestName, TestFunc, Name, Tags, TmplList)\+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \+        template<typename TestType> static void TestFunc();       \+        namespace {\+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){\+        INTERNAL_CATCH_TYPE_GEN\+        template<typename... Types>                               \+        struct TestName {                                         \+            void reg_tests() {                                          \+                int index = 0;                                    \+                using expander = int[];                           \+                (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestFunc<Types> ), CATCH_INTERNAL_LINEINFO, Catch::StringRef(), Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */\+            }                                                     \+        };\+        static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){ \+                using TestInit = typename convert<TestName, TmplList>::type; \+                TestInit t;                                           \+                t.reg_tests();                                        \+                return 0;                                             \+            }();                                                      \+        }}\+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION                       \+        template<typename TestType>                                   \+        static void TestFunc()++    #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(Name, Tags, TmplList) \+        INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), Name, Tags, TmplList )++    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, Signature, ... ) \+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \+        namespace {\+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \+            INTERNAL_CATCH_TYPE_GEN\+            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\+            INTERNAL_CATCH_DECLARE_SIG_TEST_METHOD(TestName, ClassName, INTERNAL_CATCH_REMOVE_PARENS(Signature));\+            INTERNAL_CATCH_NTTP_REG_METHOD_GEN(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))\+            template<typename...Types> \+            struct TestNameClass{\+                TestNameClass(){\+                    int index = 0;                                    \+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, __VA_ARGS__)};\+                    using expander = int[];\+                    (void)expander{(reg_test(Types{}, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index]), Tags } ), index++)... };/* NOLINT */ \+                }\+            };\+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\+                TestNameClass<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(__VA_ARGS__)>();\+                return 0;\+        }();\+        }\+        }\+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \+        INTERNAL_CATCH_DEFINE_SIG_TEST_METHOD(TestName, INTERNAL_CATCH_REMOVE_PARENS(Signature))++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ )+#else+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( ClassName, Name, Tags,... ) \+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, typename T, __VA_ARGS__ ) )+#endif++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \+        INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ )+#else+    #define INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... ) \+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____C_L_A_S_S____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ) , ClassName, Name, Tags, Signature, __VA_ARGS__ ) )+#endif++    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2(TestNameClass, TestName, ClassName, Name, Tags, Signature, TmplTypes, TypesList)\+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+        CATCH_INTERNAL_SUPPRESS_ZERO_VARIADIC_WARNINGS \+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \+        template<typename TestType> \+            struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \+                void test();\+            };\+        namespace {\+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestNameClass) {\+            INTERNAL_CATCH_TYPE_GEN                  \+            INTERNAL_CATCH_NTTP_GEN(INTERNAL_CATCH_REMOVE_PARENS(Signature))\+            template<typename...Types>\+            struct TestNameClass{\+                void reg_tests(){\+                    int index = 0;\+                    using expander = int[];\+                    constexpr char const* tmpl_types[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TmplTypes))};\+                    constexpr char const* types_list[] = {CATCH_REC_LIST(INTERNAL_CATCH_STRINGIZE_WITHOUT_PARENS, INTERNAL_CATCH_REMOVE_PARENS(TypesList))};\+                    constexpr auto num_types = sizeof(types_list) / sizeof(types_list[0]);\+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(tmpl_types[index / num_types]) + "<" + std::string(types_list[index % num_types]) + ">", Tags } ), index++)... };/* NOLINT */ \+                }\+            };\+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\+                using TestInit = typename create<TestNameClass, decltype(get_wrapper<INTERNAL_CATCH_REMOVE_PARENS(TmplTypes)>()), TypeList<INTERNAL_CATCH_MAKE_TYPE_LISTS_FROM_TYPES(INTERNAL_CATCH_REMOVE_PARENS(TypesList))>>::type;\+                TestInit t;\+                t.reg_tests();\+                return 0;\+            }(); \+        }\+        }\+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \+        template<typename TestType> \+        void TestName<TestType>::test()++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T, __VA_ARGS__ )+#else+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( ClassName, Name, Tags, ... )\+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, typename T,__VA_ARGS__ ) )+#endif++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\+        INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature, __VA_ARGS__ )+#else+    #define INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( ClassName, Name, Tags, Signature, ... )\+        INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, Signature,__VA_ARGS__ ) )+#endif++    #define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( TestNameClass, TestName, ClassName, Name, Tags, TmplList) \+        CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+        CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+        CATCH_INTERNAL_SUPPRESS_UNUSED_TEMPLATE_WARNINGS \+        template<typename TestType> \+        struct TestName : INTERNAL_CATCH_REMOVE_PARENS(ClassName <TestType>) { \+            void test();\+        };\+        namespace {\+        namespace INTERNAL_CATCH_MAKE_NAMESPACE(TestName){ \+            INTERNAL_CATCH_TYPE_GEN\+            template<typename...Types>\+            struct TestNameClass{\+                void reg_tests(){\+                    int index = 0;\+                    using expander = int[];\+                    (void)expander{(Catch::AutoReg( Catch::makeTestInvoker( &TestName<Types>::test ), CATCH_INTERNAL_LINEINFO, #ClassName, Catch::NameAndTags{ Name " - " + std::string(INTERNAL_CATCH_STRINGIZE(TmplList)) + " - " + std::to_string(index), Tags } ), index++)... };/* NOLINT */ \+                }\+            };\+            static int INTERNAL_CATCH_UNIQUE_NAME( globalRegistrar ) = [](){\+                using TestInit = typename convert<TestNameClass, TmplList>::type;\+                TestInit t;\+                t.reg_tests();\+                return 0;\+            }(); \+        }}\+        CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \+        template<typename TestType> \+        void TestName<TestType>::test()++#define INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD(ClassName, Name, Tags, TmplList) \+        INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD_2( INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____ ), INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_M_P_L_A_T_E____T_E_S_T____F_U_N_C____ ), ClassName, Name, Tags, TmplList )++// end catch_test_registry.h+// start catch_capture.hpp++// start catch_assertionhandler.h++// start catch_assertioninfo.h++// start catch_result_type.h++namespace Catch {++    // ResultWas::OfType enum+    struct ResultWas { enum OfType {+        Unknown = -1,+        Ok = 0,+        Info = 1,+        Warning = 2,++        FailureBit = 0x10,++        ExpressionFailed = FailureBit | 1,+        ExplicitFailure = FailureBit | 2,++        Exception = 0x100 | FailureBit,++        ThrewException = Exception | 1,+        DidntThrowException = Exception | 2,++        FatalErrorCondition = 0x200 | FailureBit++    }; };++    bool isOk( ResultWas::OfType resultType );+    bool isJustInfo( int flags );++    // ResultDisposition::Flags enum+    struct ResultDisposition { enum Flags {+        Normal = 0x01,++        ContinueOnFailure = 0x02,   // Failures fail test, but execution continues+        FalseTest = 0x04,           // Prefix expression with !+        SuppressFail = 0x08         // Failures are reported but do not fail the test+    }; };++    ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs );++    bool shouldContinueOnFailure( int flags );+    inline bool isFalseTest( int flags ) { return ( flags & ResultDisposition::FalseTest ) != 0; }+    bool shouldSuppressFailure( int flags );++} // end namespace Catch++// end catch_result_type.h+namespace Catch {++    struct AssertionInfo+    {+        StringRef macroName;+        SourceLineInfo lineInfo;+        StringRef capturedExpression;+        ResultDisposition::Flags resultDisposition;++        // We want to delete this constructor but a compiler bug in 4.8 means+        // the struct is then treated as non-aggregate+        //AssertionInfo() = delete;+    };++} // end namespace Catch++// end catch_assertioninfo.h+// start catch_decomposer.h++// start catch_tostring.h++#include <vector>+#include <cstddef>+#include <type_traits>+#include <string>+// start catch_stream.h++#include <iosfwd>+#include <cstddef>+#include <ostream>++namespace Catch {++    std::ostream& cout();+    std::ostream& cerr();+    std::ostream& clog();++    class StringRef;++    struct IStream {+        virtual ~IStream();+        virtual std::ostream& stream() const = 0;+    };++    auto makeStream( StringRef const &filename ) -> IStream const*;++    class ReusableStringStream : NonCopyable {+        std::size_t m_index;+        std::ostream* m_oss;+    public:+        ReusableStringStream();+        ~ReusableStringStream();++        auto str() const -> std::string;++        template<typename T>+        auto operator << ( T const& value ) -> ReusableStringStream& {+            *m_oss << value;+            return *this;+        }+        auto get() -> std::ostream& { return *m_oss; }+    };+}++// end catch_stream.h+// start catch_interfaces_enum_values_registry.h++#include <vector>++namespace Catch {++    namespace Detail {+        struct EnumInfo {+            StringRef m_name;+            std::vector<std::pair<int, StringRef>> m_values;++            ~EnumInfo();++            StringRef lookup( int value ) const;+        };+    } // namespace Detail++    struct IMutableEnumValuesRegistry {+        virtual ~IMutableEnumValuesRegistry();++        virtual Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values ) = 0;++        template<typename E>+        Detail::EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::initializer_list<E> values ) {+            static_assert(sizeof(int) >= sizeof(E), "Cannot serialize enum to int");+            std::vector<int> intValues;+            intValues.reserve( values.size() );+            for( auto enumValue : values )+                intValues.push_back( static_cast<int>( enumValue ) );+            return registerEnum( enumName, allEnums, intValues );+        }+    };++} // Catch++// end catch_interfaces_enum_values_registry.h++#ifdef CATCH_CONFIG_CPP17_STRING_VIEW+#include <string_view>+#endif++#ifdef __OBJC__+// start catch_objc_arc.hpp++#import <Foundation/Foundation.h>++#ifdef __has_feature+#define CATCH_ARC_ENABLED __has_feature(objc_arc)+#else+#define CATCH_ARC_ENABLED 0+#endif++void arcSafeRelease( NSObject* obj );+id performOptionalSelector( id obj, SEL sel );++#if !CATCH_ARC_ENABLED+inline void arcSafeRelease( NSObject* obj ) {+    [obj release];+}+inline id performOptionalSelector( id obj, SEL sel ) {+    if( [obj respondsToSelector: sel] )+        return [obj performSelector: sel];+    return nil;+}+#define CATCH_UNSAFE_UNRETAINED+#define CATCH_ARC_STRONG+#else+inline void arcSafeRelease( NSObject* ){}+inline id performOptionalSelector( id obj, SEL sel ) {+#ifdef __clang__+#pragma clang diagnostic push+#pragma clang diagnostic ignored "-Warc-performSelector-leaks"+#endif+    if( [obj respondsToSelector: sel] )+        return [obj performSelector: sel];+#ifdef __clang__+#pragma clang diagnostic pop+#endif+    return nil;+}+#define CATCH_UNSAFE_UNRETAINED __unsafe_unretained+#define CATCH_ARC_STRONG __strong+#endif++// end catch_objc_arc.hpp+#endif++#ifdef _MSC_VER+#pragma warning(push)+#pragma warning(disable:4180) // We attempt to stream a function (address) by const&, which MSVC complains about but is harmless+#endif++namespace Catch {+    namespace Detail {++        extern const std::string unprintableString;++        std::string rawMemoryToString( const void *object, std::size_t size );++        template<typename T>+        std::string rawMemoryToString( const T& object ) {+          return rawMemoryToString( &object, sizeof(object) );+        }++        template<typename T>+        class IsStreamInsertable {+            template<typename Stream, typename U>+            static auto test(int)+                -> decltype(std::declval<Stream&>() << std::declval<U>(), std::true_type());++            template<typename, typename>+            static auto test(...)->std::false_type;++        public:+            static const bool value = decltype(test<std::ostream, const T&>(0))::value;+        };++        template<typename E>+        std::string convertUnknownEnumToString( E e );++        template<typename T>+        typename std::enable_if<+            !std::is_enum<T>::value && !std::is_base_of<std::exception, T>::value,+        std::string>::type convertUnstreamable( T const& ) {+            return Detail::unprintableString;+        }+        template<typename T>+        typename std::enable_if<+            !std::is_enum<T>::value && std::is_base_of<std::exception, T>::value,+         std::string>::type convertUnstreamable(T const& ex) {+            return ex.what();+        }++        template<typename T>+        typename std::enable_if<+            std::is_enum<T>::value+        , std::string>::type convertUnstreamable( T const& value ) {+            return convertUnknownEnumToString( value );+        }++#if defined(_MANAGED)+        //! Convert a CLR string to a utf8 std::string+        template<typename T>+        std::string clrReferenceToString( T^ ref ) {+            if (ref == nullptr)+                return std::string("null");+            auto bytes = System::Text::Encoding::UTF8->GetBytes(ref->ToString());+            cli::pin_ptr<System::Byte> p = &bytes[0];+            return std::string(reinterpret_cast<char const *>(p), bytes->Length);+        }+#endif++    } // namespace Detail++    // If we decide for C++14, change these to enable_if_ts+    template <typename T, typename = void>+    struct StringMaker {+        template <typename Fake = T>+        static+        typename std::enable_if<::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type+            convert(const Fake& value) {+                ReusableStringStream rss;+                // NB: call using the function-like syntax to avoid ambiguity with+                // user-defined templated operator<< under clang.+                rss.operator<<(value);+                return rss.str();+        }++        template <typename Fake = T>+        static+        typename std::enable_if<!::Catch::Detail::IsStreamInsertable<Fake>::value, std::string>::type+            convert( const Fake& value ) {+#if !defined(CATCH_CONFIG_FALLBACK_STRINGIFIER)+            return Detail::convertUnstreamable(value);+#else+            return CATCH_CONFIG_FALLBACK_STRINGIFIER(value);+#endif+        }+    };++    namespace Detail {++        // This function dispatches all stringification requests inside of Catch.+        // Should be preferably called fully qualified, like ::Catch::Detail::stringify+        template <typename T>+        std::string stringify(const T& e) {+            return ::Catch::StringMaker<typename std::remove_cv<typename std::remove_reference<T>::type>::type>::convert(e);+        }++        template<typename E>+        std::string convertUnknownEnumToString( E e ) {+            return ::Catch::Detail::stringify(static_cast<typename std::underlying_type<E>::type>(e));+        }++#if defined(_MANAGED)+        template <typename T>+        std::string stringify( T^ e ) {+            return ::Catch::StringMaker<T^>::convert(e);+        }+#endif++    } // namespace Detail++    // Some predefined specializations++    template<>+    struct StringMaker<std::string> {+        static std::string convert(const std::string& str);+    };++#ifdef CATCH_CONFIG_CPP17_STRING_VIEW+    template<>+    struct StringMaker<std::string_view> {+        static std::string convert(std::string_view str);+    };+#endif++    template<>+    struct StringMaker<char const *> {+        static std::string convert(char const * str);+    };+    template<>+    struct StringMaker<char *> {+        static std::string convert(char * str);+    };++#ifdef CATCH_CONFIG_WCHAR+    template<>+    struct StringMaker<std::wstring> {+        static std::string convert(const std::wstring& wstr);+    };++# ifdef CATCH_CONFIG_CPP17_STRING_VIEW+    template<>+    struct StringMaker<std::wstring_view> {+        static std::string convert(std::wstring_view str);+    };+# endif++    template<>+    struct StringMaker<wchar_t const *> {+        static std::string convert(wchar_t const * str);+    };+    template<>+    struct StringMaker<wchar_t *> {+        static std::string convert(wchar_t * str);+    };+#endif++    // TBD: Should we use `strnlen` to ensure that we don't go out of the buffer,+    //      while keeping string semantics?+    template<int SZ>+    struct StringMaker<char[SZ]> {+        static std::string convert(char const* str) {+            return ::Catch::Detail::stringify(std::string{ str });+        }+    };+    template<int SZ>+    struct StringMaker<signed char[SZ]> {+        static std::string convert(signed char const* str) {+            return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });+        }+    };+    template<int SZ>+    struct StringMaker<unsigned char[SZ]> {+        static std::string convert(unsigned char const* str) {+            return ::Catch::Detail::stringify(std::string{ reinterpret_cast<char const *>(str) });+        }+    };++#if defined(CATCH_CONFIG_CPP17_BYTE)+    template<>+    struct StringMaker<std::byte> {+        static std::string convert(std::byte value);+    };+#endif // defined(CATCH_CONFIG_CPP17_BYTE)+    template<>+    struct StringMaker<int> {+        static std::string convert(int value);+    };+    template<>+    struct StringMaker<long> {+        static std::string convert(long value);+    };+    template<>+    struct StringMaker<long long> {+        static std::string convert(long long value);+    };+    template<>+    struct StringMaker<unsigned int> {+        static std::string convert(unsigned int value);+    };+    template<>+    struct StringMaker<unsigned long> {+        static std::string convert(unsigned long value);+    };+    template<>+    struct StringMaker<unsigned long long> {+        static std::string convert(unsigned long long value);+    };++    template<>+    struct StringMaker<bool> {+        static std::string convert(bool b);+    };++    template<>+    struct StringMaker<char> {+        static std::string convert(char c);+    };+    template<>+    struct StringMaker<signed char> {+        static std::string convert(signed char c);+    };+    template<>+    struct StringMaker<unsigned char> {+        static std::string convert(unsigned char c);+    };++    template<>+    struct StringMaker<std::nullptr_t> {+        static std::string convert(std::nullptr_t);+    };++    template<>+    struct StringMaker<float> {+        static std::string convert(float value);+        static int precision;+    };++    template<>+    struct StringMaker<double> {+        static std::string convert(double value);+        static int precision;+    };++    template <typename T>+    struct StringMaker<T*> {+        template <typename U>+        static std::string convert(U* p) {+            if (p) {+                return ::Catch::Detail::rawMemoryToString(p);+            } else {+                return "nullptr";+            }+        }+    };++    template <typename R, typename C>+    struct StringMaker<R C::*> {+        static std::string convert(R C::* p) {+            if (p) {+                return ::Catch::Detail::rawMemoryToString(p);+            } else {+                return "nullptr";+            }+        }+    };++#if defined(_MANAGED)+    template <typename T>+    struct StringMaker<T^> {+        static std::string convert( T^ ref ) {+            return ::Catch::Detail::clrReferenceToString(ref);+        }+    };+#endif++    namespace Detail {+        template<typename InputIterator, typename Sentinel = InputIterator>+        std::string rangeToString(InputIterator first, Sentinel last) {+            ReusableStringStream rss;+            rss << "{ ";+            if (first != last) {+                rss << ::Catch::Detail::stringify(*first);+                for (++first; first != last; ++first)+                    rss << ", " << ::Catch::Detail::stringify(*first);+            }+            rss << " }";+            return rss.str();+        }+    }++#ifdef __OBJC__+    template<>+    struct StringMaker<NSString*> {+        static std::string convert(NSString * nsstring) {+            if (!nsstring)+                return "nil";+            return std::string("@") + [nsstring UTF8String];+        }+    };+    template<>+    struct StringMaker<NSObject*> {+        static std::string convert(NSObject* nsObject) {+            return ::Catch::Detail::stringify([nsObject description]);+        }++    };+    namespace Detail {+        inline std::string stringify( NSString* nsstring ) {+            return StringMaker<NSString*>::convert( nsstring );+        }++    } // namespace Detail+#endif // __OBJC__++} // namespace Catch++//////////////////////////////////////////////////////+// Separate std-lib types stringification, so it can be selectively enabled+// This means that we do not bring in++#if defined(CATCH_CONFIG_ENABLE_ALL_STRINGMAKERS)+#  define CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER+#  define CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER+#  define CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER+#  define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER+#  define CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER+#endif++// Separate std::pair specialization+#if defined(CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER)+#include <utility>+namespace Catch {+    template<typename T1, typename T2>+    struct StringMaker<std::pair<T1, T2> > {+        static std::string convert(const std::pair<T1, T2>& pair) {+            ReusableStringStream rss;+            rss << "{ "+                << ::Catch::Detail::stringify(pair.first)+                << ", "+                << ::Catch::Detail::stringify(pair.second)+                << " }";+            return rss.str();+        }+    };+}+#endif // CATCH_CONFIG_ENABLE_PAIR_STRINGMAKER++#if defined(CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_OPTIONAL)+#include <optional>+namespace Catch {+    template<typename T>+    struct StringMaker<std::optional<T> > {+        static std::string convert(const std::optional<T>& optional) {+            ReusableStringStream rss;+            if (optional.has_value()) {+                rss << ::Catch::Detail::stringify(*optional);+            } else {+                rss << "{ }";+            }+            return rss.str();+        }+    };+}+#endif // CATCH_CONFIG_ENABLE_OPTIONAL_STRINGMAKER++// Separate std::tuple specialization+#if defined(CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER)+#include <tuple>+namespace Catch {+    namespace Detail {+        template<+            typename Tuple,+            std::size_t N = 0,+            bool = (N < std::tuple_size<Tuple>::value)+            >+            struct TupleElementPrinter {+            static void print(const Tuple& tuple, std::ostream& os) {+                os << (N ? ", " : " ")+                    << ::Catch::Detail::stringify(std::get<N>(tuple));+                TupleElementPrinter<Tuple, N + 1>::print(tuple, os);+            }+        };++        template<+            typename Tuple,+            std::size_t N+        >+            struct TupleElementPrinter<Tuple, N, false> {+            static void print(const Tuple&, std::ostream&) {}+        };++    }++    template<typename ...Types>+    struct StringMaker<std::tuple<Types...>> {+        static std::string convert(const std::tuple<Types...>& tuple) {+            ReusableStringStream rss;+            rss << '{';+            Detail::TupleElementPrinter<std::tuple<Types...>>::print(tuple, rss.get());+            rss << " }";+            return rss.str();+        }+    };+}+#endif // CATCH_CONFIG_ENABLE_TUPLE_STRINGMAKER++#if defined(CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER) && defined(CATCH_CONFIG_CPP17_VARIANT)+#include <variant>+namespace Catch {+    template<>+    struct StringMaker<std::monostate> {+        static std::string convert(const std::monostate&) {+            return "{ }";+        }+    };++    template<typename... Elements>+    struct StringMaker<std::variant<Elements...>> {+        static std::string convert(const std::variant<Elements...>& variant) {+            if (variant.valueless_by_exception()) {+                return "{valueless variant}";+            } else {+                return std::visit(+                    [](const auto& value) {+                        return ::Catch::Detail::stringify(value);+                    },+                    variant+                );+            }+        }+    };+}+#endif // CATCH_CONFIG_ENABLE_VARIANT_STRINGMAKER++namespace Catch {+    // Import begin/ end from std here+    using std::begin;+    using std::end;++    namespace detail {+        template <typename...>+        struct void_type {+            using type = void;+        };++        template <typename T, typename = void>+        struct is_range_impl : std::false_type {+        };++        template <typename T>+        struct is_range_impl<T, typename void_type<decltype(begin(std::declval<T>()))>::type> : std::true_type {+        };+    } // namespace detail++    template <typename T>+    struct is_range : detail::is_range_impl<T> {+    };++#if defined(_MANAGED) // Managed types are never ranges+    template <typename T>+    struct is_range<T^> {+        static const bool value = false;+    };+#endif++    template<typename Range>+    std::string rangeToString( Range const& range ) {+        return ::Catch::Detail::rangeToString( begin( range ), end( range ) );+    }++    // Handle vector<bool> specially+    template<typename Allocator>+    std::string rangeToString( std::vector<bool, Allocator> const& v ) {+        ReusableStringStream rss;+        rss << "{ ";+        bool first = true;+        for( bool b : v ) {+            if( first )+                first = false;+            else+                rss << ", ";+            rss << ::Catch::Detail::stringify( b );+        }+        rss << " }";+        return rss.str();+    }++    template<typename R>+    struct StringMaker<R, typename std::enable_if<is_range<R>::value && !::Catch::Detail::IsStreamInsertable<R>::value>::type> {+        static std::string convert( R const& range ) {+            return rangeToString( range );+        }+    };++    template <typename T, int SZ>+    struct StringMaker<T[SZ]> {+        static std::string convert(T const(&arr)[SZ]) {+            return rangeToString(arr);+        }+    };++} // namespace Catch++// Separate std::chrono::duration specialization+#if defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)+#include <ctime>+#include <ratio>+#include <chrono>++namespace Catch {++template <class Ratio>+struct ratio_string {+    static std::string symbol();+};++template <class Ratio>+std::string ratio_string<Ratio>::symbol() {+    Catch::ReusableStringStream rss;+    rss << '[' << Ratio::num << '/'+        << Ratio::den << ']';+    return rss.str();+}+template <>+struct ratio_string<std::atto> {+    static std::string symbol();+};+template <>+struct ratio_string<std::femto> {+    static std::string symbol();+};+template <>+struct ratio_string<std::pico> {+    static std::string symbol();+};+template <>+struct ratio_string<std::nano> {+    static std::string symbol();+};+template <>+struct ratio_string<std::micro> {+    static std::string symbol();+};+template <>+struct ratio_string<std::milli> {+    static std::string symbol();+};++    ////////////+    // std::chrono::duration specializations+    template<typename Value, typename Ratio>+    struct StringMaker<std::chrono::duration<Value, Ratio>> {+        static std::string convert(std::chrono::duration<Value, Ratio> const& duration) {+            ReusableStringStream rss;+            rss << duration.count() << ' ' << ratio_string<Ratio>::symbol() << 's';+            return rss.str();+        }+    };+    template<typename Value>+    struct StringMaker<std::chrono::duration<Value, std::ratio<1>>> {+        static std::string convert(std::chrono::duration<Value, std::ratio<1>> const& duration) {+            ReusableStringStream rss;+            rss << duration.count() << " s";+            return rss.str();+        }+    };+    template<typename Value>+    struct StringMaker<std::chrono::duration<Value, std::ratio<60>>> {+        static std::string convert(std::chrono::duration<Value, std::ratio<60>> const& duration) {+            ReusableStringStream rss;+            rss << duration.count() << " m";+            return rss.str();+        }+    };+    template<typename Value>+    struct StringMaker<std::chrono::duration<Value, std::ratio<3600>>> {+        static std::string convert(std::chrono::duration<Value, std::ratio<3600>> const& duration) {+            ReusableStringStream rss;+            rss << duration.count() << " h";+            return rss.str();+        }+    };++    ////////////+    // std::chrono::time_point specialization+    // Generic time_point cannot be specialized, only std::chrono::time_point<system_clock>+    template<typename Clock, typename Duration>+    struct StringMaker<std::chrono::time_point<Clock, Duration>> {+        static std::string convert(std::chrono::time_point<Clock, Duration> const& time_point) {+            return ::Catch::Detail::stringify(time_point.time_since_epoch()) + " since epoch";+        }+    };+    // std::chrono::time_point<system_clock> specialization+    template<typename Duration>+    struct StringMaker<std::chrono::time_point<std::chrono::system_clock, Duration>> {+        static std::string convert(std::chrono::time_point<std::chrono::system_clock, Duration> const& time_point) {+            auto converted = std::chrono::system_clock::to_time_t(time_point);++#ifdef _MSC_VER+            std::tm timeInfo = {};+            gmtime_s(&timeInfo, &converted);+#else+            std::tm* timeInfo = std::gmtime(&converted);+#endif++            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");+            char timeStamp[timeStampSize];+            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";++#ifdef _MSC_VER+            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);+#else+            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);+#endif+            return std::string(timeStamp);+        }+    };+}+#endif // CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER++#define INTERNAL_CATCH_REGISTER_ENUM( enumName, ... ) \+namespace Catch { \+    template<> struct StringMaker<enumName> { \+        static std::string convert( enumName value ) { \+            static const auto& enumInfo = ::Catch::getMutableRegistryHub().getMutableEnumValuesRegistry().registerEnum( #enumName, #__VA_ARGS__, { __VA_ARGS__ } ); \+            return static_cast<std::string>(enumInfo.lookup( static_cast<int>( value ) )); \+        } \+    }; \+}++#define CATCH_REGISTER_ENUM( enumName, ... ) INTERNAL_CATCH_REGISTER_ENUM( enumName, __VA_ARGS__ )++#ifdef _MSC_VER+#pragma warning(pop)+#endif++// end catch_tostring.h+#include <iosfwd>++#ifdef _MSC_VER+#pragma warning(push)+#pragma warning(disable:4389) // '==' : signed/unsigned mismatch+#pragma warning(disable:4018) // more "signed/unsigned mismatch"+#pragma warning(disable:4312) // Converting int to T* using reinterpret_cast (issue on x64 platform)+#pragma warning(disable:4180) // qualifier applied to function type has no meaning+#pragma warning(disable:4800) // Forcing result to true or false+#endif++namespace Catch {++    struct ITransientExpression {+        auto isBinaryExpression() const -> bool { return m_isBinaryExpression; }+        auto getResult() const -> bool { return m_result; }+        virtual void streamReconstructedExpression( std::ostream &os ) const = 0;++        ITransientExpression( bool isBinaryExpression, bool result )+        :   m_isBinaryExpression( isBinaryExpression ),+            m_result( result )+        {}++        // We don't actually need a virtual destructor, but many static analysers+        // complain if it's not here :-(+        virtual ~ITransientExpression();++        bool m_isBinaryExpression;+        bool m_result;++    };++    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs );++    template<typename LhsT, typename RhsT>+    class BinaryExpr  : public ITransientExpression {+        LhsT m_lhs;+        StringRef m_op;+        RhsT m_rhs;++        void streamReconstructedExpression( std::ostream &os ) const override {+            formatReconstructedExpression+                    ( os, Catch::Detail::stringify( m_lhs ), m_op, Catch::Detail::stringify( m_rhs ) );+        }++    public:+        BinaryExpr( bool comparisonResult, LhsT lhs, StringRef op, RhsT rhs )+        :   ITransientExpression{ true, comparisonResult },+            m_lhs( lhs ),+            m_op( op ),+            m_rhs( rhs )+        {}++        template<typename T>+        auto operator && ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<T>::value,+            "chained comparisons are not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }++        template<typename T>+        auto operator || ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<T>::value,+            "chained comparisons are not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }++        template<typename T>+        auto operator == ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<T>::value,+            "chained comparisons are not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }++        template<typename T>+        auto operator != ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<T>::value,+            "chained comparisons are not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }++        template<typename T>+        auto operator > ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<T>::value,+            "chained comparisons are not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }++        template<typename T>+        auto operator < ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<T>::value,+            "chained comparisons are not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }++        template<typename T>+        auto operator >= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<T>::value,+            "chained comparisons are not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }++        template<typename T>+        auto operator <= ( T ) const -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<T>::value,+            "chained comparisons are not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }+    };++    template<typename LhsT>+    class UnaryExpr : public ITransientExpression {+        LhsT m_lhs;++        void streamReconstructedExpression( std::ostream &os ) const override {+            os << Catch::Detail::stringify( m_lhs );+        }++    public:+        explicit UnaryExpr( LhsT lhs )+        :   ITransientExpression{ false, static_cast<bool>(lhs) },+            m_lhs( lhs )+        {}+    };++    // Specialised comparison functions to handle equality comparisons between ints and pointers (NULL deduces as an int)+    template<typename LhsT, typename RhsT>+    auto compareEqual( LhsT const& lhs, RhsT const& rhs ) -> bool { return static_cast<bool>(lhs == rhs); }+    template<typename T>+    auto compareEqual( T* const& lhs, int rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }+    template<typename T>+    auto compareEqual( T* const& lhs, long rhs ) -> bool { return lhs == reinterpret_cast<void const*>( rhs ); }+    template<typename T>+    auto compareEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }+    template<typename T>+    auto compareEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) == rhs; }++    template<typename LhsT, typename RhsT>+    auto compareNotEqual( LhsT const& lhs, RhsT&& rhs ) -> bool { return static_cast<bool>(lhs != rhs); }+    template<typename T>+    auto compareNotEqual( T* const& lhs, int rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }+    template<typename T>+    auto compareNotEqual( T* const& lhs, long rhs ) -> bool { return lhs != reinterpret_cast<void const*>( rhs ); }+    template<typename T>+    auto compareNotEqual( int lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }+    template<typename T>+    auto compareNotEqual( long lhs, T* const& rhs ) -> bool { return reinterpret_cast<void const*>( lhs ) != rhs; }++    template<typename LhsT>+    class ExprLhs {+        LhsT m_lhs;+    public:+        explicit ExprLhs( LhsT lhs ) : m_lhs( lhs ) {}++        template<typename RhsT>+        auto operator == ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {+            return { compareEqual( m_lhs, rhs ), m_lhs, "==", rhs };+        }+        auto operator == ( bool rhs ) -> BinaryExpr<LhsT, bool> const {+            return { m_lhs == rhs, m_lhs, "==", rhs };+        }++        template<typename RhsT>+        auto operator != ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {+            return { compareNotEqual( m_lhs, rhs ), m_lhs, "!=", rhs };+        }+        auto operator != ( bool rhs ) -> BinaryExpr<LhsT, bool> const {+            return { m_lhs != rhs, m_lhs, "!=", rhs };+        }++        template<typename RhsT>+        auto operator > ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {+            return { static_cast<bool>(m_lhs > rhs), m_lhs, ">", rhs };+        }+        template<typename RhsT>+        auto operator < ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {+            return { static_cast<bool>(m_lhs < rhs), m_lhs, "<", rhs };+        }+        template<typename RhsT>+        auto operator >= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {+            return { static_cast<bool>(m_lhs >= rhs), m_lhs, ">=", rhs };+        }+        template<typename RhsT>+        auto operator <= ( RhsT const& rhs ) -> BinaryExpr<LhsT, RhsT const&> const {+            return { static_cast<bool>(m_lhs <= rhs), m_lhs, "<=", rhs };+        }+        template <typename RhsT>+        auto operator | (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {+            return { static_cast<bool>(m_lhs | rhs), m_lhs, "|", rhs };+        }+        template <typename RhsT>+        auto operator & (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {+            return { static_cast<bool>(m_lhs & rhs), m_lhs, "&", rhs };+        }+        template <typename RhsT>+        auto operator ^ (RhsT const& rhs) -> BinaryExpr<LhsT, RhsT const&> const {+            return { static_cast<bool>(m_lhs ^ rhs), m_lhs, "^", rhs };+        }++        template<typename RhsT>+        auto operator && ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<RhsT>::value,+            "operator&& is not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }++        template<typename RhsT>+        auto operator || ( RhsT const& ) -> BinaryExpr<LhsT, RhsT const&> const {+            static_assert(always_false<RhsT>::value,+            "operator|| is not supported inside assertions, "+            "wrap the expression inside parentheses, or decompose it");+        }++        auto makeUnaryExpr() const -> UnaryExpr<LhsT> {+            return UnaryExpr<LhsT>{ m_lhs };+        }+    };++    void handleExpression( ITransientExpression const& expr );++    template<typename T>+    void handleExpression( ExprLhs<T> const& expr ) {+        handleExpression( expr.makeUnaryExpr() );+    }++    struct Decomposer {+        template<typename T>+        auto operator <= ( T const& lhs ) -> ExprLhs<T const&> {+            return ExprLhs<T const&>{ lhs };+        }++        auto operator <=( bool value ) -> ExprLhs<bool> {+            return ExprLhs<bool>{ value };+        }+    };++} // end namespace Catch++#ifdef _MSC_VER+#pragma warning(pop)+#endif++// end catch_decomposer.h+// start catch_interfaces_capture.h++#include <string>+#include <chrono>++namespace Catch {++    class AssertionResult;+    struct AssertionInfo;+    struct SectionInfo;+    struct SectionEndInfo;+    struct MessageInfo;+    struct MessageBuilder;+    struct Counts;+    struct AssertionReaction;+    struct SourceLineInfo;++    struct ITransientExpression;+    struct IGeneratorTracker;++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+    struct BenchmarkInfo;+    template <typename Duration = std::chrono::duration<double, std::nano>>+    struct BenchmarkStats;+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++    struct IResultCapture {++        virtual ~IResultCapture();++        virtual bool sectionStarted(    SectionInfo const& sectionInfo,+                                        Counts& assertions ) = 0;+        virtual void sectionEnded( SectionEndInfo const& endInfo ) = 0;+        virtual void sectionEndedEarly( SectionEndInfo const& endInfo ) = 0;++        virtual auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& = 0;++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+        virtual void benchmarkPreparing( std::string const& name ) = 0;+        virtual void benchmarkStarting( BenchmarkInfo const& info ) = 0;+        virtual void benchmarkEnded( BenchmarkStats<> const& stats ) = 0;+        virtual void benchmarkFailed( std::string const& error ) = 0;+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++        virtual void pushScopedMessage( MessageInfo const& message ) = 0;+        virtual void popScopedMessage( MessageInfo const& message ) = 0;++        virtual void emplaceUnscopedMessage( MessageBuilder const& builder ) = 0;++        virtual void handleFatalErrorCondition( StringRef message ) = 0;++        virtual void handleExpr+                (   AssertionInfo const& info,+                    ITransientExpression const& expr,+                    AssertionReaction& reaction ) = 0;+        virtual void handleMessage+                (   AssertionInfo const& info,+                    ResultWas::OfType resultType,+                    StringRef const& message,+                    AssertionReaction& reaction ) = 0;+        virtual void handleUnexpectedExceptionNotThrown+                (   AssertionInfo const& info,+                    AssertionReaction& reaction ) = 0;+        virtual void handleUnexpectedInflightException+                (   AssertionInfo const& info,+                    std::string const& message,+                    AssertionReaction& reaction ) = 0;+        virtual void handleIncomplete+                (   AssertionInfo const& info ) = 0;+        virtual void handleNonExpr+                (   AssertionInfo const &info,+                    ResultWas::OfType resultType,+                    AssertionReaction &reaction ) = 0;++        virtual bool lastAssertionPassed() = 0;+        virtual void assertionPassed() = 0;++        // Deprecated, do not use:+        virtual std::string getCurrentTestName() const = 0;+        virtual const AssertionResult* getLastResult() const = 0;+        virtual void exceptionEarlyReported() = 0;+    };++    IResultCapture& getResultCapture();+}++// end catch_interfaces_capture.h+namespace Catch {++    struct TestFailureException{};+    struct AssertionResultData;+    struct IResultCapture;+    class RunContext;++    class LazyExpression {+        friend class AssertionHandler;+        friend struct AssertionStats;+        friend class RunContext;++        ITransientExpression const* m_transientExpression = nullptr;+        bool m_isNegated;+    public:+        LazyExpression( bool isNegated );+        LazyExpression( LazyExpression const& other );+        LazyExpression& operator = ( LazyExpression const& ) = delete;++        explicit operator bool() const;++        friend auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream&;+    };++    struct AssertionReaction {+        bool shouldDebugBreak = false;+        bool shouldThrow = false;+    };++    class AssertionHandler {+        AssertionInfo m_assertionInfo;+        AssertionReaction m_reaction;+        bool m_completed = false;+        IResultCapture& m_resultCapture;++    public:+        AssertionHandler+            (   StringRef const& macroName,+                SourceLineInfo const& lineInfo,+                StringRef capturedExpression,+                ResultDisposition::Flags resultDisposition );+        ~AssertionHandler() {+            if ( !m_completed ) {+                m_resultCapture.handleIncomplete( m_assertionInfo );+            }+        }++        template<typename T>+        void handleExpr( ExprLhs<T> const& expr ) {+            handleExpr( expr.makeUnaryExpr() );+        }+        void handleExpr( ITransientExpression const& expr );++        void handleMessage(ResultWas::OfType resultType, StringRef const& message);++        void handleExceptionThrownAsExpected();+        void handleUnexpectedExceptionNotThrown();+        void handleExceptionNotThrownAsExpected();+        void handleThrowingCallSkipped();+        void handleUnexpectedInflightException();++        void complete();+        void setCompleted();++        // query+        auto allowThrows() const -> bool;+    };++    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString );++} // namespace Catch++// end catch_assertionhandler.h+// start catch_message.h++#include <string>+#include <vector>++namespace Catch {++    struct MessageInfo {+        MessageInfo(    StringRef const& _macroName,+                        SourceLineInfo const& _lineInfo,+                        ResultWas::OfType _type );++        StringRef macroName;+        std::string message;+        SourceLineInfo lineInfo;+        ResultWas::OfType type;+        unsigned int sequence;++        bool operator == ( MessageInfo const& other ) const;+        bool operator < ( MessageInfo const& other ) const;+    private:+        static unsigned int globalCount;+    };++    struct MessageStream {++        template<typename T>+        MessageStream& operator << ( T const& value ) {+            m_stream << value;+            return *this;+        }++        ReusableStringStream m_stream;+    };++    struct MessageBuilder : MessageStream {+        MessageBuilder( StringRef const& macroName,+                        SourceLineInfo const& lineInfo,+                        ResultWas::OfType type );++        template<typename T>+        MessageBuilder& operator << ( T const& value ) {+            m_stream << value;+            return *this;+        }++        MessageInfo m_info;+    };++    class ScopedMessage {+    public:+        explicit ScopedMessage( MessageBuilder const& builder );+        ScopedMessage( ScopedMessage& duplicate ) = delete;+        ScopedMessage( ScopedMessage&& old );+        ~ScopedMessage();++        MessageInfo m_info;+        bool m_moved;+    };++    class Capturer {+        std::vector<MessageInfo> m_messages;+        IResultCapture& m_resultCapture = getResultCapture();+        size_t m_captured = 0;+    public:+        Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names );+        ~Capturer();++        void captureValue( size_t index, std::string const& value );++        template<typename T>+        void captureValues( size_t index, T const& value ) {+            captureValue( index, Catch::Detail::stringify( value ) );+        }++        template<typename T, typename... Ts>+        void captureValues( size_t index, T const& value, Ts const&... values ) {+            captureValue( index, Catch::Detail::stringify(value) );+            captureValues( index+1, values... );+        }+    };++} // end namespace Catch++// end catch_message.h+#if !defined(CATCH_CONFIG_DISABLE)++#if !defined(CATCH_CONFIG_DISABLE_STRINGIFICATION)+  #define CATCH_INTERNAL_STRINGIFY(...) #__VA_ARGS__+#else+  #define CATCH_INTERNAL_STRINGIFY(...) "Disabled by CATCH_CONFIG_DISABLE_STRINGIFICATION"+#endif++#if defined(CATCH_CONFIG_FAST_COMPILE) || defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)++///////////////////////////////////////////////////////////////////////////////+// Another way to speed-up compilation is to omit local try-catch for REQUIRE*+// macros.+#define INTERNAL_CATCH_TRY+#define INTERNAL_CATCH_CATCH( capturer )++#else // CATCH_CONFIG_FAST_COMPILE++#define INTERNAL_CATCH_TRY try+#define INTERNAL_CATCH_CATCH( handler ) catch(...) { handler.handleUnexpectedInflightException(); }++#endif++#define INTERNAL_CATCH_REACT( handler ) handler.complete();++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_TEST( macroName, resultDisposition, ... ) \+    do { \+        CATCH_INTERNAL_IGNORE_BUT_WARN(__VA_ARGS__); \+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \+        INTERNAL_CATCH_TRY { \+            CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+            CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \+            catchAssertionHandler.handleExpr( Catch::Decomposer() <= __VA_ARGS__ ); \+            CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \+        } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \+    } while( (void)0, (false) && static_cast<bool>( !!(__VA_ARGS__) ) )++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_IF( macroName, resultDisposition, ... ) \+    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \+    if( Catch::getResultCapture().lastAssertionPassed() )++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_ELSE( macroName, resultDisposition, ... ) \+    INTERNAL_CATCH_TEST( macroName, resultDisposition, __VA_ARGS__ ); \+    if( !Catch::getResultCapture().lastAssertionPassed() )++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_NO_THROW( macroName, resultDisposition, ... ) \+    do { \+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition ); \+        try { \+            static_cast<void>(__VA_ARGS__); \+            catchAssertionHandler.handleExceptionNotThrownAsExpected(); \+        } \+        catch( ... ) { \+            catchAssertionHandler.handleUnexpectedInflightException(); \+        } \+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \+    } while( false )++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_THROWS( macroName, resultDisposition, ... ) \+    do { \+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__), resultDisposition); \+        if( catchAssertionHandler.allowThrows() ) \+            try { \+                static_cast<void>(__VA_ARGS__); \+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \+            } \+            catch( ... ) { \+                catchAssertionHandler.handleExceptionThrownAsExpected(); \+            } \+        else \+            catchAssertionHandler.handleThrowingCallSkipped(); \+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \+    } while( false )++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_THROWS_AS( macroName, exceptionType, resultDisposition, expr ) \+    do { \+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(expr) ", " CATCH_INTERNAL_STRINGIFY(exceptionType), resultDisposition ); \+        if( catchAssertionHandler.allowThrows() ) \+            try { \+                static_cast<void>(expr); \+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \+            } \+            catch( exceptionType const& ) { \+                catchAssertionHandler.handleExceptionThrownAsExpected(); \+            } \+            catch( ... ) { \+                catchAssertionHandler.handleUnexpectedInflightException(); \+            } \+        else \+            catchAssertionHandler.handleThrowingCallSkipped(); \+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \+    } while( false )++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_MSG( macroName, messageType, resultDisposition, ... ) \+    do { \+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::StringRef(), resultDisposition ); \+        catchAssertionHandler.handleMessage( messageType, ( Catch::MessageStream() << __VA_ARGS__ + ::Catch::StreamEndStop() ).m_stream.str() ); \+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \+    } while( false )++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_CAPTURE( varName, macroName, ... ) \+    auto varName = Catch::Capturer( macroName, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info, #__VA_ARGS__ ); \+    varName.captureValues( 0, __VA_ARGS__ )++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_INFO( macroName, log ) \+    Catch::ScopedMessage INTERNAL_CATCH_UNIQUE_NAME( scopedMessage )( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log );++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_UNSCOPED_INFO( macroName, log ) \+    Catch::getResultCapture().emplaceUnscopedMessage( Catch::MessageBuilder( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, Catch::ResultWas::Info ) << log )++///////////////////////////////////////////////////////////////////////////////+// Although this is matcher-based, it can be used with just a string+#define INTERNAL_CATCH_THROWS_STR_MATCHES( macroName, resultDisposition, matcher, ... ) \+    do { \+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \+        if( catchAssertionHandler.allowThrows() ) \+            try { \+                static_cast<void>(__VA_ARGS__); \+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \+            } \+            catch( ... ) { \+                Catch::handleExceptionMatchExpr( catchAssertionHandler, matcher, #matcher##_catch_sr ); \+            } \+        else \+            catchAssertionHandler.handleThrowingCallSkipped(); \+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \+    } while( false )++#endif // CATCH_CONFIG_DISABLE++// end catch_capture.hpp+// start catch_section.h++// start catch_section_info.h++// start catch_totals.h++#include <cstddef>++namespace Catch {++    struct Counts {+        Counts operator - ( Counts const& other ) const;+        Counts& operator += ( Counts const& other );++        std::size_t total() const;+        bool allPassed() const;+        bool allOk() const;++        std::size_t passed = 0;+        std::size_t failed = 0;+        std::size_t failedButOk = 0;+    };++    struct Totals {++        Totals operator - ( Totals const& other ) const;+        Totals& operator += ( Totals const& other );++        Totals delta( Totals const& prevTotals ) const;++        int error = 0;+        Counts assertions;+        Counts testCases;+    };+}++// end catch_totals.h+#include <string>++namespace Catch {++    struct SectionInfo {+        SectionInfo+            (   SourceLineInfo const& _lineInfo,+                std::string const& _name );++        // Deprecated+        SectionInfo+            (   SourceLineInfo const& _lineInfo,+                std::string const& _name,+                std::string const& ) : SectionInfo( _lineInfo, _name ) {}++        std::string name;+        std::string description; // !Deprecated: this will always be empty+        SourceLineInfo lineInfo;+    };++    struct SectionEndInfo {+        SectionInfo sectionInfo;+        Counts prevAssertions;+        double durationInSeconds;+    };++} // end namespace Catch++// end catch_section_info.h+// start catch_timer.h++#include <cstdint>++namespace Catch {++    auto getCurrentNanosecondsSinceEpoch() -> uint64_t;+    auto getEstimatedClockResolution() -> uint64_t;++    class Timer {+        uint64_t m_nanoseconds = 0;+    public:+        void start();+        auto getElapsedNanoseconds() const -> uint64_t;+        auto getElapsedMicroseconds() const -> uint64_t;+        auto getElapsedMilliseconds() const -> unsigned int;+        auto getElapsedSeconds() const -> double;+    };++} // namespace Catch++// end catch_timer.h+#include <string>++namespace Catch {++    class Section : NonCopyable {+    public:+        Section( SectionInfo const& info );+        ~Section();++        // This indicates whether the section should be executed or not+        explicit operator bool() const;++    private:+        SectionInfo m_info;++        std::string m_name;+        Counts m_assertions;+        bool m_sectionIncluded;+        Timer m_timer;+    };++} // end namespace Catch++#define INTERNAL_CATCH_SECTION( ... ) \+    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+    CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \+    if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, __VA_ARGS__ ) ) \+    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION++#define INTERNAL_CATCH_DYNAMIC_SECTION( ... ) \+    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+    CATCH_INTERNAL_SUPPRESS_UNUSED_WARNINGS \+    if( Catch::Section const& INTERNAL_CATCH_UNIQUE_NAME( catch_internal_Section ) = Catch::SectionInfo( CATCH_INTERNAL_LINEINFO, (Catch::ReusableStringStream() << __VA_ARGS__).str() ) ) \+    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION++// end catch_section.h+// start catch_interfaces_exception.h++// start catch_interfaces_registry_hub.h++#include <string>+#include <memory>++namespace Catch {++    class TestCase;+    struct ITestCaseRegistry;+    struct IExceptionTranslatorRegistry;+    struct IExceptionTranslator;+    struct IReporterRegistry;+    struct IReporterFactory;+    struct ITagAliasRegistry;+    struct IMutableEnumValuesRegistry;++    class StartupExceptionRegistry;++    using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;++    struct IRegistryHub {+        virtual ~IRegistryHub();++        virtual IReporterRegistry const& getReporterRegistry() const = 0;+        virtual ITestCaseRegistry const& getTestCaseRegistry() const = 0;+        virtual ITagAliasRegistry const& getTagAliasRegistry() const = 0;+        virtual IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const = 0;++        virtual StartupExceptionRegistry const& getStartupExceptionRegistry() const = 0;+    };++    struct IMutableRegistryHub {+        virtual ~IMutableRegistryHub();+        virtual void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) = 0;+        virtual void registerListener( IReporterFactoryPtr const& factory ) = 0;+        virtual void registerTest( TestCase const& testInfo ) = 0;+        virtual void registerTranslator( const IExceptionTranslator* translator ) = 0;+        virtual void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) = 0;+        virtual void registerStartupException() noexcept = 0;+        virtual IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() = 0;+    };++    IRegistryHub const& getRegistryHub();+    IMutableRegistryHub& getMutableRegistryHub();+    void cleanUp();+    std::string translateActiveException();++}++// end catch_interfaces_registry_hub.h+#if defined(CATCH_CONFIG_DISABLE)+    #define INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( translatorName, signature) \+        static std::string translatorName( signature )+#endif++#include <exception>+#include <string>+#include <vector>++namespace Catch {+    using exceptionTranslateFunction = std::string(*)();++    struct IExceptionTranslator;+    using ExceptionTranslators = std::vector<std::unique_ptr<IExceptionTranslator const>>;++    struct IExceptionTranslator {+        virtual ~IExceptionTranslator();+        virtual std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const = 0;+    };++    struct IExceptionTranslatorRegistry {+        virtual ~IExceptionTranslatorRegistry();++        virtual std::string translateActiveException() const = 0;+    };++    class ExceptionTranslatorRegistrar {+        template<typename T>+        class ExceptionTranslator : public IExceptionTranslator {+        public:++            ExceptionTranslator( std::string(*translateFunction)( T& ) )+            : m_translateFunction( translateFunction )+            {}++            std::string translate( ExceptionTranslators::const_iterator it, ExceptionTranslators::const_iterator itEnd ) const override {+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+                return "";+#else+                try {+                    if( it == itEnd )+                        std::rethrow_exception(std::current_exception());+                    else+                        return (*it)->translate( it+1, itEnd );+                }+                catch( T& ex ) {+                    return m_translateFunction( ex );+                }+#endif+            }++        protected:+            std::string(*m_translateFunction)( T& );+        };++    public:+        template<typename T>+        ExceptionTranslatorRegistrar( std::string(*translateFunction)( T& ) ) {+            getMutableRegistryHub().registerTranslator+                ( new ExceptionTranslator<T>( translateFunction ) );+        }+    };+}++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_TRANSLATE_EXCEPTION2( translatorName, signature ) \+    static std::string translatorName( signature ); \+    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION \+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS \+    namespace{ Catch::ExceptionTranslatorRegistrar INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionRegistrar )( &translatorName ); } \+    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION \+    static std::string translatorName( signature )++#define INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION2( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )++// end catch_interfaces_exception.h+// start catch_approx.h++#include <type_traits>++namespace Catch {+namespace Detail {++    class Approx {+    private:+        bool equalityComparisonImpl(double other) const;+        // Validates the new margin (margin >= 0)+        // out-of-line to avoid including stdexcept in the header+        void setMargin(double margin);+        // Validates the new epsilon (0 < epsilon < 1)+        // out-of-line to avoid including stdexcept in the header+        void setEpsilon(double epsilon);++    public:+        explicit Approx ( double value );++        static Approx custom();++        Approx operator-() const;++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        Approx operator()( T const& value ) {+            Approx approx( static_cast<double>(value) );+            approx.m_epsilon = m_epsilon;+            approx.m_margin = m_margin;+            approx.m_scale = m_scale;+            return approx;+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        explicit Approx( T const& value ): Approx(static_cast<double>(value))+        {}++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        friend bool operator == ( const T& lhs, Approx const& rhs ) {+            auto lhs_v = static_cast<double>(lhs);+            return rhs.equalityComparisonImpl(lhs_v);+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        friend bool operator == ( Approx const& lhs, const T& rhs ) {+            return operator==( rhs, lhs );+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        friend bool operator != ( T const& lhs, Approx const& rhs ) {+            return !operator==( lhs, rhs );+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        friend bool operator != ( Approx const& lhs, T const& rhs ) {+            return !operator==( rhs, lhs );+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        friend bool operator <= ( T const& lhs, Approx const& rhs ) {+            return static_cast<double>(lhs) < rhs.m_value || lhs == rhs;+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        friend bool operator <= ( Approx const& lhs, T const& rhs ) {+            return lhs.m_value < static_cast<double>(rhs) || lhs == rhs;+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        friend bool operator >= ( T const& lhs, Approx const& rhs ) {+            return static_cast<double>(lhs) > rhs.m_value || lhs == rhs;+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        friend bool operator >= ( Approx const& lhs, T const& rhs ) {+            return lhs.m_value > static_cast<double>(rhs) || lhs == rhs;+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        Approx& epsilon( T const& newEpsilon ) {+            double epsilonAsDouble = static_cast<double>(newEpsilon);+            setEpsilon(epsilonAsDouble);+            return *this;+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        Approx& margin( T const& newMargin ) {+            double marginAsDouble = static_cast<double>(newMargin);+            setMargin(marginAsDouble);+            return *this;+        }++        template <typename T, typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+        Approx& scale( T const& newScale ) {+            m_scale = static_cast<double>(newScale);+            return *this;+        }++        std::string toString() const;++    private:+        double m_epsilon;+        double m_margin;+        double m_scale;+        double m_value;+    };+} // end namespace Detail++namespace literals {+    Detail::Approx operator "" _a(long double val);+    Detail::Approx operator "" _a(unsigned long long val);+} // end namespace literals++template<>+struct StringMaker<Catch::Detail::Approx> {+    static std::string convert(Catch::Detail::Approx const& value);+};++} // end namespace Catch++// end catch_approx.h+// start catch_string_manip.h++#include <string>+#include <iosfwd>+#include <vector>++namespace Catch {++    bool startsWith( std::string const& s, std::string const& prefix );+    bool startsWith( std::string const& s, char prefix );+    bool endsWith( std::string const& s, std::string const& suffix );+    bool endsWith( std::string const& s, char suffix );+    bool contains( std::string const& s, std::string const& infix );+    void toLowerInPlace( std::string& s );+    std::string toLower( std::string const& s );+    //! Returns a new string without whitespace at the start/end+    std::string trim( std::string const& str );+    //! Returns a substring of the original ref without whitespace. Beware lifetimes!+    StringRef trim(StringRef ref);++    // !!! Be aware, returns refs into original string - make sure original string outlives them+    std::vector<StringRef> splitStringRef( StringRef str, char delimiter );+    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis );++    struct pluralise {+        pluralise( std::size_t count, std::string const& label );++        friend std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser );++        std::size_t m_count;+        std::string m_label;+    };+}++// end catch_string_manip.h+#ifndef CATCH_CONFIG_DISABLE_MATCHERS+// start catch_capture_matchers.h++// start catch_matchers.h++#include <string>+#include <vector>++namespace Catch {+namespace Matchers {+    namespace Impl {++        template<typename ArgT> struct MatchAllOf;+        template<typename ArgT> struct MatchAnyOf;+        template<typename ArgT> struct MatchNotOf;++        class MatcherUntypedBase {+        public:+            MatcherUntypedBase() = default;+            MatcherUntypedBase ( MatcherUntypedBase const& ) = default;+            MatcherUntypedBase& operator = ( MatcherUntypedBase const& ) = delete;+            std::string toString() const;++        protected:+            virtual ~MatcherUntypedBase();+            virtual std::string describe() const = 0;+            mutable std::string m_cachedToString;+        };++#ifdef __clang__+#    pragma clang diagnostic push+#    pragma clang diagnostic ignored "-Wnon-virtual-dtor"+#endif++        template<typename ObjectT>+        struct MatcherMethod {+            virtual bool match( ObjectT const& arg ) const = 0;+        };++#if defined(__OBJC__)+        // Hack to fix Catch GH issue #1661. Could use id for generic Object support.+        // use of const for Object pointers is very uncommon and under ARC it causes some kind of signature mismatch that breaks compilation+        template<>+        struct MatcherMethod<NSString*> {+            virtual bool match( NSString* arg ) const = 0;+        };+#endif++#ifdef __clang__+#    pragma clang diagnostic pop+#endif++        template<typename T>+        struct MatcherBase : MatcherUntypedBase, MatcherMethod<T> {++            MatchAllOf<T> operator && ( MatcherBase const& other ) const;+            MatchAnyOf<T> operator || ( MatcherBase const& other ) const;+            MatchNotOf<T> operator ! () const;+        };++        template<typename ArgT>+        struct MatchAllOf : MatcherBase<ArgT> {+            bool match( ArgT const& arg ) const override {+                for( auto matcher : m_matchers ) {+                    if (!matcher->match(arg))+                        return false;+                }+                return true;+            }+            std::string describe() const override {+                std::string description;+                description.reserve( 4 + m_matchers.size()*32 );+                description += "( ";+                bool first = true;+                for( auto matcher : m_matchers ) {+                    if( first )+                        first = false;+                    else+                        description += " and ";+                    description += matcher->toString();+                }+                description += " )";+                return description;+            }++            MatchAllOf<ArgT> operator && ( MatcherBase<ArgT> const& other ) {+                auto copy(*this);+                copy.m_matchers.push_back( &other );+                return copy;+            }++            std::vector<MatcherBase<ArgT> const*> m_matchers;+        };+        template<typename ArgT>+        struct MatchAnyOf : MatcherBase<ArgT> {++            bool match( ArgT const& arg ) const override {+                for( auto matcher : m_matchers ) {+                    if (matcher->match(arg))+                        return true;+                }+                return false;+            }+            std::string describe() const override {+                std::string description;+                description.reserve( 4 + m_matchers.size()*32 );+                description += "( ";+                bool first = true;+                for( auto matcher : m_matchers ) {+                    if( first )+                        first = false;+                    else+                        description += " or ";+                    description += matcher->toString();+                }+                description += " )";+                return description;+            }++            MatchAnyOf<ArgT> operator || ( MatcherBase<ArgT> const& other ) {+                auto copy(*this);+                copy.m_matchers.push_back( &other );+                return copy;+            }++            std::vector<MatcherBase<ArgT> const*> m_matchers;+        };++        template<typename ArgT>+        struct MatchNotOf : MatcherBase<ArgT> {++            MatchNotOf( MatcherBase<ArgT> const& underlyingMatcher ) : m_underlyingMatcher( underlyingMatcher ) {}++            bool match( ArgT const& arg ) const override {+                return !m_underlyingMatcher.match( arg );+            }++            std::string describe() const override {+                return "not " + m_underlyingMatcher.toString();+            }+            MatcherBase<ArgT> const& m_underlyingMatcher;+        };++        template<typename T>+        MatchAllOf<T> MatcherBase<T>::operator && ( MatcherBase const& other ) const {+            return MatchAllOf<T>() && *this && other;+        }+        template<typename T>+        MatchAnyOf<T> MatcherBase<T>::operator || ( MatcherBase const& other ) const {+            return MatchAnyOf<T>() || *this || other;+        }+        template<typename T>+        MatchNotOf<T> MatcherBase<T>::operator ! () const {+            return MatchNotOf<T>( *this );+        }++    } // namespace Impl++} // namespace Matchers++using namespace Matchers;+using Matchers::Impl::MatcherBase;++} // namespace Catch++// end catch_matchers.h+// start catch_matchers_exception.hpp++namespace Catch {+namespace Matchers {+namespace Exception {++class ExceptionMessageMatcher : public MatcherBase<std::exception> {+    std::string m_message;+public:++    ExceptionMessageMatcher(std::string const& message):+        m_message(message)+    {}++    bool match(std::exception const& ex) const override;++    std::string describe() const override;+};++} // namespace Exception++Exception::ExceptionMessageMatcher Message(std::string const& message);++} // namespace Matchers+} // namespace Catch++// end catch_matchers_exception.hpp+// start catch_matchers_floating.h++namespace Catch {+namespace Matchers {++    namespace Floating {++        enum class FloatingPointKind : uint8_t;++        struct WithinAbsMatcher : MatcherBase<double> {+            WithinAbsMatcher(double target, double margin);+            bool match(double const& matchee) const override;+            std::string describe() const override;+        private:+            double m_target;+            double m_margin;+        };++        struct WithinUlpsMatcher : MatcherBase<double> {+            WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType);+            bool match(double const& matchee) const override;+            std::string describe() const override;+        private:+            double m_target;+            uint64_t m_ulps;+            FloatingPointKind m_type;+        };++        // Given IEEE-754 format for floats and doubles, we can assume+        // that float -> double promotion is lossless. Given this, we can+        // assume that if we do the standard relative comparison of+        // |lhs - rhs| <= epsilon * max(fabs(lhs), fabs(rhs)), then we get+        // the same result if we do this for floats, as if we do this for+        // doubles that were promoted from floats.+        struct WithinRelMatcher : MatcherBase<double> {+            WithinRelMatcher(double target, double epsilon);+            bool match(double const& matchee) const override;+            std::string describe() const override;+        private:+            double m_target;+            double m_epsilon;+        };++    } // namespace Floating++    // The following functions create the actual matcher objects.+    // This allows the types to be inferred+    Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff);+    Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff);+    Floating::WithinAbsMatcher WithinAbs(double target, double margin);+    Floating::WithinRelMatcher WithinRel(double target, double eps);+    // defaults epsilon to 100*numeric_limits<double>::epsilon()+    Floating::WithinRelMatcher WithinRel(double target);+    Floating::WithinRelMatcher WithinRel(float target, float eps);+    // defaults epsilon to 100*numeric_limits<float>::epsilon()+    Floating::WithinRelMatcher WithinRel(float target);++} // namespace Matchers+} // namespace Catch++// end catch_matchers_floating.h+// start catch_matchers_generic.hpp++#include <functional>+#include <string>++namespace Catch {+namespace Matchers {+namespace Generic {++namespace Detail {+    std::string finalizeDescription(const std::string& desc);+}++template <typename T>+class PredicateMatcher : public MatcherBase<T> {+    std::function<bool(T const&)> m_predicate;+    std::string m_description;+public:++    PredicateMatcher(std::function<bool(T const&)> const& elem, std::string const& descr)+        :m_predicate(std::move(elem)),+        m_description(Detail::finalizeDescription(descr))+    {}++    bool match( T const& item ) const override {+        return m_predicate(item);+    }++    std::string describe() const override {+        return m_description;+    }+};++} // namespace Generic++    // The following functions create the actual matcher objects.+    // The user has to explicitly specify type to the function, because+    // inferring std::function<bool(T const&)> is hard (but possible) and+    // requires a lot of TMP.+    template<typename T>+    Generic::PredicateMatcher<T> Predicate(std::function<bool(T const&)> const& predicate, std::string const& description = "") {+        return Generic::PredicateMatcher<T>(predicate, description);+    }++} // namespace Matchers+} // namespace Catch++// end catch_matchers_generic.hpp+// start catch_matchers_string.h++#include <string>++namespace Catch {+namespace Matchers {++    namespace StdString {++        struct CasedString+        {+            CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity );+            std::string adjustString( std::string const& str ) const;+            std::string caseSensitivitySuffix() const;++            CaseSensitive::Choice m_caseSensitivity;+            std::string m_str;+        };++        struct StringMatcherBase : MatcherBase<std::string> {+            StringMatcherBase( std::string const& operation, CasedString const& comparator );+            std::string describe() const override;++            CasedString m_comparator;+            std::string m_operation;+        };++        struct EqualsMatcher : StringMatcherBase {+            EqualsMatcher( CasedString const& comparator );+            bool match( std::string const& source ) const override;+        };+        struct ContainsMatcher : StringMatcherBase {+            ContainsMatcher( CasedString const& comparator );+            bool match( std::string const& source ) const override;+        };+        struct StartsWithMatcher : StringMatcherBase {+            StartsWithMatcher( CasedString const& comparator );+            bool match( std::string const& source ) const override;+        };+        struct EndsWithMatcher : StringMatcherBase {+            EndsWithMatcher( CasedString const& comparator );+            bool match( std::string const& source ) const override;+        };++        struct RegexMatcher : MatcherBase<std::string> {+            RegexMatcher( std::string regex, CaseSensitive::Choice caseSensitivity );+            bool match( std::string const& matchee ) const override;+            std::string describe() const override;++        private:+            std::string m_regex;+            CaseSensitive::Choice m_caseSensitivity;+        };++    } // namespace StdString++    // The following functions create the actual matcher objects.+    // This allows the types to be inferred++    StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );+    StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );+    StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );+    StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );+    StdString::RegexMatcher Matches( std::string const& regex, CaseSensitive::Choice caseSensitivity = CaseSensitive::Yes );++} // namespace Matchers+} // namespace Catch++// end catch_matchers_string.h+// start catch_matchers_vector.h++#include <algorithm>++namespace Catch {+namespace Matchers {++    namespace Vector {+        template<typename T, typename Alloc>+        struct ContainsElementMatcher : MatcherBase<std::vector<T, Alloc>> {++            ContainsElementMatcher(T const &comparator) : m_comparator( comparator) {}++            bool match(std::vector<T, Alloc> const &v) const override {+                for (auto const& el : v) {+                    if (el == m_comparator) {+                        return true;+                    }+                }+                return false;+            }++            std::string describe() const override {+                return "Contains: " + ::Catch::Detail::stringify( m_comparator );+            }++            T const& m_comparator;+        };++        template<typename T, typename AllocComp, typename AllocMatch>+        struct ContainsMatcher : MatcherBase<std::vector<T, AllocMatch>> {++            ContainsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}++            bool match(std::vector<T, AllocMatch> const &v) const override {+                // !TBD: see note in EqualsMatcher+                if (m_comparator.size() > v.size())+                    return false;+                for (auto const& comparator : m_comparator) {+                    auto present = false;+                    for (const auto& el : v) {+                        if (el == comparator) {+                            present = true;+                            break;+                        }+                    }+                    if (!present) {+                        return false;+                    }+                }+                return true;+            }+            std::string describe() const override {+                return "Contains: " + ::Catch::Detail::stringify( m_comparator );+            }++            std::vector<T, AllocComp> const& m_comparator;+        };++        template<typename T, typename AllocComp, typename AllocMatch>+        struct EqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {++            EqualsMatcher(std::vector<T, AllocComp> const &comparator) : m_comparator( comparator ) {}++            bool match(std::vector<T, AllocMatch> const &v) const override {+                // !TBD: This currently works if all elements can be compared using !=+                // - a more general approach would be via a compare template that defaults+                // to using !=. but could be specialised for, e.g. std::vector<T, Alloc> etc+                // - then just call that directly+                if (m_comparator.size() != v.size())+                    return false;+                for (std::size_t i = 0; i < v.size(); ++i)+                    if (m_comparator[i] != v[i])+                        return false;+                return true;+            }+            std::string describe() const override {+                return "Equals: " + ::Catch::Detail::stringify( m_comparator );+            }+            std::vector<T, AllocComp> const& m_comparator;+        };++        template<typename T, typename AllocComp, typename AllocMatch>+        struct ApproxMatcher : MatcherBase<std::vector<T, AllocMatch>> {++            ApproxMatcher(std::vector<T, AllocComp> const& comparator) : m_comparator( comparator ) {}++            bool match(std::vector<T, AllocMatch> const &v) const override {+                if (m_comparator.size() != v.size())+                    return false;+                for (std::size_t i = 0; i < v.size(); ++i)+                    if (m_comparator[i] != approx(v[i]))+                        return false;+                return true;+            }+            std::string describe() const override {+                return "is approx: " + ::Catch::Detail::stringify( m_comparator );+            }+            template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+            ApproxMatcher& epsilon( T const& newEpsilon ) {+                approx.epsilon(newEpsilon);+                return *this;+            }+            template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+            ApproxMatcher& margin( T const& newMargin ) {+                approx.margin(newMargin);+                return *this;+            }+            template <typename = typename std::enable_if<std::is_constructible<double, T>::value>::type>+            ApproxMatcher& scale( T const& newScale ) {+                approx.scale(newScale);+                return *this;+            }++            std::vector<T, AllocComp> const& m_comparator;+            mutable Catch::Detail::Approx approx = Catch::Detail::Approx::custom();+        };++        template<typename T, typename AllocComp, typename AllocMatch>+        struct UnorderedEqualsMatcher : MatcherBase<std::vector<T, AllocMatch>> {+            UnorderedEqualsMatcher(std::vector<T, AllocComp> const& target) : m_target(target) {}+            bool match(std::vector<T, AllocMatch> const& vec) const override {+                if (m_target.size() != vec.size()) {+                    return false;+                }+                return std::is_permutation(m_target.begin(), m_target.end(), vec.begin());+            }++            std::string describe() const override {+                return "UnorderedEquals: " + ::Catch::Detail::stringify(m_target);+            }+        private:+            std::vector<T, AllocComp> const& m_target;+        };++    } // namespace Vector++    // The following functions create the actual matcher objects.+    // This allows the types to be inferred++    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>+    Vector::ContainsMatcher<T, AllocComp, AllocMatch> Contains( std::vector<T, AllocComp> const& comparator ) {+        return Vector::ContainsMatcher<T, AllocComp, AllocMatch>( comparator );+    }++    template<typename T, typename Alloc = std::allocator<T>>+    Vector::ContainsElementMatcher<T, Alloc> VectorContains( T const& comparator ) {+        return Vector::ContainsElementMatcher<T, Alloc>( comparator );+    }++    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>+    Vector::EqualsMatcher<T, AllocComp, AllocMatch> Equals( std::vector<T, AllocComp> const& comparator ) {+        return Vector::EqualsMatcher<T, AllocComp, AllocMatch>( comparator );+    }++    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>+    Vector::ApproxMatcher<T, AllocComp, AllocMatch> Approx( std::vector<T, AllocComp> const& comparator ) {+        return Vector::ApproxMatcher<T, AllocComp, AllocMatch>( comparator );+    }++    template<typename T, typename AllocComp = std::allocator<T>, typename AllocMatch = AllocComp>+    Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch> UnorderedEquals(std::vector<T, AllocComp> const& target) {+        return Vector::UnorderedEqualsMatcher<T, AllocComp, AllocMatch>( target );+    }++} // namespace Matchers+} // namespace Catch++// end catch_matchers_vector.h+namespace Catch {++    template<typename ArgT, typename MatcherT>+    class MatchExpr : public ITransientExpression {+        ArgT const& m_arg;+        MatcherT m_matcher;+        StringRef m_matcherString;+    public:+        MatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString )+        :   ITransientExpression{ true, matcher.match( arg ) },+            m_arg( arg ),+            m_matcher( matcher ),+            m_matcherString( matcherString )+        {}++        void streamReconstructedExpression( std::ostream &os ) const override {+            auto matcherAsString = m_matcher.toString();+            os << Catch::Detail::stringify( m_arg ) << ' ';+            if( matcherAsString == Detail::unprintableString )+                os << m_matcherString;+            else+                os << matcherAsString;+        }+    };++    using StringMatcher = Matchers::Impl::MatcherBase<std::string>;++    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  );++    template<typename ArgT, typename MatcherT>+    auto makeMatchExpr( ArgT const& arg, MatcherT const& matcher, StringRef const& matcherString  ) -> MatchExpr<ArgT, MatcherT> {+        return MatchExpr<ArgT, MatcherT>( arg, matcher, matcherString );+    }++} // namespace Catch++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CHECK_THAT( macroName, matcher, resultDisposition, arg ) \+    do { \+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(arg) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \+        INTERNAL_CATCH_TRY { \+            catchAssertionHandler.handleExpr( Catch::makeMatchExpr( arg, matcher, #matcher##_catch_sr ) ); \+        } INTERNAL_CATCH_CATCH( catchAssertionHandler ) \+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \+    } while( false )++///////////////////////////////////////////////////////////////////////////////+#define INTERNAL_CATCH_THROWS_MATCHES( macroName, exceptionType, resultDisposition, matcher, ... ) \+    do { \+        Catch::AssertionHandler catchAssertionHandler( macroName##_catch_sr, CATCH_INTERNAL_LINEINFO, CATCH_INTERNAL_STRINGIFY(__VA_ARGS__) ", " CATCH_INTERNAL_STRINGIFY(exceptionType) ", " CATCH_INTERNAL_STRINGIFY(matcher), resultDisposition ); \+        if( catchAssertionHandler.allowThrows() ) \+            try { \+                static_cast<void>(__VA_ARGS__ ); \+                catchAssertionHandler.handleUnexpectedExceptionNotThrown(); \+            } \+            catch( exceptionType const& ex ) { \+                catchAssertionHandler.handleExpr( Catch::makeMatchExpr( ex, matcher, #matcher##_catch_sr ) ); \+            } \+            catch( ... ) { \+                catchAssertionHandler.handleUnexpectedInflightException(); \+            } \+        else \+            catchAssertionHandler.handleThrowingCallSkipped(); \+        INTERNAL_CATCH_REACT( catchAssertionHandler ) \+    } while( false )++// end catch_capture_matchers.h+#endif+// start catch_generators.hpp++// start catch_interfaces_generatortracker.h+++#include <memory>++namespace Catch {++    namespace Generators {+        class GeneratorUntypedBase {+        public:+            GeneratorUntypedBase() = default;+            virtual ~GeneratorUntypedBase();+            // Attempts to move the generator to the next element+             //+             // Returns true iff the move succeeded (and a valid element+             // can be retrieved).+            virtual bool next() = 0;+        };+        using GeneratorBasePtr = std::unique_ptr<GeneratorUntypedBase>;++    } // namespace Generators++    struct IGeneratorTracker {+        virtual ~IGeneratorTracker();+        virtual auto hasGenerator() const -> bool = 0;+        virtual auto getGenerator() const -> Generators::GeneratorBasePtr const& = 0;+        virtual void setGenerator( Generators::GeneratorBasePtr&& generator ) = 0;+    };++} // namespace Catch++// end catch_interfaces_generatortracker.h+// start catch_enforce.h++#include <exception>++namespace Catch {+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+    template <typename Ex>+    [[noreturn]]+    void throw_exception(Ex const& e) {+        throw e;+    }+#else // ^^ Exceptions are enabled //  Exceptions are disabled vv+    [[noreturn]]+    void throw_exception(std::exception const& e);+#endif++    [[noreturn]]+    void throw_logic_error(std::string const& msg);+    [[noreturn]]+    void throw_domain_error(std::string const& msg);+    [[noreturn]]+    void throw_runtime_error(std::string const& msg);++} // namespace Catch;++#define CATCH_MAKE_MSG(...) \+    (Catch::ReusableStringStream() << __VA_ARGS__).str()++#define CATCH_INTERNAL_ERROR(...) \+    Catch::throw_logic_error(CATCH_MAKE_MSG( CATCH_INTERNAL_LINEINFO << ": Internal Catch2 error: " << __VA_ARGS__))++#define CATCH_ERROR(...) \+    Catch::throw_domain_error(CATCH_MAKE_MSG( __VA_ARGS__ ))++#define CATCH_RUNTIME_ERROR(...) \+    Catch::throw_runtime_error(CATCH_MAKE_MSG( __VA_ARGS__ ))++#define CATCH_ENFORCE( condition, ... ) \+    do{ if( !(condition) ) CATCH_ERROR( __VA_ARGS__ ); } while(false)++// end catch_enforce.h+#include <memory>+#include <vector>+#include <cassert>++#include <utility>+#include <exception>++namespace Catch {++class GeneratorException : public std::exception {+    const char* const m_msg = "";++public:+    GeneratorException(const char* msg):+        m_msg(msg)+    {}++    const char* what() const noexcept override final;+};++namespace Generators {++    // !TBD move this into its own location?+    namespace pf{+        template<typename T, typename... Args>+        std::unique_ptr<T> make_unique( Args&&... args ) {+            return std::unique_ptr<T>(new T(std::forward<Args>(args)...));+        }+    }++    template<typename T>+    struct IGenerator : GeneratorUntypedBase {+        virtual ~IGenerator() = default;++        // Returns the current element of the generator+        //+        // \Precondition The generator is either freshly constructed,+        // or the last call to `next()` returned true+        virtual T const& get() const = 0;+        using type = T;+    };++    template<typename T>+    class SingleValueGenerator final : public IGenerator<T> {+        T m_value;+    public:+        SingleValueGenerator(T&& value) : m_value(std::move(value)) {}++        T const& get() const override {+            return m_value;+        }+        bool next() override {+            return false;+        }+    };++    template<typename T>+    class FixedValuesGenerator final : public IGenerator<T> {+        static_assert(!std::is_same<T, bool>::value,+            "FixedValuesGenerator does not support bools because of std::vector<bool>"+            "specialization, use SingleValue Generator instead.");+        std::vector<T> m_values;+        size_t m_idx = 0;+    public:+        FixedValuesGenerator( std::initializer_list<T> values ) : m_values( values ) {}++        T const& get() const override {+            return m_values[m_idx];+        }+        bool next() override {+            ++m_idx;+            return m_idx < m_values.size();+        }+    };++    template <typename T>+    class GeneratorWrapper final {+        std::unique_ptr<IGenerator<T>> m_generator;+    public:+        GeneratorWrapper(std::unique_ptr<IGenerator<T>> generator):+            m_generator(std::move(generator))+        {}+        T const& get() const {+            return m_generator->get();+        }+        bool next() {+            return m_generator->next();+        }+    };++    template <typename T>+    GeneratorWrapper<T> value(T&& value) {+        return GeneratorWrapper<T>(pf::make_unique<SingleValueGenerator<T>>(std::forward<T>(value)));+    }+    template <typename T>+    GeneratorWrapper<T> values(std::initializer_list<T> values) {+        return GeneratorWrapper<T>(pf::make_unique<FixedValuesGenerator<T>>(values));+    }++    template<typename T>+    class Generators : public IGenerator<T> {+        std::vector<GeneratorWrapper<T>> m_generators;+        size_t m_current = 0;++        void populate(GeneratorWrapper<T>&& generator) {+            m_generators.emplace_back(std::move(generator));+        }+        void populate(T&& val) {+            m_generators.emplace_back(value(std::forward<T>(val)));+        }+        template<typename U>+        void populate(U&& val) {+            populate(T(std::forward<U>(val)));+        }+        template<typename U, typename... Gs>+        void populate(U&& valueOrGenerator, Gs &&... moreGenerators) {+            populate(std::forward<U>(valueOrGenerator));+            populate(std::forward<Gs>(moreGenerators)...);+        }++    public:+        template <typename... Gs>+        Generators(Gs &&... moreGenerators) {+            m_generators.reserve(sizeof...(Gs));+            populate(std::forward<Gs>(moreGenerators)...);+        }++        T const& get() const override {+            return m_generators[m_current].get();+        }++        bool next() override {+            if (m_current >= m_generators.size()) {+                return false;+            }+            const bool current_status = m_generators[m_current].next();+            if (!current_status) {+                ++m_current;+            }+            return m_current < m_generators.size();+        }+    };++    template<typename... Ts>+    GeneratorWrapper<std::tuple<Ts...>> table( std::initializer_list<std::tuple<typename std::decay<Ts>::type...>> tuples ) {+        return values<std::tuple<Ts...>>( tuples );+    }++    // Tag type to signal that a generator sequence should convert arguments to a specific type+    template <typename T>+    struct as {};++    template<typename T, typename... Gs>+    auto makeGenerators( GeneratorWrapper<T>&& generator, Gs &&... moreGenerators ) -> Generators<T> {+        return Generators<T>(std::move(generator), std::forward<Gs>(moreGenerators)...);+    }+    template<typename T>+    auto makeGenerators( GeneratorWrapper<T>&& generator ) -> Generators<T> {+        return Generators<T>(std::move(generator));+    }+    template<typename T, typename... Gs>+    auto makeGenerators( T&& val, Gs &&... moreGenerators ) -> Generators<T> {+        return makeGenerators( value( std::forward<T>( val ) ), std::forward<Gs>( moreGenerators )... );+    }+    template<typename T, typename U, typename... Gs>+    auto makeGenerators( as<T>, U&& val, Gs &&... moreGenerators ) -> Generators<T> {+        return makeGenerators( value( T( std::forward<U>( val ) ) ), std::forward<Gs>( moreGenerators )... );+    }++    auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker&;++    template<typename L>+    // Note: The type after -> is weird, because VS2015 cannot parse+    //       the expression used in the typedef inside, when it is in+    //       return type. Yeah.+    auto generate( StringRef generatorName, SourceLineInfo const& lineInfo, L const& generatorExpression ) -> decltype(std::declval<decltype(generatorExpression())>().get()) {+        using UnderlyingType = typename decltype(generatorExpression())::type;++        IGeneratorTracker& tracker = acquireGeneratorTracker( generatorName, lineInfo );+        if (!tracker.hasGenerator()) {+            tracker.setGenerator(pf::make_unique<Generators<UnderlyingType>>(generatorExpression()));+        }++        auto const& generator = static_cast<IGenerator<UnderlyingType> const&>( *tracker.getGenerator() );+        return generator.get();+    }++} // namespace Generators+} // namespace Catch++#define GENERATE( ... ) \+    Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \+                                 CATCH_INTERNAL_LINEINFO, \+                                 [ ]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)+#define GENERATE_COPY( ... ) \+    Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \+                                 CATCH_INTERNAL_LINEINFO, \+                                 [=]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)+#define GENERATE_REF( ... ) \+    Catch::Generators::generate( INTERNAL_CATCH_STRINGIZE(INTERNAL_CATCH_UNIQUE_NAME(generator)), \+                                 CATCH_INTERNAL_LINEINFO, \+                                 [&]{ using namespace Catch::Generators; return makeGenerators( __VA_ARGS__ ); } ) //NOLINT(google-build-using-namespace)++// end catch_generators.hpp+// start catch_generators_generic.hpp++namespace Catch {+namespace Generators {++    template <typename T>+    class TakeGenerator : public IGenerator<T> {+        GeneratorWrapper<T> m_generator;+        size_t m_returned = 0;+        size_t m_target;+    public:+        TakeGenerator(size_t target, GeneratorWrapper<T>&& generator):+            m_generator(std::move(generator)),+            m_target(target)+        {+            assert(target != 0 && "Empty generators are not allowed");+        }+        T const& get() const override {+            return m_generator.get();+        }+        bool next() override {+            ++m_returned;+            if (m_returned >= m_target) {+                return false;+            }++            const auto success = m_generator.next();+            // If the underlying generator does not contain enough values+            // then we cut short as well+            if (!success) {+                m_returned = m_target;+            }+            return success;+        }+    };++    template <typename T>+    GeneratorWrapper<T> take(size_t target, GeneratorWrapper<T>&& generator) {+        return GeneratorWrapper<T>(pf::make_unique<TakeGenerator<T>>(target, std::move(generator)));+    }++    template <typename T, typename Predicate>+    class FilterGenerator : public IGenerator<T> {+        GeneratorWrapper<T> m_generator;+        Predicate m_predicate;+    public:+        template <typename P = Predicate>+        FilterGenerator(P&& pred, GeneratorWrapper<T>&& generator):+            m_generator(std::move(generator)),+            m_predicate(std::forward<P>(pred))+        {+            if (!m_predicate(m_generator.get())) {+                // It might happen that there are no values that pass the+                // filter. In that case we throw an exception.+                auto has_initial_value = next();+                if (!has_initial_value) {+                    Catch::throw_exception(GeneratorException("No valid value found in filtered generator"));+                }+            }+        }++        T const& get() const override {+            return m_generator.get();+        }++        bool next() override {+            bool success = m_generator.next();+            if (!success) {+                return false;+            }+            while (!m_predicate(m_generator.get()) && (success = m_generator.next()) == true);+            return success;+        }+    };++    template <typename T, typename Predicate>+    GeneratorWrapper<T> filter(Predicate&& pred, GeneratorWrapper<T>&& generator) {+        return GeneratorWrapper<T>(std::unique_ptr<IGenerator<T>>(pf::make_unique<FilterGenerator<T, Predicate>>(std::forward<Predicate>(pred), std::move(generator))));+    }++    template <typename T>+    class RepeatGenerator : public IGenerator<T> {+        static_assert(!std::is_same<T, bool>::value,+            "RepeatGenerator currently does not support bools"+            "because of std::vector<bool> specialization");+        GeneratorWrapper<T> m_generator;+        mutable std::vector<T> m_returned;+        size_t m_target_repeats;+        size_t m_current_repeat = 0;+        size_t m_repeat_index = 0;+    public:+        RepeatGenerator(size_t repeats, GeneratorWrapper<T>&& generator):+            m_generator(std::move(generator)),+            m_target_repeats(repeats)+        {+            assert(m_target_repeats > 0 && "Repeat generator must repeat at least once");+        }++        T const& get() const override {+            if (m_current_repeat == 0) {+                m_returned.push_back(m_generator.get());+                return m_returned.back();+            }+            return m_returned[m_repeat_index];+        }++        bool next() override {+            // There are 2 basic cases:+            // 1) We are still reading the generator+            // 2) We are reading our own cache++            // In the first case, we need to poke the underlying generator.+            // If it happily moves, we are left in that state, otherwise it is time to start reading from our cache+            if (m_current_repeat == 0) {+                const auto success = m_generator.next();+                if (!success) {+                    ++m_current_repeat;+                }+                return m_current_repeat < m_target_repeats;+            }++            // In the second case, we need to move indices forward and check that we haven't run up against the end+            ++m_repeat_index;+            if (m_repeat_index == m_returned.size()) {+                m_repeat_index = 0;+                ++m_current_repeat;+            }+            return m_current_repeat < m_target_repeats;+        }+    };++    template <typename T>+    GeneratorWrapper<T> repeat(size_t repeats, GeneratorWrapper<T>&& generator) {+        return GeneratorWrapper<T>(pf::make_unique<RepeatGenerator<T>>(repeats, std::move(generator)));+    }++    template <typename T, typename U, typename Func>+    class MapGenerator : public IGenerator<T> {+        // TBD: provide static assert for mapping function, for friendly error message+        GeneratorWrapper<U> m_generator;+        Func m_function;+        // To avoid returning dangling reference, we have to save the values+        T m_cache;+    public:+        template <typename F2 = Func>+        MapGenerator(F2&& function, GeneratorWrapper<U>&& generator) :+            m_generator(std::move(generator)),+            m_function(std::forward<F2>(function)),+            m_cache(m_function(m_generator.get()))+        {}++        T const& get() const override {+            return m_cache;+        }+        bool next() override {+            const auto success = m_generator.next();+            if (success) {+                m_cache = m_function(m_generator.get());+            }+            return success;+        }+    };++    template <typename Func, typename U, typename T = FunctionReturnType<Func, U>>+    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {+        return GeneratorWrapper<T>(+            pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))+        );+    }++    template <typename T, typename U, typename Func>+    GeneratorWrapper<T> map(Func&& function, GeneratorWrapper<U>&& generator) {+        return GeneratorWrapper<T>(+            pf::make_unique<MapGenerator<T, U, Func>>(std::forward<Func>(function), std::move(generator))+        );+    }++    template <typename T>+    class ChunkGenerator final : public IGenerator<std::vector<T>> {+        std::vector<T> m_chunk;+        size_t m_chunk_size;+        GeneratorWrapper<T> m_generator;+        bool m_used_up = false;+    public:+        ChunkGenerator(size_t size, GeneratorWrapper<T> generator) :+            m_chunk_size(size), m_generator(std::move(generator))+        {+            m_chunk.reserve(m_chunk_size);+            if (m_chunk_size != 0) {+                m_chunk.push_back(m_generator.get());+                for (size_t i = 1; i < m_chunk_size; ++i) {+                    if (!m_generator.next()) {+                        Catch::throw_exception(GeneratorException("Not enough values to initialize the first chunk"));+                    }+                    m_chunk.push_back(m_generator.get());+                }+            }+        }+        std::vector<T> const& get() const override {+            return m_chunk;+        }+        bool next() override {+            m_chunk.clear();+            for (size_t idx = 0; idx < m_chunk_size; ++idx) {+                if (!m_generator.next()) {+                    return false;+                }+                m_chunk.push_back(m_generator.get());+            }+            return true;+        }+    };++    template <typename T>+    GeneratorWrapper<std::vector<T>> chunk(size_t size, GeneratorWrapper<T>&& generator) {+        return GeneratorWrapper<std::vector<T>>(+            pf::make_unique<ChunkGenerator<T>>(size, std::move(generator))+        );+    }++} // namespace Generators+} // namespace Catch++// end catch_generators_generic.hpp+// start catch_generators_specific.hpp++// start catch_context.h++#include <memory>++namespace Catch {++    struct IResultCapture;+    struct IRunner;+    struct IConfig;+    struct IMutableContext;++    using IConfigPtr = std::shared_ptr<IConfig const>;++    struct IContext+    {+        virtual ~IContext();++        virtual IResultCapture* getResultCapture() = 0;+        virtual IRunner* getRunner() = 0;+        virtual IConfigPtr const& getConfig() const = 0;+    };++    struct IMutableContext : IContext+    {+        virtual ~IMutableContext();+        virtual void setResultCapture( IResultCapture* resultCapture ) = 0;+        virtual void setRunner( IRunner* runner ) = 0;+        virtual void setConfig( IConfigPtr const& config ) = 0;++    private:+        static IMutableContext *currentContext;+        friend IMutableContext& getCurrentMutableContext();+        friend void cleanUpContext();+        static void createContext();+    };++    inline IMutableContext& getCurrentMutableContext()+    {+        if( !IMutableContext::currentContext )+            IMutableContext::createContext();+        // NOLINTNEXTLINE(clang-analyzer-core.uninitialized.UndefReturn)+        return *IMutableContext::currentContext;+    }++    inline IContext& getCurrentContext()+    {+        return getCurrentMutableContext();+    }++    void cleanUpContext();++    class SimplePcg32;+    SimplePcg32& rng();+}++// end catch_context.h+// start catch_interfaces_config.h++// start catch_option.hpp++namespace Catch {++    // An optional type+    template<typename T>+    class Option {+    public:+        Option() : nullableValue( nullptr ) {}+        Option( T const& _value )+        : nullableValue( new( storage ) T( _value ) )+        {}+        Option( Option const& _other )+        : nullableValue( _other ? new( storage ) T( *_other ) : nullptr )+        {}++        ~Option() {+            reset();+        }++        Option& operator= ( Option const& _other ) {+            if( &_other != this ) {+                reset();+                if( _other )+                    nullableValue = new( storage ) T( *_other );+            }+            return *this;+        }+        Option& operator = ( T const& _value ) {+            reset();+            nullableValue = new( storage ) T( _value );+            return *this;+        }++        void reset() {+            if( nullableValue )+                nullableValue->~T();+            nullableValue = nullptr;+        }++        T& operator*() { return *nullableValue; }+        T const& operator*() const { return *nullableValue; }+        T* operator->() { return nullableValue; }+        const T* operator->() const { return nullableValue; }++        T valueOr( T const& defaultValue ) const {+            return nullableValue ? *nullableValue : defaultValue;+        }++        bool some() const { return nullableValue != nullptr; }+        bool none() const { return nullableValue == nullptr; }++        bool operator !() const { return nullableValue == nullptr; }+        explicit operator bool() const {+            return some();+        }++    private:+        T *nullableValue;+        alignas(alignof(T)) char storage[sizeof(T)];+    };++} // end namespace Catch++// end catch_option.hpp+#include <chrono>+#include <iosfwd>+#include <string>+#include <vector>+#include <memory>++namespace Catch {++    enum class Verbosity {+        Quiet = 0,+        Normal,+        High+    };++    struct WarnAbout { enum What {+        Nothing = 0x00,+        NoAssertions = 0x01,+        NoTests = 0x02+    }; };++    struct ShowDurations { enum OrNot {+        DefaultForReporter,+        Always,+        Never+    }; };+    struct RunTests { enum InWhatOrder {+        InDeclarationOrder,+        InLexicographicalOrder,+        InRandomOrder+    }; };+    struct UseColour { enum YesOrNo {+        Auto,+        Yes,+        No+    }; };+    struct WaitForKeypress { enum When {+        Never,+        BeforeStart = 1,+        BeforeExit = 2,+        BeforeStartAndExit = BeforeStart | BeforeExit+    }; };++    class TestSpec;++    struct IConfig : NonCopyable {++        virtual ~IConfig();++        virtual bool allowThrows() const = 0;+        virtual std::ostream& stream() const = 0;+        virtual std::string name() const = 0;+        virtual bool includeSuccessfulResults() const = 0;+        virtual bool shouldDebugBreak() const = 0;+        virtual bool warnAboutMissingAssertions() const = 0;+        virtual bool warnAboutNoTests() const = 0;+        virtual int abortAfter() const = 0;+        virtual bool showInvisibles() const = 0;+        virtual ShowDurations::OrNot showDurations() const = 0;+        virtual double minDuration() const = 0;+        virtual TestSpec const& testSpec() const = 0;+        virtual bool hasTestFilters() const = 0;+        virtual std::vector<std::string> const& getTestsOrTags() const = 0;+        virtual RunTests::InWhatOrder runOrder() const = 0;+        virtual unsigned int rngSeed() const = 0;+        virtual UseColour::YesOrNo useColour() const = 0;+        virtual std::vector<std::string> const& getSectionsToRun() const = 0;+        virtual Verbosity verbosity() const = 0;++        virtual bool benchmarkNoAnalysis() const = 0;+        virtual int benchmarkSamples() const = 0;+        virtual double benchmarkConfidenceInterval() const = 0;+        virtual unsigned int benchmarkResamples() const = 0;+        virtual std::chrono::milliseconds benchmarkWarmupTime() const = 0;+    };++    using IConfigPtr = std::shared_ptr<IConfig const>;+}++// end catch_interfaces_config.h+// start catch_random_number_generator.h++#include <cstdint>++namespace Catch {++    // This is a simple implementation of C++11 Uniform Random Number+    // Generator. It does not provide all operators, because Catch2+    // does not use it, but it should behave as expected inside stdlib's+    // distributions.+    // The implementation is based on the PCG family (http://pcg-random.org)+    class SimplePcg32 {+        using state_type = std::uint64_t;+    public:+        using result_type = std::uint32_t;+        static constexpr result_type (min)() {+            return 0;+        }+        static constexpr result_type (max)() {+            return static_cast<result_type>(-1);+        }++        // Provide some default initial state for the default constructor+        SimplePcg32():SimplePcg32(0xed743cc4U) {}++        explicit SimplePcg32(result_type seed_);++        void seed(result_type seed_);+        void discard(uint64_t skip);++        result_type operator()();++    private:+        friend bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs);+        friend bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs);++        // In theory we also need operator<< and operator>>+        // In practice we do not use them, so we will skip them for now++        std::uint64_t m_state;+        // This part of the state determines which "stream" of the numbers+        // is chosen -- we take it as a constant for Catch2, so we only+        // need to deal with seeding the main state.+        // Picked by reading 8 bytes from `/dev/random` :-)+        static const std::uint64_t s_inc = (0x13ed0cc53f939476ULL << 1ULL) | 1ULL;+    };++} // end namespace Catch++// end catch_random_number_generator.h+#include <random>++namespace Catch {+namespace Generators {++template <typename Float>+class RandomFloatingGenerator final : public IGenerator<Float> {+    Catch::SimplePcg32& m_rng;+    std::uniform_real_distribution<Float> m_dist;+    Float m_current_number;+public:++    RandomFloatingGenerator(Float a, Float b):+        m_rng(rng()),+        m_dist(a, b) {+        static_cast<void>(next());+    }++    Float const& get() const override {+        return m_current_number;+    }+    bool next() override {+        m_current_number = m_dist(m_rng);+        return true;+    }+};++template <typename Integer>+class RandomIntegerGenerator final : public IGenerator<Integer> {+    Catch::SimplePcg32& m_rng;+    std::uniform_int_distribution<Integer> m_dist;+    Integer m_current_number;+public:++    RandomIntegerGenerator(Integer a, Integer b):+        m_rng(rng()),+        m_dist(a, b) {+        static_cast<void>(next());+    }++    Integer const& get() const override {+        return m_current_number;+    }+    bool next() override {+        m_current_number = m_dist(m_rng);+        return true;+    }+};++// TODO: Ideally this would be also constrained against the various char types,+//       but I don't expect users to run into that in practice.+template <typename T>+typename std::enable_if<std::is_integral<T>::value && !std::is_same<T, bool>::value,+GeneratorWrapper<T>>::type+random(T a, T b) {+    return GeneratorWrapper<T>(+        pf::make_unique<RandomIntegerGenerator<T>>(a, b)+    );+}++template <typename T>+typename std::enable_if<std::is_floating_point<T>::value,+GeneratorWrapper<T>>::type+random(T a, T b) {+    return GeneratorWrapper<T>(+        pf::make_unique<RandomFloatingGenerator<T>>(a, b)+    );+}++template <typename T>+class RangeGenerator final : public IGenerator<T> {+    T m_current;+    T m_end;+    T m_step;+    bool m_positive;++public:+    RangeGenerator(T const& start, T const& end, T const& step):+        m_current(start),+        m_end(end),+        m_step(step),+        m_positive(m_step > T(0))+    {+        assert(m_current != m_end && "Range start and end cannot be equal");+        assert(m_step != T(0) && "Step size cannot be zero");+        assert(((m_positive && m_current <= m_end) || (!m_positive && m_current >= m_end)) && "Step moves away from end");+    }++    RangeGenerator(T const& start, T const& end):+        RangeGenerator(start, end, (start < end) ? T(1) : T(-1))+    {}++    T const& get() const override {+        return m_current;+    }++    bool next() override {+        m_current += m_step;+        return (m_positive) ? (m_current < m_end) : (m_current > m_end);+    }+};++template <typename T>+GeneratorWrapper<T> range(T const& start, T const& end, T const& step) {+    static_assert(std::is_arithmetic<T>::value && !std::is_same<T, bool>::value, "Type must be numeric");+    return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end, step));+}++template <typename T>+GeneratorWrapper<T> range(T const& start, T const& end) {+    static_assert(std::is_integral<T>::value && !std::is_same<T, bool>::value, "Type must be an integer");+    return GeneratorWrapper<T>(pf::make_unique<RangeGenerator<T>>(start, end));+}++template <typename T>+class IteratorGenerator final : public IGenerator<T> {+    static_assert(!std::is_same<T, bool>::value,+        "IteratorGenerator currently does not support bools"+        "because of std::vector<bool> specialization");++    std::vector<T> m_elems;+    size_t m_current = 0;+public:+    template <typename InputIterator, typename InputSentinel>+    IteratorGenerator(InputIterator first, InputSentinel last):m_elems(first, last) {+        if (m_elems.empty()) {+            Catch::throw_exception(GeneratorException("IteratorGenerator received no valid values"));+        }+    }++    T const& get() const override {+        return m_elems[m_current];+    }++    bool next() override {+        ++m_current;+        return m_current != m_elems.size();+    }+};++template <typename InputIterator,+          typename InputSentinel,+          typename ResultType = typename std::iterator_traits<InputIterator>::value_type>+GeneratorWrapper<ResultType> from_range(InputIterator from, InputSentinel to) {+    return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(from, to));+}++template <typename Container,+          typename ResultType = typename Container::value_type>+GeneratorWrapper<ResultType> from_range(Container const& cnt) {+    return GeneratorWrapper<ResultType>(pf::make_unique<IteratorGenerator<ResultType>>(cnt.begin(), cnt.end()));+}++} // namespace Generators+} // namespace Catch++// end catch_generators_specific.hpp++// These files are included here so the single_include script doesn't put them+// in the conditionally compiled sections+// start catch_test_case_info.h++#include <string>+#include <vector>+#include <memory>++#ifdef __clang__+#pragma clang diagnostic push+#pragma clang diagnostic ignored "-Wpadded"+#endif++namespace Catch {++    struct ITestInvoker;++    struct TestCaseInfo {+        enum SpecialProperties{+            None = 0,+            IsHidden = 1 << 1,+            ShouldFail = 1 << 2,+            MayFail = 1 << 3,+            Throws = 1 << 4,+            NonPortable = 1 << 5,+            Benchmark = 1 << 6+        };++        TestCaseInfo(   std::string const& _name,+                        std::string const& _className,+                        std::string const& _description,+                        std::vector<std::string> const& _tags,+                        SourceLineInfo const& _lineInfo );++        friend void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags );++        bool isHidden() const;+        bool throws() const;+        bool okToFail() const;+        bool expectedToFail() const;++        std::string tagsAsString() const;++        std::string name;+        std::string className;+        std::string description;+        std::vector<std::string> tags;+        std::vector<std::string> lcaseTags;+        SourceLineInfo lineInfo;+        SpecialProperties properties;+    };++    class TestCase : public TestCaseInfo {+    public:++        TestCase( ITestInvoker* testCase, TestCaseInfo&& info );++        TestCase withName( std::string const& _newName ) const;++        void invoke() const;++        TestCaseInfo const& getTestCaseInfo() const;++        bool operator == ( TestCase const& other ) const;+        bool operator < ( TestCase const& other ) const;++    private:+        std::shared_ptr<ITestInvoker> test;+    };++    TestCase makeTestCase(  ITestInvoker* testCase,+                            std::string const& className,+                            NameAndTags const& nameAndTags,+                            SourceLineInfo const& lineInfo );+}++#ifdef __clang__+#pragma clang diagnostic pop+#endif++// end catch_test_case_info.h+// start catch_interfaces_runner.h++namespace Catch {++    struct IRunner {+        virtual ~IRunner();+        virtual bool aborting() const = 0;+    };+}++// end catch_interfaces_runner.h++#ifdef __OBJC__+// start catch_objc.hpp++#import <objc/runtime.h>++#include <string>++// NB. Any general catch headers included here must be included+// in catch.hpp first to make sure they are included by the single+// header for non obj-usage++///////////////////////////////////////////////////////////////////////////////+// This protocol is really only here for (self) documenting purposes, since+// all its methods are optional.+@protocol OcFixture++@optional++-(void) setUp;+-(void) tearDown;++@end++namespace Catch {++    class OcMethod : public ITestInvoker {++    public:+        OcMethod( Class cls, SEL sel ) : m_cls( cls ), m_sel( sel ) {}++        virtual void invoke() const {+            id obj = [[m_cls alloc] init];++            performOptionalSelector( obj, @selector(setUp)  );+            performOptionalSelector( obj, m_sel );+            performOptionalSelector( obj, @selector(tearDown)  );++            arcSafeRelease( obj );+        }+    private:+        virtual ~OcMethod() {}++        Class m_cls;+        SEL m_sel;+    };++    namespace Detail{++        inline std::string getAnnotation(   Class cls,+                                            std::string const& annotationName,+                                            std::string const& testCaseName ) {+            NSString* selStr = [[NSString alloc] initWithFormat:@"Catch_%s_%s", annotationName.c_str(), testCaseName.c_str()];+            SEL sel = NSSelectorFromString( selStr );+            arcSafeRelease( selStr );+            id value = performOptionalSelector( cls, sel );+            if( value )+                return [(NSString*)value UTF8String];+            return "";+        }+    }++    inline std::size_t registerTestMethods() {+        std::size_t noTestMethods = 0;+        int noClasses = objc_getClassList( nullptr, 0 );++        Class* classes = (CATCH_UNSAFE_UNRETAINED Class *)malloc( sizeof(Class) * noClasses);+        objc_getClassList( classes, noClasses );++        for( int c = 0; c < noClasses; c++ ) {+            Class cls = classes[c];+            {+                u_int count;+                Method* methods = class_copyMethodList( cls, &count );+                for( u_int m = 0; m < count ; m++ ) {+                    SEL selector = method_getName(methods[m]);+                    std::string methodName = sel_getName(selector);+                    if( startsWith( methodName, "Catch_TestCase_" ) ) {+                        std::string testCaseName = methodName.substr( 15 );+                        std::string name = Detail::getAnnotation( cls, "Name", testCaseName );+                        std::string desc = Detail::getAnnotation( cls, "Description", testCaseName );+                        const char* className = class_getName( cls );++                        getMutableRegistryHub().registerTest( makeTestCase( new OcMethod( cls, selector ), className, NameAndTags( name.c_str(), desc.c_str() ), SourceLineInfo("",0) ) );+                        noTestMethods++;+                    }+                }+                free(methods);+            }+        }+        return noTestMethods;+    }++#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)++    namespace Matchers {+        namespace Impl {+        namespace NSStringMatchers {++            struct StringHolder : MatcherBase<NSString*>{+                StringHolder( NSString* substr ) : m_substr( [substr copy] ){}+                StringHolder( StringHolder const& other ) : m_substr( [other.m_substr copy] ){}+                StringHolder() {+                    arcSafeRelease( m_substr );+                }++                bool match( NSString* str ) const override {+                    return false;+                }++                NSString* CATCH_ARC_STRONG m_substr;+            };++            struct Equals : StringHolder {+                Equals( NSString* substr ) : StringHolder( substr ){}++                bool match( NSString* str ) const override {+                    return  (str != nil || m_substr == nil ) &&+                            [str isEqualToString:m_substr];+                }++                std::string describe() const override {+                    return "equals string: " + Catch::Detail::stringify( m_substr );+                }+            };++            struct Contains : StringHolder {+                Contains( NSString* substr ) : StringHolder( substr ){}++                bool match( NSString* str ) const override {+                    return  (str != nil || m_substr == nil ) &&+                            [str rangeOfString:m_substr].location != NSNotFound;+                }++                std::string describe() const override {+                    return "contains string: " + Catch::Detail::stringify( m_substr );+                }+            };++            struct StartsWith : StringHolder {+                StartsWith( NSString* substr ) : StringHolder( substr ){}++                bool match( NSString* str ) const override {+                    return  (str != nil || m_substr == nil ) &&+                            [str rangeOfString:m_substr].location == 0;+                }++                std::string describe() const override {+                    return "starts with: " + Catch::Detail::stringify( m_substr );+                }+            };+            struct EndsWith : StringHolder {+                EndsWith( NSString* substr ) : StringHolder( substr ){}++                bool match( NSString* str ) const override {+                    return  (str != nil || m_substr == nil ) &&+                            [str rangeOfString:m_substr].location == [str length] - [m_substr length];+                }++                std::string describe() const override {+                    return "ends with: " + Catch::Detail::stringify( m_substr );+                }+            };++        } // namespace NSStringMatchers+        } // namespace Impl++        inline Impl::NSStringMatchers::Equals+            Equals( NSString* substr ){ return Impl::NSStringMatchers::Equals( substr ); }++        inline Impl::NSStringMatchers::Contains+            Contains( NSString* substr ){ return Impl::NSStringMatchers::Contains( substr ); }++        inline Impl::NSStringMatchers::StartsWith+            StartsWith( NSString* substr ){ return Impl::NSStringMatchers::StartsWith( substr ); }++        inline Impl::NSStringMatchers::EndsWith+            EndsWith( NSString* substr ){ return Impl::NSStringMatchers::EndsWith( substr ); }++    } // namespace Matchers++    using namespace Matchers;++#endif // CATCH_CONFIG_DISABLE_MATCHERS++} // namespace Catch++///////////////////////////////////////////////////////////////////////////////+#define OC_MAKE_UNIQUE_NAME( root, uniqueSuffix ) root##uniqueSuffix+#define OC_TEST_CASE2( name, desc, uniqueSuffix ) \++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Name_test_, uniqueSuffix ) \+{ \+return @ name; \+} \++(NSString*) OC_MAKE_UNIQUE_NAME( Catch_Description_test_, uniqueSuffix ) \+{ \+return @ desc; \+} \+-(void) OC_MAKE_UNIQUE_NAME( Catch_TestCase_test_, uniqueSuffix )++#define OC_TEST_CASE( name, desc ) OC_TEST_CASE2( name, desc, __LINE__ )++// end catch_objc.hpp+#endif++// Benchmarking needs the externally-facing parts of reporters to work+#if defined(CATCH_CONFIG_EXTERNAL_INTERFACES) || defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+// start catch_external_interfaces.h++// start catch_reporter_bases.hpp++// start catch_interfaces_reporter.h++// start catch_config.hpp++// start catch_test_spec_parser.h++#ifdef __clang__+#pragma clang diagnostic push+#pragma clang diagnostic ignored "-Wpadded"+#endif++// start catch_test_spec.h++#ifdef __clang__+#pragma clang diagnostic push+#pragma clang diagnostic ignored "-Wpadded"+#endif++// start catch_wildcard_pattern.h++namespace Catch+{+    class WildcardPattern {+        enum WildcardPosition {+            NoWildcard = 0,+            WildcardAtStart = 1,+            WildcardAtEnd = 2,+            WildcardAtBothEnds = WildcardAtStart | WildcardAtEnd+        };++    public:++        WildcardPattern( std::string const& pattern, CaseSensitive::Choice caseSensitivity );+        virtual ~WildcardPattern() = default;+        virtual bool matches( std::string const& str ) const;++    private:+        std::string normaliseString( std::string const& str ) const;+        CaseSensitive::Choice m_caseSensitivity;+        WildcardPosition m_wildcard = NoWildcard;+        std::string m_pattern;+    };+}++// end catch_wildcard_pattern.h+#include <string>+#include <vector>+#include <memory>++namespace Catch {++    struct IConfig;++    class TestSpec {+        class Pattern {+        public:+            explicit Pattern( std::string const& name );+            virtual ~Pattern();+            virtual bool matches( TestCaseInfo const& testCase ) const = 0;+            std::string const& name() const;+        private:+            std::string const m_name;+        };+        using PatternPtr = std::shared_ptr<Pattern>;++        class NamePattern : public Pattern {+        public:+            explicit NamePattern( std::string const& name, std::string const& filterString );+            bool matches( TestCaseInfo const& testCase ) const override;+        private:+            WildcardPattern m_wildcardPattern;+        };++        class TagPattern : public Pattern {+        public:+            explicit TagPattern( std::string const& tag, std::string const& filterString );+            bool matches( TestCaseInfo const& testCase ) const override;+        private:+            std::string m_tag;+        };++        class ExcludedPattern : public Pattern {+        public:+            explicit ExcludedPattern( PatternPtr const& underlyingPattern );+            bool matches( TestCaseInfo const& testCase ) const override;+        private:+            PatternPtr m_underlyingPattern;+        };++        struct Filter {+            std::vector<PatternPtr> m_patterns;++            bool matches( TestCaseInfo const& testCase ) const;+            std::string name() const;+        };++    public:+        struct FilterMatch {+            std::string name;+            std::vector<TestCase const*> tests;+        };+        using Matches = std::vector<FilterMatch>;+        using vectorStrings = std::vector<std::string>;++        bool hasFilters() const;+        bool matches( TestCaseInfo const& testCase ) const;+        Matches matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const;+        const vectorStrings & getInvalidArgs() const;++    private:+        std::vector<Filter> m_filters;+        std::vector<std::string> m_invalidArgs;+        friend class TestSpecParser;+    };+}++#ifdef __clang__+#pragma clang diagnostic pop+#endif++// end catch_test_spec.h+// start catch_interfaces_tag_alias_registry.h++#include <string>++namespace Catch {++    struct TagAlias;++    struct ITagAliasRegistry {+        virtual ~ITagAliasRegistry();+        // Nullptr if not present+        virtual TagAlias const* find( std::string const& alias ) const = 0;+        virtual std::string expandAliases( std::string const& unexpandedTestSpec ) const = 0;++        static ITagAliasRegistry const& get();+    };++} // end namespace Catch++// end catch_interfaces_tag_alias_registry.h+namespace Catch {++    class TestSpecParser {+        enum Mode{ None, Name, QuotedName, Tag, EscapedName };+        Mode m_mode = None;+        Mode lastMode = None;+        bool m_exclusion = false;+        std::size_t m_pos = 0;+        std::size_t m_realPatternPos = 0;+        std::string m_arg;+        std::string m_substring;+        std::string m_patternName;+        std::vector<std::size_t> m_escapeChars;+        TestSpec::Filter m_currentFilter;+        TestSpec m_testSpec;+        ITagAliasRegistry const* m_tagAliases = nullptr;++    public:+        TestSpecParser( ITagAliasRegistry const& tagAliases );++        TestSpecParser& parse( std::string const& arg );+        TestSpec testSpec();++    private:+        bool visitChar( char c );+        void startNewMode( Mode mode );+        bool processNoneChar( char c );+        void processNameChar( char c );+        bool processOtherChar( char c );+        void endMode();+        void escape();+        bool isControlChar( char c ) const;+        void saveLastMode();+        void revertBackToLastMode();+        void addFilter();+        bool separate();++        // Handles common preprocessing of the pattern for name/tag patterns+        std::string preprocessPattern();+        // Adds the current pattern as a test name+        void addNamePattern();+        // Adds the current pattern as a tag+        void addTagPattern();++        inline void addCharToPattern(char c) {+            m_substring += c;+            m_patternName += c;+            m_realPatternPos++;+        }++    };+    TestSpec parseTestSpec( std::string const& arg );++} // namespace Catch++#ifdef __clang__+#pragma clang diagnostic pop+#endif++// end catch_test_spec_parser.h+// Libstdc++ doesn't like incomplete classes for unique_ptr++#include <memory>+#include <vector>+#include <string>++#ifndef CATCH_CONFIG_CONSOLE_WIDTH+#define CATCH_CONFIG_CONSOLE_WIDTH 80+#endif++namespace Catch {++    struct IStream;++    struct ConfigData {+        bool listTests = false;+        bool listTags = false;+        bool listReporters = false;+        bool listTestNamesOnly = false;++        bool showSuccessfulTests = false;+        bool shouldDebugBreak = false;+        bool noThrow = false;+        bool showHelp = false;+        bool showInvisibles = false;+        bool filenamesAsTags = false;+        bool libIdentify = false;++        int abortAfter = -1;+        unsigned int rngSeed = 0;++        bool benchmarkNoAnalysis = false;+        unsigned int benchmarkSamples = 100;+        double benchmarkConfidenceInterval = 0.95;+        unsigned int benchmarkResamples = 100000;+        std::chrono::milliseconds::rep benchmarkWarmupTime = 100;++        Verbosity verbosity = Verbosity::Normal;+        WarnAbout::What warnings = WarnAbout::Nothing;+        ShowDurations::OrNot showDurations = ShowDurations::DefaultForReporter;+        double minDuration = -1;+        RunTests::InWhatOrder runOrder = RunTests::InDeclarationOrder;+        UseColour::YesOrNo useColour = UseColour::Auto;+        WaitForKeypress::When waitForKeypress = WaitForKeypress::Never;++        std::string outputFilename;+        std::string name;+        std::string processName;+#ifndef CATCH_CONFIG_DEFAULT_REPORTER+#define CATCH_CONFIG_DEFAULT_REPORTER "console"+#endif+        std::string reporterName = CATCH_CONFIG_DEFAULT_REPORTER;+#undef CATCH_CONFIG_DEFAULT_REPORTER++        std::vector<std::string> testsOrTags;+        std::vector<std::string> sectionsToRun;+    };++    class Config : public IConfig {+    public:++        Config() = default;+        Config( ConfigData const& data );+        virtual ~Config() = default;++        std::string const& getFilename() const;++        bool listTests() const;+        bool listTestNamesOnly() const;+        bool listTags() const;+        bool listReporters() const;++        std::string getProcessName() const;+        std::string const& getReporterName() const;++        std::vector<std::string> const& getTestsOrTags() const override;+        std::vector<std::string> const& getSectionsToRun() const override;++        TestSpec const& testSpec() const override;+        bool hasTestFilters() const override;++        bool showHelp() const;++        // IConfig interface+        bool allowThrows() const override;+        std::ostream& stream() const override;+        std::string name() const override;+        bool includeSuccessfulResults() const override;+        bool warnAboutMissingAssertions() const override;+        bool warnAboutNoTests() const override;+        ShowDurations::OrNot showDurations() const override;+        double minDuration() const override;+        RunTests::InWhatOrder runOrder() const override;+        unsigned int rngSeed() const override;+        UseColour::YesOrNo useColour() const override;+        bool shouldDebugBreak() const override;+        int abortAfter() const override;+        bool showInvisibles() const override;+        Verbosity verbosity() const override;+        bool benchmarkNoAnalysis() const override;+        int benchmarkSamples() const override;+        double benchmarkConfidenceInterval() const override;+        unsigned int benchmarkResamples() const override;+        std::chrono::milliseconds benchmarkWarmupTime() const override;++    private:++        IStream const* openStream();+        ConfigData m_data;++        std::unique_ptr<IStream const> m_stream;+        TestSpec m_testSpec;+        bool m_hasTestFilters = false;+    };++} // end namespace Catch++// end catch_config.hpp+// start catch_assertionresult.h++#include <string>++namespace Catch {++    struct AssertionResultData+    {+        AssertionResultData() = delete;++        AssertionResultData( ResultWas::OfType _resultType, LazyExpression const& _lazyExpression );++        std::string message;+        mutable std::string reconstructedExpression;+        LazyExpression lazyExpression;+        ResultWas::OfType resultType;++        std::string reconstructExpression() const;+    };++    class AssertionResult {+    public:+        AssertionResult() = delete;+        AssertionResult( AssertionInfo const& info, AssertionResultData const& data );++        bool isOk() const;+        bool succeeded() const;+        ResultWas::OfType getResultType() const;+        bool hasExpression() const;+        bool hasMessage() const;+        std::string getExpression() const;+        std::string getExpressionInMacro() const;+        bool hasExpandedExpression() const;+        std::string getExpandedExpression() const;+        std::string getMessage() const;+        SourceLineInfo getSourceInfo() const;+        StringRef getTestMacroName() const;++    //protected:+        AssertionInfo m_info;+        AssertionResultData m_resultData;+    };++} // end namespace Catch++// end catch_assertionresult.h+#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+// start catch_estimate.hpp++ // Statistics estimates+++namespace Catch {+    namespace Benchmark {+        template <typename Duration>+        struct Estimate {+            Duration point;+            Duration lower_bound;+            Duration upper_bound;+            double confidence_interval;++            template <typename Duration2>+            operator Estimate<Duration2>() const {+                return { point, lower_bound, upper_bound, confidence_interval };+            }+        };+    } // namespace Benchmark+} // namespace Catch++// end catch_estimate.hpp+// start catch_outlier_classification.hpp++// Outlier information++namespace Catch {+    namespace Benchmark {+        struct OutlierClassification {+            int samples_seen = 0;+            int low_severe = 0;     // more than 3 times IQR below Q1+            int low_mild = 0;       // 1.5 to 3 times IQR below Q1+            int high_mild = 0;      // 1.5 to 3 times IQR above Q3+            int high_severe = 0;    // more than 3 times IQR above Q3++            int total() const {+                return low_severe + low_mild + high_mild + high_severe;+            }+        };+    } // namespace Benchmark+} // namespace Catch++// end catch_outlier_classification.hpp++#include <iterator>+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++#include <string>+#include <iosfwd>+#include <map>+#include <set>+#include <memory>+#include <algorithm>++namespace Catch {++    struct ReporterConfig {+        explicit ReporterConfig( IConfigPtr const& _fullConfig );++        ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream );++        std::ostream& stream() const;+        IConfigPtr fullConfig() const;++    private:+        std::ostream* m_stream;+        IConfigPtr m_fullConfig;+    };++    struct ReporterPreferences {+        bool shouldRedirectStdOut = false;+        bool shouldReportAllAssertions = false;+    };++    template<typename T>+    struct LazyStat : Option<T> {+        LazyStat& operator=( T const& _value ) {+            Option<T>::operator=( _value );+            used = false;+            return *this;+        }+        void reset() {+            Option<T>::reset();+            used = false;+        }+        bool used = false;+    };++    struct TestRunInfo {+        TestRunInfo( std::string const& _name );+        std::string name;+    };+    struct GroupInfo {+        GroupInfo(  std::string const& _name,+                    std::size_t _groupIndex,+                    std::size_t _groupsCount );++        std::string name;+        std::size_t groupIndex;+        std::size_t groupsCounts;+    };++    struct AssertionStats {+        AssertionStats( AssertionResult const& _assertionResult,+                        std::vector<MessageInfo> const& _infoMessages,+                        Totals const& _totals );++        AssertionStats( AssertionStats const& )              = default;+        AssertionStats( AssertionStats && )                  = default;+        AssertionStats& operator = ( AssertionStats const& ) = delete;+        AssertionStats& operator = ( AssertionStats && )     = delete;+        virtual ~AssertionStats();++        AssertionResult assertionResult;+        std::vector<MessageInfo> infoMessages;+        Totals totals;+    };++    struct SectionStats {+        SectionStats(   SectionInfo const& _sectionInfo,+                        Counts const& _assertions,+                        double _durationInSeconds,+                        bool _missingAssertions );+        SectionStats( SectionStats const& )              = default;+        SectionStats( SectionStats && )                  = default;+        SectionStats& operator = ( SectionStats const& ) = default;+        SectionStats& operator = ( SectionStats && )     = default;+        virtual ~SectionStats();++        SectionInfo sectionInfo;+        Counts assertions;+        double durationInSeconds;+        bool missingAssertions;+    };++    struct TestCaseStats {+        TestCaseStats(  TestCaseInfo const& _testInfo,+                        Totals const& _totals,+                        std::string const& _stdOut,+                        std::string const& _stdErr,+                        bool _aborting );++        TestCaseStats( TestCaseStats const& )              = default;+        TestCaseStats( TestCaseStats && )                  = default;+        TestCaseStats& operator = ( TestCaseStats const& ) = default;+        TestCaseStats& operator = ( TestCaseStats && )     = default;+        virtual ~TestCaseStats();++        TestCaseInfo testInfo;+        Totals totals;+        std::string stdOut;+        std::string stdErr;+        bool aborting;+    };++    struct TestGroupStats {+        TestGroupStats( GroupInfo const& _groupInfo,+                        Totals const& _totals,+                        bool _aborting );+        TestGroupStats( GroupInfo const& _groupInfo );++        TestGroupStats( TestGroupStats const& )              = default;+        TestGroupStats( TestGroupStats && )                  = default;+        TestGroupStats& operator = ( TestGroupStats const& ) = default;+        TestGroupStats& operator = ( TestGroupStats && )     = default;+        virtual ~TestGroupStats();++        GroupInfo groupInfo;+        Totals totals;+        bool aborting;+    };++    struct TestRunStats {+        TestRunStats(   TestRunInfo const& _runInfo,+                        Totals const& _totals,+                        bool _aborting );++        TestRunStats( TestRunStats const& )              = default;+        TestRunStats( TestRunStats && )                  = default;+        TestRunStats& operator = ( TestRunStats const& ) = default;+        TestRunStats& operator = ( TestRunStats && )     = default;+        virtual ~TestRunStats();++        TestRunInfo runInfo;+        Totals totals;+        bool aborting;+    };++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+    struct BenchmarkInfo {+        std::string name;+        double estimatedDuration;+        int iterations;+        int samples;+        unsigned int resamples;+        double clockResolution;+        double clockCost;+    };++    template <class Duration>+    struct BenchmarkStats {+        BenchmarkInfo info;++        std::vector<Duration> samples;+        Benchmark::Estimate<Duration> mean;+        Benchmark::Estimate<Duration> standardDeviation;+        Benchmark::OutlierClassification outliers;+        double outlierVariance;++        template <typename Duration2>+        operator BenchmarkStats<Duration2>() const {+            std::vector<Duration2> samples2;+            samples2.reserve(samples.size());+            std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); });+            return {+                info,+                std::move(samples2),+                mean,+                standardDeviation,+                outliers,+                outlierVariance,+            };+        }+    };+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++    struct IStreamingReporter {+        virtual ~IStreamingReporter() = default;++        // Implementing class must also provide the following static methods:+        // static std::string getDescription();+        // static std::set<Verbosity> getSupportedVerbosities()++        virtual ReporterPreferences getPreferences() const = 0;++        virtual void noMatchingTestCases( std::string const& spec ) = 0;++        virtual void reportInvalidArguments(std::string const&) {}++        virtual void testRunStarting( TestRunInfo const& testRunInfo ) = 0;+        virtual void testGroupStarting( GroupInfo const& groupInfo ) = 0;++        virtual void testCaseStarting( TestCaseInfo const& testInfo ) = 0;+        virtual void sectionStarting( SectionInfo const& sectionInfo ) = 0;++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+        virtual void benchmarkPreparing( std::string const& ) {}+        virtual void benchmarkStarting( BenchmarkInfo const& ) {}+        virtual void benchmarkEnded( BenchmarkStats<> const& ) {}+        virtual void benchmarkFailed( std::string const& ) {}+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++        virtual void assertionStarting( AssertionInfo const& assertionInfo ) = 0;++        // The return value indicates if the messages buffer should be cleared:+        virtual bool assertionEnded( AssertionStats const& assertionStats ) = 0;++        virtual void sectionEnded( SectionStats const& sectionStats ) = 0;+        virtual void testCaseEnded( TestCaseStats const& testCaseStats ) = 0;+        virtual void testGroupEnded( TestGroupStats const& testGroupStats ) = 0;+        virtual void testRunEnded( TestRunStats const& testRunStats ) = 0;++        virtual void skipTest( TestCaseInfo const& testInfo ) = 0;++        // Default empty implementation provided+        virtual void fatalErrorEncountered( StringRef name );++        virtual bool isMulti() const;+    };+    using IStreamingReporterPtr = std::unique_ptr<IStreamingReporter>;++    struct IReporterFactory {+        virtual ~IReporterFactory();+        virtual IStreamingReporterPtr create( ReporterConfig const& config ) const = 0;+        virtual std::string getDescription() const = 0;+    };+    using IReporterFactoryPtr = std::shared_ptr<IReporterFactory>;++    struct IReporterRegistry {+        using FactoryMap = std::map<std::string, IReporterFactoryPtr>;+        using Listeners = std::vector<IReporterFactoryPtr>;++        virtual ~IReporterRegistry();+        virtual IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const = 0;+        virtual FactoryMap const& getFactories() const = 0;+        virtual Listeners const& getListeners() const = 0;+    };++} // end namespace Catch++// end catch_interfaces_reporter.h+#include <algorithm>+#include <cstring>+#include <cfloat>+#include <cstdio>+#include <cassert>+#include <memory>+#include <ostream>++namespace Catch {+    void prepareExpandedExpression(AssertionResult& result);++    // Returns double formatted as %.3f (format expected on output)+    std::string getFormattedDuration( double duration );++    //! Should the reporter show+    bool shouldShowDuration( IConfig const& config, double duration );++    std::string serializeFilters( std::vector<std::string> const& container );++    template<typename DerivedT>+    struct StreamingReporterBase : IStreamingReporter {++        StreamingReporterBase( ReporterConfig const& _config )+        :   m_config( _config.fullConfig() ),+            stream( _config.stream() )+        {+            m_reporterPrefs.shouldRedirectStdOut = false;+            if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )+                CATCH_ERROR( "Verbosity level not supported by this reporter" );+        }++        ReporterPreferences getPreferences() const override {+            return m_reporterPrefs;+        }++        static std::set<Verbosity> getSupportedVerbosities() {+            return { Verbosity::Normal };+        }++        ~StreamingReporterBase() override = default;++        void noMatchingTestCases(std::string const&) override {}++        void reportInvalidArguments(std::string const&) override {}++        void testRunStarting(TestRunInfo const& _testRunInfo) override {+            currentTestRunInfo = _testRunInfo;+        }++        void testGroupStarting(GroupInfo const& _groupInfo) override {+            currentGroupInfo = _groupInfo;+        }++        void testCaseStarting(TestCaseInfo const& _testInfo) override  {+            currentTestCaseInfo = _testInfo;+        }+        void sectionStarting(SectionInfo const& _sectionInfo) override {+            m_sectionStack.push_back(_sectionInfo);+        }++        void sectionEnded(SectionStats const& /* _sectionStats */) override {+            m_sectionStack.pop_back();+        }+        void testCaseEnded(TestCaseStats const& /* _testCaseStats */) override {+            currentTestCaseInfo.reset();+        }+        void testGroupEnded(TestGroupStats const& /* _testGroupStats */) override {+            currentGroupInfo.reset();+        }+        void testRunEnded(TestRunStats const& /* _testRunStats */) override {+            currentTestCaseInfo.reset();+            currentGroupInfo.reset();+            currentTestRunInfo.reset();+        }++        void skipTest(TestCaseInfo const&) override {+            // Don't do anything with this by default.+            // It can optionally be overridden in the derived class.+        }++        IConfigPtr m_config;+        std::ostream& stream;++        LazyStat<TestRunInfo> currentTestRunInfo;+        LazyStat<GroupInfo> currentGroupInfo;+        LazyStat<TestCaseInfo> currentTestCaseInfo;++        std::vector<SectionInfo> m_sectionStack;+        ReporterPreferences m_reporterPrefs;+    };++    template<typename DerivedT>+    struct CumulativeReporterBase : IStreamingReporter {+        template<typename T, typename ChildNodeT>+        struct Node {+            explicit Node( T const& _value ) : value( _value ) {}+            virtual ~Node() {}++            using ChildNodes = std::vector<std::shared_ptr<ChildNodeT>>;+            T value;+            ChildNodes children;+        };+        struct SectionNode {+            explicit SectionNode(SectionStats const& _stats) : stats(_stats) {}+            virtual ~SectionNode() = default;++            bool operator == (SectionNode const& other) const {+                return stats.sectionInfo.lineInfo == other.stats.sectionInfo.lineInfo;+            }+            bool operator == (std::shared_ptr<SectionNode> const& other) const {+                return operator==(*other);+            }++            SectionStats stats;+            using ChildSections = std::vector<std::shared_ptr<SectionNode>>;+            using Assertions = std::vector<AssertionStats>;+            ChildSections childSections;+            Assertions assertions;+            std::string stdOut;+            std::string stdErr;+        };++        struct BySectionInfo {+            BySectionInfo( SectionInfo const& other ) : m_other( other ) {}+            BySectionInfo( BySectionInfo const& other ) : m_other( other.m_other ) {}+            bool operator() (std::shared_ptr<SectionNode> const& node) const {+                return ((node->stats.sectionInfo.name == m_other.name) &&+                        (node->stats.sectionInfo.lineInfo == m_other.lineInfo));+            }+            void operator=(BySectionInfo const&) = delete;++        private:+            SectionInfo const& m_other;+        };++        using TestCaseNode = Node<TestCaseStats, SectionNode>;+        using TestGroupNode = Node<TestGroupStats, TestCaseNode>;+        using TestRunNode = Node<TestRunStats, TestGroupNode>;++        CumulativeReporterBase( ReporterConfig const& _config )+        :   m_config( _config.fullConfig() ),+            stream( _config.stream() )+        {+            m_reporterPrefs.shouldRedirectStdOut = false;+            if( !DerivedT::getSupportedVerbosities().count( m_config->verbosity() ) )+                CATCH_ERROR( "Verbosity level not supported by this reporter" );+        }+        ~CumulativeReporterBase() override = default;++        ReporterPreferences getPreferences() const override {+            return m_reporterPrefs;+        }++        static std::set<Verbosity> getSupportedVerbosities() {+            return { Verbosity::Normal };+        }++        void testRunStarting( TestRunInfo const& ) override {}+        void testGroupStarting( GroupInfo const& ) override {}++        void testCaseStarting( TestCaseInfo const& ) override {}++        void sectionStarting( SectionInfo const& sectionInfo ) override {+            SectionStats incompleteStats( sectionInfo, Counts(), 0, false );+            std::shared_ptr<SectionNode> node;+            if( m_sectionStack.empty() ) {+                if( !m_rootSection )+                    m_rootSection = std::make_shared<SectionNode>( incompleteStats );+                node = m_rootSection;+            }+            else {+                SectionNode& parentNode = *m_sectionStack.back();+                auto it =+                    std::find_if(   parentNode.childSections.begin(),+                                    parentNode.childSections.end(),+                                    BySectionInfo( sectionInfo ) );+                if( it == parentNode.childSections.end() ) {+                    node = std::make_shared<SectionNode>( incompleteStats );+                    parentNode.childSections.push_back( node );+                }+                else+                    node = *it;+            }+            m_sectionStack.push_back( node );+            m_deepestSection = std::move(node);+        }++        void assertionStarting(AssertionInfo const&) override {}++        bool assertionEnded(AssertionStats const& assertionStats) override {+            assert(!m_sectionStack.empty());+            // AssertionResult holds a pointer to a temporary DecomposedExpression,+            // which getExpandedExpression() calls to build the expression string.+            // Our section stack copy of the assertionResult will likely outlive the+            // temporary, so it must be expanded or discarded now to avoid calling+            // a destroyed object later.+            prepareExpandedExpression(const_cast<AssertionResult&>( assertionStats.assertionResult ) );+            SectionNode& sectionNode = *m_sectionStack.back();+            sectionNode.assertions.push_back(assertionStats);+            return true;+        }+        void sectionEnded(SectionStats const& sectionStats) override {+            assert(!m_sectionStack.empty());+            SectionNode& node = *m_sectionStack.back();+            node.stats = sectionStats;+            m_sectionStack.pop_back();+        }+        void testCaseEnded(TestCaseStats const& testCaseStats) override {+            auto node = std::make_shared<TestCaseNode>(testCaseStats);+            assert(m_sectionStack.size() == 0);+            node->children.push_back(m_rootSection);+            m_testCases.push_back(node);+            m_rootSection.reset();++            assert(m_deepestSection);+            m_deepestSection->stdOut = testCaseStats.stdOut;+            m_deepestSection->stdErr = testCaseStats.stdErr;+        }+        void testGroupEnded(TestGroupStats const& testGroupStats) override {+            auto node = std::make_shared<TestGroupNode>(testGroupStats);+            node->children.swap(m_testCases);+            m_testGroups.push_back(node);+        }+        void testRunEnded(TestRunStats const& testRunStats) override {+            auto node = std::make_shared<TestRunNode>(testRunStats);+            node->children.swap(m_testGroups);+            m_testRuns.push_back(node);+            testRunEndedCumulative();+        }+        virtual void testRunEndedCumulative() = 0;++        void skipTest(TestCaseInfo const&) override {}++        IConfigPtr m_config;+        std::ostream& stream;+        std::vector<AssertionStats> m_assertions;+        std::vector<std::vector<std::shared_ptr<SectionNode>>> m_sections;+        std::vector<std::shared_ptr<TestCaseNode>> m_testCases;+        std::vector<std::shared_ptr<TestGroupNode>> m_testGroups;++        std::vector<std::shared_ptr<TestRunNode>> m_testRuns;++        std::shared_ptr<SectionNode> m_rootSection;+        std::shared_ptr<SectionNode> m_deepestSection;+        std::vector<std::shared_ptr<SectionNode>> m_sectionStack;+        ReporterPreferences m_reporterPrefs;+    };++    template<char C>+    char const* getLineOfChars() {+        static char line[CATCH_CONFIG_CONSOLE_WIDTH] = {0};+        if( !*line ) {+            std::memset( line, C, CATCH_CONFIG_CONSOLE_WIDTH-1 );+            line[CATCH_CONFIG_CONSOLE_WIDTH-1] = 0;+        }+        return line;+    }++    struct TestEventListenerBase : StreamingReporterBase<TestEventListenerBase> {+        TestEventListenerBase( ReporterConfig const& _config );++        static std::set<Verbosity> getSupportedVerbosities();++        void assertionStarting(AssertionInfo const&) override;+        bool assertionEnded(AssertionStats const&) override;+    };++} // end namespace Catch++// end catch_reporter_bases.hpp+// start catch_console_colour.h++namespace Catch {++    struct Colour {+        enum Code {+            None = 0,++            White,+            Red,+            Green,+            Blue,+            Cyan,+            Yellow,+            Grey,++            Bright = 0x10,++            BrightRed = Bright | Red,+            BrightGreen = Bright | Green,+            LightGrey = Bright | Grey,+            BrightWhite = Bright | White,+            BrightYellow = Bright | Yellow,++            // By intention+            FileName = LightGrey,+            Warning = BrightYellow,+            ResultError = BrightRed,+            ResultSuccess = BrightGreen,+            ResultExpectedFailure = Warning,++            Error = BrightRed,+            Success = Green,++            OriginalExpression = Cyan,+            ReconstructedExpression = BrightYellow,++            SecondaryText = LightGrey,+            Headers = White+        };++        // Use constructed object for RAII guard+        Colour( Code _colourCode );+        Colour( Colour&& other ) noexcept;+        Colour& operator=( Colour&& other ) noexcept;+        ~Colour();++        // Use static method for one-shot changes+        static void use( Code _colourCode );++    private:+        bool m_moved = false;+    };++    std::ostream& operator << ( std::ostream& os, Colour const& );++} // end namespace Catch++// end catch_console_colour.h+// start catch_reporter_registrars.hpp+++namespace Catch {++    template<typename T>+    class ReporterRegistrar {++        class ReporterFactory : public IReporterFactory {++            IStreamingReporterPtr create( ReporterConfig const& config ) const override {+                return std::unique_ptr<T>( new T( config ) );+            }++            std::string getDescription() const override {+                return T::getDescription();+            }+        };++    public:++        explicit ReporterRegistrar( std::string const& name ) {+            getMutableRegistryHub().registerReporter( name, std::make_shared<ReporterFactory>() );+        }+    };++    template<typename T>+    class ListenerRegistrar {++        class ListenerFactory : public IReporterFactory {++            IStreamingReporterPtr create( ReporterConfig const& config ) const override {+                return std::unique_ptr<T>( new T( config ) );+            }+            std::string getDescription() const override {+                return std::string();+            }+        };++    public:++        ListenerRegistrar() {+            getMutableRegistryHub().registerListener( std::make_shared<ListenerFactory>() );+        }+    };+}++#if !defined(CATCH_CONFIG_DISABLE)++#define CATCH_REGISTER_REPORTER( name, reporterType ) \+    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION         \+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS          \+    namespace{ Catch::ReporterRegistrar<reporterType> catch_internal_RegistrarFor##reporterType( name ); } \+    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION++#define CATCH_REGISTER_LISTENER( listenerType ) \+    CATCH_INTERNAL_START_WARNINGS_SUPPRESSION   \+    CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS    \+    namespace{ Catch::ListenerRegistrar<listenerType> catch_internal_RegistrarFor##listenerType; } \+    CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION+#else // CATCH_CONFIG_DISABLE++#define CATCH_REGISTER_REPORTER(name, reporterType)+#define CATCH_REGISTER_LISTENER(listenerType)++#endif // CATCH_CONFIG_DISABLE++// end catch_reporter_registrars.hpp+// Allow users to base their work off existing reporters+// start catch_reporter_compact.h++namespace Catch {++    struct CompactReporter : StreamingReporterBase<CompactReporter> {++        using StreamingReporterBase::StreamingReporterBase;++        ~CompactReporter() override;++        static std::string getDescription();++        void noMatchingTestCases(std::string const& spec) override;++        void assertionStarting(AssertionInfo const&) override;++        bool assertionEnded(AssertionStats const& _assertionStats) override;++        void sectionEnded(SectionStats const& _sectionStats) override;++        void testRunEnded(TestRunStats const& _testRunStats) override;++    };++} // end namespace Catch++// end catch_reporter_compact.h+// start catch_reporter_console.h++#if defined(_MSC_VER)+#pragma warning(push)+#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch+                              // Note that 4062 (not all labels are handled+                              // and default is missing) is enabled+#endif++namespace Catch {+    // Fwd decls+    struct SummaryColumn;+    class TablePrinter;++    struct ConsoleReporter : StreamingReporterBase<ConsoleReporter> {+        std::unique_ptr<TablePrinter> m_tablePrinter;++        ConsoleReporter(ReporterConfig const& config);+        ~ConsoleReporter() override;+        static std::string getDescription();++        void noMatchingTestCases(std::string const& spec) override;++        void reportInvalidArguments(std::string const&arg) override;++        void assertionStarting(AssertionInfo const&) override;++        bool assertionEnded(AssertionStats const& _assertionStats) override;++        void sectionStarting(SectionInfo const& _sectionInfo) override;+        void sectionEnded(SectionStats const& _sectionStats) override;++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+        void benchmarkPreparing(std::string const& name) override;+        void benchmarkStarting(BenchmarkInfo const& info) override;+        void benchmarkEnded(BenchmarkStats<> const& stats) override;+        void benchmarkFailed(std::string const& error) override;+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++        void testCaseEnded(TestCaseStats const& _testCaseStats) override;+        void testGroupEnded(TestGroupStats const& _testGroupStats) override;+        void testRunEnded(TestRunStats const& _testRunStats) override;+        void testRunStarting(TestRunInfo const& _testRunInfo) override;+    private:++        void lazyPrint();++        void lazyPrintWithoutClosingBenchmarkTable();+        void lazyPrintRunInfo();+        void lazyPrintGroupInfo();+        void printTestCaseAndSectionHeader();++        void printClosedHeader(std::string const& _name);+        void printOpenHeader(std::string const& _name);++        // if string has a : in first line will set indent to follow it on+        // subsequent lines+        void printHeaderString(std::string const& _string, std::size_t indent = 0);++        void printTotals(Totals const& totals);+        void printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row);++        void printTotalsDivider(Totals const& totals);+        void printSummaryDivider();+        void printTestFilters();++    private:+        bool m_headerPrinted = false;+    };++} // end namespace Catch++#if defined(_MSC_VER)+#pragma warning(pop)+#endif++// end catch_reporter_console.h+// start catch_reporter_junit.h++// start catch_xmlwriter.h++#include <vector>++namespace Catch {+    enum class XmlFormatting {+        None = 0x00,+        Indent = 0x01,+        Newline = 0x02,+    };++    XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs);+    XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs);++    class XmlEncode {+    public:+        enum ForWhat { ForTextNodes, ForAttributes };++        XmlEncode( std::string const& str, ForWhat forWhat = ForTextNodes );++        void encodeTo( std::ostream& os ) const;++        friend std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode );++    private:+        std::string m_str;+        ForWhat m_forWhat;+    };++    class XmlWriter {+    public:++        class ScopedElement {+        public:+            ScopedElement( XmlWriter* writer, XmlFormatting fmt );++            ScopedElement( ScopedElement&& other ) noexcept;+            ScopedElement& operator=( ScopedElement&& other ) noexcept;++            ~ScopedElement();++            ScopedElement& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent );++            template<typename T>+            ScopedElement& writeAttribute( std::string const& name, T const& attribute ) {+                m_writer->writeAttribute( name, attribute );+                return *this;+            }++        private:+            mutable XmlWriter* m_writer = nullptr;+            XmlFormatting m_fmt;+        };++        XmlWriter( std::ostream& os = Catch::cout() );+        ~XmlWriter();++        XmlWriter( XmlWriter const& ) = delete;+        XmlWriter& operator=( XmlWriter const& ) = delete;++        XmlWriter& startElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);++        ScopedElement scopedElement( std::string const& name, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);++        XmlWriter& endElement(XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);++        XmlWriter& writeAttribute( std::string const& name, std::string const& attribute );++        XmlWriter& writeAttribute( std::string const& name, bool attribute );++        template<typename T>+        XmlWriter& writeAttribute( std::string const& name, T const& attribute ) {+            ReusableStringStream rss;+            rss << attribute;+            return writeAttribute( name, rss.str() );+        }++        XmlWriter& writeText( std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);++        XmlWriter& writeComment(std::string const& text, XmlFormatting fmt = XmlFormatting::Newline | XmlFormatting::Indent);++        void writeStylesheetRef( std::string const& url );++        XmlWriter& writeBlankLine();++        void ensureTagClosed();++    private:++        void applyFormatting(XmlFormatting fmt);++        void writeDeclaration();++        void newlineIfNecessary();++        bool m_tagIsOpen = false;+        bool m_needsNewline = false;+        std::vector<std::string> m_tags;+        std::string m_indent;+        std::ostream& m_os;+    };++}++// end catch_xmlwriter.h+namespace Catch {++    class JunitReporter : public CumulativeReporterBase<JunitReporter> {+    public:+        JunitReporter(ReporterConfig const& _config);++        ~JunitReporter() override;++        static std::string getDescription();++        void noMatchingTestCases(std::string const& /*spec*/) override;++        void testRunStarting(TestRunInfo const& runInfo) override;++        void testGroupStarting(GroupInfo const& groupInfo) override;++        void testCaseStarting(TestCaseInfo const& testCaseInfo) override;+        bool assertionEnded(AssertionStats const& assertionStats) override;++        void testCaseEnded(TestCaseStats const& testCaseStats) override;++        void testGroupEnded(TestGroupStats const& testGroupStats) override;++        void testRunEndedCumulative() override;++        void writeGroup(TestGroupNode const& groupNode, double suiteTime);++        void writeTestCase(TestCaseNode const& testCaseNode);++        void writeSection( std::string const& className,+                           std::string const& rootName,+                           SectionNode const& sectionNode,+                           bool testOkToFail );++        void writeAssertions(SectionNode const& sectionNode);+        void writeAssertion(AssertionStats const& stats);++        XmlWriter xml;+        Timer suiteTimer;+        std::string stdOutForSuite;+        std::string stdErrForSuite;+        unsigned int unexpectedExceptions = 0;+        bool m_okToFail = false;+    };++} // end namespace Catch++// end catch_reporter_junit.h+// start catch_reporter_xml.h++namespace Catch {+    class XmlReporter : public StreamingReporterBase<XmlReporter> {+    public:+        XmlReporter(ReporterConfig const& _config);++        ~XmlReporter() override;++        static std::string getDescription();++        virtual std::string getStylesheetRef() const;++        void writeSourceInfo(SourceLineInfo const& sourceInfo);++    public: // StreamingReporterBase++        void noMatchingTestCases(std::string const& s) override;++        void testRunStarting(TestRunInfo const& testInfo) override;++        void testGroupStarting(GroupInfo const& groupInfo) override;++        void testCaseStarting(TestCaseInfo const& testInfo) override;++        void sectionStarting(SectionInfo const& sectionInfo) override;++        void assertionStarting(AssertionInfo const&) override;++        bool assertionEnded(AssertionStats const& assertionStats) override;++        void sectionEnded(SectionStats const& sectionStats) override;++        void testCaseEnded(TestCaseStats const& testCaseStats) override;++        void testGroupEnded(TestGroupStats const& testGroupStats) override;++        void testRunEnded(TestRunStats const& testRunStats) override;++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+        void benchmarkPreparing(std::string const& name) override;+        void benchmarkStarting(BenchmarkInfo const&) override;+        void benchmarkEnded(BenchmarkStats<> const&) override;+        void benchmarkFailed(std::string const&) override;+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++    private:+        Timer m_testCaseTimer;+        XmlWriter m_xml;+        int m_sectionDepth = 0;+    };++} // end namespace Catch++// end catch_reporter_xml.h++// end catch_external_interfaces.h+#endif++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+// start catch_benchmarking_all.hpp++// A proxy header that includes all of the benchmarking headers to allow+// concise include of the benchmarking features. You should prefer the+// individual includes in standard use.++// start catch_benchmark.hpp++ // Benchmark++// start catch_chronometer.hpp++// User-facing chronometer+++// start catch_clock.hpp++// Clocks+++#include <chrono>+#include <ratio>++namespace Catch {+    namespace Benchmark {+        template <typename Clock>+        using ClockDuration = typename Clock::duration;+        template <typename Clock>+        using FloatDuration = std::chrono::duration<double, typename Clock::period>;++        template <typename Clock>+        using TimePoint = typename Clock::time_point;++        using default_clock = std::chrono::steady_clock;++        template <typename Clock>+        struct now {+            TimePoint<Clock> operator()() const {+                return Clock::now();+            }+        };++        using fp_seconds = std::chrono::duration<double, std::ratio<1>>;+    } // namespace Benchmark+} // namespace Catch++// end catch_clock.hpp+// start catch_optimizer.hpp++ // Hinting the optimizer+++#if defined(_MSC_VER)+#   include <atomic> // atomic_thread_fence+#endif++namespace Catch {+    namespace Benchmark {+#if defined(__GNUC__) || defined(__clang__)+        template <typename T>+        inline void keep_memory(T* p) {+            asm volatile("" : : "g"(p) : "memory");+        }+        inline void keep_memory() {+            asm volatile("" : : : "memory");+        }++        namespace Detail {+            inline void optimizer_barrier() { keep_memory(); }+        } // namespace Detail+#elif defined(_MSC_VER)++#pragma optimize("", off)+        template <typename T>+        inline void keep_memory(T* p) {+            // thanks @milleniumbug+            *reinterpret_cast<char volatile*>(p) = *reinterpret_cast<char const volatile*>(p);+        }+        // TODO equivalent keep_memory()+#pragma optimize("", on)++        namespace Detail {+            inline void optimizer_barrier() {+                std::atomic_thread_fence(std::memory_order_seq_cst);+            }+        } // namespace Detail++#endif++        template <typename T>+        inline void deoptimize_value(T&& x) {+            keep_memory(&x);+        }++        template <typename Fn, typename... Args>+        inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<!std::is_same<void, decltype(fn(args...))>::value>::type {+            deoptimize_value(std::forward<Fn>(fn) (std::forward<Args...>(args...)));+        }++        template <typename Fn, typename... Args>+        inline auto invoke_deoptimized(Fn&& fn, Args&&... args) -> typename std::enable_if<std::is_same<void, decltype(fn(args...))>::value>::type {+            std::forward<Fn>(fn) (std::forward<Args...>(args...));+        }+    } // namespace Benchmark+} // namespace Catch++// end catch_optimizer.hpp+// start catch_complete_invoke.hpp++// Invoke with a special case for void+++#include <type_traits>+#include <utility>++namespace Catch {+    namespace Benchmark {+        namespace Detail {+            template <typename T>+            struct CompleteType { using type = T; };+            template <>+            struct CompleteType<void> { struct type {}; };++            template <typename T>+            using CompleteType_t = typename CompleteType<T>::type;++            template <typename Result>+            struct CompleteInvoker {+                template <typename Fun, typename... Args>+                static Result invoke(Fun&& fun, Args&&... args) {+                    return std::forward<Fun>(fun)(std::forward<Args>(args)...);+                }+            };+            template <>+            struct CompleteInvoker<void> {+                template <typename Fun, typename... Args>+                static CompleteType_t<void> invoke(Fun&& fun, Args&&... args) {+                    std::forward<Fun>(fun)(std::forward<Args>(args)...);+                    return {};+                }+            };++            // invoke and not return void :(+            template <typename Fun, typename... Args>+            CompleteType_t<FunctionReturnType<Fun, Args...>> complete_invoke(Fun&& fun, Args&&... args) {+                return CompleteInvoker<FunctionReturnType<Fun, Args...>>::invoke(std::forward<Fun>(fun), std::forward<Args>(args)...);+            }++            const std::string benchmarkErrorMsg = "a benchmark failed to run successfully";+        } // namespace Detail++        template <typename Fun>+        Detail::CompleteType_t<FunctionReturnType<Fun>> user_code(Fun&& fun) {+            CATCH_TRY{+                return Detail::complete_invoke(std::forward<Fun>(fun));+            } CATCH_CATCH_ALL{+                getResultCapture().benchmarkFailed(translateActiveException());+                CATCH_RUNTIME_ERROR(Detail::benchmarkErrorMsg);+            }+        }+    } // namespace Benchmark+} // namespace Catch++// end catch_complete_invoke.hpp+namespace Catch {+    namespace Benchmark {+        namespace Detail {+            struct ChronometerConcept {+                virtual void start() = 0;+                virtual void finish() = 0;+                virtual ~ChronometerConcept() = default;+            };+            template <typename Clock>+            struct ChronometerModel final : public ChronometerConcept {+                void start() override { started = Clock::now(); }+                void finish() override { finished = Clock::now(); }++                ClockDuration<Clock> elapsed() const { return finished - started; }++                TimePoint<Clock> started;+                TimePoint<Clock> finished;+            };+        } // namespace Detail++        struct Chronometer {+        public:+            template <typename Fun>+            void measure(Fun&& fun) { measure(std::forward<Fun>(fun), is_callable<Fun(int)>()); }++            int runs() const { return k; }++            Chronometer(Detail::ChronometerConcept& meter, int k)+                : impl(&meter)+                , k(k) {}++        private:+            template <typename Fun>+            void measure(Fun&& fun, std::false_type) {+                measure([&fun](int) { return fun(); }, std::true_type());+            }++            template <typename Fun>+            void measure(Fun&& fun, std::true_type) {+                Detail::optimizer_barrier();+                impl->start();+                for (int i = 0; i < k; ++i) invoke_deoptimized(fun, i);+                impl->finish();+                Detail::optimizer_barrier();+            }++            Detail::ChronometerConcept* impl;+            int k;+        };+    } // namespace Benchmark+} // namespace Catch++// end catch_chronometer.hpp+// start catch_environment.hpp++// Environment information+++namespace Catch {+    namespace Benchmark {+        template <typename Duration>+        struct EnvironmentEstimate {+            Duration mean;+            OutlierClassification outliers;++            template <typename Duration2>+            operator EnvironmentEstimate<Duration2>() const {+                return { mean, outliers };+            }+        };+        template <typename Clock>+        struct Environment {+            using clock_type = Clock;+            EnvironmentEstimate<FloatDuration<Clock>> clock_resolution;+            EnvironmentEstimate<FloatDuration<Clock>> clock_cost;+        };+    } // namespace Benchmark+} // namespace Catch++// end catch_environment.hpp+// start catch_execution_plan.hpp++ // Execution plan+++// start catch_benchmark_function.hpp++ // Dumb std::function implementation for consistent call overhead+++#include <cassert>+#include <type_traits>+#include <utility>+#include <memory>++namespace Catch {+    namespace Benchmark {+        namespace Detail {+            template <typename T>+            using Decay = typename std::decay<T>::type;+            template <typename T, typename U>+            struct is_related+                : std::is_same<Decay<T>, Decay<U>> {};++            /// We need to reinvent std::function because every piece of code that might add overhead+            /// in a measurement context needs to have consistent performance characteristics so that we+            /// can account for it in the measurement.+            /// Implementations of std::function with optimizations that aren't always applicable, like+            /// small buffer optimizations, are not uncommon.+            /// This is effectively an implementation of std::function without any such optimizations;+            /// it may be slow, but it is consistently slow.+            struct BenchmarkFunction {+            private:+                struct callable {+                    virtual void call(Chronometer meter) const = 0;+                    virtual callable* clone() const = 0;+                    virtual ~callable() = default;+                };+                template <typename Fun>+                struct model : public callable {+                    model(Fun&& fun) : fun(std::move(fun)) {}+                    model(Fun const& fun) : fun(fun) {}++                    model<Fun>* clone() const override { return new model<Fun>(*this); }++                    void call(Chronometer meter) const override {+                        call(meter, is_callable<Fun(Chronometer)>());+                    }+                    void call(Chronometer meter, std::true_type) const {+                        fun(meter);+                    }+                    void call(Chronometer meter, std::false_type) const {+                        meter.measure(fun);+                    }++                    Fun fun;+                };++                struct do_nothing { void operator()() const {} };++                template <typename T>+                BenchmarkFunction(model<T>* c) : f(c) {}++            public:+                BenchmarkFunction()+                    : f(new model<do_nothing>{ {} }) {}++                template <typename Fun,+                    typename std::enable_if<!is_related<Fun, BenchmarkFunction>::value, int>::type = 0>+                    BenchmarkFunction(Fun&& fun)+                    : f(new model<typename std::decay<Fun>::type>(std::forward<Fun>(fun))) {}++                BenchmarkFunction(BenchmarkFunction&& that)+                    : f(std::move(that.f)) {}++                BenchmarkFunction(BenchmarkFunction const& that)+                    : f(that.f->clone()) {}++                BenchmarkFunction& operator=(BenchmarkFunction&& that) {+                    f = std::move(that.f);+                    return *this;+                }++                BenchmarkFunction& operator=(BenchmarkFunction const& that) {+                    f.reset(that.f->clone());+                    return *this;+                }++                void operator()(Chronometer meter) const { f->call(meter); }++            private:+                std::unique_ptr<callable> f;+            };+        } // namespace Detail+    } // namespace Benchmark+} // namespace Catch++// end catch_benchmark_function.hpp+// start catch_repeat.hpp++// repeat algorithm+++#include <type_traits>+#include <utility>++namespace Catch {+    namespace Benchmark {+        namespace Detail {+            template <typename Fun>+            struct repeater {+                void operator()(int k) const {+                    for (int i = 0; i < k; ++i) {+                        fun();+                    }+                }+                Fun fun;+            };+            template <typename Fun>+            repeater<typename std::decay<Fun>::type> repeat(Fun&& fun) {+                return { std::forward<Fun>(fun) };+            }+        } // namespace Detail+    } // namespace Benchmark+} // namespace Catch++// end catch_repeat.hpp+// start catch_run_for_at_least.hpp++// Run a function for a minimum amount of time+++// start catch_measure.hpp++// Measure+++// start catch_timing.hpp++// Timing+++#include <tuple>+#include <type_traits>++namespace Catch {+    namespace Benchmark {+        template <typename Duration, typename Result>+        struct Timing {+            Duration elapsed;+            Result result;+            int iterations;+        };+        template <typename Clock, typename Func, typename... Args>+        using TimingOf = Timing<ClockDuration<Clock>, Detail::CompleteType_t<FunctionReturnType<Func, Args...>>>;+    } // namespace Benchmark+} // namespace Catch++// end catch_timing.hpp+#include <utility>++namespace Catch {+    namespace Benchmark {+        namespace Detail {+            template <typename Clock, typename Fun, typename... Args>+            TimingOf<Clock, Fun, Args...> measure(Fun&& fun, Args&&... args) {+                auto start = Clock::now();+                auto&& r = Detail::complete_invoke(fun, std::forward<Args>(args)...);+                auto end = Clock::now();+                auto delta = end - start;+                return { delta, std::forward<decltype(r)>(r), 1 };+            }+        } // namespace Detail+    } // namespace Benchmark+} // namespace Catch++// end catch_measure.hpp+#include <utility>+#include <type_traits>++namespace Catch {+    namespace Benchmark {+        namespace Detail {+            template <typename Clock, typename Fun>+            TimingOf<Clock, Fun, int> measure_one(Fun&& fun, int iters, std::false_type) {+                return Detail::measure<Clock>(fun, iters);+            }+            template <typename Clock, typename Fun>+            TimingOf<Clock, Fun, Chronometer> measure_one(Fun&& fun, int iters, std::true_type) {+                Detail::ChronometerModel<Clock> meter;+                auto&& result = Detail::complete_invoke(fun, Chronometer(meter, iters));++                return { meter.elapsed(), std::move(result), iters };+            }++            template <typename Clock, typename Fun>+            using run_for_at_least_argument_t = typename std::conditional<is_callable<Fun(Chronometer)>::value, Chronometer, int>::type;++            struct optimized_away_error : std::exception {+                const char* what() const noexcept override {+                    return "could not measure benchmark, maybe it was optimized away";+                }+            };++            template <typename Clock, typename Fun>+            TimingOf<Clock, Fun, run_for_at_least_argument_t<Clock, Fun>> run_for_at_least(ClockDuration<Clock> how_long, int seed, Fun&& fun) {+                auto iters = seed;+                while (iters < (1 << 30)) {+                    auto&& Timing = measure_one<Clock>(fun, iters, is_callable<Fun(Chronometer)>());++                    if (Timing.elapsed >= how_long) {+                        return { Timing.elapsed, std::move(Timing.result), iters };+                    }+                    iters *= 2;+                }+                Catch::throw_exception(optimized_away_error{});+            }+        } // namespace Detail+    } // namespace Benchmark+} // namespace Catch++// end catch_run_for_at_least.hpp+#include <algorithm>+#include <iterator>++namespace Catch {+    namespace Benchmark {+        template <typename Duration>+        struct ExecutionPlan {+            int iterations_per_sample;+            Duration estimated_duration;+            Detail::BenchmarkFunction benchmark;+            Duration warmup_time;+            int warmup_iterations;++            template <typename Duration2>+            operator ExecutionPlan<Duration2>() const {+                return { iterations_per_sample, estimated_duration, benchmark, warmup_time, warmup_iterations };+            }++            template <typename Clock>+            std::vector<FloatDuration<Clock>> run(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {+                // warmup a bit+                Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_iterations, Detail::repeat(now<Clock>{}));++                std::vector<FloatDuration<Clock>> times;+                times.reserve(cfg.benchmarkSamples());+                std::generate_n(std::back_inserter(times), cfg.benchmarkSamples(), [this, env] {+                    Detail::ChronometerModel<Clock> model;+                    this->benchmark(Chronometer(model, iterations_per_sample));+                    auto sample_time = model.elapsed() - env.clock_cost.mean;+                    if (sample_time < FloatDuration<Clock>::zero()) sample_time = FloatDuration<Clock>::zero();+                    return sample_time / iterations_per_sample;+                });+                return times;+            }+        };+    } // namespace Benchmark+} // namespace Catch++// end catch_execution_plan.hpp+// start catch_estimate_clock.hpp++ // Environment measurement+++// start catch_stats.hpp++// Statistical analysis tools+++#include <algorithm>+#include <functional>+#include <vector>+#include <iterator>+#include <numeric>+#include <tuple>+#include <cmath>+#include <utility>+#include <cstddef>+#include <random>++namespace Catch {+    namespace Benchmark {+        namespace Detail {+            using sample = std::vector<double>;++            double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last);++            template <typename Iterator>+            OutlierClassification classify_outliers(Iterator first, Iterator last) {+                std::vector<double> copy(first, last);++                auto q1 = weighted_average_quantile(1, 4, copy.begin(), copy.end());+                auto q3 = weighted_average_quantile(3, 4, copy.begin(), copy.end());+                auto iqr = q3 - q1;+                auto los = q1 - (iqr * 3.);+                auto lom = q1 - (iqr * 1.5);+                auto him = q3 + (iqr * 1.5);+                auto his = q3 + (iqr * 3.);++                OutlierClassification o;+                for (; first != last; ++first) {+                    auto&& t = *first;+                    if (t < los) ++o.low_severe;+                    else if (t < lom) ++o.low_mild;+                    else if (t > his) ++o.high_severe;+                    else if (t > him) ++o.high_mild;+                    ++o.samples_seen;+                }+                return o;+            }++            template <typename Iterator>+            double mean(Iterator first, Iterator last) {+                auto count = last - first;+                double sum = std::accumulate(first, last, 0.);+                return sum / count;+            }++            template <typename URng, typename Iterator, typename Estimator>+            sample resample(URng& rng, int resamples, Iterator first, Iterator last, Estimator& estimator) {+                auto n = last - first;+                std::uniform_int_distribution<decltype(n)> dist(0, n - 1);++                sample out;+                out.reserve(resamples);+                std::generate_n(std::back_inserter(out), resamples, [n, first, &estimator, &dist, &rng] {+                    std::vector<double> resampled;+                    resampled.reserve(n);+                    std::generate_n(std::back_inserter(resampled), n, [first, &dist, &rng] { return first[dist(rng)]; });+                    return estimator(resampled.begin(), resampled.end());+                });+                std::sort(out.begin(), out.end());+                return out;+            }++            template <typename Estimator, typename Iterator>+            sample jackknife(Estimator&& estimator, Iterator first, Iterator last) {+                auto n = last - first;+                auto second = std::next(first);+                sample results;+                results.reserve(n);++                for (auto it = first; it != last; ++it) {+                    std::iter_swap(it, first);+                    results.push_back(estimator(second, last));+                }++                return results;+            }++            inline double normal_cdf(double x) {+                return std::erfc(-x / std::sqrt(2.0)) / 2.0;+            }++            double erfc_inv(double x);++            double normal_quantile(double p);++            template <typename Iterator, typename Estimator>+            Estimate<double> bootstrap(double confidence_level, Iterator first, Iterator last, sample const& resample, Estimator&& estimator) {+                auto n_samples = last - first;++                double point = estimator(first, last);+                // Degenerate case with a single sample+                if (n_samples == 1) return { point, point, point, confidence_level };++                sample jack = jackknife(estimator, first, last);+                double jack_mean = mean(jack.begin(), jack.end());+                double sum_squares, sum_cubes;+                std::tie(sum_squares, sum_cubes) = std::accumulate(jack.begin(), jack.end(), std::make_pair(0., 0.), [jack_mean](std::pair<double, double> sqcb, double x) -> std::pair<double, double> {+                    auto d = jack_mean - x;+                    auto d2 = d * d;+                    auto d3 = d2 * d;+                    return { sqcb.first + d2, sqcb.second + d3 };+                });++                double accel = sum_cubes / (6 * std::pow(sum_squares, 1.5));+                int n = static_cast<int>(resample.size());+                double prob_n = std::count_if(resample.begin(), resample.end(), [point](double x) { return x < point; }) / (double)n;+                // degenerate case with uniform samples+                if (prob_n == 0) return { point, point, point, confidence_level };++                double bias = normal_quantile(prob_n);+                double z1 = normal_quantile((1. - confidence_level) / 2.);++                auto cumn = [n](double x) -> int {+                    return std::lround(normal_cdf(x) * n); };+                auto a = [bias, accel](double b) { return bias + b / (1. - accel * b); };+                double b1 = bias + z1;+                double b2 = bias - z1;+                double a1 = a(b1);+                double a2 = a(b2);+                auto lo = (std::max)(cumn(a1), 0);+                auto hi = (std::min)(cumn(a2), n - 1);++                return { point, resample[lo], resample[hi], confidence_level };+            }++            double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n);++            struct bootstrap_analysis {+                Estimate<double> mean;+                Estimate<double> standard_deviation;+                double outlier_variance;+            };++            bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last);+        } // namespace Detail+    } // namespace Benchmark+} // namespace Catch++// end catch_stats.hpp+#include <algorithm>+#include <iterator>+#include <tuple>+#include <vector>+#include <cmath>++namespace Catch {+    namespace Benchmark {+        namespace Detail {+            template <typename Clock>+            std::vector<double> resolution(int k) {+                std::vector<TimePoint<Clock>> times;+                times.reserve(k + 1);+                std::generate_n(std::back_inserter(times), k + 1, now<Clock>{});++                std::vector<double> deltas;+                deltas.reserve(k);+                std::transform(std::next(times.begin()), times.end(), times.begin(),+                    std::back_inserter(deltas),+                    [](TimePoint<Clock> a, TimePoint<Clock> b) { return static_cast<double>((a - b).count()); });++                return deltas;+            }++            const auto warmup_iterations = 10000;+            const auto warmup_time = std::chrono::milliseconds(100);+            const auto minimum_ticks = 1000;+            const auto warmup_seed = 10000;+            const auto clock_resolution_estimation_time = std::chrono::milliseconds(500);+            const auto clock_cost_estimation_time_limit = std::chrono::seconds(1);+            const auto clock_cost_estimation_tick_limit = 100000;+            const auto clock_cost_estimation_time = std::chrono::milliseconds(10);+            const auto clock_cost_estimation_iterations = 10000;++            template <typename Clock>+            int warmup() {+                return run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(warmup_time), warmup_seed, &resolution<Clock>)+                    .iterations;+            }+            template <typename Clock>+            EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_resolution(int iterations) {+                auto r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_resolution_estimation_time), iterations, &resolution<Clock>)+                    .result;+                return {+                    FloatDuration<Clock>(mean(r.begin(), r.end())),+                    classify_outliers(r.begin(), r.end()),+                };+            }+            template <typename Clock>+            EnvironmentEstimate<FloatDuration<Clock>> estimate_clock_cost(FloatDuration<Clock> resolution) {+                auto time_limit = (std::min)(+                    resolution * clock_cost_estimation_tick_limit,+                    FloatDuration<Clock>(clock_cost_estimation_time_limit));+                auto time_clock = [](int k) {+                    return Detail::measure<Clock>([k] {+                        for (int i = 0; i < k; ++i) {+                            volatile auto ignored = Clock::now();+                            (void)ignored;+                        }+                    }).elapsed;+                };+                time_clock(1);+                int iters = clock_cost_estimation_iterations;+                auto&& r = run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(clock_cost_estimation_time), iters, time_clock);+                std::vector<double> times;+                int nsamples = static_cast<int>(std::ceil(time_limit / r.elapsed));+                times.reserve(nsamples);+                std::generate_n(std::back_inserter(times), nsamples, [time_clock, &r] {+                    return static_cast<double>((time_clock(r.iterations) / r.iterations).count());+                });+                return {+                    FloatDuration<Clock>(mean(times.begin(), times.end())),+                    classify_outliers(times.begin(), times.end()),+                };+            }++            template <typename Clock>+            Environment<FloatDuration<Clock>> measure_environment() {+                static Environment<FloatDuration<Clock>>* env = nullptr;+                if (env) {+                    return *env;+                }++                auto iters = Detail::warmup<Clock>();+                auto resolution = Detail::estimate_clock_resolution<Clock>(iters);+                auto cost = Detail::estimate_clock_cost<Clock>(resolution.mean);++                env = new Environment<FloatDuration<Clock>>{ resolution, cost };+                return *env;+            }+        } // namespace Detail+    } // namespace Benchmark+} // namespace Catch++// end catch_estimate_clock.hpp+// start catch_analyse.hpp++ // Run and analyse one benchmark+++// start catch_sample_analysis.hpp++// Benchmark results+++#include <algorithm>+#include <vector>+#include <string>+#include <iterator>++namespace Catch {+    namespace Benchmark {+        template <typename Duration>+        struct SampleAnalysis {+            std::vector<Duration> samples;+            Estimate<Duration> mean;+            Estimate<Duration> standard_deviation;+            OutlierClassification outliers;+            double outlier_variance;++            template <typename Duration2>+            operator SampleAnalysis<Duration2>() const {+                std::vector<Duration2> samples2;+                samples2.reserve(samples.size());+                std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](Duration d) { return Duration2(d); });+                return {+                    std::move(samples2),+                    mean,+                    standard_deviation,+                    outliers,+                    outlier_variance,+                };+            }+        };+    } // namespace Benchmark+} // namespace Catch++// end catch_sample_analysis.hpp+#include <algorithm>+#include <iterator>+#include <vector>++namespace Catch {+    namespace Benchmark {+        namespace Detail {+            template <typename Duration, typename Iterator>+            SampleAnalysis<Duration> analyse(const IConfig &cfg, Environment<Duration>, Iterator first, Iterator last) {+                if (!cfg.benchmarkNoAnalysis()) {+                    std::vector<double> samples;+                    samples.reserve(last - first);+                    std::transform(first, last, std::back_inserter(samples), [](Duration d) { return d.count(); });++                    auto analysis = Catch::Benchmark::Detail::analyse_samples(cfg.benchmarkConfidenceInterval(), cfg.benchmarkResamples(), samples.begin(), samples.end());+                    auto outliers = Catch::Benchmark::Detail::classify_outliers(samples.begin(), samples.end());++                    auto wrap_estimate = [](Estimate<double> e) {+                        return Estimate<Duration> {+                            Duration(e.point),+                                Duration(e.lower_bound),+                                Duration(e.upper_bound),+                                e.confidence_interval,+                        };+                    };+                    std::vector<Duration> samples2;+                    samples2.reserve(samples.size());+                    std::transform(samples.begin(), samples.end(), std::back_inserter(samples2), [](double d) { return Duration(d); });+                    return {+                        std::move(samples2),+                        wrap_estimate(analysis.mean),+                        wrap_estimate(analysis.standard_deviation),+                        outliers,+                        analysis.outlier_variance,+                    };+                } else {+                    std::vector<Duration> samples;+                    samples.reserve(last - first);++                    Duration mean = Duration(0);+                    int i = 0;+                    for (auto it = first; it < last; ++it, ++i) {+                        samples.push_back(Duration(*it));+                        mean += Duration(*it);+                    }+                    mean /= i;++                    return {+                        std::move(samples),+                        Estimate<Duration>{mean, mean, mean, 0.0},+                        Estimate<Duration>{Duration(0), Duration(0), Duration(0), 0.0},+                        OutlierClassification{},+                        0.0+                    };+                }+            }+        } // namespace Detail+    } // namespace Benchmark+} // namespace Catch++// end catch_analyse.hpp+#include <algorithm>+#include <functional>+#include <string>+#include <vector>+#include <cmath>++namespace Catch {+    namespace Benchmark {+        struct Benchmark {+            Benchmark(std::string &&name)+                : name(std::move(name)) {}++            template <class FUN>+            Benchmark(std::string &&name, FUN &&func)+                : fun(std::move(func)), name(std::move(name)) {}++            template <typename Clock>+            ExecutionPlan<FloatDuration<Clock>> prepare(const IConfig &cfg, Environment<FloatDuration<Clock>> env) const {+                auto min_time = env.clock_resolution.mean * Detail::minimum_ticks;+                auto run_time = std::max(min_time, std::chrono::duration_cast<decltype(min_time)>(cfg.benchmarkWarmupTime()));+                auto&& test = Detail::run_for_at_least<Clock>(std::chrono::duration_cast<ClockDuration<Clock>>(run_time), 1, fun);+                int new_iters = static_cast<int>(std::ceil(min_time * test.iterations / test.elapsed));+                return { new_iters, test.elapsed / test.iterations * new_iters * cfg.benchmarkSamples(), fun, std::chrono::duration_cast<FloatDuration<Clock>>(cfg.benchmarkWarmupTime()), Detail::warmup_iterations };+            }++            template <typename Clock = default_clock>+            void run() {+                IConfigPtr cfg = getCurrentContext().getConfig();++                auto env = Detail::measure_environment<Clock>();++                getResultCapture().benchmarkPreparing(name);+                CATCH_TRY{+                    auto plan = user_code([&] {+                        return prepare<Clock>(*cfg, env);+                    });++                    BenchmarkInfo info {+                        name,+                        plan.estimated_duration.count(),+                        plan.iterations_per_sample,+                        cfg->benchmarkSamples(),+                        cfg->benchmarkResamples(),+                        env.clock_resolution.mean.count(),+                        env.clock_cost.mean.count()+                    };++                    getResultCapture().benchmarkStarting(info);++                    auto samples = user_code([&] {+                        return plan.template run<Clock>(*cfg, env);+                    });++                    auto analysis = Detail::analyse(*cfg, env, samples.begin(), samples.end());+                    BenchmarkStats<FloatDuration<Clock>> stats{ info, analysis.samples, analysis.mean, analysis.standard_deviation, analysis.outliers, analysis.outlier_variance };+                    getResultCapture().benchmarkEnded(stats);++                } CATCH_CATCH_ALL{+                    if (translateActiveException() != Detail::benchmarkErrorMsg) // benchmark errors have been reported, otherwise rethrow.+                        std::rethrow_exception(std::current_exception());+                }+            }++            // sets lambda to be used in fun *and* executes benchmark!+            template <typename Fun,+                typename std::enable_if<!Detail::is_related<Fun, Benchmark>::value, int>::type = 0>+                Benchmark & operator=(Fun func) {+                fun = Detail::BenchmarkFunction(func);+                run();+                return *this;+            }++            explicit operator bool() {+                return true;+            }++        private:+            Detail::BenchmarkFunction fun;+            std::string name;+        };+    }+} // namespace Catch++#define INTERNAL_CATCH_GET_1_ARG(arg1, arg2, ...) arg1+#define INTERNAL_CATCH_GET_2_ARG(arg1, arg2, ...) arg2++#define INTERNAL_CATCH_BENCHMARK(BenchmarkName, name, benchmarkIndex)\+    if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \+        BenchmarkName = [&](int benchmarkIndex)++#define INTERNAL_CATCH_BENCHMARK_ADVANCED(BenchmarkName, name)\+    if( Catch::Benchmark::Benchmark BenchmarkName{name} ) \+        BenchmarkName = [&]++// end catch_benchmark.hpp+// start catch_constructor.hpp++// Constructor and destructor helpers+++#include <type_traits>++namespace Catch {+    namespace Benchmark {+        namespace Detail {+            template <typename T, bool Destruct>+            struct ObjectStorage+            {+                using TStorage = typename std::aligned_storage<sizeof(T), std::alignment_of<T>::value>::type;++                ObjectStorage() : data() {}++                ObjectStorage(const ObjectStorage& other)+                {+                    new(&data) T(other.stored_object());+                }++                ObjectStorage(ObjectStorage&& other)+                {+                    new(&data) T(std::move(other.stored_object()));+                }++                ~ObjectStorage() { destruct_on_exit<T>(); }++                template <typename... Args>+                void construct(Args&&... args)+                {+                    new (&data) T(std::forward<Args>(args)...);+                }++                template <bool AllowManualDestruction = !Destruct>+                typename std::enable_if<AllowManualDestruction>::type destruct()+                {+                    stored_object().~T();+                }++            private:+                // If this is a constructor benchmark, destruct the underlying object+                template <typename U>+                void destruct_on_exit(typename std::enable_if<Destruct, U>::type* = 0) { destruct<true>(); }+                // Otherwise, don't+                template <typename U>+                void destruct_on_exit(typename std::enable_if<!Destruct, U>::type* = 0) { }++                T& stored_object() {+                    return *static_cast<T*>(static_cast<void*>(&data));+                }++                T const& stored_object() const {+                    return *static_cast<T*>(static_cast<void*>(&data));+                }++                TStorage data;+            };+        }++        template <typename T>+        using storage_for = Detail::ObjectStorage<T, true>;++        template <typename T>+        using destructable_object = Detail::ObjectStorage<T, false>;+    }+}++// end catch_constructor.hpp+// end catch_benchmarking_all.hpp+#endif++#endif // ! CATCH_CONFIG_IMPL_ONLY++#ifdef CATCH_IMPL+// start catch_impl.hpp++#ifdef __clang__+#pragma clang diagnostic push+#pragma clang diagnostic ignored "-Wweak-vtables"+#endif++// Keep these here for external reporters+// start catch_test_case_tracker.h++#include <string>+#include <vector>+#include <memory>++namespace Catch {+namespace TestCaseTracking {++    struct NameAndLocation {+        std::string name;+        SourceLineInfo location;++        NameAndLocation( std::string const& _name, SourceLineInfo const& _location );+        friend bool operator==(NameAndLocation const& lhs, NameAndLocation const& rhs) {+            return lhs.name == rhs.name+                && lhs.location == rhs.location;+        }+    };++    class ITracker;++    using ITrackerPtr = std::shared_ptr<ITracker>;++    class  ITracker {+        NameAndLocation m_nameAndLocation;++    public:+        ITracker(NameAndLocation const& nameAndLoc) :+            m_nameAndLocation(nameAndLoc)+        {}++        // static queries+        NameAndLocation const& nameAndLocation() const {+            return m_nameAndLocation;+        }++        virtual ~ITracker();++        // dynamic queries+        virtual bool isComplete() const = 0; // Successfully completed or failed+        virtual bool isSuccessfullyCompleted() const = 0;+        virtual bool isOpen() const = 0; // Started but not complete+        virtual bool hasChildren() const = 0;+        virtual bool hasStarted() const = 0;++        virtual ITracker& parent() = 0;++        // actions+        virtual void close() = 0; // Successfully complete+        virtual void fail() = 0;+        virtual void markAsNeedingAnotherRun() = 0;++        virtual void addChild( ITrackerPtr const& child ) = 0;+        virtual ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) = 0;+        virtual void openChild() = 0;++        // Debug/ checking+        virtual bool isSectionTracker() const = 0;+        virtual bool isGeneratorTracker() const = 0;+    };++    class TrackerContext {++        enum RunState {+            NotStarted,+            Executing,+            CompletedCycle+        };++        ITrackerPtr m_rootTracker;+        ITracker* m_currentTracker = nullptr;+        RunState m_runState = NotStarted;++    public:++        ITracker& startRun();+        void endRun();++        void startCycle();+        void completeCycle();++        bool completedCycle() const;+        ITracker& currentTracker();+        void setCurrentTracker( ITracker* tracker );+    };++    class TrackerBase : public ITracker {+    protected:+        enum CycleState {+            NotStarted,+            Executing,+            ExecutingChildren,+            NeedsAnotherRun,+            CompletedSuccessfully,+            Failed+        };++        using Children = std::vector<ITrackerPtr>;+        TrackerContext& m_ctx;+        ITracker* m_parent;+        Children m_children;+        CycleState m_runState = NotStarted;++    public:+        TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );++        bool isComplete() const override;+        bool isSuccessfullyCompleted() const override;+        bool isOpen() const override;+        bool hasChildren() const override;+        bool hasStarted() const override {+            return m_runState != NotStarted;+        }++        void addChild( ITrackerPtr const& child ) override;++        ITrackerPtr findChild( NameAndLocation const& nameAndLocation ) override;+        ITracker& parent() override;++        void openChild() override;++        bool isSectionTracker() const override;+        bool isGeneratorTracker() const override;++        void open();++        void close() override;+        void fail() override;+        void markAsNeedingAnotherRun() override;++    private:+        void moveToParent();+        void moveToThis();+    };++    class SectionTracker : public TrackerBase {+        std::vector<std::string> m_filters;+        std::string m_trimmed_name;+    public:+        SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent );++        bool isSectionTracker() const override;++        bool isComplete() const override;++        static SectionTracker& acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation );++        void tryOpen();++        void addInitialFilters( std::vector<std::string> const& filters );+        void addNextFilters( std::vector<std::string> const& filters );+        //! Returns filters active in this tracker+        std::vector<std::string> const& getFilters() const;+        //! Returns whitespace-trimmed name of the tracked section+        std::string const& trimmedName() const;+    };++} // namespace TestCaseTracking++using TestCaseTracking::ITracker;+using TestCaseTracking::TrackerContext;+using TestCaseTracking::SectionTracker;++} // namespace Catch++// end catch_test_case_tracker.h++// start catch_leak_detector.h++namespace Catch {++    struct LeakDetector {+        LeakDetector();+        ~LeakDetector();+    };++}+// end catch_leak_detector.h+// Cpp files will be included in the single-header file here+// start catch_stats.cpp++// Statistical analysis tools++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)++#include <cassert>+#include <random>++#if defined(CATCH_CONFIG_USE_ASYNC)+#include <future>+#endif++namespace {+    double erf_inv(double x) {+        // Code accompanying the article "Approximating the erfinv function" in GPU Computing Gems, Volume 2+        double w, p;++        w = -log((1.0 - x) * (1.0 + x));++        if (w < 6.250000) {+            w = w - 3.125000;+            p = -3.6444120640178196996e-21;+            p = -1.685059138182016589e-19 + p * w;+            p = 1.2858480715256400167e-18 + p * w;+            p = 1.115787767802518096e-17 + p * w;+            p = -1.333171662854620906e-16 + p * w;+            p = 2.0972767875968561637e-17 + p * w;+            p = 6.6376381343583238325e-15 + p * w;+            p = -4.0545662729752068639e-14 + p * w;+            p = -8.1519341976054721522e-14 + p * w;+            p = 2.6335093153082322977e-12 + p * w;+            p = -1.2975133253453532498e-11 + p * w;+            p = -5.4154120542946279317e-11 + p * w;+            p = 1.051212273321532285e-09 + p * w;+            p = -4.1126339803469836976e-09 + p * w;+            p = -2.9070369957882005086e-08 + p * w;+            p = 4.2347877827932403518e-07 + p * w;+            p = -1.3654692000834678645e-06 + p * w;+            p = -1.3882523362786468719e-05 + p * w;+            p = 0.0001867342080340571352 + p * w;+            p = -0.00074070253416626697512 + p * w;+            p = -0.0060336708714301490533 + p * w;+            p = 0.24015818242558961693 + p * w;+            p = 1.6536545626831027356 + p * w;+        } else if (w < 16.000000) {+            w = sqrt(w) - 3.250000;+            p = 2.2137376921775787049e-09;+            p = 9.0756561938885390979e-08 + p * w;+            p = -2.7517406297064545428e-07 + p * w;+            p = 1.8239629214389227755e-08 + p * w;+            p = 1.5027403968909827627e-06 + p * w;+            p = -4.013867526981545969e-06 + p * w;+            p = 2.9234449089955446044e-06 + p * w;+            p = 1.2475304481671778723e-05 + p * w;+            p = -4.7318229009055733981e-05 + p * w;+            p = 6.8284851459573175448e-05 + p * w;+            p = 2.4031110387097893999e-05 + p * w;+            p = -0.0003550375203628474796 + p * w;+            p = 0.00095328937973738049703 + p * w;+            p = -0.0016882755560235047313 + p * w;+            p = 0.0024914420961078508066 + p * w;+            p = -0.0037512085075692412107 + p * w;+            p = 0.005370914553590063617 + p * w;+            p = 1.0052589676941592334 + p * w;+            p = 3.0838856104922207635 + p * w;+        } else {+            w = sqrt(w) - 5.000000;+            p = -2.7109920616438573243e-11;+            p = -2.5556418169965252055e-10 + p * w;+            p = 1.5076572693500548083e-09 + p * w;+            p = -3.7894654401267369937e-09 + p * w;+            p = 7.6157012080783393804e-09 + p * w;+            p = -1.4960026627149240478e-08 + p * w;+            p = 2.9147953450901080826e-08 + p * w;+            p = -6.7711997758452339498e-08 + p * w;+            p = 2.2900482228026654717e-07 + p * w;+            p = -9.9298272942317002539e-07 + p * w;+            p = 4.5260625972231537039e-06 + p * w;+            p = -1.9681778105531670567e-05 + p * w;+            p = 7.5995277030017761139e-05 + p * w;+            p = -0.00021503011930044477347 + p * w;+            p = -0.00013871931833623122026 + p * w;+            p = 1.0103004648645343977 + p * w;+            p = 4.8499064014085844221 + p * w;+        }+        return p * x;+    }++    double standard_deviation(std::vector<double>::iterator first, std::vector<double>::iterator last) {+        auto m = Catch::Benchmark::Detail::mean(first, last);+        double variance = std::accumulate(first, last, 0., [m](double a, double b) {+            double diff = b - m;+            return a + diff * diff;+            }) / (last - first);+            return std::sqrt(variance);+    }++}++namespace Catch {+    namespace Benchmark {+        namespace Detail {++            double weighted_average_quantile(int k, int q, std::vector<double>::iterator first, std::vector<double>::iterator last) {+                auto count = last - first;+                double idx = (count - 1) * k / static_cast<double>(q);+                int j = static_cast<int>(idx);+                double g = idx - j;+                std::nth_element(first, first + j, last);+                auto xj = first[j];+                if (g == 0) return xj;++                auto xj1 = *std::min_element(first + (j + 1), last);+                return xj + g * (xj1 - xj);+            }++            double erfc_inv(double x) {+                return erf_inv(1.0 - x);+            }++            double normal_quantile(double p) {+                static const double ROOT_TWO = std::sqrt(2.0);++                double result = 0.0;+                assert(p >= 0 && p <= 1);+                if (p < 0 || p > 1) {+                    return result;+                }++                result = -erfc_inv(2.0 * p);+                // result *= normal distribution standard deviation (1.0) * sqrt(2)+                result *= /*sd * */ ROOT_TWO;+                // result += normal disttribution mean (0)+                return result;+            }++            double outlier_variance(Estimate<double> mean, Estimate<double> stddev, int n) {+                double sb = stddev.point;+                double mn = mean.point / n;+                double mg_min = mn / 2.;+                double sg = (std::min)(mg_min / 4., sb / std::sqrt(n));+                double sg2 = sg * sg;+                double sb2 = sb * sb;++                auto c_max = [n, mn, sb2, sg2](double x) -> double {+                    double k = mn - x;+                    double d = k * k;+                    double nd = n * d;+                    double k0 = -n * nd;+                    double k1 = sb2 - n * sg2 + nd;+                    double det = k1 * k1 - 4 * sg2 * k0;+                    return (int)(-2. * k0 / (k1 + std::sqrt(det)));+                };++                auto var_out = [n, sb2, sg2](double c) {+                    double nc = n - c;+                    return (nc / n) * (sb2 - nc * sg2);+                };++                return (std::min)(var_out(1), var_out((std::min)(c_max(0.), c_max(mg_min)))) / sb2;+            }++            bootstrap_analysis analyse_samples(double confidence_level, int n_resamples, std::vector<double>::iterator first, std::vector<double>::iterator last) {+                CATCH_INTERNAL_START_WARNINGS_SUPPRESSION+                CATCH_INTERNAL_SUPPRESS_GLOBALS_WARNINGS+                static std::random_device entropy;+                CATCH_INTERNAL_STOP_WARNINGS_SUPPRESSION++                auto n = static_cast<int>(last - first); // seriously, one can't use integral types without hell in C++++                auto mean = &Detail::mean<std::vector<double>::iterator>;+                auto stddev = &standard_deviation;++#if defined(CATCH_CONFIG_USE_ASYNC)+                auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {+                    auto seed = entropy();+                    return std::async(std::launch::async, [=] {+                        std::mt19937 rng(seed);+                        auto resampled = resample(rng, n_resamples, first, last, f);+                        return bootstrap(confidence_level, first, last, resampled, f);+                    });+                };++                auto mean_future = Estimate(mean);+                auto stddev_future = Estimate(stddev);++                auto mean_estimate = mean_future.get();+                auto stddev_estimate = stddev_future.get();+#else+                auto Estimate = [=](double(*f)(std::vector<double>::iterator, std::vector<double>::iterator)) {+                    auto seed = entropy();+                    std::mt19937 rng(seed);+                    auto resampled = resample(rng, n_resamples, first, last, f);+                    return bootstrap(confidence_level, first, last, resampled, f);+                };++                auto mean_estimate = Estimate(mean);+                auto stddev_estimate = Estimate(stddev);+#endif // CATCH_USE_ASYNC++                double outlier_variance = Detail::outlier_variance(mean_estimate, stddev_estimate, n);++                return { mean_estimate, stddev_estimate, outlier_variance };+            }+        } // namespace Detail+    } // namespace Benchmark+} // namespace Catch++#endif // CATCH_CONFIG_ENABLE_BENCHMARKING+// end catch_stats.cpp+// start catch_approx.cpp++#include <cmath>+#include <limits>++namespace {++// Performs equivalent check of std::fabs(lhs - rhs) <= margin+// But without the subtraction to allow for INFINITY in comparison+bool marginComparison(double lhs, double rhs, double margin) {+    return (lhs + margin >= rhs) && (rhs + margin >= lhs);+}++}++namespace Catch {+namespace Detail {++    Approx::Approx ( double value )+    :   m_epsilon( std::numeric_limits<float>::epsilon()*100 ),+        m_margin( 0.0 ),+        m_scale( 0.0 ),+        m_value( value )+    {}++    Approx Approx::custom() {+        return Approx( 0 );+    }++    Approx Approx::operator-() const {+        auto temp(*this);+        temp.m_value = -temp.m_value;+        return temp;+    }++    std::string Approx::toString() const {+        ReusableStringStream rss;+        rss << "Approx( " << ::Catch::Detail::stringify( m_value ) << " )";+        return rss.str();+    }++    bool Approx::equalityComparisonImpl(const double other) const {+        // First try with fixed margin, then compute margin based on epsilon, scale and Approx's value+        // Thanks to Richard Harris for his help refining the scaled margin value+        return marginComparison(m_value, other, m_margin)+            || marginComparison(m_value, other, m_epsilon * (m_scale + std::fabs(std::isinf(m_value)? 0 : m_value)));+    }++    void Approx::setMargin(double newMargin) {+        CATCH_ENFORCE(newMargin >= 0,+            "Invalid Approx::margin: " << newMargin << '.'+            << " Approx::Margin has to be non-negative.");+        m_margin = newMargin;+    }++    void Approx::setEpsilon(double newEpsilon) {+        CATCH_ENFORCE(newEpsilon >= 0 && newEpsilon <= 1.0,+            "Invalid Approx::epsilon: " << newEpsilon << '.'+            << " Approx::epsilon has to be in [0, 1]");+        m_epsilon = newEpsilon;+    }++} // end namespace Detail++namespace literals {+    Detail::Approx operator "" _a(long double val) {+        return Detail::Approx(val);+    }+    Detail::Approx operator "" _a(unsigned long long val) {+        return Detail::Approx(val);+    }+} // end namespace literals++std::string StringMaker<Catch::Detail::Approx>::convert(Catch::Detail::Approx const& value) {+    return value.toString();+}++} // end namespace Catch+// end catch_approx.cpp+// start catch_assertionhandler.cpp++// start catch_debugger.h++namespace Catch {+    bool isDebuggerActive();+}++#ifdef CATCH_PLATFORM_MAC++    #if defined(__i386__) || defined(__x86_64__)+        #define CATCH_TRAP() __asm__("int $3\n" : : ) /* NOLINT */+    #elif defined(__aarch64__)+        #define CATCH_TRAP()  __asm__(".inst 0xd4200000")+    #endif++#elif defined(CATCH_PLATFORM_IPHONE)++    // use inline assembler+    #if defined(__i386__) || defined(__x86_64__)+        #define CATCH_TRAP()  __asm__("int $3")+    #elif defined(__aarch64__)+        #define CATCH_TRAP()  __asm__(".inst 0xd4200000")+    #elif defined(__arm__) && !defined(__thumb__)+        #define CATCH_TRAP()  __asm__(".inst 0xe7f001f0")+    #elif defined(__arm__) &&  defined(__thumb__)+        #define CATCH_TRAP()  __asm__(".inst 0xde01")+    #endif++#elif defined(CATCH_PLATFORM_LINUX)+    // If we can use inline assembler, do it because this allows us to break+    // directly at the location of the failing check instead of breaking inside+    // raise() called from it, i.e. one stack frame below.+    #if defined(__GNUC__) && (defined(__i386) || defined(__x86_64))+        #define CATCH_TRAP() asm volatile ("int $3") /* NOLINT */+    #else // Fall back to the generic way.+        #include <signal.h>++        #define CATCH_TRAP() raise(SIGTRAP)+    #endif+#elif defined(_MSC_VER)+    #define CATCH_TRAP() __debugbreak()+#elif defined(__MINGW32__)+    extern "C" __declspec(dllimport) void __stdcall DebugBreak();+    #define CATCH_TRAP() DebugBreak()+#endif++#ifndef CATCH_BREAK_INTO_DEBUGGER+    #ifdef CATCH_TRAP+        #define CATCH_BREAK_INTO_DEBUGGER() []{ if( Catch::isDebuggerActive() ) { CATCH_TRAP(); } }()+    #else+        #define CATCH_BREAK_INTO_DEBUGGER() []{}()+    #endif+#endif++// end catch_debugger.h+// start catch_run_context.h++// start catch_fatal_condition.h++#include <cassert>++namespace Catch {++    // Wrapper for platform-specific fatal error (signals/SEH) handlers+    //+    // Tries to be cooperative with other handlers, and not step over+    // other handlers. This means that unknown structured exceptions+    // are passed on, previous signal handlers are called, and so on.+    //+    // Can only be instantiated once, and assumes that once a signal+    // is caught, the binary will end up terminating. Thus, there+    class FatalConditionHandler {+        bool m_started = false;++        // Install/disengage implementation for specific platform.+        // Should be if-defed to work on current platform, can assume+        // engage-disengage 1:1 pairing.+        void engage_platform();+        void disengage_platform();+    public:+        // Should also have platform-specific implementations as needed+        FatalConditionHandler();+        ~FatalConditionHandler();++        void engage() {+            assert(!m_started && "Handler cannot be installed twice.");+            m_started = true;+            engage_platform();+        }++        void disengage() {+            assert(m_started && "Handler cannot be uninstalled without being installed first");+            m_started = false;+            disengage_platform();+        }+    };++    //! Simple RAII guard for (dis)engaging the FatalConditionHandler+    class FatalConditionHandlerGuard {+        FatalConditionHandler* m_handler;+    public:+        FatalConditionHandlerGuard(FatalConditionHandler* handler):+            m_handler(handler) {+            m_handler->engage();+        }+        ~FatalConditionHandlerGuard() {+            m_handler->disengage();+        }+    };++} // end namespace Catch++// end catch_fatal_condition.h+#include <string>++namespace Catch {++    struct IMutableContext;++    ///////////////////////////////////////////////////////////////////////////++    class RunContext : public IResultCapture, public IRunner {++    public:+        RunContext( RunContext const& ) = delete;+        RunContext& operator =( RunContext const& ) = delete;++        explicit RunContext( IConfigPtr const& _config, IStreamingReporterPtr&& reporter );++        ~RunContext() override;++        void testGroupStarting( std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount );+        void testGroupEnded( std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount );++        Totals runTest(TestCase const& testCase);++        IConfigPtr config() const;+        IStreamingReporter& reporter() const;++    public: // IResultCapture++        // Assertion handlers+        void handleExpr+                (   AssertionInfo const& info,+                    ITransientExpression const& expr,+                    AssertionReaction& reaction ) override;+        void handleMessage+                (   AssertionInfo const& info,+                    ResultWas::OfType resultType,+                    StringRef const& message,+                    AssertionReaction& reaction ) override;+        void handleUnexpectedExceptionNotThrown+                (   AssertionInfo const& info,+                    AssertionReaction& reaction ) override;+        void handleUnexpectedInflightException+                (   AssertionInfo const& info,+                    std::string const& message,+                    AssertionReaction& reaction ) override;+        void handleIncomplete+                (   AssertionInfo const& info ) override;+        void handleNonExpr+                (   AssertionInfo const &info,+                    ResultWas::OfType resultType,+                    AssertionReaction &reaction ) override;++        bool sectionStarted( SectionInfo const& sectionInfo, Counts& assertions ) override;++        void sectionEnded( SectionEndInfo const& endInfo ) override;+        void sectionEndedEarly( SectionEndInfo const& endInfo ) override;++        auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& override;++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+        void benchmarkPreparing( std::string const& name ) override;+        void benchmarkStarting( BenchmarkInfo const& info ) override;+        void benchmarkEnded( BenchmarkStats<> const& stats ) override;+        void benchmarkFailed( std::string const& error ) override;+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++        void pushScopedMessage( MessageInfo const& message ) override;+        void popScopedMessage( MessageInfo const& message ) override;++        void emplaceUnscopedMessage( MessageBuilder const& builder ) override;++        std::string getCurrentTestName() const override;++        const AssertionResult* getLastResult() const override;++        void exceptionEarlyReported() override;++        void handleFatalErrorCondition( StringRef message ) override;++        bool lastAssertionPassed() override;++        void assertionPassed() override;++    public:+        // !TBD We need to do this another way!+        bool aborting() const final;++    private:++        void runCurrentTest( std::string& redirectedCout, std::string& redirectedCerr );+        void invokeActiveTestCase();++        void resetAssertionInfo();+        bool testForMissingAssertions( Counts& assertions );++        void assertionEnded( AssertionResult const& result );+        void reportExpr+                (   AssertionInfo const &info,+                    ResultWas::OfType resultType,+                    ITransientExpression const *expr,+                    bool negated );++        void populateReaction( AssertionReaction& reaction );++    private:++        void handleUnfinishedSections();++        TestRunInfo m_runInfo;+        IMutableContext& m_context;+        TestCase const* m_activeTestCase = nullptr;+        ITracker* m_testCaseTracker = nullptr;+        Option<AssertionResult> m_lastResult;++        IConfigPtr m_config;+        Totals m_totals;+        IStreamingReporterPtr m_reporter;+        std::vector<MessageInfo> m_messages;+        std::vector<ScopedMessage> m_messageScopes; /* Keeps owners of so-called unscoped messages. */+        AssertionInfo m_lastAssertionInfo;+        std::vector<SectionEndInfo> m_unfinishedSections;+        std::vector<ITracker*> m_activeSections;+        TrackerContext m_trackerContext;+        FatalConditionHandler m_fatalConditionhandler;+        bool m_lastAssertionPassed = false;+        bool m_shouldReportUnexpected = true;+        bool m_includeSuccessfulResults;+    };++    void seedRng(IConfig const& config);+    unsigned int rngSeed();+} // end namespace Catch++// end catch_run_context.h+namespace Catch {++    namespace {+        auto operator <<( std::ostream& os, ITransientExpression const& expr ) -> std::ostream& {+            expr.streamReconstructedExpression( os );+            return os;+        }+    }++    LazyExpression::LazyExpression( bool isNegated )+    :   m_isNegated( isNegated )+    {}++    LazyExpression::LazyExpression( LazyExpression const& other ) : m_isNegated( other.m_isNegated ) {}++    LazyExpression::operator bool() const {+        return m_transientExpression != nullptr;+    }++    auto operator << ( std::ostream& os, LazyExpression const& lazyExpr ) -> std::ostream& {+        if( lazyExpr.m_isNegated )+            os << "!";++        if( lazyExpr ) {+            if( lazyExpr.m_isNegated && lazyExpr.m_transientExpression->isBinaryExpression() )+                os << "(" << *lazyExpr.m_transientExpression << ")";+            else+                os << *lazyExpr.m_transientExpression;+        }+        else {+            os << "{** error - unchecked empty expression requested **}";+        }+        return os;+    }++    AssertionHandler::AssertionHandler+        (   StringRef const& macroName,+            SourceLineInfo const& lineInfo,+            StringRef capturedExpression,+            ResultDisposition::Flags resultDisposition )+    :   m_assertionInfo{ macroName, lineInfo, capturedExpression, resultDisposition },+        m_resultCapture( getResultCapture() )+    {}++    void AssertionHandler::handleExpr( ITransientExpression const& expr ) {+        m_resultCapture.handleExpr( m_assertionInfo, expr, m_reaction );+    }+    void AssertionHandler::handleMessage(ResultWas::OfType resultType, StringRef const& message) {+        m_resultCapture.handleMessage( m_assertionInfo, resultType, message, m_reaction );+    }++    auto AssertionHandler::allowThrows() const -> bool {+        return getCurrentContext().getConfig()->allowThrows();+    }++    void AssertionHandler::complete() {+        setCompleted();+        if( m_reaction.shouldDebugBreak ) {++            // If you find your debugger stopping you here then go one level up on the+            // call-stack for the code that caused it (typically a failed assertion)++            // (To go back to the test and change execution, jump over the throw, next)+            CATCH_BREAK_INTO_DEBUGGER();+        }+        if (m_reaction.shouldThrow) {+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+            throw Catch::TestFailureException();+#else+            CATCH_ERROR( "Test failure requires aborting test!" );+#endif+        }+    }+    void AssertionHandler::setCompleted() {+        m_completed = true;+    }++    void AssertionHandler::handleUnexpectedInflightException() {+        m_resultCapture.handleUnexpectedInflightException( m_assertionInfo, Catch::translateActiveException(), m_reaction );+    }++    void AssertionHandler::handleExceptionThrownAsExpected() {+        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);+    }+    void AssertionHandler::handleExceptionNotThrownAsExpected() {+        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);+    }++    void AssertionHandler::handleUnexpectedExceptionNotThrown() {+        m_resultCapture.handleUnexpectedExceptionNotThrown( m_assertionInfo, m_reaction );+    }++    void AssertionHandler::handleThrowingCallSkipped() {+        m_resultCapture.handleNonExpr(m_assertionInfo, ResultWas::Ok, m_reaction);+    }++    // This is the overload that takes a string and infers the Equals matcher from it+    // The more general overload, that takes any string matcher, is in catch_capture_matchers.cpp+    void handleExceptionMatchExpr( AssertionHandler& handler, std::string const& str, StringRef const& matcherString  ) {+        handleExceptionMatchExpr( handler, Matchers::Equals( str ), matcherString );+    }++} // namespace Catch+// end catch_assertionhandler.cpp+// start catch_assertionresult.cpp++namespace Catch {+    AssertionResultData::AssertionResultData(ResultWas::OfType _resultType, LazyExpression const & _lazyExpression):+        lazyExpression(_lazyExpression),+        resultType(_resultType) {}++    std::string AssertionResultData::reconstructExpression() const {++        if( reconstructedExpression.empty() ) {+            if( lazyExpression ) {+                ReusableStringStream rss;+                rss << lazyExpression;+                reconstructedExpression = rss.str();+            }+        }+        return reconstructedExpression;+    }++    AssertionResult::AssertionResult( AssertionInfo const& info, AssertionResultData const& data )+    :   m_info( info ),+        m_resultData( data )+    {}++    // Result was a success+    bool AssertionResult::succeeded() const {+        return Catch::isOk( m_resultData.resultType );+    }++    // Result was a success, or failure is suppressed+    bool AssertionResult::isOk() const {+        return Catch::isOk( m_resultData.resultType ) || shouldSuppressFailure( m_info.resultDisposition );+    }++    ResultWas::OfType AssertionResult::getResultType() const {+        return m_resultData.resultType;+    }++    bool AssertionResult::hasExpression() const {+        return !m_info.capturedExpression.empty();+    }++    bool AssertionResult::hasMessage() const {+        return !m_resultData.message.empty();+    }++    std::string AssertionResult::getExpression() const {+        // Possibly overallocating by 3 characters should be basically free+        std::string expr; expr.reserve(m_info.capturedExpression.size() + 3);+        if (isFalseTest(m_info.resultDisposition)) {+            expr += "!(";+        }+        expr += m_info.capturedExpression;+        if (isFalseTest(m_info.resultDisposition)) {+            expr += ')';+        }+        return expr;+    }++    std::string AssertionResult::getExpressionInMacro() const {+        std::string expr;+        if( m_info.macroName.empty() )+            expr = static_cast<std::string>(m_info.capturedExpression);+        else {+            expr.reserve( m_info.macroName.size() + m_info.capturedExpression.size() + 4 );+            expr += m_info.macroName;+            expr += "( ";+            expr += m_info.capturedExpression;+            expr += " )";+        }+        return expr;+    }++    bool AssertionResult::hasExpandedExpression() const {+        return hasExpression() && getExpandedExpression() != getExpression();+    }++    std::string AssertionResult::getExpandedExpression() const {+        std::string expr = m_resultData.reconstructExpression();+        return expr.empty()+                ? getExpression()+                : expr;+    }++    std::string AssertionResult::getMessage() const {+        return m_resultData.message;+    }+    SourceLineInfo AssertionResult::getSourceInfo() const {+        return m_info.lineInfo;+    }++    StringRef AssertionResult::getTestMacroName() const {+        return m_info.macroName;+    }++} // end namespace Catch+// end catch_assertionresult.cpp+// start catch_capture_matchers.cpp++namespace Catch {++    using StringMatcher = Matchers::Impl::MatcherBase<std::string>;++    // This is the general overload that takes a any string matcher+    // There is another overload, in catch_assertionhandler.h/.cpp, that only takes a string and infers+    // the Equals matcher (so the header does not mention matchers)+    void handleExceptionMatchExpr( AssertionHandler& handler, StringMatcher const& matcher, StringRef const& matcherString  ) {+        std::string exceptionMessage = Catch::translateActiveException();+        MatchExpr<std::string, StringMatcher const&> expr( exceptionMessage, matcher, matcherString );+        handler.handleExpr( expr );+    }++} // namespace Catch+// end catch_capture_matchers.cpp+// start catch_commandline.cpp++// start catch_commandline.h++// start catch_clara.h++// Use Catch's value for console width (store Clara's off to the side, if present)+#ifdef CLARA_CONFIG_CONSOLE_WIDTH+#define CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH+#undef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH+#endif+#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CONFIG_CONSOLE_WIDTH-1++#ifdef __clang__+#pragma clang diagnostic push+#pragma clang diagnostic ignored "-Wweak-vtables"+#pragma clang diagnostic ignored "-Wexit-time-destructors"+#pragma clang diagnostic ignored "-Wshadow"+#endif++// start clara.hpp+// Copyright 2017 Two Blue Cubes Ltd. All rights reserved.+//+// 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)+//+// See https://github.com/philsquared/Clara for more details++// Clara v1.1.5+++#ifndef CATCH_CLARA_CONFIG_CONSOLE_WIDTH+#define CATCH_CLARA_CONFIG_CONSOLE_WIDTH 80+#endif++#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH+#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_CLARA_CONFIG_CONSOLE_WIDTH+#endif++#ifndef CLARA_CONFIG_OPTIONAL_TYPE+#ifdef __has_include+#if __has_include(<optional>) && __cplusplus >= 201703L+#include <optional>+#define CLARA_CONFIG_OPTIONAL_TYPE std::optional+#endif+#endif+#endif++// ----------- #included from clara_textflow.hpp -----------++// TextFlowCpp+//+// A single-header library for wrapping and laying out basic text, by Phil Nash+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//+// This project is hosted at https://github.com/philsquared/textflowcpp+++#include <cassert>+#include <ostream>+#include <sstream>+#include <vector>++#ifndef CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH+#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH 80+#endif++namespace Catch {+namespace clara {+namespace TextFlow {++inline auto isWhitespace(char c) -> bool {+	static std::string chars = " \t\n\r";+	return chars.find(c) != std::string::npos;+}+inline auto isBreakableBefore(char c) -> bool {+	static std::string chars = "[({<|";+	return chars.find(c) != std::string::npos;+}+inline auto isBreakableAfter(char c) -> bool {+	static std::string chars = "])}>.,:;*+-=&/\\";+	return chars.find(c) != std::string::npos;+}++class Columns;++class Column {+	std::vector<std::string> m_strings;+	size_t m_width = CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH;+	size_t m_indent = 0;+	size_t m_initialIndent = std::string::npos;++public:+	class iterator {+		friend Column;++		Column const& m_column;+		size_t m_stringIndex = 0;+		size_t m_pos = 0;++		size_t m_len = 0;+		size_t m_end = 0;+		bool m_suffix = false;++		iterator(Column const& column, size_t stringIndex)+			: m_column(column),+			m_stringIndex(stringIndex) {}++		auto line() const -> std::string const& { return m_column.m_strings[m_stringIndex]; }++		auto isBoundary(size_t at) const -> bool {+			assert(at > 0);+			assert(at <= line().size());++			return at == line().size() ||+				(isWhitespace(line()[at]) && !isWhitespace(line()[at - 1])) ||+				isBreakableBefore(line()[at]) ||+				isBreakableAfter(line()[at - 1]);+		}++		void calcLength() {+			assert(m_stringIndex < m_column.m_strings.size());++			m_suffix = false;+			auto width = m_column.m_width - indent();+			m_end = m_pos;+			if (line()[m_pos] == '\n') {+				++m_end;+			}+			while (m_end < line().size() && line()[m_end] != '\n')+				++m_end;++			if (m_end < m_pos + width) {+				m_len = m_end - m_pos;+			} else {+				size_t len = width;+				while (len > 0 && !isBoundary(m_pos + len))+					--len;+				while (len > 0 && isWhitespace(line()[m_pos + len - 1]))+					--len;++				if (len > 0) {+					m_len = len;+				} else {+					m_suffix = true;+					m_len = width - 1;+				}+			}+		}++		auto indent() const -> size_t {+			auto initial = m_pos == 0 && m_stringIndex == 0 ? m_column.m_initialIndent : std::string::npos;+			return initial == std::string::npos ? m_column.m_indent : initial;+		}++		auto addIndentAndSuffix(std::string const &plain) const -> std::string {+			return std::string(indent(), ' ') + (m_suffix ? plain + "-" : plain);+		}++	public:+		using difference_type = std::ptrdiff_t;+		using value_type = std::string;+		using pointer = value_type * ;+		using reference = value_type & ;+		using iterator_category = std::forward_iterator_tag;++		explicit iterator(Column const& column) : m_column(column) {+			assert(m_column.m_width > m_column.m_indent);+			assert(m_column.m_initialIndent == std::string::npos || m_column.m_width > m_column.m_initialIndent);+			calcLength();+			if (m_len == 0)+				m_stringIndex++; // Empty string+		}++		auto operator *() const -> std::string {+			assert(m_stringIndex < m_column.m_strings.size());+			assert(m_pos <= m_end);+			return addIndentAndSuffix(line().substr(m_pos, m_len));+		}++		auto operator ++() -> iterator& {+			m_pos += m_len;+			if (m_pos < line().size() && line()[m_pos] == '\n')+				m_pos += 1;+			else+				while (m_pos < line().size() && isWhitespace(line()[m_pos]))+					++m_pos;++			if (m_pos == line().size()) {+				m_pos = 0;+				++m_stringIndex;+			}+			if (m_stringIndex < m_column.m_strings.size())+				calcLength();+			return *this;+		}+		auto operator ++(int) -> iterator {+			iterator prev(*this);+			operator++();+			return prev;+		}++		auto operator ==(iterator const& other) const -> bool {+			return+				m_pos == other.m_pos &&+				m_stringIndex == other.m_stringIndex &&+				&m_column == &other.m_column;+		}+		auto operator !=(iterator const& other) const -> bool {+			return !operator==(other);+		}+	};+	using const_iterator = iterator;++	explicit Column(std::string const& text) { m_strings.push_back(text); }++	auto width(size_t newWidth) -> Column& {+		assert(newWidth > 0);+		m_width = newWidth;+		return *this;+	}+	auto indent(size_t newIndent) -> Column& {+		m_indent = newIndent;+		return *this;+	}+	auto initialIndent(size_t newIndent) -> Column& {+		m_initialIndent = newIndent;+		return *this;+	}++	auto width() const -> size_t { return m_width; }+	auto begin() const -> iterator { return iterator(*this); }+	auto end() const -> iterator { return { *this, m_strings.size() }; }++	inline friend std::ostream& operator << (std::ostream& os, Column const& col) {+		bool first = true;+		for (auto line : col) {+			if (first)+				first = false;+			else+				os << "\n";+			os << line;+		}+		return os;+	}++	auto operator + (Column const& other)->Columns;++	auto toString() const -> std::string {+		std::ostringstream oss;+		oss << *this;+		return oss.str();+	}+};++class Spacer : public Column {++public:+	explicit Spacer(size_t spaceWidth) : Column("") {+		width(spaceWidth);+	}+};++class Columns {+	std::vector<Column> m_columns;++public:++	class iterator {+		friend Columns;+		struct EndTag {};++		std::vector<Column> const& m_columns;+		std::vector<Column::iterator> m_iterators;+		size_t m_activeIterators;++		iterator(Columns const& columns, EndTag)+			: m_columns(columns.m_columns),+			m_activeIterators(0) {+			m_iterators.reserve(m_columns.size());++			for (auto const& col : m_columns)+				m_iterators.push_back(col.end());+		}++	public:+		using difference_type = std::ptrdiff_t;+		using value_type = std::string;+		using pointer = value_type * ;+		using reference = value_type & ;+		using iterator_category = std::forward_iterator_tag;++		explicit iterator(Columns const& columns)+			: m_columns(columns.m_columns),+			m_activeIterators(m_columns.size()) {+			m_iterators.reserve(m_columns.size());++			for (auto const& col : m_columns)+				m_iterators.push_back(col.begin());+		}++		auto operator ==(iterator const& other) const -> bool {+			return m_iterators == other.m_iterators;+		}+		auto operator !=(iterator const& other) const -> bool {+			return m_iterators != other.m_iterators;+		}+		auto operator *() const -> std::string {+			std::string row, padding;++			for (size_t i = 0; i < m_columns.size(); ++i) {+				auto width = m_columns[i].width();+				if (m_iterators[i] != m_columns[i].end()) {+					std::string col = *m_iterators[i];+					row += padding + col;+					if (col.size() < width)+						padding = std::string(width - col.size(), ' ');+					else+						padding = "";+				} else {+					padding += std::string(width, ' ');+				}+			}+			return row;+		}+		auto operator ++() -> iterator& {+			for (size_t i = 0; i < m_columns.size(); ++i) {+				if (m_iterators[i] != m_columns[i].end())+					++m_iterators[i];+			}+			return *this;+		}+		auto operator ++(int) -> iterator {+			iterator prev(*this);+			operator++();+			return prev;+		}+	};+	using const_iterator = iterator;++	auto begin() const -> iterator { return iterator(*this); }+	auto end() const -> iterator { return { *this, iterator::EndTag() }; }++	auto operator += (Column const& col) -> Columns& {+		m_columns.push_back(col);+		return *this;+	}+	auto operator + (Column const& col) -> Columns {+		Columns combined = *this;+		combined += col;+		return combined;+	}++	inline friend std::ostream& operator << (std::ostream& os, Columns const& cols) {++		bool first = true;+		for (auto line : cols) {+			if (first)+				first = false;+			else+				os << "\n";+			os << line;+		}+		return os;+	}++	auto toString() const -> std::string {+		std::ostringstream oss;+		oss << *this;+		return oss.str();+	}+};++inline auto Column::operator + (Column const& other) -> Columns {+	Columns cols;+	cols += *this;+	cols += other;+	return cols;+}+}++}+}++// ----------- end of #include from clara_textflow.hpp -----------+// ........... back in clara.hpp++#include <cctype>+#include <string>+#include <memory>+#include <set>+#include <algorithm>++#if !defined(CATCH_PLATFORM_WINDOWS) && ( defined(WIN32) || defined(__WIN32__) || defined(_WIN32) || defined(_MSC_VER) )+#define CATCH_PLATFORM_WINDOWS+#endif++namespace Catch { namespace clara {+namespace detail {++    // Traits for extracting arg and return type of lambdas (for single argument lambdas)+    template<typename L>+    struct UnaryLambdaTraits : UnaryLambdaTraits<decltype( &L::operator() )> {};++    template<typename ClassT, typename ReturnT, typename... Args>+    struct UnaryLambdaTraits<ReturnT( ClassT::* )( Args... ) const> {+        static const bool isValid = false;+    };++    template<typename ClassT, typename ReturnT, typename ArgT>+    struct UnaryLambdaTraits<ReturnT( ClassT::* )( ArgT ) const> {+        static const bool isValid = true;+        using ArgType = typename std::remove_const<typename std::remove_reference<ArgT>::type>::type;+        using ReturnType = ReturnT;+    };++    class TokenStream;++    // Transport for raw args (copied from main args, or supplied via init list for testing)+    class Args {+        friend TokenStream;+        std::string m_exeName;+        std::vector<std::string> m_args;++    public:+        Args( int argc, char const* const* argv )+            : m_exeName(argv[0]),+              m_args(argv + 1, argv + argc) {}++        Args( std::initializer_list<std::string> args )+        :   m_exeName( *args.begin() ),+            m_args( args.begin()+1, args.end() )+        {}++        auto exeName() const -> std::string {+            return m_exeName;+        }+    };++    // Wraps a token coming from a token stream. These may not directly correspond to strings as a single string+    // may encode an option + its argument if the : or = form is used+    enum class TokenType {+        Option, Argument+    };+    struct Token {+        TokenType type;+        std::string token;+    };++    inline auto isOptPrefix( char c ) -> bool {+        return c == '-'+#ifdef CATCH_PLATFORM_WINDOWS+            || c == '/'+#endif+        ;+    }++    // Abstracts iterators into args as a stream of tokens, with option arguments uniformly handled+    class TokenStream {+        using Iterator = std::vector<std::string>::const_iterator;+        Iterator it;+        Iterator itEnd;+        std::vector<Token> m_tokenBuffer;++        void loadBuffer() {+            m_tokenBuffer.resize( 0 );++            // Skip any empty strings+            while( it != itEnd && it->empty() )+                ++it;++            if( it != itEnd ) {+                auto const &next = *it;+                if( isOptPrefix( next[0] ) ) {+                    auto delimiterPos = next.find_first_of( " :=" );+                    if( delimiterPos != std::string::npos ) {+                        m_tokenBuffer.push_back( { TokenType::Option, next.substr( 0, delimiterPos ) } );+                        m_tokenBuffer.push_back( { TokenType::Argument, next.substr( delimiterPos + 1 ) } );+                    } else {+                        if( next[1] != '-' && next.size() > 2 ) {+                            std::string opt = "- ";+                            for( size_t i = 1; i < next.size(); ++i ) {+                                opt[1] = next[i];+                                m_tokenBuffer.push_back( { TokenType::Option, opt } );+                            }+                        } else {+                            m_tokenBuffer.push_back( { TokenType::Option, next } );+                        }+                    }+                } else {+                    m_tokenBuffer.push_back( { TokenType::Argument, next } );+                }+            }+        }++    public:+        explicit TokenStream( Args const &args ) : TokenStream( args.m_args.begin(), args.m_args.end() ) {}++        TokenStream( Iterator it, Iterator itEnd ) : it( it ), itEnd( itEnd ) {+            loadBuffer();+        }++        explicit operator bool() const {+            return !m_tokenBuffer.empty() || it != itEnd;+        }++        auto count() const -> size_t { return m_tokenBuffer.size() + (itEnd - it); }++        auto operator*() const -> Token {+            assert( !m_tokenBuffer.empty() );+            return m_tokenBuffer.front();+        }++        auto operator->() const -> Token const * {+            assert( !m_tokenBuffer.empty() );+            return &m_tokenBuffer.front();+        }++        auto operator++() -> TokenStream & {+            if( m_tokenBuffer.size() >= 2 ) {+                m_tokenBuffer.erase( m_tokenBuffer.begin() );+            } else {+                if( it != itEnd )+                    ++it;+                loadBuffer();+            }+            return *this;+        }+    };++    class ResultBase {+    public:+        enum Type {+            Ok, LogicError, RuntimeError+        };++    protected:+        ResultBase( Type type ) : m_type( type ) {}+        virtual ~ResultBase() = default;++        virtual void enforceOk() const = 0;++        Type m_type;+    };++    template<typename T>+    class ResultValueBase : public ResultBase {+    public:+        auto value() const -> T const & {+            enforceOk();+            return m_value;+        }++    protected:+        ResultValueBase( Type type ) : ResultBase( type ) {}++        ResultValueBase( ResultValueBase const &other ) : ResultBase( other ) {+            if( m_type == ResultBase::Ok )+                new( &m_value ) T( other.m_value );+        }++        ResultValueBase( Type, T const &value ) : ResultBase( Ok ) {+            new( &m_value ) T( value );+        }++        auto operator=( ResultValueBase const &other ) -> ResultValueBase & {+            if( m_type == ResultBase::Ok )+                m_value.~T();+            ResultBase::operator=(other);+            if( m_type == ResultBase::Ok )+                new( &m_value ) T( other.m_value );+            return *this;+        }++        ~ResultValueBase() override {+            if( m_type == Ok )+                m_value.~T();+        }++        union {+            T m_value;+        };+    };++    template<>+    class ResultValueBase<void> : public ResultBase {+    protected:+        using ResultBase::ResultBase;+    };++    template<typename T = void>+    class BasicResult : public ResultValueBase<T> {+    public:+        template<typename U>+        explicit BasicResult( BasicResult<U> const &other )+        :   ResultValueBase<T>( other.type() ),+            m_errorMessage( other.errorMessage() )+        {+            assert( type() != ResultBase::Ok );+        }++        template<typename U>+        static auto ok( U const &value ) -> BasicResult { return { ResultBase::Ok, value }; }+        static auto ok() -> BasicResult { return { ResultBase::Ok }; }+        static auto logicError( std::string const &message ) -> BasicResult { return { ResultBase::LogicError, message }; }+        static auto runtimeError( std::string const &message ) -> BasicResult { return { ResultBase::RuntimeError, message }; }++        explicit operator bool() const { return m_type == ResultBase::Ok; }+        auto type() const -> ResultBase::Type { return m_type; }+        auto errorMessage() const -> std::string { return m_errorMessage; }++    protected:+        void enforceOk() const override {++            // Errors shouldn't reach this point, but if they do+            // the actual error message will be in m_errorMessage+            assert( m_type != ResultBase::LogicError );+            assert( m_type != ResultBase::RuntimeError );+            if( m_type != ResultBase::Ok )+                std::abort();+        }++        std::string m_errorMessage; // Only populated if resultType is an error++        BasicResult( ResultBase::Type type, std::string const &message )+        :   ResultValueBase<T>(type),+            m_errorMessage(message)+        {+            assert( m_type != ResultBase::Ok );+        }++        using ResultValueBase<T>::ResultValueBase;+        using ResultBase::m_type;+    };++    enum class ParseResultType {+        Matched, NoMatch, ShortCircuitAll, ShortCircuitSame+    };++    class ParseState {+    public:++        ParseState( ParseResultType type, TokenStream const &remainingTokens )+        : m_type(type),+          m_remainingTokens( remainingTokens )+        {}++        auto type() const -> ParseResultType { return m_type; }+        auto remainingTokens() const -> TokenStream { return m_remainingTokens; }++    private:+        ParseResultType m_type;+        TokenStream m_remainingTokens;+    };++    using Result = BasicResult<void>;+    using ParserResult = BasicResult<ParseResultType>;+    using InternalParseResult = BasicResult<ParseState>;++    struct HelpColumns {+        std::string left;+        std::string right;+    };++    template<typename T>+    inline auto convertInto( std::string const &source, T& target ) -> ParserResult {+        std::stringstream ss;+        ss << source;+        ss >> target;+        if( ss.fail() )+            return ParserResult::runtimeError( "Unable to convert '" + source + "' to destination type" );+        else+            return ParserResult::ok( ParseResultType::Matched );+    }+    inline auto convertInto( std::string const &source, std::string& target ) -> ParserResult {+        target = source;+        return ParserResult::ok( ParseResultType::Matched );+    }+    inline auto convertInto( std::string const &source, bool &target ) -> ParserResult {+        std::string srcLC = source;+        std::transform( srcLC.begin(), srcLC.end(), srcLC.begin(), []( unsigned char c ) { return static_cast<char>( std::tolower(c) ); } );+        if (srcLC == "y" || srcLC == "1" || srcLC == "true" || srcLC == "yes" || srcLC == "on")+            target = true;+        else if (srcLC == "n" || srcLC == "0" || srcLC == "false" || srcLC == "no" || srcLC == "off")+            target = false;+        else+            return ParserResult::runtimeError( "Expected a boolean value but did not recognise: '" + source + "'" );+        return ParserResult::ok( ParseResultType::Matched );+    }+#ifdef CLARA_CONFIG_OPTIONAL_TYPE+    template<typename T>+    inline auto convertInto( std::string const &source, CLARA_CONFIG_OPTIONAL_TYPE<T>& target ) -> ParserResult {+        T temp;+        auto result = convertInto( source, temp );+        if( result )+            target = std::move(temp);+        return result;+    }+#endif // CLARA_CONFIG_OPTIONAL_TYPE++    struct NonCopyable {+        NonCopyable() = default;+        NonCopyable( NonCopyable const & ) = delete;+        NonCopyable( NonCopyable && ) = delete;+        NonCopyable &operator=( NonCopyable const & ) = delete;+        NonCopyable &operator=( NonCopyable && ) = delete;+    };++    struct BoundRef : NonCopyable {+        virtual ~BoundRef() = default;+        virtual auto isContainer() const -> bool { return false; }+        virtual auto isFlag() const -> bool { return false; }+    };+    struct BoundValueRefBase : BoundRef {+        virtual auto setValue( std::string const &arg ) -> ParserResult = 0;+    };+    struct BoundFlagRefBase : BoundRef {+        virtual auto setFlag( bool flag ) -> ParserResult = 0;+        virtual auto isFlag() const -> bool { return true; }+    };++    template<typename T>+    struct BoundValueRef : BoundValueRefBase {+        T &m_ref;++        explicit BoundValueRef( T &ref ) : m_ref( ref ) {}++        auto setValue( std::string const &arg ) -> ParserResult override {+            return convertInto( arg, m_ref );+        }+    };++    template<typename T>+    struct BoundValueRef<std::vector<T>> : BoundValueRefBase {+        std::vector<T> &m_ref;++        explicit BoundValueRef( std::vector<T> &ref ) : m_ref( ref ) {}++        auto isContainer() const -> bool override { return true; }++        auto setValue( std::string const &arg ) -> ParserResult override {+            T temp;+            auto result = convertInto( arg, temp );+            if( result )+                m_ref.push_back( temp );+            return result;+        }+    };++    struct BoundFlagRef : BoundFlagRefBase {+        bool &m_ref;++        explicit BoundFlagRef( bool &ref ) : m_ref( ref ) {}++        auto setFlag( bool flag ) -> ParserResult override {+            m_ref = flag;+            return ParserResult::ok( ParseResultType::Matched );+        }+    };++    template<typename ReturnType>+    struct LambdaInvoker {+        static_assert( std::is_same<ReturnType, ParserResult>::value, "Lambda must return void or clara::ParserResult" );++        template<typename L, typename ArgType>+        static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {+            return lambda( arg );+        }+    };++    template<>+    struct LambdaInvoker<void> {+        template<typename L, typename ArgType>+        static auto invoke( L const &lambda, ArgType const &arg ) -> ParserResult {+            lambda( arg );+            return ParserResult::ok( ParseResultType::Matched );+        }+    };++    template<typename ArgType, typename L>+    inline auto invokeLambda( L const &lambda, std::string const &arg ) -> ParserResult {+        ArgType temp{};+        auto result = convertInto( arg, temp );+        return !result+           ? result+           : LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( lambda, temp );+    }++    template<typename L>+    struct BoundLambda : BoundValueRefBase {+        L m_lambda;++        static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );+        explicit BoundLambda( L const &lambda ) : m_lambda( lambda ) {}++        auto setValue( std::string const &arg ) -> ParserResult override {+            return invokeLambda<typename UnaryLambdaTraits<L>::ArgType>( m_lambda, arg );+        }+    };++    template<typename L>+    struct BoundFlagLambda : BoundFlagRefBase {+        L m_lambda;++        static_assert( UnaryLambdaTraits<L>::isValid, "Supplied lambda must take exactly one argument" );+        static_assert( std::is_same<typename UnaryLambdaTraits<L>::ArgType, bool>::value, "flags must be boolean" );++        explicit BoundFlagLambda( L const &lambda ) : m_lambda( lambda ) {}++        auto setFlag( bool flag ) -> ParserResult override {+            return LambdaInvoker<typename UnaryLambdaTraits<L>::ReturnType>::invoke( m_lambda, flag );+        }+    };++    enum class Optionality { Optional, Required };++    struct Parser;++    class ParserBase {+    public:+        virtual ~ParserBase() = default;+        virtual auto validate() const -> Result { return Result::ok(); }+        virtual auto parse( std::string const& exeName, TokenStream const &tokens) const -> InternalParseResult  = 0;+        virtual auto cardinality() const -> size_t { return 1; }++        auto parse( Args const &args ) const -> InternalParseResult {+            return parse( args.exeName(), TokenStream( args ) );+        }+    };++    template<typename DerivedT>+    class ComposableParserImpl : public ParserBase {+    public:+        template<typename T>+        auto operator|( T const &other ) const -> Parser;++		template<typename T>+        auto operator+( T const &other ) const -> Parser;+    };++    // Common code and state for Args and Opts+    template<typename DerivedT>+    class ParserRefImpl : public ComposableParserImpl<DerivedT> {+    protected:+        Optionality m_optionality = Optionality::Optional;+        std::shared_ptr<BoundRef> m_ref;+        std::string m_hint;+        std::string m_description;++        explicit ParserRefImpl( std::shared_ptr<BoundRef> const &ref ) : m_ref( ref ) {}++    public:+        template<typename T>+        ParserRefImpl( T &ref, std::string const &hint )+        :   m_ref( std::make_shared<BoundValueRef<T>>( ref ) ),+            m_hint( hint )+        {}++        template<typename LambdaT>+        ParserRefImpl( LambdaT const &ref, std::string const &hint )+        :   m_ref( std::make_shared<BoundLambda<LambdaT>>( ref ) ),+            m_hint(hint)+        {}++        auto operator()( std::string const &description ) -> DerivedT & {+            m_description = description;+            return static_cast<DerivedT &>( *this );+        }++        auto optional() -> DerivedT & {+            m_optionality = Optionality::Optional;+            return static_cast<DerivedT &>( *this );+        };++        auto required() -> DerivedT & {+            m_optionality = Optionality::Required;+            return static_cast<DerivedT &>( *this );+        };++        auto isOptional() const -> bool {+            return m_optionality == Optionality::Optional;+        }++        auto cardinality() const -> size_t override {+            if( m_ref->isContainer() )+                return 0;+            else+                return 1;+        }++        auto hint() const -> std::string { return m_hint; }+    };++    class ExeName : public ComposableParserImpl<ExeName> {+        std::shared_ptr<std::string> m_name;+        std::shared_ptr<BoundValueRefBase> m_ref;++        template<typename LambdaT>+        static auto makeRef(LambdaT const &lambda) -> std::shared_ptr<BoundValueRefBase> {+            return std::make_shared<BoundLambda<LambdaT>>( lambda) ;+        }++    public:+        ExeName() : m_name( std::make_shared<std::string>( "<executable>" ) ) {}++        explicit ExeName( std::string &ref ) : ExeName() {+            m_ref = std::make_shared<BoundValueRef<std::string>>( ref );+        }++        template<typename LambdaT>+        explicit ExeName( LambdaT const& lambda ) : ExeName() {+            m_ref = std::make_shared<BoundLambda<LambdaT>>( lambda );+        }++        // The exe name is not parsed out of the normal tokens, but is handled specially+        auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {+            return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );+        }++        auto name() const -> std::string { return *m_name; }+        auto set( std::string const& newName ) -> ParserResult {++            auto lastSlash = newName.find_last_of( "\\/" );+            auto filename = ( lastSlash == std::string::npos )+                    ? newName+                    : newName.substr( lastSlash+1 );++            *m_name = filename;+            if( m_ref )+                return m_ref->setValue( filename );+            else+                return ParserResult::ok( ParseResultType::Matched );+        }+    };++    class Arg : public ParserRefImpl<Arg> {+    public:+        using ParserRefImpl::ParserRefImpl;++        auto parse( std::string const &, TokenStream const &tokens ) const -> InternalParseResult override {+            auto validationResult = validate();+            if( !validationResult )+                return InternalParseResult( validationResult );++            auto remainingTokens = tokens;+            auto const &token = *remainingTokens;+            if( token.type != TokenType::Argument )+                return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );++            assert( !m_ref->isFlag() );+            auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );++            auto result = valueRef->setValue( remainingTokens->token );+            if( !result )+                return InternalParseResult( result );+            else+                return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );+        }+    };++    inline auto normaliseOpt( std::string const &optName ) -> std::string {+#ifdef CATCH_PLATFORM_WINDOWS+        if( optName[0] == '/' )+            return "-" + optName.substr( 1 );+        else+#endif+            return optName;+    }++    class Opt : public ParserRefImpl<Opt> {+    protected:+        std::vector<std::string> m_optNames;++    public:+        template<typename LambdaT>+        explicit Opt( LambdaT const &ref ) : ParserRefImpl( std::make_shared<BoundFlagLambda<LambdaT>>( ref ) ) {}++        explicit Opt( bool &ref ) : ParserRefImpl( std::make_shared<BoundFlagRef>( ref ) ) {}++        template<typename LambdaT>+        Opt( LambdaT const &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}++        template<typename T>+        Opt( T &ref, std::string const &hint ) : ParserRefImpl( ref, hint ) {}++        auto operator[]( std::string const &optName ) -> Opt & {+            m_optNames.push_back( optName );+            return *this;+        }++        auto getHelpColumns() const -> std::vector<HelpColumns> {+            std::ostringstream oss;+            bool first = true;+            for( auto const &opt : m_optNames ) {+                if (first)+                    first = false;+                else+                    oss << ", ";+                oss << opt;+            }+            if( !m_hint.empty() )+                oss << " <" << m_hint << ">";+            return { { oss.str(), m_description } };+        }++        auto isMatch( std::string const &optToken ) const -> bool {+            auto normalisedToken = normaliseOpt( optToken );+            for( auto const &name : m_optNames ) {+                if( normaliseOpt( name ) == normalisedToken )+                    return true;+            }+            return false;+        }++        using ParserBase::parse;++        auto parse( std::string const&, TokenStream const &tokens ) const -> InternalParseResult override {+            auto validationResult = validate();+            if( !validationResult )+                return InternalParseResult( validationResult );++            auto remainingTokens = tokens;+            if( remainingTokens && remainingTokens->type == TokenType::Option ) {+                auto const &token = *remainingTokens;+                if( isMatch(token.token ) ) {+                    if( m_ref->isFlag() ) {+                        auto flagRef = static_cast<detail::BoundFlagRefBase*>( m_ref.get() );+                        auto result = flagRef->setFlag( true );+                        if( !result )+                            return InternalParseResult( result );+                        if( result.value() == ParseResultType::ShortCircuitAll )+                            return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );+                    } else {+                        auto valueRef = static_cast<detail::BoundValueRefBase*>( m_ref.get() );+                        ++remainingTokens;+                        if( !remainingTokens )+                            return InternalParseResult::runtimeError( "Expected argument following " + token.token );+                        auto const &argToken = *remainingTokens;+                        if( argToken.type != TokenType::Argument )+                            return InternalParseResult::runtimeError( "Expected argument following " + token.token );+                        auto result = valueRef->setValue( argToken.token );+                        if( !result )+                            return InternalParseResult( result );+                        if( result.value() == ParseResultType::ShortCircuitAll )+                            return InternalParseResult::ok( ParseState( result.value(), remainingTokens ) );+                    }+                    return InternalParseResult::ok( ParseState( ParseResultType::Matched, ++remainingTokens ) );+                }+            }+            return InternalParseResult::ok( ParseState( ParseResultType::NoMatch, remainingTokens ) );+        }++        auto validate() const -> Result override {+            if( m_optNames.empty() )+                return Result::logicError( "No options supplied to Opt" );+            for( auto const &name : m_optNames ) {+                if( name.empty() )+                    return Result::logicError( "Option name cannot be empty" );+#ifdef CATCH_PLATFORM_WINDOWS+                if( name[0] != '-' && name[0] != '/' )+                    return Result::logicError( "Option name must begin with '-' or '/'" );+#else+                if( name[0] != '-' )+                    return Result::logicError( "Option name must begin with '-'" );+#endif+            }+            return ParserRefImpl::validate();+        }+    };++    struct Help : Opt {+        Help( bool &showHelpFlag )+        :   Opt([&]( bool flag ) {+                showHelpFlag = flag;+                return ParserResult::ok( ParseResultType::ShortCircuitAll );+            })+        {+            static_cast<Opt &>( *this )+                    ("display usage information")+                    ["-?"]["-h"]["--help"]+                    .optional();+        }+    };++    struct Parser : ParserBase {++        mutable ExeName m_exeName;+        std::vector<Opt> m_options;+        std::vector<Arg> m_args;++        auto operator|=( ExeName const &exeName ) -> Parser & {+            m_exeName = exeName;+            return *this;+        }++        auto operator|=( Arg const &arg ) -> Parser & {+            m_args.push_back(arg);+            return *this;+        }++        auto operator|=( Opt const &opt ) -> Parser & {+            m_options.push_back(opt);+            return *this;+        }++        auto operator|=( Parser const &other ) -> Parser & {+            m_options.insert(m_options.end(), other.m_options.begin(), other.m_options.end());+            m_args.insert(m_args.end(), other.m_args.begin(), other.m_args.end());+            return *this;+        }++        template<typename T>+        auto operator|( T const &other ) const -> Parser {+            return Parser( *this ) |= other;+        }++        // Forward deprecated interface with '+' instead of '|'+        template<typename T>+        auto operator+=( T const &other ) -> Parser & { return operator|=( other ); }+        template<typename T>+        auto operator+( T const &other ) const -> Parser { return operator|( other ); }++        auto getHelpColumns() const -> std::vector<HelpColumns> {+            std::vector<HelpColumns> cols;+            for (auto const &o : m_options) {+                auto childCols = o.getHelpColumns();+                cols.insert( cols.end(), childCols.begin(), childCols.end() );+            }+            return cols;+        }++        void writeToStream( std::ostream &os ) const {+            if (!m_exeName.name().empty()) {+                os << "usage:\n" << "  " << m_exeName.name() << " ";+                bool required = true, first = true;+                for( auto const &arg : m_args ) {+                    if (first)+                        first = false;+                    else+                        os << " ";+                    if( arg.isOptional() && required ) {+                        os << "[";+                        required = false;+                    }+                    os << "<" << arg.hint() << ">";+                    if( arg.cardinality() == 0 )+                        os << " ... ";+                }+                if( !required )+                    os << "]";+                if( !m_options.empty() )+                    os << " options";+                os << "\n\nwhere options are:" << std::endl;+            }++            auto rows = getHelpColumns();+            size_t consoleWidth = CATCH_CLARA_CONFIG_CONSOLE_WIDTH;+            size_t optWidth = 0;+            for( auto const &cols : rows )+                optWidth = (std::max)(optWidth, cols.left.size() + 2);++            optWidth = (std::min)(optWidth, consoleWidth/2);++            for( auto const &cols : rows ) {+                auto row =+                        TextFlow::Column( cols.left ).width( optWidth ).indent( 2 ) ++                        TextFlow::Spacer(4) ++                        TextFlow::Column( cols.right ).width( consoleWidth - 7 - optWidth );+                os << row << std::endl;+            }+        }++        friend auto operator<<( std::ostream &os, Parser const &parser ) -> std::ostream& {+            parser.writeToStream( os );+            return os;+        }++        auto validate() const -> Result override {+            for( auto const &opt : m_options ) {+                auto result = opt.validate();+                if( !result )+                    return result;+            }+            for( auto const &arg : m_args ) {+                auto result = arg.validate();+                if( !result )+                    return result;+            }+            return Result::ok();+        }++        using ParserBase::parse;++        auto parse( std::string const& exeName, TokenStream const &tokens ) const -> InternalParseResult override {++            struct ParserInfo {+                ParserBase const* parser = nullptr;+                size_t count = 0;+            };+            const size_t totalParsers = m_options.size() + m_args.size();+            assert( totalParsers < 512 );+            // ParserInfo parseInfos[totalParsers]; // <-- this is what we really want to do+            ParserInfo parseInfos[512];++            {+                size_t i = 0;+                for (auto const &opt : m_options) parseInfos[i++].parser = &opt;+                for (auto const &arg : m_args) parseInfos[i++].parser = &arg;+            }++            m_exeName.set( exeName );++            auto result = InternalParseResult::ok( ParseState( ParseResultType::NoMatch, tokens ) );+            while( result.value().remainingTokens() ) {+                bool tokenParsed = false;++                for( size_t i = 0; i < totalParsers; ++i ) {+                    auto&  parseInfo = parseInfos[i];+                    if( parseInfo.parser->cardinality() == 0 || parseInfo.count < parseInfo.parser->cardinality() ) {+                        result = parseInfo.parser->parse(exeName, result.value().remainingTokens());+                        if (!result)+                            return result;+                        if (result.value().type() != ParseResultType::NoMatch) {+                            tokenParsed = true;+                            ++parseInfo.count;+                            break;+                        }+                    }+                }++                if( result.value().type() == ParseResultType::ShortCircuitAll )+                    return result;+                if( !tokenParsed )+                    return InternalParseResult::runtimeError( "Unrecognised token: " + result.value().remainingTokens()->token );+            }+            // !TBD Check missing required options+            return result;+        }+    };++    template<typename DerivedT>+    template<typename T>+    auto ComposableParserImpl<DerivedT>::operator|( T const &other ) const -> Parser {+        return Parser() | static_cast<DerivedT const &>( *this ) | other;+    }+} // namespace detail++// A Combined parser+using detail::Parser;++// A parser for options+using detail::Opt;++// A parser for arguments+using detail::Arg;++// Wrapper for argc, argv from main()+using detail::Args;++// Specifies the name of the executable+using detail::ExeName;++// Convenience wrapper for option parser that specifies the help option+using detail::Help;++// enum of result types from a parse+using detail::ParseResultType;++// Result type for parser operation+using detail::ParserResult;++}} // namespace Catch::clara++// end clara.hpp+#ifdef __clang__+#pragma clang diagnostic pop+#endif++// Restore Clara's value for console width, if present+#ifdef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH+#define CATCH_CLARA_TEXTFLOW_CONFIG_CONSOLE_WIDTH CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH+#undef CATCH_TEMP_CLARA_CONFIG_CONSOLE_WIDTH+#endif++// end catch_clara.h+namespace Catch {++    clara::Parser makeCommandLineParser( ConfigData& config );++} // end namespace Catch++// end catch_commandline.h+#include <fstream>+#include <ctime>++namespace Catch {++    clara::Parser makeCommandLineParser( ConfigData& config ) {++        using namespace clara;++        auto const setWarning = [&]( std::string const& warning ) {+                auto warningSet = [&]() {+                    if( warning == "NoAssertions" )+                        return WarnAbout::NoAssertions;++                    if ( warning == "NoTests" )+                        return WarnAbout::NoTests;++                    return WarnAbout::Nothing;+                }();++                if (warningSet == WarnAbout::Nothing)+                    return ParserResult::runtimeError( "Unrecognised warning: '" + warning + "'" );+                config.warnings = static_cast<WarnAbout::What>( config.warnings | warningSet );+                return ParserResult::ok( ParseResultType::Matched );+            };+        auto const loadTestNamesFromFile = [&]( std::string const& filename ) {+                std::ifstream f( filename.c_str() );+                if( !f.is_open() )+                    return ParserResult::runtimeError( "Unable to load input file: '" + filename + "'" );++                std::string line;+                while( std::getline( f, line ) ) {+                    line = trim(line);+                    if( !line.empty() && !startsWith( line, '#' ) ) {+                        if( !startsWith( line, '"' ) )+                            line = '"' + line + '"';+                        config.testsOrTags.push_back( line );+                        config.testsOrTags.emplace_back( "," );+                    }+                }+                //Remove comma in the end+                if(!config.testsOrTags.empty())+                    config.testsOrTags.erase( config.testsOrTags.end()-1 );++                return ParserResult::ok( ParseResultType::Matched );+            };+        auto const setTestOrder = [&]( std::string const& order ) {+                if( startsWith( "declared", order ) )+                    config.runOrder = RunTests::InDeclarationOrder;+                else if( startsWith( "lexical", order ) )+                    config.runOrder = RunTests::InLexicographicalOrder;+                else if( startsWith( "random", order ) )+                    config.runOrder = RunTests::InRandomOrder;+                else+                    return clara::ParserResult::runtimeError( "Unrecognised ordering: '" + order + "'" );+                return ParserResult::ok( ParseResultType::Matched );+            };+        auto const setRngSeed = [&]( std::string const& seed ) {+                if( seed != "time" )+                    return clara::detail::convertInto( seed, config.rngSeed );+                config.rngSeed = static_cast<unsigned int>( std::time(nullptr) );+                return ParserResult::ok( ParseResultType::Matched );+            };+        auto const setColourUsage = [&]( std::string const& useColour ) {+                    auto mode = toLower( useColour );++                    if( mode == "yes" )+                        config.useColour = UseColour::Yes;+                    else if( mode == "no" )+                        config.useColour = UseColour::No;+                    else if( mode == "auto" )+                        config.useColour = UseColour::Auto;+                    else+                        return ParserResult::runtimeError( "colour mode must be one of: auto, yes or no. '" + useColour + "' not recognised" );+                return ParserResult::ok( ParseResultType::Matched );+            };+        auto const setWaitForKeypress = [&]( std::string const& keypress ) {+                auto keypressLc = toLower( keypress );+                if (keypressLc == "never")+                    config.waitForKeypress = WaitForKeypress::Never;+                else if( keypressLc == "start" )+                    config.waitForKeypress = WaitForKeypress::BeforeStart;+                else if( keypressLc == "exit" )+                    config.waitForKeypress = WaitForKeypress::BeforeExit;+                else if( keypressLc == "both" )+                    config.waitForKeypress = WaitForKeypress::BeforeStartAndExit;+                else+                    return ParserResult::runtimeError( "keypress argument must be one of: never, start, exit or both. '" + keypress + "' not recognised" );+            return ParserResult::ok( ParseResultType::Matched );+            };+        auto const setVerbosity = [&]( std::string const& verbosity ) {+            auto lcVerbosity = toLower( verbosity );+            if( lcVerbosity == "quiet" )+                config.verbosity = Verbosity::Quiet;+            else if( lcVerbosity == "normal" )+                config.verbosity = Verbosity::Normal;+            else if( lcVerbosity == "high" )+                config.verbosity = Verbosity::High;+            else+                return ParserResult::runtimeError( "Unrecognised verbosity, '" + verbosity + "'" );+            return ParserResult::ok( ParseResultType::Matched );+        };+        auto const setReporter = [&]( std::string const& reporter ) {+            IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();++            auto lcReporter = toLower( reporter );+            auto result = factories.find( lcReporter );++            if( factories.end() != result )+                config.reporterName = lcReporter;+            else+                return ParserResult::runtimeError( "Unrecognized reporter, '" + reporter + "'. Check available with --list-reporters" );+            return ParserResult::ok( ParseResultType::Matched );+        };++        auto cli+            = ExeName( config.processName )+            | Help( config.showHelp )+            | Opt( config.listTests )+                ["-l"]["--list-tests"]+                ( "list all/matching test cases" )+            | Opt( config.listTags )+                ["-t"]["--list-tags"]+                ( "list all/matching tags" )+            | Opt( config.showSuccessfulTests )+                ["-s"]["--success"]+                ( "include successful tests in output" )+            | Opt( config.shouldDebugBreak )+                ["-b"]["--break"]+                ( "break into debugger on failure" )+            | Opt( config.noThrow )+                ["-e"]["--nothrow"]+                ( "skip exception tests" )+            | Opt( config.showInvisibles )+                ["-i"]["--invisibles"]+                ( "show invisibles (tabs, newlines)" )+            | Opt( config.outputFilename, "filename" )+                ["-o"]["--out"]+                ( "output filename" )+            | Opt( setReporter, "name" )+                ["-r"]["--reporter"]+                ( "reporter to use (defaults to console)" )+            | Opt( config.name, "name" )+                ["-n"]["--name"]+                ( "suite name" )+            | Opt( [&]( bool ){ config.abortAfter = 1; } )+                ["-a"]["--abort"]+                ( "abort at first failure" )+            | Opt( [&]( int x ){ config.abortAfter = x; }, "no. failures" )+                ["-x"]["--abortx"]+                ( "abort after x failures" )+            | Opt( setWarning, "warning name" )+                ["-w"]["--warn"]+                ( "enable warnings" )+            | Opt( [&]( bool flag ) { config.showDurations = flag ? ShowDurations::Always : ShowDurations::Never; }, "yes|no" )+                ["-d"]["--durations"]+                ( "show test durations" )+            | Opt( config.minDuration, "seconds" )+                ["-D"]["--min-duration"]+                ( "show test durations for tests taking at least the given number of seconds" )+            | Opt( loadTestNamesFromFile, "filename" )+                ["-f"]["--input-file"]+                ( "load test names to run from a file" )+            | Opt( config.filenamesAsTags )+                ["-#"]["--filenames-as-tags"]+                ( "adds a tag for the filename" )+            | Opt( config.sectionsToRun, "section name" )+                ["-c"]["--section"]+                ( "specify section to run" )+            | Opt( setVerbosity, "quiet|normal|high" )+                ["-v"]["--verbosity"]+                ( "set output verbosity" )+            | Opt( config.listTestNamesOnly )+                ["--list-test-names-only"]+                ( "list all/matching test cases names only" )+            | Opt( config.listReporters )+                ["--list-reporters"]+                ( "list all reporters" )+            | Opt( setTestOrder, "decl|lex|rand" )+                ["--order"]+                ( "test case order (defaults to decl)" )+            | Opt( setRngSeed, "'time'|number" )+                ["--rng-seed"]+                ( "set a specific seed for random numbers" )+            | Opt( setColourUsage, "yes|no" )+                ["--use-colour"]+                ( "should output be colourised" )+            | Opt( config.libIdentify )+                ["--libidentify"]+                ( "report name and version according to libidentify standard" )+            | Opt( setWaitForKeypress, "never|start|exit|both" )+                ["--wait-for-keypress"]+                ( "waits for a keypress before exiting" )+            | Opt( config.benchmarkSamples, "samples" )+                ["--benchmark-samples"]+                ( "number of samples to collect (default: 100)" )+            | Opt( config.benchmarkResamples, "resamples" )+                ["--benchmark-resamples"]+                ( "number of resamples for the bootstrap (default: 100000)" )+            | Opt( config.benchmarkConfidenceInterval, "confidence interval" )+                ["--benchmark-confidence-interval"]+                ( "confidence interval for the bootstrap (between 0 and 1, default: 0.95)" )+            | Opt( config.benchmarkNoAnalysis )+                ["--benchmark-no-analysis"]+                ( "perform only measurements; do not perform any analysis" )+            | Opt( config.benchmarkWarmupTime, "benchmarkWarmupTime" )+                ["--benchmark-warmup-time"]+                ( "amount of time in milliseconds spent on warming up each test (default: 100)" )+            | Arg( config.testsOrTags, "test name|pattern|tags" )+                ( "which test or tests to use" );++        return cli;+    }++} // end namespace Catch+// end catch_commandline.cpp+// start catch_common.cpp++#include <cstring>+#include <ostream>++namespace Catch {++    bool SourceLineInfo::operator == ( SourceLineInfo const& other ) const noexcept {+        return line == other.line && (file == other.file || std::strcmp(file, other.file) == 0);+    }+    bool SourceLineInfo::operator < ( SourceLineInfo const& other ) const noexcept {+        // We can assume that the same file will usually have the same pointer.+        // Thus, if the pointers are the same, there is no point in calling the strcmp+        return line < other.line || ( line == other.line && file != other.file && (std::strcmp(file, other.file) < 0));+    }++    std::ostream& operator << ( std::ostream& os, SourceLineInfo const& info ) {+#ifndef __GNUG__+        os << info.file << '(' << info.line << ')';+#else+        os << info.file << ':' << info.line;+#endif+        return os;+    }++    std::string StreamEndStop::operator+() const {+        return std::string();+    }++    NonCopyable::NonCopyable() = default;+    NonCopyable::~NonCopyable() = default;++}+// end catch_common.cpp+// start catch_config.cpp++namespace Catch {++    Config::Config( ConfigData const& data )+    :   m_data( data ),+        m_stream( openStream() )+    {+        // We need to trim filter specs to avoid trouble with superfluous+        // whitespace (esp. important for bdd macros, as those are manually+        // aligned with whitespace).++        for (auto& elem : m_data.testsOrTags) {+            elem = trim(elem);+        }+        for (auto& elem : m_data.sectionsToRun) {+            elem = trim(elem);+        }++        TestSpecParser parser(ITagAliasRegistry::get());+        if (!m_data.testsOrTags.empty()) {+            m_hasTestFilters = true;+            for (auto const& testOrTags : m_data.testsOrTags) {+                parser.parse(testOrTags);+            }+        }+        m_testSpec = parser.testSpec();+    }++    std::string const& Config::getFilename() const {+        return m_data.outputFilename ;+    }++    bool Config::listTests() const          { return m_data.listTests; }+    bool Config::listTestNamesOnly() const  { return m_data.listTestNamesOnly; }+    bool Config::listTags() const           { return m_data.listTags; }+    bool Config::listReporters() const      { return m_data.listReporters; }++    std::string Config::getProcessName() const { return m_data.processName; }+    std::string const& Config::getReporterName() const { return m_data.reporterName; }++    std::vector<std::string> const& Config::getTestsOrTags() const { return m_data.testsOrTags; }+    std::vector<std::string> const& Config::getSectionsToRun() const { return m_data.sectionsToRun; }++    TestSpec const& Config::testSpec() const { return m_testSpec; }+    bool Config::hasTestFilters() const { return m_hasTestFilters; }++    bool Config::showHelp() const { return m_data.showHelp; }++    // IConfig interface+    bool Config::allowThrows() const                   { return !m_data.noThrow; }+    std::ostream& Config::stream() const               { return m_stream->stream(); }+    std::string Config::name() const                   { return m_data.name.empty() ? m_data.processName : m_data.name; }+    bool Config::includeSuccessfulResults() const      { return m_data.showSuccessfulTests; }+    bool Config::warnAboutMissingAssertions() const    { return !!(m_data.warnings & WarnAbout::NoAssertions); }+    bool Config::warnAboutNoTests() const              { return !!(m_data.warnings & WarnAbout::NoTests); }+    ShowDurations::OrNot Config::showDurations() const { return m_data.showDurations; }+    double Config::minDuration() const                 { return m_data.minDuration; }+    RunTests::InWhatOrder Config::runOrder() const     { return m_data.runOrder; }+    unsigned int Config::rngSeed() const               { return m_data.rngSeed; }+    UseColour::YesOrNo Config::useColour() const       { return m_data.useColour; }+    bool Config::shouldDebugBreak() const              { return m_data.shouldDebugBreak; }+    int Config::abortAfter() const                     { return m_data.abortAfter; }+    bool Config::showInvisibles() const                { return m_data.showInvisibles; }+    Verbosity Config::verbosity() const                { return m_data.verbosity; }++    bool Config::benchmarkNoAnalysis() const                      { return m_data.benchmarkNoAnalysis; }+    int Config::benchmarkSamples() const                          { return m_data.benchmarkSamples; }+    double Config::benchmarkConfidenceInterval() const            { return m_data.benchmarkConfidenceInterval; }+    unsigned int Config::benchmarkResamples() const               { return m_data.benchmarkResamples; }+    std::chrono::milliseconds Config::benchmarkWarmupTime() const { return std::chrono::milliseconds(m_data.benchmarkWarmupTime); }++    IStream const* Config::openStream() {+        return Catch::makeStream(m_data.outputFilename);+    }++} // end namespace Catch+// end catch_config.cpp+// start catch_console_colour.cpp++#if defined(__clang__)+#    pragma clang diagnostic push+#    pragma clang diagnostic ignored "-Wexit-time-destructors"+#endif++// start catch_errno_guard.h++namespace Catch {++    class ErrnoGuard {+    public:+        ErrnoGuard();+        ~ErrnoGuard();+    private:+        int m_oldErrno;+    };++}++// end catch_errno_guard.h+// start catch_windows_h_proxy.h+++#if defined(CATCH_PLATFORM_WINDOWS)++#if !defined(NOMINMAX) && !defined(CATCH_CONFIG_NO_NOMINMAX)+#  define CATCH_DEFINED_NOMINMAX+#  define NOMINMAX+#endif+#if !defined(WIN32_LEAN_AND_MEAN) && !defined(CATCH_CONFIG_NO_WIN32_LEAN_AND_MEAN)+#  define CATCH_DEFINED_WIN32_LEAN_AND_MEAN+#  define WIN32_LEAN_AND_MEAN+#endif++#ifdef __AFXDLL+#include <AfxWin.h>+#else+#include <windows.h>+#endif++#ifdef CATCH_DEFINED_NOMINMAX+#  undef NOMINMAX+#endif+#ifdef CATCH_DEFINED_WIN32_LEAN_AND_MEAN+#  undef WIN32_LEAN_AND_MEAN+#endif++#endif // defined(CATCH_PLATFORM_WINDOWS)++// end catch_windows_h_proxy.h+#include <sstream>++namespace Catch {+    namespace {++        struct IColourImpl {+            virtual ~IColourImpl() = default;+            virtual void use( Colour::Code _colourCode ) = 0;+        };++        struct NoColourImpl : IColourImpl {+            void use( Colour::Code ) override {}++            static IColourImpl* instance() {+                static NoColourImpl s_instance;+                return &s_instance;+            }+        };++    } // anon namespace+} // namespace Catch++#if !defined( CATCH_CONFIG_COLOUR_NONE ) && !defined( CATCH_CONFIG_COLOUR_WINDOWS ) && !defined( CATCH_CONFIG_COLOUR_ANSI )+#   ifdef CATCH_PLATFORM_WINDOWS+#       define CATCH_CONFIG_COLOUR_WINDOWS+#   else+#       define CATCH_CONFIG_COLOUR_ANSI+#   endif+#endif++#if defined ( CATCH_CONFIG_COLOUR_WINDOWS ) /////////////////////////////////////////++namespace Catch {+namespace {++    class Win32ColourImpl : public IColourImpl {+    public:+        Win32ColourImpl() : stdoutHandle( GetStdHandle(STD_OUTPUT_HANDLE) )+        {+            CONSOLE_SCREEN_BUFFER_INFO csbiInfo;+            GetConsoleScreenBufferInfo( stdoutHandle, &csbiInfo );+            originalForegroundAttributes = csbiInfo.wAttributes & ~( BACKGROUND_GREEN | BACKGROUND_RED | BACKGROUND_BLUE | BACKGROUND_INTENSITY );+            originalBackgroundAttributes = csbiInfo.wAttributes & ~( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_INTENSITY );+        }++        void use( Colour::Code _colourCode ) override {+            switch( _colourCode ) {+                case Colour::None:      return setTextAttribute( originalForegroundAttributes );+                case Colour::White:     return setTextAttribute( FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );+                case Colour::Red:       return setTextAttribute( FOREGROUND_RED );+                case Colour::Green:     return setTextAttribute( FOREGROUND_GREEN );+                case Colour::Blue:      return setTextAttribute( FOREGROUND_BLUE );+                case Colour::Cyan:      return setTextAttribute( FOREGROUND_BLUE | FOREGROUND_GREEN );+                case Colour::Yellow:    return setTextAttribute( FOREGROUND_RED | FOREGROUND_GREEN );+                case Colour::Grey:      return setTextAttribute( 0 );++                case Colour::LightGrey:     return setTextAttribute( FOREGROUND_INTENSITY );+                case Colour::BrightRed:     return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED );+                case Colour::BrightGreen:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN );+                case Colour::BrightWhite:   return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_BLUE );+                case Colour::BrightYellow:  return setTextAttribute( FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN );++                case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );++                default:+                    CATCH_ERROR( "Unknown colour requested" );+            }+        }++    private:+        void setTextAttribute( WORD _textAttribute ) {+            SetConsoleTextAttribute( stdoutHandle, _textAttribute | originalBackgroundAttributes );+        }+        HANDLE stdoutHandle;+        WORD originalForegroundAttributes;+        WORD originalBackgroundAttributes;+    };++    IColourImpl* platformColourInstance() {+        static Win32ColourImpl s_instance;++        IConfigPtr config = getCurrentContext().getConfig();+        UseColour::YesOrNo colourMode = config+            ? config->useColour()+            : UseColour::Auto;+        if( colourMode == UseColour::Auto )+            colourMode = UseColour::Yes;+        return colourMode == UseColour::Yes+            ? &s_instance+            : NoColourImpl::instance();+    }++} // end anon namespace+} // end namespace Catch++#elif defined( CATCH_CONFIG_COLOUR_ANSI ) //////////////////////////////////////++#include <unistd.h>++namespace Catch {+namespace {++    // use POSIX/ ANSI console terminal codes+    // Thanks to Adam Strzelecki for original contribution+    // (http://github.com/nanoant)+    // https://github.com/philsquared/Catch/pull/131+    class PosixColourImpl : public IColourImpl {+    public:+        void use( Colour::Code _colourCode ) override {+            switch( _colourCode ) {+                case Colour::None:+                case Colour::White:     return setColour( "[0m" );+                case Colour::Red:       return setColour( "[0;31m" );+                case Colour::Green:     return setColour( "[0;32m" );+                case Colour::Blue:      return setColour( "[0;34m" );+                case Colour::Cyan:      return setColour( "[0;36m" );+                case Colour::Yellow:    return setColour( "[0;33m" );+                case Colour::Grey:      return setColour( "[1;30m" );++                case Colour::LightGrey:     return setColour( "[0;37m" );+                case Colour::BrightRed:     return setColour( "[1;31m" );+                case Colour::BrightGreen:   return setColour( "[1;32m" );+                case Colour::BrightWhite:   return setColour( "[1;37m" );+                case Colour::BrightYellow:  return setColour( "[1;33m" );++                case Colour::Bright: CATCH_INTERNAL_ERROR( "not a colour" );+                default: CATCH_INTERNAL_ERROR( "Unknown colour requested" );+            }+        }+        static IColourImpl* instance() {+            static PosixColourImpl s_instance;+            return &s_instance;+        }++    private:+        void setColour( const char* _escapeCode ) {+            getCurrentContext().getConfig()->stream()+                << '\033' << _escapeCode;+        }+    };++    bool useColourOnPlatform() {+        return+#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)+            !isDebuggerActive() &&+#endif+#if !(defined(__DJGPP__) && defined(__STRICT_ANSI__))+            isatty(STDOUT_FILENO)+#else+            false+#endif+            ;+    }+    IColourImpl* platformColourInstance() {+        ErrnoGuard guard;+        IConfigPtr config = getCurrentContext().getConfig();+        UseColour::YesOrNo colourMode = config+            ? config->useColour()+            : UseColour::Auto;+        if( colourMode == UseColour::Auto )+            colourMode = useColourOnPlatform()+                ? UseColour::Yes+                : UseColour::No;+        return colourMode == UseColour::Yes+            ? PosixColourImpl::instance()+            : NoColourImpl::instance();+    }++} // end anon namespace+} // end namespace Catch++#else  // not Windows or ANSI ///////////////////////////////////////////////++namespace Catch {++    static IColourImpl* platformColourInstance() { return NoColourImpl::instance(); }++} // end namespace Catch++#endif // Windows/ ANSI/ None++namespace Catch {++    Colour::Colour( Code _colourCode ) { use( _colourCode ); }+    Colour::Colour( Colour&& other ) noexcept {+        m_moved = other.m_moved;+        other.m_moved = true;+    }+    Colour& Colour::operator=( Colour&& other ) noexcept {+        m_moved = other.m_moved;+        other.m_moved  = true;+        return *this;+    }++    Colour::~Colour(){ if( !m_moved ) use( None ); }++    void Colour::use( Code _colourCode ) {+        static IColourImpl* impl = platformColourInstance();+        // Strictly speaking, this cannot possibly happen.+        // However, under some conditions it does happen (see #1626),+        // and this change is small enough that we can let practicality+        // triumph over purity in this case.+        if (impl != nullptr) {+            impl->use( _colourCode );+        }+    }++    std::ostream& operator << ( std::ostream& os, Colour const& ) {+        return os;+    }++} // end namespace Catch++#if defined(__clang__)+#    pragma clang diagnostic pop+#endif++// end catch_console_colour.cpp+// start catch_context.cpp++namespace Catch {++    class Context : public IMutableContext, NonCopyable {++    public: // IContext+        IResultCapture* getResultCapture() override {+            return m_resultCapture;+        }+        IRunner* getRunner() override {+            return m_runner;+        }++        IConfigPtr const& getConfig() const override {+            return m_config;+        }++        ~Context() override;++    public: // IMutableContext+        void setResultCapture( IResultCapture* resultCapture ) override {+            m_resultCapture = resultCapture;+        }+        void setRunner( IRunner* runner ) override {+            m_runner = runner;+        }+        void setConfig( IConfigPtr const& config ) override {+            m_config = config;+        }++        friend IMutableContext& getCurrentMutableContext();++    private:+        IConfigPtr m_config;+        IRunner* m_runner = nullptr;+        IResultCapture* m_resultCapture = nullptr;+    };++    IMutableContext *IMutableContext::currentContext = nullptr;++    void IMutableContext::createContext()+    {+        currentContext = new Context();+    }++    void cleanUpContext() {+        delete IMutableContext::currentContext;+        IMutableContext::currentContext = nullptr;+    }+    IContext::~IContext() = default;+    IMutableContext::~IMutableContext() = default;+    Context::~Context() = default;++    SimplePcg32& rng() {+        static SimplePcg32 s_rng;+        return s_rng;+    }++}+// end catch_context.cpp+// start catch_debug_console.cpp++// start catch_debug_console.h++#include <string>++namespace Catch {+    void writeToDebugConsole( std::string const& text );+}++// end catch_debug_console.h+#if defined(CATCH_CONFIG_ANDROID_LOGWRITE)+#include <android/log.h>++    namespace Catch {+        void writeToDebugConsole( std::string const& text ) {+            __android_log_write( ANDROID_LOG_DEBUG, "Catch", text.c_str() );+        }+    }++#elif defined(CATCH_PLATFORM_WINDOWS)++    namespace Catch {+        void writeToDebugConsole( std::string const& text ) {+            ::OutputDebugStringA( text.c_str() );+        }+    }++#else++    namespace Catch {+        void writeToDebugConsole( std::string const& text ) {+            // !TBD: Need a version for Mac/ XCode and other IDEs+            Catch::cout() << text;+        }+    }++#endif // Platform+// end catch_debug_console.cpp+// start catch_debugger.cpp++#if defined(CATCH_PLATFORM_MAC) || defined(CATCH_PLATFORM_IPHONE)++#  include <cassert>+#  include <sys/types.h>+#  include <unistd.h>+#  include <cstddef>+#  include <ostream>++#ifdef __apple_build_version__+    // These headers will only compile with AppleClang (XCode)+    // For other compilers (Clang, GCC, ... ) we need to exclude them+#  include <sys/sysctl.h>+#endif++    namespace Catch {+        #ifdef __apple_build_version__+        // The following function is taken directly from the following technical note:+        // https://developer.apple.com/library/archive/qa/qa1361/_index.html++        // Returns true if the current process is being debugged (either+        // running under the debugger or has a debugger attached post facto).+        bool isDebuggerActive(){+            int                 mib[4];+            struct kinfo_proc   info;+            std::size_t         size;++            // Initialize the flags so that, if sysctl fails for some bizarre+            // reason, we get a predictable result.++            info.kp_proc.p_flag = 0;++            // Initialize mib, which tells sysctl the info we want, in this case+            // we're looking for information about a specific process ID.++            mib[0] = CTL_KERN;+            mib[1] = KERN_PROC;+            mib[2] = KERN_PROC_PID;+            mib[3] = getpid();++            // Call sysctl.++            size = sizeof(info);+            if( sysctl(mib, sizeof(mib) / sizeof(*mib), &info, &size, nullptr, 0) != 0 ) {+                Catch::cerr() << "\n** Call to sysctl failed - unable to determine if debugger is active **\n" << std::endl;+                return false;+            }++            // We're being debugged if the P_TRACED flag is set.++            return ( (info.kp_proc.p_flag & P_TRACED) != 0 );+        }+        #else+        bool isDebuggerActive() {+            // We need to find another way to determine this for non-appleclang compilers on macOS+            return false;+        }+        #endif+    } // namespace Catch++#elif defined(CATCH_PLATFORM_LINUX)+    #include <fstream>+    #include <string>++    namespace Catch{+        // The standard POSIX way of detecting a debugger is to attempt to+        // ptrace() the process, but this needs to be done from a child and not+        // this process itself to still allow attaching to this process later+        // if wanted, so is rather heavy. Under Linux we have the PID of the+        // "debugger" (which doesn't need to be gdb, of course, it could also+        // be strace, for example) in /proc/$PID/status, so just get it from+        // there instead.+        bool isDebuggerActive(){+            // Libstdc++ has a bug, where std::ifstream sets errno to 0+            // This way our users can properly assert over errno values+            ErrnoGuard guard;+            std::ifstream in("/proc/self/status");+            for( std::string line; std::getline(in, line); ) {+                static const int PREFIX_LEN = 11;+                if( line.compare(0, PREFIX_LEN, "TracerPid:\t") == 0 ) {+                    // We're traced if the PID is not 0 and no other PID starts+                    // with 0 digit, so it's enough to check for just a single+                    // character.+                    return line.length() > PREFIX_LEN && line[PREFIX_LEN] != '0';+                }+            }++            return false;+        }+    } // namespace Catch+#elif defined(_MSC_VER)+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();+    namespace Catch {+        bool isDebuggerActive() {+            return IsDebuggerPresent() != 0;+        }+    }+#elif defined(__MINGW32__)+    extern "C" __declspec(dllimport) int __stdcall IsDebuggerPresent();+    namespace Catch {+        bool isDebuggerActive() {+            return IsDebuggerPresent() != 0;+        }+    }+#else+    namespace Catch {+       bool isDebuggerActive() { return false; }+    }+#endif // Platform+// end catch_debugger.cpp+// start catch_decomposer.cpp++namespace Catch {++    ITransientExpression::~ITransientExpression() = default;++    void formatReconstructedExpression( std::ostream &os, std::string const& lhs, StringRef op, std::string const& rhs ) {+        if( lhs.size() + rhs.size() < 40 &&+                lhs.find('\n') == std::string::npos &&+                rhs.find('\n') == std::string::npos )+            os << lhs << " " << op << " " << rhs;+        else+            os << lhs << "\n" << op << "\n" << rhs;+    }+}+// end catch_decomposer.cpp+// start catch_enforce.cpp++#include <stdexcept>++namespace Catch {+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS) && !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS_CUSTOM_HANDLER)+    [[noreturn]]+    void throw_exception(std::exception const& e) {+        Catch::cerr() << "Catch will terminate because it needed to throw an exception.\n"+                      << "The message was: " << e.what() << '\n';+        std::terminate();+    }+#endif++    [[noreturn]]+    void throw_logic_error(std::string const& msg) {+        throw_exception(std::logic_error(msg));+    }++    [[noreturn]]+    void throw_domain_error(std::string const& msg) {+        throw_exception(std::domain_error(msg));+    }++    [[noreturn]]+    void throw_runtime_error(std::string const& msg) {+        throw_exception(std::runtime_error(msg));+    }++} // namespace Catch;+// end catch_enforce.cpp+// start catch_enum_values_registry.cpp+// start catch_enum_values_registry.h++#include <vector>+#include <memory>++namespace Catch {++    namespace Detail {++        std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values );++        class EnumValuesRegistry : public IMutableEnumValuesRegistry {++            std::vector<std::unique_ptr<EnumInfo>> m_enumInfos;++            EnumInfo const& registerEnum( StringRef enumName, StringRef allEnums, std::vector<int> const& values) override;+        };++        std::vector<StringRef> parseEnums( StringRef enums );++    } // Detail++} // Catch++// end catch_enum_values_registry.h++#include <map>+#include <cassert>++namespace Catch {++    IMutableEnumValuesRegistry::~IMutableEnumValuesRegistry() {}++    namespace Detail {++        namespace {+            // Extracts the actual name part of an enum instance+            // In other words, it returns the Blue part of Bikeshed::Colour::Blue+            StringRef extractInstanceName(StringRef enumInstance) {+                // Find last occurrence of ":"+                size_t name_start = enumInstance.size();+                while (name_start > 0 && enumInstance[name_start - 1] != ':') {+                    --name_start;+                }+                return enumInstance.substr(name_start, enumInstance.size() - name_start);+            }+        }++        std::vector<StringRef> parseEnums( StringRef enums ) {+            auto enumValues = splitStringRef( enums, ',' );+            std::vector<StringRef> parsed;+            parsed.reserve( enumValues.size() );+            for( auto const& enumValue : enumValues ) {+                parsed.push_back(trim(extractInstanceName(enumValue)));+            }+            return parsed;+        }++        EnumInfo::~EnumInfo() {}++        StringRef EnumInfo::lookup( int value ) const {+            for( auto const& valueToName : m_values ) {+                if( valueToName.first == value )+                    return valueToName.second;+            }+            return "{** unexpected enum value **}"_sr;+        }++        std::unique_ptr<EnumInfo> makeEnumInfo( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {+            std::unique_ptr<EnumInfo> enumInfo( new EnumInfo );+            enumInfo->m_name = enumName;+            enumInfo->m_values.reserve( values.size() );++            const auto valueNames = Catch::Detail::parseEnums( allValueNames );+            assert( valueNames.size() == values.size() );+            std::size_t i = 0;+            for( auto value : values )+                enumInfo->m_values.emplace_back(value, valueNames[i++]);++            return enumInfo;+        }++        EnumInfo const& EnumValuesRegistry::registerEnum( StringRef enumName, StringRef allValueNames, std::vector<int> const& values ) {+            m_enumInfos.push_back(makeEnumInfo(enumName, allValueNames, values));+            return *m_enumInfos.back();+        }++    } // Detail+} // Catch++// end catch_enum_values_registry.cpp+// start catch_errno_guard.cpp++#include <cerrno>++namespace Catch {+        ErrnoGuard::ErrnoGuard():m_oldErrno(errno){}+        ErrnoGuard::~ErrnoGuard() { errno = m_oldErrno; }+}+// end catch_errno_guard.cpp+// start catch_exception_translator_registry.cpp++// start catch_exception_translator_registry.h++#include <vector>+#include <string>+#include <memory>++namespace Catch {++    class ExceptionTranslatorRegistry : public IExceptionTranslatorRegistry {+    public:+        ~ExceptionTranslatorRegistry();+        virtual void registerTranslator( const IExceptionTranslator* translator );+        std::string translateActiveException() const override;+        std::string tryTranslators() const;++    private:+        std::vector<std::unique_ptr<IExceptionTranslator const>> m_translators;+    };+}++// end catch_exception_translator_registry.h+#ifdef __OBJC__+#import "Foundation/Foundation.h"+#endif++namespace Catch {++    ExceptionTranslatorRegistry::~ExceptionTranslatorRegistry() {+    }++    void ExceptionTranslatorRegistry::registerTranslator( const IExceptionTranslator* translator ) {+        m_translators.push_back( std::unique_ptr<const IExceptionTranslator>( translator ) );+    }++#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+    std::string ExceptionTranslatorRegistry::translateActiveException() const {+        try {+#ifdef __OBJC__+            // In Objective-C try objective-c exceptions first+            @try {+                return tryTranslators();+            }+            @catch (NSException *exception) {+                return Catch::Detail::stringify( [exception description] );+            }+#else+            // Compiling a mixed mode project with MSVC means that CLR+            // exceptions will be caught in (...) as well. However, these+            // do not fill-in std::current_exception and thus lead to crash+            // when attempting rethrow.+            // /EHa switch also causes structured exceptions to be caught+            // here, but they fill-in current_exception properly, so+            // at worst the output should be a little weird, instead of+            // causing a crash.+            if (std::current_exception() == nullptr) {+                return "Non C++ exception. Possibly a CLR exception.";+            }+            return tryTranslators();+#endif+        }+        catch( TestFailureException& ) {+            std::rethrow_exception(std::current_exception());+        }+        catch( std::exception& ex ) {+            return ex.what();+        }+        catch( std::string& msg ) {+            return msg;+        }+        catch( const char* msg ) {+            return msg;+        }+        catch(...) {+            return "Unknown exception";+        }+    }++    std::string ExceptionTranslatorRegistry::tryTranslators() const {+        if (m_translators.empty()) {+            std::rethrow_exception(std::current_exception());+        } else {+            return m_translators[0]->translate(m_translators.begin() + 1, m_translators.end());+        }+    }++#else // ^^ Exceptions are enabled // Exceptions are disabled vv+    std::string ExceptionTranslatorRegistry::translateActiveException() const {+        CATCH_INTERNAL_ERROR("Attempted to translate active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");+    }++    std::string ExceptionTranslatorRegistry::tryTranslators() const {+        CATCH_INTERNAL_ERROR("Attempted to use exception translators under CATCH_CONFIG_DISABLE_EXCEPTIONS!");+    }+#endif++}+// end catch_exception_translator_registry.cpp+// start catch_fatal_condition.cpp++#include <algorithm>++#if !defined( CATCH_CONFIG_WINDOWS_SEH ) && !defined( CATCH_CONFIG_POSIX_SIGNALS )++namespace Catch {++    // If neither SEH nor signal handling is required, the handler impls+    // do not have to do anything, and can be empty.+    void FatalConditionHandler::engage_platform() {}+    void FatalConditionHandler::disengage_platform() {}+    FatalConditionHandler::FatalConditionHandler() = default;+    FatalConditionHandler::~FatalConditionHandler() = default;++} // end namespace Catch++#endif // !CATCH_CONFIG_WINDOWS_SEH && !CATCH_CONFIG_POSIX_SIGNALS++#if defined( CATCH_CONFIG_WINDOWS_SEH ) && defined( CATCH_CONFIG_POSIX_SIGNALS )+#error "Inconsistent configuration: Windows' SEH handling and POSIX signals cannot be enabled at the same time"+#endif // CATCH_CONFIG_WINDOWS_SEH && CATCH_CONFIG_POSIX_SIGNALS++#if defined( CATCH_CONFIG_WINDOWS_SEH ) || defined( CATCH_CONFIG_POSIX_SIGNALS )++namespace {+    //! Signals fatal error message to the run context+    void reportFatal( char const * const message ) {+        Catch::getCurrentContext().getResultCapture()->handleFatalErrorCondition( message );+    }++    //! Minimal size Catch2 needs for its own fatal error handling.+    //! Picked anecdotally, so it might not be sufficient on all+    //! platforms, and for all configurations.+    constexpr std::size_t minStackSizeForErrors = 32 * 1024;+} // end unnamed namespace++#endif // CATCH_CONFIG_WINDOWS_SEH || CATCH_CONFIG_POSIX_SIGNALS++#if defined( CATCH_CONFIG_WINDOWS_SEH )++namespace Catch {++    struct SignalDefs { DWORD id; const char* name; };++    // There is no 1-1 mapping between signals and windows exceptions.+    // Windows can easily distinguish between SO and SigSegV,+    // but SigInt, SigTerm, etc are handled differently.+    static SignalDefs signalDefs[] = {+        { static_cast<DWORD>(EXCEPTION_ILLEGAL_INSTRUCTION),  "SIGILL - Illegal instruction signal" },+        { static_cast<DWORD>(EXCEPTION_STACK_OVERFLOW), "SIGSEGV - Stack overflow" },+        { static_cast<DWORD>(EXCEPTION_ACCESS_VIOLATION), "SIGSEGV - Segmentation violation signal" },+        { static_cast<DWORD>(EXCEPTION_INT_DIVIDE_BY_ZERO), "Divide by zero error" },+    };++    static LONG CALLBACK handleVectoredException(PEXCEPTION_POINTERS ExceptionInfo) {+        for (auto const& def : signalDefs) {+            if (ExceptionInfo->ExceptionRecord->ExceptionCode == def.id) {+                reportFatal(def.name);+            }+        }+        // If its not an exception we care about, pass it along.+        // This stops us from eating debugger breaks etc.+        return EXCEPTION_CONTINUE_SEARCH;+    }++    // Since we do not support multiple instantiations, we put these+    // into global variables and rely on cleaning them up in outlined+    // constructors/destructors+    static PVOID exceptionHandlerHandle = nullptr;++    // For MSVC, we reserve part of the stack memory for handling+    // memory overflow structured exception.+    FatalConditionHandler::FatalConditionHandler() {+        ULONG guaranteeSize = static_cast<ULONG>(minStackSizeForErrors);+        if (!SetThreadStackGuarantee(&guaranteeSize)) {+            // We do not want to fully error out, because needing+            // the stack reserve should be rare enough anyway.+            Catch::cerr()+                << "Failed to reserve piece of stack."+                << " Stack overflows will not be reported successfully.";+        }+    }++    // We do not attempt to unset the stack guarantee, because+    // Windows does not support lowering the stack size guarantee.+    FatalConditionHandler::~FatalConditionHandler() = default;++    void FatalConditionHandler::engage_platform() {+        // Register as first handler in current chain+        exceptionHandlerHandle = AddVectoredExceptionHandler(1, handleVectoredException);+        if (!exceptionHandlerHandle) {+            CATCH_RUNTIME_ERROR("Could not register vectored exception handler");+        }+    }++    void FatalConditionHandler::disengage_platform() {+        if (!RemoveVectoredExceptionHandler(exceptionHandlerHandle)) {+            CATCH_RUNTIME_ERROR("Could not unregister vectored exception handler");+        }+        exceptionHandlerHandle = nullptr;+    }++} // end namespace Catch++#endif // CATCH_CONFIG_WINDOWS_SEH++#if defined( CATCH_CONFIG_POSIX_SIGNALS )++#include <signal.h>++namespace Catch {++    struct SignalDefs {+        int id;+        const char* name;+    };++    static SignalDefs signalDefs[] = {+        { SIGINT,  "SIGINT - Terminal interrupt signal" },+        { SIGILL,  "SIGILL - Illegal instruction signal" },+        { SIGFPE,  "SIGFPE - Floating point error signal" },+        { SIGSEGV, "SIGSEGV - Segmentation violation signal" },+        { SIGTERM, "SIGTERM - Termination request signal" },+        { SIGABRT, "SIGABRT - Abort (abnormal termination) signal" }+    };++// Older GCCs trigger -Wmissing-field-initializers for T foo = {}+// which is zero initialization, but not explicit. We want to avoid+// that.+#if defined(__GNUC__)+#    pragma GCC diagnostic push+#    pragma GCC diagnostic ignored "-Wmissing-field-initializers"+#endif++    static char* altStackMem = nullptr;+    static std::size_t altStackSize = 0;+    static stack_t oldSigStack{};+    static struct sigaction oldSigActions[sizeof(signalDefs) / sizeof(SignalDefs)]{};++    static void restorePreviousSignalHandlers() {+        // We set signal handlers back to the previous ones. Hopefully+        // nobody overwrote them in the meantime, and doesn't expect+        // their signal handlers to live past ours given that they+        // installed them after ours..+        for (std::size_t i = 0; i < sizeof(signalDefs) / sizeof(SignalDefs); ++i) {+            sigaction(signalDefs[i].id, &oldSigActions[i], nullptr);+        }+        // Return the old stack+        sigaltstack(&oldSigStack, nullptr);+    }++    static void handleSignal( int sig ) {+        char const * name = "<unknown signal>";+        for (auto const& def : signalDefs) {+            if (sig == def.id) {+                name = def.name;+                break;+            }+        }+        // We need to restore previous signal handlers and let them do+        // their thing, so that the users can have the debugger break+        // when a signal is raised, and so on.+        restorePreviousSignalHandlers();+        reportFatal( name );+        raise( sig );+    }++    FatalConditionHandler::FatalConditionHandler() {+        assert(!altStackMem && "Cannot initialize POSIX signal handler when one already exists");+        if (altStackSize == 0) {+            altStackSize = std::max(static_cast<size_t>(SIGSTKSZ), minStackSizeForErrors);+        }+        altStackMem = new char[altStackSize]();+    }++    FatalConditionHandler::~FatalConditionHandler() {+        delete[] altStackMem;+        // We signal that another instance can be constructed by zeroing+        // out the pointer.+        altStackMem = nullptr;+    }++    void FatalConditionHandler::engage_platform() {+        stack_t sigStack;+        sigStack.ss_sp = altStackMem;+        sigStack.ss_size = altStackSize;+        sigStack.ss_flags = 0;+        sigaltstack(&sigStack, &oldSigStack);+        struct sigaction sa = { };++        sa.sa_handler = handleSignal;+        sa.sa_flags = SA_ONSTACK;+        for (std::size_t i = 0; i < sizeof(signalDefs)/sizeof(SignalDefs); ++i) {+            sigaction(signalDefs[i].id, &sa, &oldSigActions[i]);+        }+    }++#if defined(__GNUC__)+#    pragma GCC diagnostic pop+#endif++    void FatalConditionHandler::disengage_platform() {+        restorePreviousSignalHandlers();+    }++} // end namespace Catch++#endif // CATCH_CONFIG_POSIX_SIGNALS+// end catch_fatal_condition.cpp+// start catch_generators.cpp++#include <limits>+#include <set>++namespace Catch {++IGeneratorTracker::~IGeneratorTracker() {}++const char* GeneratorException::what() const noexcept {+    return m_msg;+}++namespace Generators {++    GeneratorUntypedBase::~GeneratorUntypedBase() {}++    auto acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {+        return getResultCapture().acquireGeneratorTracker( generatorName, lineInfo );+    }++} // namespace Generators+} // namespace Catch+// end catch_generators.cpp+// start catch_interfaces_capture.cpp++namespace Catch {+    IResultCapture::~IResultCapture() = default;+}+// end catch_interfaces_capture.cpp+// start catch_interfaces_config.cpp++namespace Catch {+    IConfig::~IConfig() = default;+}+// end catch_interfaces_config.cpp+// start catch_interfaces_exception.cpp++namespace Catch {+    IExceptionTranslator::~IExceptionTranslator() = default;+    IExceptionTranslatorRegistry::~IExceptionTranslatorRegistry() = default;+}+// end catch_interfaces_exception.cpp+// start catch_interfaces_registry_hub.cpp++namespace Catch {+    IRegistryHub::~IRegistryHub() = default;+    IMutableRegistryHub::~IMutableRegistryHub() = default;+}+// end catch_interfaces_registry_hub.cpp+// start catch_interfaces_reporter.cpp++// start catch_reporter_listening.h++namespace Catch {++    class ListeningReporter : public IStreamingReporter {+        using Reporters = std::vector<IStreamingReporterPtr>;+        Reporters m_listeners;+        IStreamingReporterPtr m_reporter = nullptr;+        ReporterPreferences m_preferences;++    public:+        ListeningReporter();++        void addListener( IStreamingReporterPtr&& listener );+        void addReporter( IStreamingReporterPtr&& reporter );++    public: // IStreamingReporter++        ReporterPreferences getPreferences() const override;++        void noMatchingTestCases( std::string const& spec ) override;++        void reportInvalidArguments(std::string const&arg) override;++        static std::set<Verbosity> getSupportedVerbosities();++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+        void benchmarkPreparing(std::string const& name) override;+        void benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) override;+        void benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) override;+        void benchmarkFailed(std::string const&) override;+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++        void testRunStarting( TestRunInfo const& testRunInfo ) override;+        void testGroupStarting( GroupInfo const& groupInfo ) override;+        void testCaseStarting( TestCaseInfo const& testInfo ) override;+        void sectionStarting( SectionInfo const& sectionInfo ) override;+        void assertionStarting( AssertionInfo const& assertionInfo ) override;++        // The return value indicates if the messages buffer should be cleared:+        bool assertionEnded( AssertionStats const& assertionStats ) override;+        void sectionEnded( SectionStats const& sectionStats ) override;+        void testCaseEnded( TestCaseStats const& testCaseStats ) override;+        void testGroupEnded( TestGroupStats const& testGroupStats ) override;+        void testRunEnded( TestRunStats const& testRunStats ) override;++        void skipTest( TestCaseInfo const& testInfo ) override;+        bool isMulti() const override;++    };++} // end namespace Catch++// end catch_reporter_listening.h+namespace Catch {++    ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig )+    :   m_stream( &_fullConfig->stream() ), m_fullConfig( _fullConfig ) {}++    ReporterConfig::ReporterConfig( IConfigPtr const& _fullConfig, std::ostream& _stream )+    :   m_stream( &_stream ), m_fullConfig( _fullConfig ) {}++    std::ostream& ReporterConfig::stream() const { return *m_stream; }+    IConfigPtr ReporterConfig::fullConfig() const { return m_fullConfig; }++    TestRunInfo::TestRunInfo( std::string const& _name ) : name( _name ) {}++    GroupInfo::GroupInfo(  std::string const& _name,+                           std::size_t _groupIndex,+                           std::size_t _groupsCount )+    :   name( _name ),+        groupIndex( _groupIndex ),+        groupsCounts( _groupsCount )+    {}++     AssertionStats::AssertionStats( AssertionResult const& _assertionResult,+                                     std::vector<MessageInfo> const& _infoMessages,+                                     Totals const& _totals )+    :   assertionResult( _assertionResult ),+        infoMessages( _infoMessages ),+        totals( _totals )+    {+        assertionResult.m_resultData.lazyExpression.m_transientExpression = _assertionResult.m_resultData.lazyExpression.m_transientExpression;++        if( assertionResult.hasMessage() ) {+            // Copy message into messages list.+            // !TBD This should have been done earlier, somewhere+            MessageBuilder builder( assertionResult.getTestMacroName(), assertionResult.getSourceInfo(), assertionResult.getResultType() );+            builder << assertionResult.getMessage();+            builder.m_info.message = builder.m_stream.str();++            infoMessages.push_back( builder.m_info );+        }+    }++     AssertionStats::~AssertionStats() = default;++    SectionStats::SectionStats(  SectionInfo const& _sectionInfo,+                                 Counts const& _assertions,+                                 double _durationInSeconds,+                                 bool _missingAssertions )+    :   sectionInfo( _sectionInfo ),+        assertions( _assertions ),+        durationInSeconds( _durationInSeconds ),+        missingAssertions( _missingAssertions )+    {}++    SectionStats::~SectionStats() = default;++    TestCaseStats::TestCaseStats(  TestCaseInfo const& _testInfo,+                                   Totals const& _totals,+                                   std::string const& _stdOut,+                                   std::string const& _stdErr,+                                   bool _aborting )+    : testInfo( _testInfo ),+        totals( _totals ),+        stdOut( _stdOut ),+        stdErr( _stdErr ),+        aborting( _aborting )+    {}++    TestCaseStats::~TestCaseStats() = default;++    TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo,+                                    Totals const& _totals,+                                    bool _aborting )+    :   groupInfo( _groupInfo ),+        totals( _totals ),+        aborting( _aborting )+    {}++    TestGroupStats::TestGroupStats( GroupInfo const& _groupInfo )+    :   groupInfo( _groupInfo ),+        aborting( false )+    {}++    TestGroupStats::~TestGroupStats() = default;++    TestRunStats::TestRunStats(   TestRunInfo const& _runInfo,+                    Totals const& _totals,+                    bool _aborting )+    :   runInfo( _runInfo ),+        totals( _totals ),+        aborting( _aborting )+    {}++    TestRunStats::~TestRunStats() = default;++    void IStreamingReporter::fatalErrorEncountered( StringRef ) {}+    bool IStreamingReporter::isMulti() const { return false; }++    IReporterFactory::~IReporterFactory() = default;+    IReporterRegistry::~IReporterRegistry() = default;++} // end namespace Catch+// end catch_interfaces_reporter.cpp+// start catch_interfaces_runner.cpp++namespace Catch {+    IRunner::~IRunner() = default;+}+// end catch_interfaces_runner.cpp+// start catch_interfaces_testcase.cpp++namespace Catch {+    ITestInvoker::~ITestInvoker() = default;+    ITestCaseRegistry::~ITestCaseRegistry() = default;+}+// end catch_interfaces_testcase.cpp+// start catch_leak_detector.cpp++#ifdef CATCH_CONFIG_WINDOWS_CRTDBG+#include <crtdbg.h>++namespace Catch {++    LeakDetector::LeakDetector() {+        int flag = _CrtSetDbgFlag(_CRTDBG_REPORT_FLAG);+        flag |= _CRTDBG_LEAK_CHECK_DF;+        flag |= _CRTDBG_ALLOC_MEM_DF;+        _CrtSetDbgFlag(flag);+        _CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE | _CRTDBG_MODE_DEBUG);+        _CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDERR);+        // Change this to leaking allocation's number to break there+        _CrtSetBreakAlloc(-1);+    }+}++#else++    Catch::LeakDetector::LeakDetector() {}++#endif++Catch::LeakDetector::~LeakDetector() {+    Catch::cleanUp();+}+// end catch_leak_detector.cpp+// start catch_list.cpp++// start catch_list.h++#include <set>++namespace Catch {++    std::size_t listTests( Config const& config );++    std::size_t listTestsNamesOnly( Config const& config );++    struct TagInfo {+        void add( std::string const& spelling );+        std::string all() const;++        std::set<std::string> spellings;+        std::size_t count = 0;+    };++    std::size_t listTags( Config const& config );++    std::size_t listReporters();++    Option<std::size_t> list( std::shared_ptr<Config> const& config );++} // end namespace Catch++// end catch_list.h+// start catch_text.h++namespace Catch {+    using namespace clara::TextFlow;+}++// end catch_text.h+#include <limits>+#include <algorithm>+#include <iomanip>++namespace Catch {++    std::size_t listTests( Config const& config ) {+        TestSpec const& testSpec = config.testSpec();+        if( config.hasTestFilters() )+            Catch::cout() << "Matching test cases:\n";+        else {+            Catch::cout() << "All available test cases:\n";+        }++        auto matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );+        for( auto const& testCaseInfo : matchedTestCases ) {+            Colour::Code colour = testCaseInfo.isHidden()+                ? Colour::SecondaryText+                : Colour::None;+            Colour colourGuard( colour );++            Catch::cout() << Column( testCaseInfo.name ).initialIndent( 2 ).indent( 4 ) << "\n";+            if( config.verbosity() >= Verbosity::High ) {+                Catch::cout() << Column( Catch::Detail::stringify( testCaseInfo.lineInfo ) ).indent(4) << std::endl;+                std::string description = testCaseInfo.description;+                if( description.empty() )+                    description = "(NO DESCRIPTION)";+                Catch::cout() << Column( description ).indent(4) << std::endl;+            }+            if( !testCaseInfo.tags.empty() )+                Catch::cout() << Column( testCaseInfo.tagsAsString() ).indent( 6 ) << "\n";+        }++        if( !config.hasTestFilters() )+            Catch::cout() << pluralise( matchedTestCases.size(), "test case" ) << '\n' << std::endl;+        else+            Catch::cout() << pluralise( matchedTestCases.size(), "matching test case" ) << '\n' << std::endl;+        return matchedTestCases.size();+    }++    std::size_t listTestsNamesOnly( Config const& config ) {+        TestSpec const& testSpec = config.testSpec();+        std::size_t matchedTests = 0;+        std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );+        for( auto const& testCaseInfo : matchedTestCases ) {+            matchedTests++;+            if( startsWith( testCaseInfo.name, '#' ) )+               Catch::cout() << '"' << testCaseInfo.name << '"';+            else+               Catch::cout() << testCaseInfo.name;+            if ( config.verbosity() >= Verbosity::High )+                Catch::cout() << "\t@" << testCaseInfo.lineInfo;+            Catch::cout() << std::endl;+        }+        return matchedTests;+    }++    void TagInfo::add( std::string const& spelling ) {+        ++count;+        spellings.insert( spelling );+    }++    std::string TagInfo::all() const {+        size_t size = 0;+        for (auto const& spelling : spellings) {+            // Add 2 for the brackes+            size += spelling.size() + 2;+        }++        std::string out; out.reserve(size);+        for (auto const& spelling : spellings) {+            out += '[';+            out += spelling;+            out += ']';+        }+        return out;+    }++    std::size_t listTags( Config const& config ) {+        TestSpec const& testSpec = config.testSpec();+        if( config.hasTestFilters() )+            Catch::cout() << "Tags for matching test cases:\n";+        else {+            Catch::cout() << "All available tags:\n";+        }++        std::map<std::string, TagInfo> tagCounts;++        std::vector<TestCase> matchedTestCases = filterTests( getAllTestCasesSorted( config ), testSpec, config );+        for( auto const& testCase : matchedTestCases ) {+            for( auto const& tagName : testCase.getTestCaseInfo().tags ) {+                std::string lcaseTagName = toLower( tagName );+                auto countIt = tagCounts.find( lcaseTagName );+                if( countIt == tagCounts.end() )+                    countIt = tagCounts.insert( std::make_pair( lcaseTagName, TagInfo() ) ).first;+                countIt->second.add( tagName );+            }+        }++        for( auto const& tagCount : tagCounts ) {+            ReusableStringStream rss;+            rss << "  " << std::setw(2) << tagCount.second.count << "  ";+            auto str = rss.str();+            auto wrapper = Column( tagCount.second.all() )+                                                    .initialIndent( 0 )+                                                    .indent( str.size() )+                                                    .width( CATCH_CONFIG_CONSOLE_WIDTH-10 );+            Catch::cout() << str << wrapper << '\n';+        }+        Catch::cout() << pluralise( tagCounts.size(), "tag" ) << '\n' << std::endl;+        return tagCounts.size();+    }++    std::size_t listReporters() {+        Catch::cout() << "Available reporters:\n";+        IReporterRegistry::FactoryMap const& factories = getRegistryHub().getReporterRegistry().getFactories();+        std::size_t maxNameLen = 0;+        for( auto const& factoryKvp : factories )+            maxNameLen = (std::max)( maxNameLen, factoryKvp.first.size() );++        for( auto const& factoryKvp : factories ) {+            Catch::cout()+                    << Column( factoryKvp.first + ":" )+                            .indent(2)+                            .width( 5+maxNameLen )+                    +  Column( factoryKvp.second->getDescription() )+                            .initialIndent(0)+                            .indent(2)+                            .width( CATCH_CONFIG_CONSOLE_WIDTH - maxNameLen-8 )+                    << "\n";+        }+        Catch::cout() << std::endl;+        return factories.size();+    }++    Option<std::size_t> list( std::shared_ptr<Config> const& config ) {+        Option<std::size_t> listedCount;+        getCurrentMutableContext().setConfig( config );+        if( config->listTests() )+            listedCount = listedCount.valueOr(0) + listTests( *config );+        if( config->listTestNamesOnly() )+            listedCount = listedCount.valueOr(0) + listTestsNamesOnly( *config );+        if( config->listTags() )+            listedCount = listedCount.valueOr(0) + listTags( *config );+        if( config->listReporters() )+            listedCount = listedCount.valueOr(0) + listReporters();+        return listedCount;+    }++} // end namespace Catch+// end catch_list.cpp+// start catch_matchers.cpp++namespace Catch {+namespace Matchers {+    namespace Impl {++        std::string MatcherUntypedBase::toString() const {+            if( m_cachedToString.empty() )+                m_cachedToString = describe();+            return m_cachedToString;+        }++        MatcherUntypedBase::~MatcherUntypedBase() = default;++    } // namespace Impl+} // namespace Matchers++using namespace Matchers;+using Matchers::Impl::MatcherBase;++} // namespace Catch+// end catch_matchers.cpp+// start catch_matchers_exception.cpp++namespace Catch {+namespace Matchers {+namespace Exception {++bool ExceptionMessageMatcher::match(std::exception const& ex) const {+    return ex.what() == m_message;+}++std::string ExceptionMessageMatcher::describe() const {+    return "exception message matches \"" + m_message + "\"";+}++}+Exception::ExceptionMessageMatcher Message(std::string const& message) {+    return Exception::ExceptionMessageMatcher(message);+}++// namespace Exception+} // namespace Matchers+} // namespace Catch+// end catch_matchers_exception.cpp+// start catch_matchers_floating.cpp++// start catch_polyfills.hpp++namespace Catch {+    bool isnan(float f);+    bool isnan(double d);+}++// end catch_polyfills.hpp+// start catch_to_string.hpp++#include <string>++namespace Catch {+    template <typename T>+    std::string to_string(T const& t) {+#if defined(CATCH_CONFIG_CPP11_TO_STRING)+        return std::to_string(t);+#else+        ReusableStringStream rss;+        rss << t;+        return rss.str();+#endif+    }+} // end namespace Catch++// end catch_to_string.hpp+#include <algorithm>+#include <cmath>+#include <cstdlib>+#include <cstdint>+#include <cstring>+#include <sstream>+#include <type_traits>+#include <iomanip>+#include <limits>++namespace Catch {+namespace {++    int32_t convert(float f) {+        static_assert(sizeof(float) == sizeof(int32_t), "Important ULP matcher assumption violated");+        int32_t i;+        std::memcpy(&i, &f, sizeof(f));+        return i;+    }++    int64_t convert(double d) {+        static_assert(sizeof(double) == sizeof(int64_t), "Important ULP matcher assumption violated");+        int64_t i;+        std::memcpy(&i, &d, sizeof(d));+        return i;+    }++    template <typename FP>+    bool almostEqualUlps(FP lhs, FP rhs, uint64_t maxUlpDiff) {+        // Comparison with NaN should always be false.+        // This way we can rule it out before getting into the ugly details+        if (Catch::isnan(lhs) || Catch::isnan(rhs)) {+            return false;+        }++        auto lc = convert(lhs);+        auto rc = convert(rhs);++        if ((lc < 0) != (rc < 0)) {+            // Potentially we can have +0 and -0+            return lhs == rhs;+        }++        // static cast as a workaround for IBM XLC+        auto ulpDiff = std::abs(static_cast<FP>(lc - rc));+        return static_cast<uint64_t>(ulpDiff) <= maxUlpDiff;+    }++#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)++    float nextafter(float x, float y) {+        return ::nextafterf(x, y);+    }++    double nextafter(double x, double y) {+        return ::nextafter(x, y);+    }++#endif // ^^^ CATCH_CONFIG_GLOBAL_NEXTAFTER ^^^++template <typename FP>+FP step(FP start, FP direction, uint64_t steps) {+    for (uint64_t i = 0; i < steps; ++i) {+#if defined(CATCH_CONFIG_GLOBAL_NEXTAFTER)+        start = Catch::nextafter(start, direction);+#else+        start = std::nextafter(start, direction);+#endif+    }+    return start;+}++// Performs equivalent check of std::fabs(lhs - rhs) <= margin+// But without the subtraction to allow for INFINITY in comparison+bool marginComparison(double lhs, double rhs, double margin) {+    return (lhs + margin >= rhs) && (rhs + margin >= lhs);+}++template <typename FloatingPoint>+void write(std::ostream& out, FloatingPoint num) {+    out << std::scientific+        << std::setprecision(std::numeric_limits<FloatingPoint>::max_digits10 - 1)+        << num;+}++} // end anonymous namespace++namespace Matchers {+namespace Floating {++    enum class FloatingPointKind : uint8_t {+        Float,+        Double+    };++    WithinAbsMatcher::WithinAbsMatcher(double target, double margin)+        :m_target{ target }, m_margin{ margin } {+        CATCH_ENFORCE(margin >= 0, "Invalid margin: " << margin << '.'+            << " Margin has to be non-negative.");+    }++    // Performs equivalent check of std::fabs(lhs - rhs) <= margin+    // But without the subtraction to allow for INFINITY in comparison+    bool WithinAbsMatcher::match(double const& matchee) const {+        return (matchee + m_margin >= m_target) && (m_target + m_margin >= matchee);+    }++    std::string WithinAbsMatcher::describe() const {+        return "is within " + ::Catch::Detail::stringify(m_margin) + " of " + ::Catch::Detail::stringify(m_target);+    }++    WithinUlpsMatcher::WithinUlpsMatcher(double target, uint64_t ulps, FloatingPointKind baseType)+        :m_target{ target }, m_ulps{ ulps }, m_type{ baseType } {+        CATCH_ENFORCE(m_type == FloatingPointKind::Double+                   || m_ulps < (std::numeric_limits<uint32_t>::max)(),+            "Provided ULP is impossibly large for a float comparison.");+    }++#if defined(__clang__)+#pragma clang diagnostic push+// Clang <3.5 reports on the default branch in the switch below+#pragma clang diagnostic ignored "-Wunreachable-code"+#endif++    bool WithinUlpsMatcher::match(double const& matchee) const {+        switch (m_type) {+        case FloatingPointKind::Float:+            return almostEqualUlps<float>(static_cast<float>(matchee), static_cast<float>(m_target), m_ulps);+        case FloatingPointKind::Double:+            return almostEqualUlps<double>(matchee, m_target, m_ulps);+        default:+            CATCH_INTERNAL_ERROR( "Unknown FloatingPointKind value" );+        }+    }++#if defined(__clang__)+#pragma clang diagnostic pop+#endif++    std::string WithinUlpsMatcher::describe() const {+        std::stringstream ret;++        ret << "is within " << m_ulps << " ULPs of ";++        if (m_type == FloatingPointKind::Float) {+            write(ret, static_cast<float>(m_target));+            ret << 'f';+        } else {+            write(ret, m_target);+        }++        ret << " ([";+        if (m_type == FloatingPointKind::Double) {+            write(ret, step(m_target, static_cast<double>(-INFINITY), m_ulps));+            ret << ", ";+            write(ret, step(m_target, static_cast<double>( INFINITY), m_ulps));+        } else {+            // We have to cast INFINITY to float because of MinGW, see #1782+            write(ret, step(static_cast<float>(m_target), static_cast<float>(-INFINITY), m_ulps));+            ret << ", ";+            write(ret, step(static_cast<float>(m_target), static_cast<float>( INFINITY), m_ulps));+        }+        ret << "])";++        return ret.str();+    }++    WithinRelMatcher::WithinRelMatcher(double target, double epsilon):+        m_target(target),+        m_epsilon(epsilon){+        CATCH_ENFORCE(m_epsilon >= 0., "Relative comparison with epsilon <  0 does not make sense.");+        CATCH_ENFORCE(m_epsilon  < 1., "Relative comparison with epsilon >= 1 does not make sense.");+    }++    bool WithinRelMatcher::match(double const& matchee) const {+        const auto relMargin = m_epsilon * (std::max)(std::fabs(matchee), std::fabs(m_target));+        return marginComparison(matchee, m_target,+                                std::isinf(relMargin)? 0 : relMargin);+    }++    std::string WithinRelMatcher::describe() const {+        Catch::ReusableStringStream sstr;+        sstr << "and " << m_target << " are within " << m_epsilon * 100. << "% of each other";+        return sstr.str();+    }++}// namespace Floating++Floating::WithinUlpsMatcher WithinULP(double target, uint64_t maxUlpDiff) {+    return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Double);+}++Floating::WithinUlpsMatcher WithinULP(float target, uint64_t maxUlpDiff) {+    return Floating::WithinUlpsMatcher(target, maxUlpDiff, Floating::FloatingPointKind::Float);+}++Floating::WithinAbsMatcher WithinAbs(double target, double margin) {+    return Floating::WithinAbsMatcher(target, margin);+}++Floating::WithinRelMatcher WithinRel(double target, double eps) {+    return Floating::WithinRelMatcher(target, eps);+}++Floating::WithinRelMatcher WithinRel(double target) {+    return Floating::WithinRelMatcher(target, std::numeric_limits<double>::epsilon() * 100);+}++Floating::WithinRelMatcher WithinRel(float target, float eps) {+    return Floating::WithinRelMatcher(target, eps);+}++Floating::WithinRelMatcher WithinRel(float target) {+    return Floating::WithinRelMatcher(target, std::numeric_limits<float>::epsilon() * 100);+}++} // namespace Matchers+} // namespace Catch+// end catch_matchers_floating.cpp+// start catch_matchers_generic.cpp++std::string Catch::Matchers::Generic::Detail::finalizeDescription(const std::string& desc) {+    if (desc.empty()) {+        return "matches undescribed predicate";+    } else {+        return "matches predicate: \"" + desc + '"';+    }+}+// end catch_matchers_generic.cpp+// start catch_matchers_string.cpp++#include <regex>++namespace Catch {+namespace Matchers {++    namespace StdString {++        CasedString::CasedString( std::string const& str, CaseSensitive::Choice caseSensitivity )+        :   m_caseSensitivity( caseSensitivity ),+            m_str( adjustString( str ) )+        {}+        std::string CasedString::adjustString( std::string const& str ) const {+            return m_caseSensitivity == CaseSensitive::No+                   ? toLower( str )+                   : str;+        }+        std::string CasedString::caseSensitivitySuffix() const {+            return m_caseSensitivity == CaseSensitive::No+                   ? " (case insensitive)"+                   : std::string();+        }++        StringMatcherBase::StringMatcherBase( std::string const& operation, CasedString const& comparator )+        : m_comparator( comparator ),+          m_operation( operation ) {+        }++        std::string StringMatcherBase::describe() const {+            std::string description;+            description.reserve(5 + m_operation.size() + m_comparator.m_str.size() ++                                        m_comparator.caseSensitivitySuffix().size());+            description += m_operation;+            description += ": \"";+            description += m_comparator.m_str;+            description += "\"";+            description += m_comparator.caseSensitivitySuffix();+            return description;+        }++        EqualsMatcher::EqualsMatcher( CasedString const& comparator ) : StringMatcherBase( "equals", comparator ) {}++        bool EqualsMatcher::match( std::string const& source ) const {+            return m_comparator.adjustString( source ) == m_comparator.m_str;+        }++        ContainsMatcher::ContainsMatcher( CasedString const& comparator ) : StringMatcherBase( "contains", comparator ) {}++        bool ContainsMatcher::match( std::string const& source ) const {+            return contains( m_comparator.adjustString( source ), m_comparator.m_str );+        }++        StartsWithMatcher::StartsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "starts with", comparator ) {}++        bool StartsWithMatcher::match( std::string const& source ) const {+            return startsWith( m_comparator.adjustString( source ), m_comparator.m_str );+        }++        EndsWithMatcher::EndsWithMatcher( CasedString const& comparator ) : StringMatcherBase( "ends with", comparator ) {}++        bool EndsWithMatcher::match( std::string const& source ) const {+            return endsWith( m_comparator.adjustString( source ), m_comparator.m_str );+        }++        RegexMatcher::RegexMatcher(std::string regex, CaseSensitive::Choice caseSensitivity): m_regex(std::move(regex)), m_caseSensitivity(caseSensitivity) {}++        bool RegexMatcher::match(std::string const& matchee) const {+            auto flags = std::regex::ECMAScript; // ECMAScript is the default syntax option anyway+            if (m_caseSensitivity == CaseSensitive::Choice::No) {+                flags |= std::regex::icase;+            }+            auto reg = std::regex(m_regex, flags);+            return std::regex_match(matchee, reg);+        }++        std::string RegexMatcher::describe() const {+            return "matches " + ::Catch::Detail::stringify(m_regex) + ((m_caseSensitivity == CaseSensitive::Choice::Yes)? " case sensitively" : " case insensitively");+        }++    } // namespace StdString++    StdString::EqualsMatcher Equals( std::string const& str, CaseSensitive::Choice caseSensitivity ) {+        return StdString::EqualsMatcher( StdString::CasedString( str, caseSensitivity) );+    }+    StdString::ContainsMatcher Contains( std::string const& str, CaseSensitive::Choice caseSensitivity ) {+        return StdString::ContainsMatcher( StdString::CasedString( str, caseSensitivity) );+    }+    StdString::EndsWithMatcher EndsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {+        return StdString::EndsWithMatcher( StdString::CasedString( str, caseSensitivity) );+    }+    StdString::StartsWithMatcher StartsWith( std::string const& str, CaseSensitive::Choice caseSensitivity ) {+        return StdString::StartsWithMatcher( StdString::CasedString( str, caseSensitivity) );+    }++    StdString::RegexMatcher Matches(std::string const& regex, CaseSensitive::Choice caseSensitivity) {+        return StdString::RegexMatcher(regex, caseSensitivity);+    }++} // namespace Matchers+} // namespace Catch+// end catch_matchers_string.cpp+// start catch_message.cpp++// start catch_uncaught_exceptions.h++namespace Catch {+    bool uncaught_exceptions();+} // end namespace Catch++// end catch_uncaught_exceptions.h+#include <cassert>+#include <stack>++namespace Catch {++    MessageInfo::MessageInfo(   StringRef const& _macroName,+                                SourceLineInfo const& _lineInfo,+                                ResultWas::OfType _type )+    :   macroName( _macroName ),+        lineInfo( _lineInfo ),+        type( _type ),+        sequence( ++globalCount )+    {}++    bool MessageInfo::operator==( MessageInfo const& other ) const {+        return sequence == other.sequence;+    }++    bool MessageInfo::operator<( MessageInfo const& other ) const {+        return sequence < other.sequence;+    }++    // This may need protecting if threading support is added+    unsigned int MessageInfo::globalCount = 0;++    ////////////////////////////////////////////////////////////////////////////++    Catch::MessageBuilder::MessageBuilder( StringRef const& macroName,+                                           SourceLineInfo const& lineInfo,+                                           ResultWas::OfType type )+        :m_info(macroName, lineInfo, type) {}++    ////////////////////////////////////////////////////////////////////////////++    ScopedMessage::ScopedMessage( MessageBuilder const& builder )+    : m_info( builder.m_info ), m_moved()+    {+        m_info.message = builder.m_stream.str();+        getResultCapture().pushScopedMessage( m_info );+    }++    ScopedMessage::ScopedMessage( ScopedMessage&& old )+    : m_info( old.m_info ), m_moved()+    {+        old.m_moved = true;+    }++    ScopedMessage::~ScopedMessage() {+        if ( !uncaught_exceptions() && !m_moved ){+            getResultCapture().popScopedMessage(m_info);+        }+    }++    Capturer::Capturer( StringRef macroName, SourceLineInfo const& lineInfo, ResultWas::OfType resultType, StringRef names ) {+        auto trimmed = [&] (size_t start, size_t end) {+            while (names[start] == ',' || isspace(static_cast<unsigned char>(names[start]))) {+                ++start;+            }+            while (names[end] == ',' || isspace(static_cast<unsigned char>(names[end]))) {+                --end;+            }+            return names.substr(start, end - start + 1);+        };+        auto skipq = [&] (size_t start, char quote) {+            for (auto i = start + 1; i < names.size() ; ++i) {+                if (names[i] == quote)+                    return i;+                if (names[i] == '\\')+                    ++i;+            }+            CATCH_INTERNAL_ERROR("CAPTURE parsing encountered unmatched quote");+        };++        size_t start = 0;+        std::stack<char> openings;+        for (size_t pos = 0; pos < names.size(); ++pos) {+            char c = names[pos];+            switch (c) {+            case '[':+            case '{':+            case '(':+            // It is basically impossible to disambiguate between+            // comparison and start of template args in this context+//            case '<':+                openings.push(c);+                break;+            case ']':+            case '}':+            case ')':+//           case '>':+                openings.pop();+                break;+            case '"':+            case '\'':+                pos = skipq(pos, c);+                break;+            case ',':+                if (start != pos && openings.empty()) {+                    m_messages.emplace_back(macroName, lineInfo, resultType);+                    m_messages.back().message = static_cast<std::string>(trimmed(start, pos));+                    m_messages.back().message += " := ";+                    start = pos;+                }+            }+        }+        assert(openings.empty() && "Mismatched openings");+        m_messages.emplace_back(macroName, lineInfo, resultType);+        m_messages.back().message = static_cast<std::string>(trimmed(start, names.size() - 1));+        m_messages.back().message += " := ";+    }+    Capturer::~Capturer() {+        if ( !uncaught_exceptions() ){+            assert( m_captured == m_messages.size() );+            for( size_t i = 0; i < m_captured; ++i  )+                m_resultCapture.popScopedMessage( m_messages[i] );+        }+    }++    void Capturer::captureValue( size_t index, std::string const& value ) {+        assert( index < m_messages.size() );+        m_messages[index].message += value;+        m_resultCapture.pushScopedMessage( m_messages[index] );+        m_captured++;+    }++} // end namespace Catch+// end catch_message.cpp+// start catch_output_redirect.cpp++// start catch_output_redirect.h+#ifndef TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H+#define TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H++#include <cstdio>+#include <iosfwd>+#include <string>++namespace Catch {++    class RedirectedStream {+        std::ostream& m_originalStream;+        std::ostream& m_redirectionStream;+        std::streambuf* m_prevBuf;++    public:+        RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream );+        ~RedirectedStream();+    };++    class RedirectedStdOut {+        ReusableStringStream m_rss;+        RedirectedStream m_cout;+    public:+        RedirectedStdOut();+        auto str() const -> std::string;+    };++    // StdErr has two constituent streams in C++, std::cerr and std::clog+    // This means that we need to redirect 2 streams into 1 to keep proper+    // order of writes+    class RedirectedStdErr {+        ReusableStringStream m_rss;+        RedirectedStream m_cerr;+        RedirectedStream m_clog;+    public:+        RedirectedStdErr();+        auto str() const -> std::string;+    };++    class RedirectedStreams {+    public:+        RedirectedStreams(RedirectedStreams const&) = delete;+        RedirectedStreams& operator=(RedirectedStreams const&) = delete;+        RedirectedStreams(RedirectedStreams&&) = delete;+        RedirectedStreams& operator=(RedirectedStreams&&) = delete;++        RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr);+        ~RedirectedStreams();+    private:+        std::string& m_redirectedCout;+        std::string& m_redirectedCerr;+        RedirectedStdOut m_redirectedStdOut;+        RedirectedStdErr m_redirectedStdErr;+    };++#if defined(CATCH_CONFIG_NEW_CAPTURE)++    // Windows's implementation of std::tmpfile is terrible (it tries+    // to create a file inside system folder, thus requiring elevated+    // privileges for the binary), so we have to use tmpnam(_s) and+    // create the file ourselves there.+    class TempFile {+    public:+        TempFile(TempFile const&) = delete;+        TempFile& operator=(TempFile const&) = delete;+        TempFile(TempFile&&) = delete;+        TempFile& operator=(TempFile&&) = delete;++        TempFile();+        ~TempFile();++        std::FILE* getFile();+        std::string getContents();++    private:+        std::FILE* m_file = nullptr;+    #if defined(_MSC_VER)+        char m_buffer[L_tmpnam] = { 0 };+    #endif+    };++    class OutputRedirect {+    public:+        OutputRedirect(OutputRedirect const&) = delete;+        OutputRedirect& operator=(OutputRedirect const&) = delete;+        OutputRedirect(OutputRedirect&&) = delete;+        OutputRedirect& operator=(OutputRedirect&&) = delete;++        OutputRedirect(std::string& stdout_dest, std::string& stderr_dest);+        ~OutputRedirect();++    private:+        int m_originalStdout = -1;+        int m_originalStderr = -1;+        TempFile m_stdoutFile;+        TempFile m_stderrFile;+        std::string& m_stdoutDest;+        std::string& m_stderrDest;+    };++#endif++} // end namespace Catch++#endif // TWOBLUECUBES_CATCH_OUTPUT_REDIRECT_H+// end catch_output_redirect.h+#include <cstdio>+#include <cstring>+#include <fstream>+#include <sstream>+#include <stdexcept>++#if defined(CATCH_CONFIG_NEW_CAPTURE)+    #if defined(_MSC_VER)+    #include <io.h>      //_dup and _dup2+    #define dup _dup+    #define dup2 _dup2+    #define fileno _fileno+    #else+    #include <unistd.h>  // dup and dup2+    #endif+#endif++namespace Catch {++    RedirectedStream::RedirectedStream( std::ostream& originalStream, std::ostream& redirectionStream )+    :   m_originalStream( originalStream ),+        m_redirectionStream( redirectionStream ),+        m_prevBuf( m_originalStream.rdbuf() )+    {+        m_originalStream.rdbuf( m_redirectionStream.rdbuf() );+    }++    RedirectedStream::~RedirectedStream() {+        m_originalStream.rdbuf( m_prevBuf );+    }++    RedirectedStdOut::RedirectedStdOut() : m_cout( Catch::cout(), m_rss.get() ) {}+    auto RedirectedStdOut::str() const -> std::string { return m_rss.str(); }++    RedirectedStdErr::RedirectedStdErr()+    :   m_cerr( Catch::cerr(), m_rss.get() ),+        m_clog( Catch::clog(), m_rss.get() )+    {}+    auto RedirectedStdErr::str() const -> std::string { return m_rss.str(); }++    RedirectedStreams::RedirectedStreams(std::string& redirectedCout, std::string& redirectedCerr)+    :   m_redirectedCout(redirectedCout),+        m_redirectedCerr(redirectedCerr)+    {}++    RedirectedStreams::~RedirectedStreams() {+        m_redirectedCout += m_redirectedStdOut.str();+        m_redirectedCerr += m_redirectedStdErr.str();+    }++#if defined(CATCH_CONFIG_NEW_CAPTURE)++#if defined(_MSC_VER)+    TempFile::TempFile() {+        if (tmpnam_s(m_buffer)) {+            CATCH_RUNTIME_ERROR("Could not get a temp filename");+        }+        if (fopen_s(&m_file, m_buffer, "w+")) {+            char buffer[100];+            if (strerror_s(buffer, errno)) {+                CATCH_RUNTIME_ERROR("Could not translate errno to a string");+            }+            CATCH_RUNTIME_ERROR("Could not open the temp file: '" << m_buffer << "' because: " << buffer);+        }+    }+#else+    TempFile::TempFile() {+        m_file = std::tmpfile();+        if (!m_file) {+            CATCH_RUNTIME_ERROR("Could not create a temp file.");+        }+    }++#endif++    TempFile::~TempFile() {+         // TBD: What to do about errors here?+         std::fclose(m_file);+         // We manually create the file on Windows only, on Linux+         // it will be autodeleted+#if defined(_MSC_VER)+         std::remove(m_buffer);+#endif+    }++    FILE* TempFile::getFile() {+        return m_file;+    }++    std::string TempFile::getContents() {+        std::stringstream sstr;+        char buffer[100] = {};+        std::rewind(m_file);+        while (std::fgets(buffer, sizeof(buffer), m_file)) {+            sstr << buffer;+        }+        return sstr.str();+    }++    OutputRedirect::OutputRedirect(std::string& stdout_dest, std::string& stderr_dest) :+        m_originalStdout(dup(1)),+        m_originalStderr(dup(2)),+        m_stdoutDest(stdout_dest),+        m_stderrDest(stderr_dest) {+        dup2(fileno(m_stdoutFile.getFile()), 1);+        dup2(fileno(m_stderrFile.getFile()), 2);+    }++    OutputRedirect::~OutputRedirect() {+        Catch::cout() << std::flush;+        fflush(stdout);+        // Since we support overriding these streams, we flush cerr+        // even though std::cerr is unbuffered+        Catch::cerr() << std::flush;+        Catch::clog() << std::flush;+        fflush(stderr);++        dup2(m_originalStdout, 1);+        dup2(m_originalStderr, 2);++        m_stdoutDest += m_stdoutFile.getContents();+        m_stderrDest += m_stderrFile.getContents();+    }++#endif // CATCH_CONFIG_NEW_CAPTURE++} // namespace Catch++#if defined(CATCH_CONFIG_NEW_CAPTURE)+    #if defined(_MSC_VER)+    #undef dup+    #undef dup2+    #undef fileno+    #endif+#endif+// end catch_output_redirect.cpp+// start catch_polyfills.cpp++#include <cmath>++namespace Catch {++#if !defined(CATCH_CONFIG_POLYFILL_ISNAN)+    bool isnan(float f) {+        return std::isnan(f);+    }+    bool isnan(double d) {+        return std::isnan(d);+    }+#else+    // For now we only use this for embarcadero+    bool isnan(float f) {+        return std::_isnan(f);+    }+    bool isnan(double d) {+        return std::_isnan(d);+    }+#endif++} // end namespace Catch+// end catch_polyfills.cpp+// start catch_random_number_generator.cpp++namespace Catch {++namespace {++#if defined(_MSC_VER)+#pragma warning(push)+#pragma warning(disable:4146) // we negate uint32 during the rotate+#endif+        // Safe rotr implementation thanks to John Regehr+        uint32_t rotate_right(uint32_t val, uint32_t count) {+            const uint32_t mask = 31;+            count &= mask;+            return (val >> count) | (val << (-count & mask));+        }++#if defined(_MSC_VER)+#pragma warning(pop)+#endif++}++    SimplePcg32::SimplePcg32(result_type seed_) {+        seed(seed_);+    }++    void SimplePcg32::seed(result_type seed_) {+        m_state = 0;+        (*this)();+        m_state += seed_;+        (*this)();+    }++    void SimplePcg32::discard(uint64_t skip) {+        // We could implement this to run in O(log n) steps, but this+        // should suffice for our use case.+        for (uint64_t s = 0; s < skip; ++s) {+            static_cast<void>((*this)());+        }+    }++    SimplePcg32::result_type SimplePcg32::operator()() {+        // prepare the output value+        const uint32_t xorshifted = static_cast<uint32_t>(((m_state >> 18u) ^ m_state) >> 27u);+        const auto output = rotate_right(xorshifted, m_state >> 59u);++        // advance state+        m_state = m_state * 6364136223846793005ULL + s_inc;++        return output;+    }++    bool operator==(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {+        return lhs.m_state == rhs.m_state;+    }++    bool operator!=(SimplePcg32 const& lhs, SimplePcg32 const& rhs) {+        return lhs.m_state != rhs.m_state;+    }+}+// end catch_random_number_generator.cpp+// start catch_registry_hub.cpp++// start catch_test_case_registry_impl.h++#include <vector>+#include <set>+#include <algorithm>+#include <ios>++namespace Catch {++    class TestCase;+    struct IConfig;++    std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases );++    bool isThrowSafe( TestCase const& testCase, IConfig const& config );+    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config );++    void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions );++    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config );+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config );++    class TestRegistry : public ITestCaseRegistry {+    public:+        virtual ~TestRegistry() = default;++        virtual void registerTest( TestCase const& testCase );++        std::vector<TestCase> const& getAllTests() const override;+        std::vector<TestCase> const& getAllTestsSorted( IConfig const& config ) const override;++    private:+        std::vector<TestCase> m_functions;+        mutable RunTests::InWhatOrder m_currentSortOrder = RunTests::InDeclarationOrder;+        mutable std::vector<TestCase> m_sortedFunctions;+        std::size_t m_unnamedCount = 0;+        std::ios_base::Init m_ostreamInit; // Forces cout/ cerr to be initialised+    };++    ///////////////////////////////////////////////////////////////////////////++    class TestInvokerAsFunction : public ITestInvoker {+        void(*m_testAsFunction)();+    public:+        TestInvokerAsFunction( void(*testAsFunction)() ) noexcept;++        void invoke() const override;+    };++    std::string extractClassName( StringRef const& classOrQualifiedMethodName );++    ///////////////////////////////////////////////////////////////////////////++} // end namespace Catch++// end catch_test_case_registry_impl.h+// start catch_reporter_registry.h++#include <map>++namespace Catch {++    class ReporterRegistry : public IReporterRegistry {++    public:++        ~ReporterRegistry() override;++        IStreamingReporterPtr create( std::string const& name, IConfigPtr const& config ) const override;++        void registerReporter( std::string const& name, IReporterFactoryPtr const& factory );+        void registerListener( IReporterFactoryPtr const& factory );++        FactoryMap const& getFactories() const override;+        Listeners const& getListeners() const override;++    private:+        FactoryMap m_factories;+        Listeners m_listeners;+    };+}++// end catch_reporter_registry.h+// start catch_tag_alias_registry.h++// start catch_tag_alias.h++#include <string>++namespace Catch {++    struct TagAlias {+        TagAlias(std::string const& _tag, SourceLineInfo _lineInfo);++        std::string tag;+        SourceLineInfo lineInfo;+    };++} // end namespace Catch++// end catch_tag_alias.h+#include <map>++namespace Catch {++    class TagAliasRegistry : public ITagAliasRegistry {+    public:+        ~TagAliasRegistry() override;+        TagAlias const* find( std::string const& alias ) const override;+        std::string expandAliases( std::string const& unexpandedTestSpec ) const override;+        void add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo );++    private:+        std::map<std::string, TagAlias> m_registry;+    };++} // end namespace Catch++// end catch_tag_alias_registry.h+// start catch_startup_exception_registry.h++#include <vector>+#include <exception>++namespace Catch {++    class StartupExceptionRegistry {+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+    public:+        void add(std::exception_ptr const& exception) noexcept;+        std::vector<std::exception_ptr> const& getExceptions() const noexcept;+    private:+        std::vector<std::exception_ptr> m_exceptions;+#endif+    };++} // end namespace Catch++// end catch_startup_exception_registry.h+// start catch_singletons.hpp++namespace Catch {++    struct ISingleton {+        virtual ~ISingleton();+    };++    void addSingleton( ISingleton* singleton );+    void cleanupSingletons();++    template<typename SingletonImplT, typename InterfaceT = SingletonImplT, typename MutableInterfaceT = InterfaceT>+    class Singleton : SingletonImplT, public ISingleton {++        static auto getInternal() -> Singleton* {+            static Singleton* s_instance = nullptr;+            if( !s_instance ) {+                s_instance = new Singleton;+                addSingleton( s_instance );+            }+            return s_instance;+        }++    public:+        static auto get() -> InterfaceT const& {+            return *getInternal();+        }+        static auto getMutable() -> MutableInterfaceT& {+            return *getInternal();+        }+    };++} // namespace Catch++// end catch_singletons.hpp+namespace Catch {++    namespace {++        class RegistryHub : public IRegistryHub, public IMutableRegistryHub,+                            private NonCopyable {++        public: // IRegistryHub+            RegistryHub() = default;+            IReporterRegistry const& getReporterRegistry() const override {+                return m_reporterRegistry;+            }+            ITestCaseRegistry const& getTestCaseRegistry() const override {+                return m_testCaseRegistry;+            }+            IExceptionTranslatorRegistry const& getExceptionTranslatorRegistry() const override {+                return m_exceptionTranslatorRegistry;+            }+            ITagAliasRegistry const& getTagAliasRegistry() const override {+                return m_tagAliasRegistry;+            }+            StartupExceptionRegistry const& getStartupExceptionRegistry() const override {+                return m_exceptionRegistry;+            }++        public: // IMutableRegistryHub+            void registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) override {+                m_reporterRegistry.registerReporter( name, factory );+            }+            void registerListener( IReporterFactoryPtr const& factory ) override {+                m_reporterRegistry.registerListener( factory );+            }+            void registerTest( TestCase const& testInfo ) override {+                m_testCaseRegistry.registerTest( testInfo );+            }+            void registerTranslator( const IExceptionTranslator* translator ) override {+                m_exceptionTranslatorRegistry.registerTranslator( translator );+            }+            void registerTagAlias( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) override {+                m_tagAliasRegistry.add( alias, tag, lineInfo );+            }+            void registerStartupException() noexcept override {+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+                m_exceptionRegistry.add(std::current_exception());+#else+                CATCH_INTERNAL_ERROR("Attempted to register active exception under CATCH_CONFIG_DISABLE_EXCEPTIONS!");+#endif+            }+            IMutableEnumValuesRegistry& getMutableEnumValuesRegistry() override {+                return m_enumValuesRegistry;+            }++        private:+            TestRegistry m_testCaseRegistry;+            ReporterRegistry m_reporterRegistry;+            ExceptionTranslatorRegistry m_exceptionTranslatorRegistry;+            TagAliasRegistry m_tagAliasRegistry;+            StartupExceptionRegistry m_exceptionRegistry;+            Detail::EnumValuesRegistry m_enumValuesRegistry;+        };+    }++    using RegistryHubSingleton = Singleton<RegistryHub, IRegistryHub, IMutableRegistryHub>;++    IRegistryHub const& getRegistryHub() {+        return RegistryHubSingleton::get();+    }+    IMutableRegistryHub& getMutableRegistryHub() {+        return RegistryHubSingleton::getMutable();+    }+    void cleanUp() {+        cleanupSingletons();+        cleanUpContext();+    }+    std::string translateActiveException() {+        return getRegistryHub().getExceptionTranslatorRegistry().translateActiveException();+    }++} // end namespace Catch+// end catch_registry_hub.cpp+// start catch_reporter_registry.cpp++namespace Catch {++    ReporterRegistry::~ReporterRegistry() = default;++    IStreamingReporterPtr ReporterRegistry::create( std::string const& name, IConfigPtr const& config ) const {+        auto it =  m_factories.find( name );+        if( it == m_factories.end() )+            return nullptr;+        return it->second->create( ReporterConfig( config ) );+    }++    void ReporterRegistry::registerReporter( std::string const& name, IReporterFactoryPtr const& factory ) {+        m_factories.emplace(name, factory);+    }+    void ReporterRegistry::registerListener( IReporterFactoryPtr const& factory ) {+        m_listeners.push_back( factory );+    }++    IReporterRegistry::FactoryMap const& ReporterRegistry::getFactories() const {+        return m_factories;+    }+    IReporterRegistry::Listeners const& ReporterRegistry::getListeners() const {+        return m_listeners;+    }++}+// end catch_reporter_registry.cpp+// start catch_result_type.cpp++namespace Catch {++    bool isOk( ResultWas::OfType resultType ) {+        return ( resultType & ResultWas::FailureBit ) == 0;+    }+    bool isJustInfo( int flags ) {+        return flags == ResultWas::Info;+    }++    ResultDisposition::Flags operator | ( ResultDisposition::Flags lhs, ResultDisposition::Flags rhs ) {+        return static_cast<ResultDisposition::Flags>( static_cast<int>( lhs ) | static_cast<int>( rhs ) );+    }++    bool shouldContinueOnFailure( int flags )    { return ( flags & ResultDisposition::ContinueOnFailure ) != 0; }+    bool shouldSuppressFailure( int flags )      { return ( flags & ResultDisposition::SuppressFail ) != 0; }++} // end namespace Catch+// end catch_result_type.cpp+// start catch_run_context.cpp++#include <cassert>+#include <algorithm>+#include <sstream>++namespace Catch {++    namespace Generators {+        struct GeneratorTracker : TestCaseTracking::TrackerBase, IGeneratorTracker {+            GeneratorBasePtr m_generator;++            GeneratorTracker( TestCaseTracking::NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )+            :   TrackerBase( nameAndLocation, ctx, parent )+            {}+            ~GeneratorTracker();++            static GeneratorTracker& acquire( TrackerContext& ctx, TestCaseTracking::NameAndLocation const& nameAndLocation ) {+                std::shared_ptr<GeneratorTracker> tracker;++                ITracker& currentTracker = ctx.currentTracker();+                // Under specific circumstances, the generator we want+                // to acquire is also the current tracker. If this is+                // the case, we have to avoid looking through current+                // tracker's children, and instead return the current+                // tracker.+                // A case where this check is important is e.g.+                //     for (int i = 0; i < 5; ++i) {+                //         int n = GENERATE(1, 2);+                //     }+                //+                // without it, the code above creates 5 nested generators.+                if (currentTracker.nameAndLocation() == nameAndLocation) {+                    auto thisTracker = currentTracker.parent().findChild(nameAndLocation);+                    assert(thisTracker);+                    assert(thisTracker->isGeneratorTracker());+                    tracker = std::static_pointer_cast<GeneratorTracker>(thisTracker);+                } else if ( TestCaseTracking::ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {+                    assert( childTracker );+                    assert( childTracker->isGeneratorTracker() );+                    tracker = std::static_pointer_cast<GeneratorTracker>( childTracker );+                } else {+                    tracker = std::make_shared<GeneratorTracker>( nameAndLocation, ctx, &currentTracker );+                    currentTracker.addChild( tracker );+                }++                if( !tracker->isComplete() ) {+                    tracker->open();+                }++                return *tracker;+            }++            // TrackerBase interface+            bool isGeneratorTracker() const override { return true; }+            auto hasGenerator() const -> bool override {+                return !!m_generator;+            }+            void close() override {+                TrackerBase::close();+                // If a generator has a child (it is followed by a section)+                // and none of its children have started, then we must wait+                // until later to start consuming its values.+                // This catches cases where `GENERATE` is placed between two+                // `SECTION`s.+                // **The check for m_children.empty cannot be removed**.+                // doing so would break `GENERATE` _not_ followed by `SECTION`s.+                const bool should_wait_for_child = [&]() {+                    // No children -> nobody to wait for+                    if ( m_children.empty() ) {+                        return false;+                    }+                    // If at least one child started executing, don't wait+                    if ( std::find_if(+                             m_children.begin(),+                             m_children.end(),+                             []( TestCaseTracking::ITrackerPtr tracker ) {+                                 return tracker->hasStarted();+                             } ) != m_children.end() ) {+                        return false;+                    }++                    // No children have started. We need to check if they _can_+                    // start, and thus we should wait for them, or they cannot+                    // start (due to filters), and we shouldn't wait for them+                    auto* parent = m_parent;+                    // This is safe: there is always at least one section+                    // tracker in a test case tracking tree+                    while ( !parent->isSectionTracker() ) {+                        parent = &( parent->parent() );+                    }+                    assert( parent &&+                            "Missing root (test case) level section" );++                    auto const& parentSection =+                        static_cast<SectionTracker&>( *parent );+                    auto const& filters = parentSection.getFilters();+                    // No filters -> no restrictions on running sections+                    if ( filters.empty() ) {+                        return true;+                    }++                    for ( auto const& child : m_children ) {+                        if ( child->isSectionTracker() &&+                             std::find( filters.begin(),+                                        filters.end(),+                                        static_cast<SectionTracker&>( *child )+                                            .trimmedName() ) !=+                                 filters.end() ) {+                            return true;+                        }+                    }+                    return false;+                }();++                // This check is a bit tricky, because m_generator->next()+                // has a side-effect, where it consumes generator's current+                // value, but we do not want to invoke the side-effect if+                // this generator is still waiting for any child to start.+                if ( should_wait_for_child ||+                     ( m_runState == CompletedSuccessfully &&+                       m_generator->next() ) ) {+                    m_children.clear();+                    m_runState = Executing;+                }+            }++            // IGeneratorTracker interface+            auto getGenerator() const -> GeneratorBasePtr const& override {+                return m_generator;+            }+            void setGenerator( GeneratorBasePtr&& generator ) override {+                m_generator = std::move( generator );+            }+        };+        GeneratorTracker::~GeneratorTracker() {}+    }++    RunContext::RunContext(IConfigPtr const& _config, IStreamingReporterPtr&& reporter)+    :   m_runInfo(_config->name()),+        m_context(getCurrentMutableContext()),+        m_config(_config),+        m_reporter(std::move(reporter)),+        m_lastAssertionInfo{ StringRef(), SourceLineInfo("",0), StringRef(), ResultDisposition::Normal },+        m_includeSuccessfulResults( m_config->includeSuccessfulResults() || m_reporter->getPreferences().shouldReportAllAssertions )+    {+        m_context.setRunner(this);+        m_context.setConfig(m_config);+        m_context.setResultCapture(this);+        m_reporter->testRunStarting(m_runInfo);+    }++    RunContext::~RunContext() {+        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, aborting()));+    }++    void RunContext::testGroupStarting(std::string const& testSpec, std::size_t groupIndex, std::size_t groupsCount) {+        m_reporter->testGroupStarting(GroupInfo(testSpec, groupIndex, groupsCount));+    }++    void RunContext::testGroupEnded(std::string const& testSpec, Totals const& totals, std::size_t groupIndex, std::size_t groupsCount) {+        m_reporter->testGroupEnded(TestGroupStats(GroupInfo(testSpec, groupIndex, groupsCount), totals, aborting()));+    }++    Totals RunContext::runTest(TestCase const& testCase) {+        Totals prevTotals = m_totals;++        std::string redirectedCout;+        std::string redirectedCerr;++        auto const& testInfo = testCase.getTestCaseInfo();++        m_reporter->testCaseStarting(testInfo);++        m_activeTestCase = &testCase;++        ITracker& rootTracker = m_trackerContext.startRun();+        assert(rootTracker.isSectionTracker());+        static_cast<SectionTracker&>(rootTracker).addInitialFilters(m_config->getSectionsToRun());+        do {+            m_trackerContext.startCycle();+            m_testCaseTracker = &SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(testInfo.name, testInfo.lineInfo));+            runCurrentTest(redirectedCout, redirectedCerr);+        } while (!m_testCaseTracker->isSuccessfullyCompleted() && !aborting());++        Totals deltaTotals = m_totals.delta(prevTotals);+        if (testInfo.expectedToFail() && deltaTotals.testCases.passed > 0) {+            deltaTotals.assertions.failed++;+            deltaTotals.testCases.passed--;+            deltaTotals.testCases.failed++;+        }+        m_totals.testCases += deltaTotals.testCases;+        m_reporter->testCaseEnded(TestCaseStats(testInfo,+                                  deltaTotals,+                                  redirectedCout,+                                  redirectedCerr,+                                  aborting()));++        m_activeTestCase = nullptr;+        m_testCaseTracker = nullptr;++        return deltaTotals;+    }++    IConfigPtr RunContext::config() const {+        return m_config;+    }++    IStreamingReporter& RunContext::reporter() const {+        return *m_reporter;+    }++    void RunContext::assertionEnded(AssertionResult const & result) {+        if (result.getResultType() == ResultWas::Ok) {+            m_totals.assertions.passed++;+            m_lastAssertionPassed = true;+        } else if (!result.isOk()) {+            m_lastAssertionPassed = false;+            if( m_activeTestCase->getTestCaseInfo().okToFail() )+                m_totals.assertions.failedButOk++;+            else+                m_totals.assertions.failed++;+        }+        else {+            m_lastAssertionPassed = true;+        }++        // We have no use for the return value (whether messages should be cleared), because messages were made scoped+        // and should be let to clear themselves out.+        static_cast<void>(m_reporter->assertionEnded(AssertionStats(result, m_messages, m_totals)));++        if (result.getResultType() != ResultWas::Warning)+            m_messageScopes.clear();++        // Reset working state+        resetAssertionInfo();+        m_lastResult = result;+    }+    void RunContext::resetAssertionInfo() {+        m_lastAssertionInfo.macroName = StringRef();+        m_lastAssertionInfo.capturedExpression = "{Unknown expression after the reported line}"_sr;+    }++    bool RunContext::sectionStarted(SectionInfo const & sectionInfo, Counts & assertions) {+        ITracker& sectionTracker = SectionTracker::acquire(m_trackerContext, TestCaseTracking::NameAndLocation(sectionInfo.name, sectionInfo.lineInfo));+        if (!sectionTracker.isOpen())+            return false;+        m_activeSections.push_back(&sectionTracker);++        m_lastAssertionInfo.lineInfo = sectionInfo.lineInfo;++        m_reporter->sectionStarting(sectionInfo);++        assertions = m_totals.assertions;++        return true;+    }+    auto RunContext::acquireGeneratorTracker( StringRef generatorName, SourceLineInfo const& lineInfo ) -> IGeneratorTracker& {+        using namespace Generators;+        GeneratorTracker& tracker = GeneratorTracker::acquire(m_trackerContext,+                                                              TestCaseTracking::NameAndLocation( static_cast<std::string>(generatorName), lineInfo ) );+        m_lastAssertionInfo.lineInfo = lineInfo;+        return tracker;+    }++    bool RunContext::testForMissingAssertions(Counts& assertions) {+        if (assertions.total() != 0)+            return false;+        if (!m_config->warnAboutMissingAssertions())+            return false;+        if (m_trackerContext.currentTracker().hasChildren())+            return false;+        m_totals.assertions.failed++;+        assertions.failed++;+        return true;+    }++    void RunContext::sectionEnded(SectionEndInfo const & endInfo) {+        Counts assertions = m_totals.assertions - endInfo.prevAssertions;+        bool missingAssertions = testForMissingAssertions(assertions);++        if (!m_activeSections.empty()) {+            m_activeSections.back()->close();+            m_activeSections.pop_back();+        }++        m_reporter->sectionEnded(SectionStats(endInfo.sectionInfo, assertions, endInfo.durationInSeconds, missingAssertions));+        m_messages.clear();+        m_messageScopes.clear();+    }++    void RunContext::sectionEndedEarly(SectionEndInfo const & endInfo) {+        if (m_unfinishedSections.empty())+            m_activeSections.back()->fail();+        else+            m_activeSections.back()->close();+        m_activeSections.pop_back();++        m_unfinishedSections.push_back(endInfo);+    }++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+    void RunContext::benchmarkPreparing(std::string const& name) {+        m_reporter->benchmarkPreparing(name);+    }+    void RunContext::benchmarkStarting( BenchmarkInfo const& info ) {+        m_reporter->benchmarkStarting( info );+    }+    void RunContext::benchmarkEnded( BenchmarkStats<> const& stats ) {+        m_reporter->benchmarkEnded( stats );+    }+    void RunContext::benchmarkFailed(std::string const & error) {+        m_reporter->benchmarkFailed(error);+    }+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++    void RunContext::pushScopedMessage(MessageInfo const & message) {+        m_messages.push_back(message);+    }++    void RunContext::popScopedMessage(MessageInfo const & message) {+        m_messages.erase(std::remove(m_messages.begin(), m_messages.end(), message), m_messages.end());+    }++    void RunContext::emplaceUnscopedMessage( MessageBuilder const& builder ) {+        m_messageScopes.emplace_back( builder );+    }++    std::string RunContext::getCurrentTestName() const {+        return m_activeTestCase+            ? m_activeTestCase->getTestCaseInfo().name+            : std::string();+    }++    const AssertionResult * RunContext::getLastResult() const {+        return &(*m_lastResult);+    }++    void RunContext::exceptionEarlyReported() {+        m_shouldReportUnexpected = false;+    }++    void RunContext::handleFatalErrorCondition( StringRef message ) {+        // First notify reporter that bad things happened+        m_reporter->fatalErrorEncountered(message);++        // Don't rebuild the result -- the stringification itself can cause more fatal errors+        // Instead, fake a result data.+        AssertionResultData tempResult( ResultWas::FatalErrorCondition, { false } );+        tempResult.message = static_cast<std::string>(message);+        AssertionResult result(m_lastAssertionInfo, tempResult);++        assertionEnded(result);++        handleUnfinishedSections();++        // Recreate section for test case (as we will lose the one that was in scope)+        auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();+        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);++        Counts assertions;+        assertions.failed = 1;+        SectionStats testCaseSectionStats(testCaseSection, assertions, 0, false);+        m_reporter->sectionEnded(testCaseSectionStats);++        auto const& testInfo = m_activeTestCase->getTestCaseInfo();++        Totals deltaTotals;+        deltaTotals.testCases.failed = 1;+        deltaTotals.assertions.failed = 1;+        m_reporter->testCaseEnded(TestCaseStats(testInfo,+                                  deltaTotals,+                                  std::string(),+                                  std::string(),+                                  false));+        m_totals.testCases.failed++;+        testGroupEnded(std::string(), m_totals, 1, 1);+        m_reporter->testRunEnded(TestRunStats(m_runInfo, m_totals, false));+    }++    bool RunContext::lastAssertionPassed() {+         return m_lastAssertionPassed;+    }++    void RunContext::assertionPassed() {+        m_lastAssertionPassed = true;+        ++m_totals.assertions.passed;+        resetAssertionInfo();+        m_messageScopes.clear();+    }++    bool RunContext::aborting() const {+        return m_totals.assertions.failed >= static_cast<std::size_t>(m_config->abortAfter());+    }++    void RunContext::runCurrentTest(std::string & redirectedCout, std::string & redirectedCerr) {+        auto const& testCaseInfo = m_activeTestCase->getTestCaseInfo();+        SectionInfo testCaseSection(testCaseInfo.lineInfo, testCaseInfo.name);+        m_reporter->sectionStarting(testCaseSection);+        Counts prevAssertions = m_totals.assertions;+        double duration = 0;+        m_shouldReportUnexpected = true;+        m_lastAssertionInfo = { "TEST_CASE"_sr, testCaseInfo.lineInfo, StringRef(), ResultDisposition::Normal };++        seedRng(*m_config);++        Timer timer;+        CATCH_TRY {+            if (m_reporter->getPreferences().shouldRedirectStdOut) {+#if !defined(CATCH_CONFIG_EXPERIMENTAL_REDIRECT)+                RedirectedStreams redirectedStreams(redirectedCout, redirectedCerr);++                timer.start();+                invokeActiveTestCase();+#else+                OutputRedirect r(redirectedCout, redirectedCerr);+                timer.start();+                invokeActiveTestCase();+#endif+            } else {+                timer.start();+                invokeActiveTestCase();+            }+            duration = timer.getElapsedSeconds();+        } CATCH_CATCH_ANON (TestFailureException&) {+            // This just means the test was aborted due to failure+        } CATCH_CATCH_ALL {+            // Under CATCH_CONFIG_FAST_COMPILE, unexpected exceptions under REQUIRE assertions+            // are reported without translation at the point of origin.+            if( m_shouldReportUnexpected ) {+                AssertionReaction dummyReaction;+                handleUnexpectedInflightException( m_lastAssertionInfo, translateActiveException(), dummyReaction );+            }+        }+        Counts assertions = m_totals.assertions - prevAssertions;+        bool missingAssertions = testForMissingAssertions(assertions);++        m_testCaseTracker->close();+        handleUnfinishedSections();+        m_messages.clear();+        m_messageScopes.clear();++        SectionStats testCaseSectionStats(testCaseSection, assertions, duration, missingAssertions);+        m_reporter->sectionEnded(testCaseSectionStats);+    }++    void RunContext::invokeActiveTestCase() {+        FatalConditionHandlerGuard _(&m_fatalConditionhandler);+        m_activeTestCase->invoke();+    }++    void RunContext::handleUnfinishedSections() {+        // If sections ended prematurely due to an exception we stored their+        // infos here so we can tear them down outside the unwind process.+        for (auto it = m_unfinishedSections.rbegin(),+             itEnd = m_unfinishedSections.rend();+             it != itEnd;+             ++it)+            sectionEnded(*it);+        m_unfinishedSections.clear();+    }++    void RunContext::handleExpr(+        AssertionInfo const& info,+        ITransientExpression const& expr,+        AssertionReaction& reaction+    ) {+        m_reporter->assertionStarting( info );++        bool negated = isFalseTest( info.resultDisposition );+        bool result = expr.getResult() != negated;++        if( result ) {+            if (!m_includeSuccessfulResults) {+                assertionPassed();+            }+            else {+                reportExpr(info, ResultWas::Ok, &expr, negated);+            }+        }+        else {+            reportExpr(info, ResultWas::ExpressionFailed, &expr, negated );+            populateReaction( reaction );+        }+    }+    void RunContext::reportExpr(+            AssertionInfo const &info,+            ResultWas::OfType resultType,+            ITransientExpression const *expr,+            bool negated ) {++        m_lastAssertionInfo = info;+        AssertionResultData data( resultType, LazyExpression( negated ) );++        AssertionResult assertionResult{ info, data };+        assertionResult.m_resultData.lazyExpression.m_transientExpression = expr;++        assertionEnded( assertionResult );+    }++    void RunContext::handleMessage(+            AssertionInfo const& info,+            ResultWas::OfType resultType,+            StringRef const& message,+            AssertionReaction& reaction+    ) {+        m_reporter->assertionStarting( info );++        m_lastAssertionInfo = info;++        AssertionResultData data( resultType, LazyExpression( false ) );+        data.message = static_cast<std::string>(message);+        AssertionResult assertionResult{ m_lastAssertionInfo, data };+        assertionEnded( assertionResult );+        if( !assertionResult.isOk() )+            populateReaction( reaction );+    }+    void RunContext::handleUnexpectedExceptionNotThrown(+            AssertionInfo const& info,+            AssertionReaction& reaction+    ) {+        handleNonExpr(info, Catch::ResultWas::DidntThrowException, reaction);+    }++    void RunContext::handleUnexpectedInflightException(+            AssertionInfo const& info,+            std::string const& message,+            AssertionReaction& reaction+    ) {+        m_lastAssertionInfo = info;++        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );+        data.message = message;+        AssertionResult assertionResult{ info, data };+        assertionEnded( assertionResult );+        populateReaction( reaction );+    }++    void RunContext::populateReaction( AssertionReaction& reaction ) {+        reaction.shouldDebugBreak = m_config->shouldDebugBreak();+        reaction.shouldThrow = aborting() || (m_lastAssertionInfo.resultDisposition & ResultDisposition::Normal);+    }++    void RunContext::handleIncomplete(+            AssertionInfo const& info+    ) {+        m_lastAssertionInfo = info;++        AssertionResultData data( ResultWas::ThrewException, LazyExpression( false ) );+        data.message = "Exception translation was disabled by CATCH_CONFIG_FAST_COMPILE";+        AssertionResult assertionResult{ info, data };+        assertionEnded( assertionResult );+    }+    void RunContext::handleNonExpr(+            AssertionInfo const &info,+            ResultWas::OfType resultType,+            AssertionReaction &reaction+    ) {+        m_lastAssertionInfo = info;++        AssertionResultData data( resultType, LazyExpression( false ) );+        AssertionResult assertionResult{ info, data };+        assertionEnded( assertionResult );++        if( !assertionResult.isOk() )+            populateReaction( reaction );+    }++    IResultCapture& getResultCapture() {+        if (auto* capture = getCurrentContext().getResultCapture())+            return *capture;+        else+            CATCH_INTERNAL_ERROR("No result capture instance");+    }++    void seedRng(IConfig const& config) {+        if (config.rngSeed() != 0) {+            std::srand(config.rngSeed());+            rng().seed(config.rngSeed());+        }+    }++    unsigned int rngSeed() {+        return getCurrentContext().getConfig()->rngSeed();+    }++}+// end catch_run_context.cpp+// start catch_section.cpp++namespace Catch {++    Section::Section( SectionInfo const& info )+    :   m_info( info ),+        m_sectionIncluded( getResultCapture().sectionStarted( m_info, m_assertions ) )+    {+        m_timer.start();+    }++    Section::~Section() {+        if( m_sectionIncluded ) {+            SectionEndInfo endInfo{ m_info, m_assertions, m_timer.getElapsedSeconds() };+            if( uncaught_exceptions() )+                getResultCapture().sectionEndedEarly( endInfo );+            else+                getResultCapture().sectionEnded( endInfo );+        }+    }++    // This indicates whether the section should be executed or not+    Section::operator bool() const {+        return m_sectionIncluded;+    }++} // end namespace Catch+// end catch_section.cpp+// start catch_section_info.cpp++namespace Catch {++    SectionInfo::SectionInfo+        (   SourceLineInfo const& _lineInfo,+            std::string const& _name )+    :   name( _name ),+        lineInfo( _lineInfo )+    {}++} // end namespace Catch+// end catch_section_info.cpp+// start catch_session.cpp++// start catch_session.h++#include <memory>++namespace Catch {++    class Session : NonCopyable {+    public:++        Session();+        ~Session() override;++        void showHelp() const;+        void libIdentify();++        int applyCommandLine( int argc, char const * const * argv );+    #if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)+        int applyCommandLine( int argc, wchar_t const * const * argv );+    #endif++        void useConfigData( ConfigData const& configData );++        template<typename CharT>+        int run(int argc, CharT const * const argv[]) {+            if (m_startupExceptions)+                return 1;+            int returnCode = applyCommandLine(argc, argv);+            if (returnCode == 0)+                returnCode = run();+            return returnCode;+        }++        int run();++        clara::Parser const& cli() const;+        void cli( clara::Parser const& newParser );+        ConfigData& configData();+        Config& config();+    private:+        int runInternal();++        clara::Parser m_cli;+        ConfigData m_configData;+        std::shared_ptr<Config> m_config;+        bool m_startupExceptions = false;+    };++} // end namespace Catch++// end catch_session.h+// start catch_version.h++#include <iosfwd>++namespace Catch {++    // Versioning information+    struct Version {+        Version( Version const& ) = delete;+        Version& operator=( Version const& ) = delete;+        Version(    unsigned int _majorVersion,+                    unsigned int _minorVersion,+                    unsigned int _patchNumber,+                    char const * const _branchName,+                    unsigned int _buildNumber );++        unsigned int const majorVersion;+        unsigned int const minorVersion;+        unsigned int const patchNumber;++        // buildNumber is only used if branchName is not null+        char const * const branchName;+        unsigned int const buildNumber;++        friend std::ostream& operator << ( std::ostream& os, Version const& version );+    };++    Version const& libraryVersion();+}++// end catch_version.h+#include <cstdlib>+#include <iomanip>+#include <set>+#include <iterator>++namespace Catch {++    namespace {+        const int MaxExitCode = 255;++        IStreamingReporterPtr createReporter(std::string const& reporterName, IConfigPtr const& config) {+            auto reporter = Catch::getRegistryHub().getReporterRegistry().create(reporterName, config);+            CATCH_ENFORCE(reporter, "No reporter registered with name: '" << reporterName << "'");++            return reporter;+        }++        IStreamingReporterPtr makeReporter(std::shared_ptr<Config> const& config) {+            if (Catch::getRegistryHub().getReporterRegistry().getListeners().empty()) {+                return createReporter(config->getReporterName(), config);+            }++            // On older platforms, returning std::unique_ptr<ListeningReporter>+            // when the return type is std::unique_ptr<IStreamingReporter>+            // doesn't compile without a std::move call. However, this causes+            // a warning on newer platforms. Thus, we have to work around+            // it a bit and downcast the pointer manually.+            auto ret = std::unique_ptr<IStreamingReporter>(new ListeningReporter);+            auto& multi = static_cast<ListeningReporter&>(*ret);+            auto const& listeners = Catch::getRegistryHub().getReporterRegistry().getListeners();+            for (auto const& listener : listeners) {+                multi.addListener(listener->create(Catch::ReporterConfig(config)));+            }+            multi.addReporter(createReporter(config->getReporterName(), config));+            return ret;+        }++        class TestGroup {+        public:+            explicit TestGroup(std::shared_ptr<Config> const& config)+            : m_config{config}+            , m_context{config, makeReporter(config)}+            {+                auto const& allTestCases = getAllTestCasesSorted(*m_config);+                m_matches = m_config->testSpec().matchesByFilter(allTestCases, *m_config);+                auto const& invalidArgs = m_config->testSpec().getInvalidArgs();++                if (m_matches.empty() && invalidArgs.empty()) {+                    for (auto const& test : allTestCases)+                        if (!test.isHidden())+                            m_tests.emplace(&test);+                } else {+                    for (auto const& match : m_matches)+                        m_tests.insert(match.tests.begin(), match.tests.end());+                }+            }++            Totals execute() {+                auto const& invalidArgs = m_config->testSpec().getInvalidArgs();+                Totals totals;+                m_context.testGroupStarting(m_config->name(), 1, 1);+                for (auto const& testCase : m_tests) {+                    if (!m_context.aborting())+                        totals += m_context.runTest(*testCase);+                    else+                        m_context.reporter().skipTest(*testCase);+                }++                for (auto const& match : m_matches) {+                    if (match.tests.empty()) {+                        m_context.reporter().noMatchingTestCases(match.name);+                        totals.error = -1;+                    }+                }++                if (!invalidArgs.empty()) {+                    for (auto const& invalidArg: invalidArgs)+                         m_context.reporter().reportInvalidArguments(invalidArg);+                }++                m_context.testGroupEnded(m_config->name(), totals, 1, 1);+                return totals;+            }++        private:+            using Tests = std::set<TestCase const*>;++            std::shared_ptr<Config> m_config;+            RunContext m_context;+            Tests m_tests;+            TestSpec::Matches m_matches;+        };++        void applyFilenamesAsTags(Catch::IConfig const& config) {+            auto& tests = const_cast<std::vector<TestCase>&>(getAllTestCasesSorted(config));+            for (auto& testCase : tests) {+                auto tags = testCase.tags;++                std::string filename = testCase.lineInfo.file;+                auto lastSlash = filename.find_last_of("\\/");+                if (lastSlash != std::string::npos) {+                    filename.erase(0, lastSlash);+                    filename[0] = '#';+                }++                auto lastDot = filename.find_last_of('.');+                if (lastDot != std::string::npos) {+                    filename.erase(lastDot);+                }++                tags.push_back(std::move(filename));+                setTags(testCase, tags);+            }+        }++    } // anon namespace++    Session::Session() {+        static bool alreadyInstantiated = false;+        if( alreadyInstantiated ) {+            CATCH_TRY { CATCH_INTERNAL_ERROR( "Only one instance of Catch::Session can ever be used" ); }+            CATCH_CATCH_ALL { getMutableRegistryHub().registerStartupException(); }+        }++        // There cannot be exceptions at startup in no-exception mode.+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+        const auto& exceptions = getRegistryHub().getStartupExceptionRegistry().getExceptions();+        if ( !exceptions.empty() ) {+            config();+            getCurrentMutableContext().setConfig(m_config);++            m_startupExceptions = true;+            Colour colourGuard( Colour::Red );+            Catch::cerr() << "Errors occurred during startup!" << '\n';+            // iterate over all exceptions and notify user+            for ( const auto& ex_ptr : exceptions ) {+                try {+                    std::rethrow_exception(ex_ptr);+                } catch ( std::exception const& ex ) {+                    Catch::cerr() << Column( ex.what() ).indent(2) << '\n';+                }+            }+        }+#endif++        alreadyInstantiated = true;+        m_cli = makeCommandLineParser( m_configData );+    }+    Session::~Session() {+        Catch::cleanUp();+    }++    void Session::showHelp() const {+        Catch::cout()+                << "\nCatch v" << libraryVersion() << "\n"+                << m_cli << std::endl+                << "For more detailed usage please see the project docs\n" << std::endl;+    }+    void Session::libIdentify() {+        Catch::cout()+                << std::left << std::setw(16) << "description: " << "A Catch2 test executable\n"+                << std::left << std::setw(16) << "category: " << "testframework\n"+                << std::left << std::setw(16) << "framework: " << "Catch Test\n"+                << std::left << std::setw(16) << "version: " << libraryVersion() << std::endl;+    }++    int Session::applyCommandLine( int argc, char const * const * argv ) {+        if( m_startupExceptions )+            return 1;++        auto result = m_cli.parse( clara::Args( argc, argv ) );+        if( !result ) {+            config();+            getCurrentMutableContext().setConfig(m_config);+            Catch::cerr()+                << Colour( Colour::Red )+                << "\nError(s) in input:\n"+                << Column( result.errorMessage() ).indent( 2 )+                << "\n\n";+            Catch::cerr() << "Run with -? for usage\n" << std::endl;+            return MaxExitCode;+        }++        if( m_configData.showHelp )+            showHelp();+        if( m_configData.libIdentify )+            libIdentify();+        m_config.reset();+        return 0;+    }++#if defined(CATCH_CONFIG_WCHAR) && defined(_WIN32) && defined(UNICODE)+    int Session::applyCommandLine( int argc, wchar_t const * const * argv ) {++        char **utf8Argv = new char *[ argc ];++        for ( int i = 0; i < argc; ++i ) {+            int bufSize = WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, nullptr, 0, nullptr, nullptr );++            utf8Argv[ i ] = new char[ bufSize ];++            WideCharToMultiByte( CP_UTF8, 0, argv[i], -1, utf8Argv[i], bufSize, nullptr, nullptr );+        }++        int returnCode = applyCommandLine( argc, utf8Argv );++        for ( int i = 0; i < argc; ++i )+            delete [] utf8Argv[ i ];++        delete [] utf8Argv;++        return returnCode;+    }+#endif++    void Session::useConfigData( ConfigData const& configData ) {+        m_configData = configData;+        m_config.reset();+    }++    int Session::run() {+        if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeStart ) != 0 ) {+            Catch::cout() << "...waiting for enter/ return before starting" << std::endl;+            static_cast<void>(std::getchar());+        }+        int exitCode = runInternal();+        if( ( m_configData.waitForKeypress & WaitForKeypress::BeforeExit ) != 0 ) {+            Catch::cout() << "...waiting for enter/ return before exiting, with code: " << exitCode << std::endl;+            static_cast<void>(std::getchar());+        }+        return exitCode;+    }++    clara::Parser const& Session::cli() const {+        return m_cli;+    }+    void Session::cli( clara::Parser const& newParser ) {+        m_cli = newParser;+    }+    ConfigData& Session::configData() {+        return m_configData;+    }+    Config& Session::config() {+        if( !m_config )+            m_config = std::make_shared<Config>( m_configData );+        return *m_config;+    }++    int Session::runInternal() {+        if( m_startupExceptions )+            return 1;++        if (m_configData.showHelp || m_configData.libIdentify) {+            return 0;+        }++        CATCH_TRY {+            config(); // Force config to be constructed++            seedRng( *m_config );++            if( m_configData.filenamesAsTags )+                applyFilenamesAsTags( *m_config );++            // Handle list request+            if( Option<std::size_t> listed = list( m_config ) )+                return static_cast<int>( *listed );++            TestGroup tests { m_config };+            auto const totals = tests.execute();++            if( m_config->warnAboutNoTests() && totals.error == -1 )+                return 2;++            // Note that on unices only the lower 8 bits are usually used, clamping+            // the return value to 255 prevents false negative when some multiple+            // of 256 tests has failed+            return (std::min) (MaxExitCode, (std::max) (totals.error, static_cast<int>(totals.assertions.failed)));+        }+#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+        catch( std::exception& ex ) {+            Catch::cerr() << ex.what() << std::endl;+            return MaxExitCode;+        }+#endif+    }++} // end namespace Catch+// end catch_session.cpp+// start catch_singletons.cpp++#include <vector>++namespace Catch {++    namespace {+        static auto getSingletons() -> std::vector<ISingleton*>*& {+            static std::vector<ISingleton*>* g_singletons = nullptr;+            if( !g_singletons )+                g_singletons = new std::vector<ISingleton*>();+            return g_singletons;+        }+    }++    ISingleton::~ISingleton() {}++    void addSingleton(ISingleton* singleton ) {+        getSingletons()->push_back( singleton );+    }+    void cleanupSingletons() {+        auto& singletons = getSingletons();+        for( auto singleton : *singletons )+            delete singleton;+        delete singletons;+        singletons = nullptr;+    }++} // namespace Catch+// end catch_singletons.cpp+// start catch_startup_exception_registry.cpp++#if !defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+namespace Catch {+void StartupExceptionRegistry::add( std::exception_ptr const& exception ) noexcept {+        CATCH_TRY {+            m_exceptions.push_back(exception);+        } CATCH_CATCH_ALL {+            // If we run out of memory during start-up there's really not a lot more we can do about it+            std::terminate();+        }+    }++    std::vector<std::exception_ptr> const& StartupExceptionRegistry::getExceptions() const noexcept {+        return m_exceptions;+    }++} // end namespace Catch+#endif+// end catch_startup_exception_registry.cpp+// start catch_stream.cpp++#include <cstdio>+#include <iostream>+#include <fstream>+#include <sstream>+#include <vector>+#include <memory>++namespace Catch {++    Catch::IStream::~IStream() = default;++    namespace Detail { namespace {+        template<typename WriterF, std::size_t bufferSize=256>+        class StreamBufImpl : public std::streambuf {+            char data[bufferSize];+            WriterF m_writer;++        public:+            StreamBufImpl() {+                setp( data, data + sizeof(data) );+            }++            ~StreamBufImpl() noexcept {+                StreamBufImpl::sync();+            }++        private:+            int overflow( int c ) override {+                sync();++                if( c != EOF ) {+                    if( pbase() == epptr() )+                        m_writer( std::string( 1, static_cast<char>( c ) ) );+                    else+                        sputc( static_cast<char>( c ) );+                }+                return 0;+            }++            int sync() override {+                if( pbase() != pptr() ) {+                    m_writer( std::string( pbase(), static_cast<std::string::size_type>( pptr() - pbase() ) ) );+                    setp( pbase(), epptr() );+                }+                return 0;+            }+        };++        ///////////////////////////////////////////////////////////////////////////++        struct OutputDebugWriter {++            void operator()( std::string const&str ) {+                writeToDebugConsole( str );+            }+        };++        ///////////////////////////////////////////////////////////////////////////++        class FileStream : public IStream {+            mutable std::ofstream m_ofs;+        public:+            FileStream( StringRef filename ) {+                m_ofs.open( filename.c_str() );+                CATCH_ENFORCE( !m_ofs.fail(), "Unable to open file: '" << filename << "'" );+            }+            ~FileStream() override = default;+        public: // IStream+            std::ostream& stream() const override {+                return m_ofs;+            }+        };++        ///////////////////////////////////////////////////////////////////////////++        class CoutStream : public IStream {+            mutable std::ostream m_os;+        public:+            // Store the streambuf from cout up-front because+            // cout may get redirected when running tests+            CoutStream() : m_os( Catch::cout().rdbuf() ) {}+            ~CoutStream() override = default;++        public: // IStream+            std::ostream& stream() const override { return m_os; }+        };++        ///////////////////////////////////////////////////////////////////////////++        class DebugOutStream : public IStream {+            std::unique_ptr<StreamBufImpl<OutputDebugWriter>> m_streamBuf;+            mutable std::ostream m_os;+        public:+            DebugOutStream()+            :   m_streamBuf( new StreamBufImpl<OutputDebugWriter>() ),+                m_os( m_streamBuf.get() )+            {}++            ~DebugOutStream() override = default;++        public: // IStream+            std::ostream& stream() const override { return m_os; }+        };++    }} // namespace anon::detail++    ///////////////////////////////////////////////////////////////////////////++    auto makeStream( StringRef const &filename ) -> IStream const* {+        if( filename.empty() )+            return new Detail::CoutStream();+        else if( filename[0] == '%' ) {+            if( filename == "%debug" )+                return new Detail::DebugOutStream();+            else+                CATCH_ERROR( "Unrecognised stream: '" << filename << "'" );+        }+        else+            return new Detail::FileStream( filename );+    }++    // This class encapsulates the idea of a pool of ostringstreams that can be reused.+    struct StringStreams {+        std::vector<std::unique_ptr<std::ostringstream>> m_streams;+        std::vector<std::size_t> m_unused;+        std::ostringstream m_referenceStream; // Used for copy state/ flags from++        auto add() -> std::size_t {+            if( m_unused.empty() ) {+                m_streams.push_back( std::unique_ptr<std::ostringstream>( new std::ostringstream ) );+                return m_streams.size()-1;+            }+            else {+                auto index = m_unused.back();+                m_unused.pop_back();+                return index;+            }+        }++        void release( std::size_t index ) {+            m_streams[index]->copyfmt( m_referenceStream ); // Restore initial flags and other state+            m_unused.push_back(index);+        }+    };++    ReusableStringStream::ReusableStringStream()+    :   m_index( Singleton<StringStreams>::getMutable().add() ),+        m_oss( Singleton<StringStreams>::getMutable().m_streams[m_index].get() )+    {}++    ReusableStringStream::~ReusableStringStream() {+        static_cast<std::ostringstream*>( m_oss )->str("");+        m_oss->clear();+        Singleton<StringStreams>::getMutable().release( m_index );+    }++    auto ReusableStringStream::str() const -> std::string {+        return static_cast<std::ostringstream*>( m_oss )->str();+    }++    ///////////////////////////////////////////////////////////////////////////++#ifndef CATCH_CONFIG_NOSTDOUT // If you #define this you must implement these functions+    std::ostream& cout() { return std::cout; }+    std::ostream& cerr() { return std::cerr; }+    std::ostream& clog() { return std::clog; }+#endif+}+// end catch_stream.cpp+// start catch_string_manip.cpp++#include <algorithm>+#include <ostream>+#include <cstring>+#include <cctype>+#include <vector>++namespace Catch {++    namespace {+        char toLowerCh(char c) {+            return static_cast<char>( std::tolower( static_cast<unsigned char>(c) ) );+        }+    }++    bool startsWith( std::string const& s, std::string const& prefix ) {+        return s.size() >= prefix.size() && std::equal(prefix.begin(), prefix.end(), s.begin());+    }+    bool startsWith( std::string const& s, char prefix ) {+        return !s.empty() && s[0] == prefix;+    }+    bool endsWith( std::string const& s, std::string const& suffix ) {+        return s.size() >= suffix.size() && std::equal(suffix.rbegin(), suffix.rend(), s.rbegin());+    }+    bool endsWith( std::string const& s, char suffix ) {+        return !s.empty() && s[s.size()-1] == suffix;+    }+    bool contains( std::string const& s, std::string const& infix ) {+        return s.find( infix ) != std::string::npos;+    }+    void toLowerInPlace( std::string& s ) {+        std::transform( s.begin(), s.end(), s.begin(), toLowerCh );+    }+    std::string toLower( std::string const& s ) {+        std::string lc = s;+        toLowerInPlace( lc );+        return lc;+    }+    std::string trim( std::string const& str ) {+        static char const* whitespaceChars = "\n\r\t ";+        std::string::size_type start = str.find_first_not_of( whitespaceChars );+        std::string::size_type end = str.find_last_not_of( whitespaceChars );++        return start != std::string::npos ? str.substr( start, 1+end-start ) : std::string();+    }++    StringRef trim(StringRef ref) {+        const auto is_ws = [](char c) {+            return c == ' ' || c == '\t' || c == '\n' || c == '\r';+        };+        size_t real_begin = 0;+        while (real_begin < ref.size() && is_ws(ref[real_begin])) { ++real_begin; }+        size_t real_end = ref.size();+        while (real_end > real_begin && is_ws(ref[real_end - 1])) { --real_end; }++        return ref.substr(real_begin, real_end - real_begin);+    }++    bool replaceInPlace( std::string& str, std::string const& replaceThis, std::string const& withThis ) {+        bool replaced = false;+        std::size_t i = str.find( replaceThis );+        while( i != std::string::npos ) {+            replaced = true;+            str = str.substr( 0, i ) + withThis + str.substr( i+replaceThis.size() );+            if( i < str.size()-withThis.size() )+                i = str.find( replaceThis, i+withThis.size() );+            else+                i = std::string::npos;+        }+        return replaced;+    }++    std::vector<StringRef> splitStringRef( StringRef str, char delimiter ) {+        std::vector<StringRef> subStrings;+        std::size_t start = 0;+        for(std::size_t pos = 0; pos < str.size(); ++pos ) {+            if( str[pos] == delimiter ) {+                if( pos - start > 1 )+                    subStrings.push_back( str.substr( start, pos-start ) );+                start = pos+1;+            }+        }+        if( start < str.size() )+            subStrings.push_back( str.substr( start, str.size()-start ) );+        return subStrings;+    }++    pluralise::pluralise( std::size_t count, std::string const& label )+    :   m_count( count ),+        m_label( label )+    {}++    std::ostream& operator << ( std::ostream& os, pluralise const& pluraliser ) {+        os << pluraliser.m_count << ' ' << pluraliser.m_label;+        if( pluraliser.m_count != 1 )+            os << 's';+        return os;+    }++}+// end catch_string_manip.cpp+// start catch_stringref.cpp++#include <algorithm>+#include <ostream>+#include <cstring>+#include <cstdint>++namespace Catch {+    StringRef::StringRef( char const* rawChars ) noexcept+    : StringRef( rawChars, static_cast<StringRef::size_type>(std::strlen(rawChars) ) )+    {}++    auto StringRef::c_str() const -> char const* {+        CATCH_ENFORCE(isNullTerminated(), "Called StringRef::c_str() on a non-null-terminated instance");+        return m_start;+    }+    auto StringRef::data() const noexcept -> char const* {+        return m_start;+    }++    auto StringRef::substr( size_type start, size_type size ) const noexcept -> StringRef {+        if (start < m_size) {+            return StringRef(m_start + start, (std::min)(m_size - start, size));+        } else {+            return StringRef();+        }+    }+    auto StringRef::operator == ( StringRef const& other ) const noexcept -> bool {+        return m_size == other.m_size+            && (std::memcmp( m_start, other.m_start, m_size ) == 0);+    }++    auto operator << ( std::ostream& os, StringRef const& str ) -> std::ostream& {+        return os.write(str.data(), str.size());+    }++    auto operator+=( std::string& lhs, StringRef const& rhs ) -> std::string& {+        lhs.append(rhs.data(), rhs.size());+        return lhs;+    }++} // namespace Catch+// end catch_stringref.cpp+// start catch_tag_alias.cpp++namespace Catch {+    TagAlias::TagAlias(std::string const & _tag, SourceLineInfo _lineInfo): tag(_tag), lineInfo(_lineInfo) {}+}+// end catch_tag_alias.cpp+// start catch_tag_alias_autoregistrar.cpp++namespace Catch {++    RegistrarForTagAliases::RegistrarForTagAliases(char const* alias, char const* tag, SourceLineInfo const& lineInfo) {+        CATCH_TRY {+            getMutableRegistryHub().registerTagAlias(alias, tag, lineInfo);+        } CATCH_CATCH_ALL {+            // Do not throw when constructing global objects, instead register the exception to be processed later+            getMutableRegistryHub().registerStartupException();+        }+    }++}+// end catch_tag_alias_autoregistrar.cpp+// start catch_tag_alias_registry.cpp++#include <sstream>++namespace Catch {++    TagAliasRegistry::~TagAliasRegistry() {}++    TagAlias const* TagAliasRegistry::find( std::string const& alias ) const {+        auto it = m_registry.find( alias );+        if( it != m_registry.end() )+            return &(it->second);+        else+            return nullptr;+    }++    std::string TagAliasRegistry::expandAliases( std::string const& unexpandedTestSpec ) const {+        std::string expandedTestSpec = unexpandedTestSpec;+        for( auto const& registryKvp : m_registry ) {+            std::size_t pos = expandedTestSpec.find( registryKvp.first );+            if( pos != std::string::npos ) {+                expandedTestSpec =  expandedTestSpec.substr( 0, pos ) ++                                    registryKvp.second.tag ++                                    expandedTestSpec.substr( pos + registryKvp.first.size() );+            }+        }+        return expandedTestSpec;+    }++    void TagAliasRegistry::add( std::string const& alias, std::string const& tag, SourceLineInfo const& lineInfo ) {+        CATCH_ENFORCE( startsWith(alias, "[@") && endsWith(alias, ']'),+                      "error: tag alias, '" << alias << "' is not of the form [@alias name].\n" << lineInfo );++        CATCH_ENFORCE( m_registry.insert(std::make_pair(alias, TagAlias(tag, lineInfo))).second,+                      "error: tag alias, '" << alias << "' already registered.\n"+                      << "\tFirst seen at: " << find(alias)->lineInfo << "\n"+                      << "\tRedefined at: " << lineInfo );+    }++    ITagAliasRegistry::~ITagAliasRegistry() {}++    ITagAliasRegistry const& ITagAliasRegistry::get() {+        return getRegistryHub().getTagAliasRegistry();+    }++} // end namespace Catch+// end catch_tag_alias_registry.cpp+// start catch_test_case_info.cpp++#include <cctype>+#include <exception>+#include <algorithm>+#include <sstream>++namespace Catch {++    namespace {+        TestCaseInfo::SpecialProperties parseSpecialTag( std::string const& tag ) {+            if( startsWith( tag, '.' ) ||+                tag == "!hide" )+                return TestCaseInfo::IsHidden;+            else if( tag == "!throws" )+                return TestCaseInfo::Throws;+            else if( tag == "!shouldfail" )+                return TestCaseInfo::ShouldFail;+            else if( tag == "!mayfail" )+                return TestCaseInfo::MayFail;+            else if( tag == "!nonportable" )+                return TestCaseInfo::NonPortable;+            else if( tag == "!benchmark" )+                return static_cast<TestCaseInfo::SpecialProperties>( TestCaseInfo::Benchmark | TestCaseInfo::IsHidden );+            else+                return TestCaseInfo::None;+        }+        bool isReservedTag( std::string const& tag ) {+            return parseSpecialTag( tag ) == TestCaseInfo::None && tag.size() > 0 && !std::isalnum( static_cast<unsigned char>(tag[0]) );+        }+        void enforceNotReservedTag( std::string const& tag, SourceLineInfo const& _lineInfo ) {+            CATCH_ENFORCE( !isReservedTag(tag),+                          "Tag name: [" << tag << "] is not allowed.\n"+                          << "Tag names starting with non alphanumeric characters are reserved\n"+                          << _lineInfo );+        }+    }++    TestCase makeTestCase(  ITestInvoker* _testCase,+                            std::string const& _className,+                            NameAndTags const& nameAndTags,+                            SourceLineInfo const& _lineInfo )+    {+        bool isHidden = false;++        // Parse out tags+        std::vector<std::string> tags;+        std::string desc, tag;+        bool inTag = false;+        for (char c : nameAndTags.tags) {+            if( !inTag ) {+                if( c == '[' )+                    inTag = true;+                else+                    desc += c;+            }+            else {+                if( c == ']' ) {+                    TestCaseInfo::SpecialProperties prop = parseSpecialTag( tag );+                    if( ( prop & TestCaseInfo::IsHidden ) != 0 )+                        isHidden = true;+                    else if( prop == TestCaseInfo::None )+                        enforceNotReservedTag( tag, _lineInfo );++                    // Merged hide tags like `[.approvals]` should be added as+                    // `[.][approvals]`. The `[.]` is added at later point, so+                    // we only strip the prefix+                    if (startsWith(tag, '.') && tag.size() > 1) {+                        tag.erase(0, 1);+                    }+                    tags.push_back( tag );+                    tag.clear();+                    inTag = false;+                }+                else+                    tag += c;+            }+        }+        if( isHidden ) {+            // Add all "hidden" tags to make them behave identically+            tags.insert( tags.end(), { ".", "!hide" } );+        }++        TestCaseInfo info( static_cast<std::string>(nameAndTags.name), _className, desc, tags, _lineInfo );+        return TestCase( _testCase, std::move(info) );+    }++    void setTags( TestCaseInfo& testCaseInfo, std::vector<std::string> tags ) {+        std::sort(begin(tags), end(tags));+        tags.erase(std::unique(begin(tags), end(tags)), end(tags));+        testCaseInfo.lcaseTags.clear();++        for( auto const& tag : tags ) {+            std::string lcaseTag = toLower( tag );+            testCaseInfo.properties = static_cast<TestCaseInfo::SpecialProperties>( testCaseInfo.properties | parseSpecialTag( lcaseTag ) );+            testCaseInfo.lcaseTags.push_back( lcaseTag );+        }+        testCaseInfo.tags = std::move(tags);+    }++    TestCaseInfo::TestCaseInfo( std::string const& _name,+                                std::string const& _className,+                                std::string const& _description,+                                std::vector<std::string> const& _tags,+                                SourceLineInfo const& _lineInfo )+    :   name( _name ),+        className( _className ),+        description( _description ),+        lineInfo( _lineInfo ),+        properties( None )+    {+        setTags( *this, _tags );+    }++    bool TestCaseInfo::isHidden() const {+        return ( properties & IsHidden ) != 0;+    }+    bool TestCaseInfo::throws() const {+        return ( properties & Throws ) != 0;+    }+    bool TestCaseInfo::okToFail() const {+        return ( properties & (ShouldFail | MayFail ) ) != 0;+    }+    bool TestCaseInfo::expectedToFail() const {+        return ( properties & (ShouldFail ) ) != 0;+    }++    std::string TestCaseInfo::tagsAsString() const {+        std::string ret;+        // '[' and ']' per tag+        std::size_t full_size = 2 * tags.size();+        for (const auto& tag : tags) {+            full_size += tag.size();+        }+        ret.reserve(full_size);+        for (const auto& tag : tags) {+            ret.push_back('[');+            ret.append(tag);+            ret.push_back(']');+        }++        return ret;+    }++    TestCase::TestCase( ITestInvoker* testCase, TestCaseInfo&& info ) : TestCaseInfo( std::move(info) ), test( testCase ) {}++    TestCase TestCase::withName( std::string const& _newName ) const {+        TestCase other( *this );+        other.name = _newName;+        return other;+    }++    void TestCase::invoke() const {+        test->invoke();+    }++    bool TestCase::operator == ( TestCase const& other ) const {+        return  test.get() == other.test.get() &&+                name == other.name &&+                className == other.className;+    }++    bool TestCase::operator < ( TestCase const& other ) const {+        return name < other.name;+    }++    TestCaseInfo const& TestCase::getTestCaseInfo() const+    {+        return *this;+    }++} // end namespace Catch+// end catch_test_case_info.cpp+// start catch_test_case_registry_impl.cpp++#include <algorithm>+#include <sstream>++namespace Catch {++    namespace {+        struct TestHasher {+            using hash_t = uint64_t;++            explicit TestHasher( hash_t hashSuffix ):+                m_hashSuffix{ hashSuffix } {}++            uint32_t operator()( TestCase const& t ) const {+                // FNV-1a hash with multiplication fold.+                const hash_t prime = 1099511628211u;+                hash_t hash = 14695981039346656037u;+                for ( const char c : t.name ) {+                    hash ^= c;+                    hash *= prime;+                }+                hash ^= m_hashSuffix;+                hash *= prime;+                const uint32_t low{ static_cast<uint32_t>( hash ) };+                const uint32_t high{ static_cast<uint32_t>( hash >> 32 ) };+                return low * high;+            }++        private:+            hash_t m_hashSuffix;+        };+    } // end unnamed namespace++    std::vector<TestCase> sortTests( IConfig const& config, std::vector<TestCase> const& unsortedTestCases ) {+        switch( config.runOrder() ) {+            case RunTests::InDeclarationOrder:+                // already in declaration order+                break;++            case RunTests::InLexicographicalOrder: {+                std::vector<TestCase> sorted = unsortedTestCases;+                std::sort( sorted.begin(), sorted.end() );+                return sorted;+            }++            case RunTests::InRandomOrder: {+                seedRng( config );+                TestHasher h{ config.rngSeed() };++                using hashedTest = std::pair<TestHasher::hash_t, TestCase const*>;+                std::vector<hashedTest> indexed_tests;+                indexed_tests.reserve( unsortedTestCases.size() );++                for (auto const& testCase : unsortedTestCases) {+                    indexed_tests.emplace_back(h(testCase), &testCase);+                }++                std::sort(indexed_tests.begin(), indexed_tests.end(),+                          [](hashedTest const& lhs, hashedTest const& rhs) {+                          if (lhs.first == rhs.first) {+                              return lhs.second->name < rhs.second->name;+                          }+                          return lhs.first < rhs.first;+                });++                std::vector<TestCase> sorted;+                sorted.reserve( indexed_tests.size() );++                for (auto const& hashed : indexed_tests) {+                    sorted.emplace_back(*hashed.second);+                }++                return sorted;+            }+        }+        return unsortedTestCases;+    }++    bool isThrowSafe( TestCase const& testCase, IConfig const& config ) {+        return !testCase.throws() || config.allowThrows();+    }++    bool matchTest( TestCase const& testCase, TestSpec const& testSpec, IConfig const& config ) {+        return testSpec.matches( testCase ) && isThrowSafe( testCase, config );+    }++    void enforceNoDuplicateTestCases( std::vector<TestCase> const& functions ) {+        std::set<TestCase> seenFunctions;+        for( auto const& function : functions ) {+            auto prev = seenFunctions.insert( function );+            CATCH_ENFORCE( prev.second,+                    "error: TEST_CASE( \"" << function.name << "\" ) already defined.\n"+                    << "\tFirst seen at " << prev.first->getTestCaseInfo().lineInfo << "\n"+                    << "\tRedefined at " << function.getTestCaseInfo().lineInfo );+        }+    }++    std::vector<TestCase> filterTests( std::vector<TestCase> const& testCases, TestSpec const& testSpec, IConfig const& config ) {+        std::vector<TestCase> filtered;+        filtered.reserve( testCases.size() );+        for (auto const& testCase : testCases) {+            if ((!testSpec.hasFilters() && !testCase.isHidden()) ||+                (testSpec.hasFilters() && matchTest(testCase, testSpec, config))) {+                filtered.push_back(testCase);+            }+        }+        return filtered;+    }+    std::vector<TestCase> const& getAllTestCasesSorted( IConfig const& config ) {+        return getRegistryHub().getTestCaseRegistry().getAllTestsSorted( config );+    }++    void TestRegistry::registerTest( TestCase const& testCase ) {+        std::string name = testCase.getTestCaseInfo().name;+        if( name.empty() ) {+            ReusableStringStream rss;+            rss << "Anonymous test case " << ++m_unnamedCount;+            return registerTest( testCase.withName( rss.str() ) );+        }+        m_functions.push_back( testCase );+    }++    std::vector<TestCase> const& TestRegistry::getAllTests() const {+        return m_functions;+    }+    std::vector<TestCase> const& TestRegistry::getAllTestsSorted( IConfig const& config ) const {+        if( m_sortedFunctions.empty() )+            enforceNoDuplicateTestCases( m_functions );++        if(  m_currentSortOrder != config.runOrder() || m_sortedFunctions.empty() ) {+            m_sortedFunctions = sortTests( config, m_functions );+            m_currentSortOrder = config.runOrder();+        }+        return m_sortedFunctions;+    }++    ///////////////////////////////////////////////////////////////////////////+    TestInvokerAsFunction::TestInvokerAsFunction( void(*testAsFunction)() ) noexcept : m_testAsFunction( testAsFunction ) {}++    void TestInvokerAsFunction::invoke() const {+        m_testAsFunction();+    }++    std::string extractClassName( StringRef const& classOrQualifiedMethodName ) {+        std::string className(classOrQualifiedMethodName);+        if( startsWith( className, '&' ) )+        {+            std::size_t lastColons = className.rfind( "::" );+            std::size_t penultimateColons = className.rfind( "::", lastColons-1 );+            if( penultimateColons == std::string::npos )+                penultimateColons = 1;+            className = className.substr( penultimateColons, lastColons-penultimateColons );+        }+        return className;+    }++} // end namespace Catch+// end catch_test_case_registry_impl.cpp+// start catch_test_case_tracker.cpp++#include <algorithm>+#include <cassert>+#include <stdexcept>+#include <memory>+#include <sstream>++#if defined(__clang__)+#    pragma clang diagnostic push+#    pragma clang diagnostic ignored "-Wexit-time-destructors"+#endif++namespace Catch {+namespace TestCaseTracking {++    NameAndLocation::NameAndLocation( std::string const& _name, SourceLineInfo const& _location )+    :   name( _name ),+        location( _location )+    {}++    ITracker::~ITracker() = default;++    ITracker& TrackerContext::startRun() {+        m_rootTracker = std::make_shared<SectionTracker>( NameAndLocation( "{root}", CATCH_INTERNAL_LINEINFO ), *this, nullptr );+        m_currentTracker = nullptr;+        m_runState = Executing;+        return *m_rootTracker;+    }++    void TrackerContext::endRun() {+        m_rootTracker.reset();+        m_currentTracker = nullptr;+        m_runState = NotStarted;+    }++    void TrackerContext::startCycle() {+        m_currentTracker = m_rootTracker.get();+        m_runState = Executing;+    }+    void TrackerContext::completeCycle() {+        m_runState = CompletedCycle;+    }++    bool TrackerContext::completedCycle() const {+        return m_runState == CompletedCycle;+    }+    ITracker& TrackerContext::currentTracker() {+        return *m_currentTracker;+    }+    void TrackerContext::setCurrentTracker( ITracker* tracker ) {+        m_currentTracker = tracker;+    }++    TrackerBase::TrackerBase( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent ):+        ITracker(nameAndLocation),+        m_ctx( ctx ),+        m_parent( parent )+    {}++    bool TrackerBase::isComplete() const {+        return m_runState == CompletedSuccessfully || m_runState == Failed;+    }+    bool TrackerBase::isSuccessfullyCompleted() const {+        return m_runState == CompletedSuccessfully;+    }+    bool TrackerBase::isOpen() const {+        return m_runState != NotStarted && !isComplete();+    }+    bool TrackerBase::hasChildren() const {+        return !m_children.empty();+    }++    void TrackerBase::addChild( ITrackerPtr const& child ) {+        m_children.push_back( child );+    }++    ITrackerPtr TrackerBase::findChild( NameAndLocation const& nameAndLocation ) {+        auto it = std::find_if( m_children.begin(), m_children.end(),+            [&nameAndLocation]( ITrackerPtr const& tracker ){+                return+                    tracker->nameAndLocation().location == nameAndLocation.location &&+                    tracker->nameAndLocation().name == nameAndLocation.name;+            } );+        return( it != m_children.end() )+            ? *it+            : nullptr;+    }+    ITracker& TrackerBase::parent() {+        assert( m_parent ); // Should always be non-null except for root+        return *m_parent;+    }++    void TrackerBase::openChild() {+        if( m_runState != ExecutingChildren ) {+            m_runState = ExecutingChildren;+            if( m_parent )+                m_parent->openChild();+        }+    }++    bool TrackerBase::isSectionTracker() const { return false; }+    bool TrackerBase::isGeneratorTracker() const { return false; }++    void TrackerBase::open() {+        m_runState = Executing;+        moveToThis();+        if( m_parent )+            m_parent->openChild();+    }++    void TrackerBase::close() {++        // Close any still open children (e.g. generators)+        while( &m_ctx.currentTracker() != this )+            m_ctx.currentTracker().close();++        switch( m_runState ) {+            case NeedsAnotherRun:+                break;++            case Executing:+                m_runState = CompletedSuccessfully;+                break;+            case ExecutingChildren:+                if( std::all_of(m_children.begin(), m_children.end(), [](ITrackerPtr const& t){ return t->isComplete(); }) )+                    m_runState = CompletedSuccessfully;+                break;++            case NotStarted:+            case CompletedSuccessfully:+            case Failed:+                CATCH_INTERNAL_ERROR( "Illogical state: " << m_runState );++            default:+                CATCH_INTERNAL_ERROR( "Unknown state: " << m_runState );+        }+        moveToParent();+        m_ctx.completeCycle();+    }+    void TrackerBase::fail() {+        m_runState = Failed;+        if( m_parent )+            m_parent->markAsNeedingAnotherRun();+        moveToParent();+        m_ctx.completeCycle();+    }+    void TrackerBase::markAsNeedingAnotherRun() {+        m_runState = NeedsAnotherRun;+    }++    void TrackerBase::moveToParent() {+        assert( m_parent );+        m_ctx.setCurrentTracker( m_parent );+    }+    void TrackerBase::moveToThis() {+        m_ctx.setCurrentTracker( this );+    }++    SectionTracker::SectionTracker( NameAndLocation const& nameAndLocation, TrackerContext& ctx, ITracker* parent )+    :   TrackerBase( nameAndLocation, ctx, parent ),+        m_trimmed_name(trim(nameAndLocation.name))+    {+        if( parent ) {+            while( !parent->isSectionTracker() )+                parent = &parent->parent();++            SectionTracker& parentSection = static_cast<SectionTracker&>( *parent );+            addNextFilters( parentSection.m_filters );+        }+    }++    bool SectionTracker::isComplete() const {+        bool complete = true;++        if (m_filters.empty()+            || m_filters[0] == ""+            || std::find(m_filters.begin(), m_filters.end(), m_trimmed_name) != m_filters.end()) {+            complete = TrackerBase::isComplete();+        }+        return complete;+    }++    bool SectionTracker::isSectionTracker() const { return true; }++    SectionTracker& SectionTracker::acquire( TrackerContext& ctx, NameAndLocation const& nameAndLocation ) {+        std::shared_ptr<SectionTracker> section;++        ITracker& currentTracker = ctx.currentTracker();+        if( ITrackerPtr childTracker = currentTracker.findChild( nameAndLocation ) ) {+            assert( childTracker );+            assert( childTracker->isSectionTracker() );+            section = std::static_pointer_cast<SectionTracker>( childTracker );+        }+        else {+            section = std::make_shared<SectionTracker>( nameAndLocation, ctx, &currentTracker );+            currentTracker.addChild( section );+        }+        if( !ctx.completedCycle() )+            section->tryOpen();+        return *section;+    }++    void SectionTracker::tryOpen() {+        if( !isComplete() )+            open();+    }++    void SectionTracker::addInitialFilters( std::vector<std::string> const& filters ) {+        if( !filters.empty() ) {+            m_filters.reserve( m_filters.size() + filters.size() + 2 );+            m_filters.emplace_back(""); // Root - should never be consulted+            m_filters.emplace_back(""); // Test Case - not a section filter+            m_filters.insert( m_filters.end(), filters.begin(), filters.end() );+        }+    }+    void SectionTracker::addNextFilters( std::vector<std::string> const& filters ) {+        if( filters.size() > 1 )+            m_filters.insert( m_filters.end(), filters.begin()+1, filters.end() );+    }++    std::vector<std::string> const& SectionTracker::getFilters() const {+        return m_filters;+    }++    std::string const& SectionTracker::trimmedName() const {+        return m_trimmed_name;+    }++} // namespace TestCaseTracking++using TestCaseTracking::ITracker;+using TestCaseTracking::TrackerContext;+using TestCaseTracking::SectionTracker;++} // namespace Catch++#if defined(__clang__)+#    pragma clang diagnostic pop+#endif+// end catch_test_case_tracker.cpp+// start catch_test_registry.cpp++namespace Catch {++    auto makeTestInvoker( void(*testAsFunction)() ) noexcept -> ITestInvoker* {+        return new(std::nothrow) TestInvokerAsFunction( testAsFunction );+    }++    NameAndTags::NameAndTags( StringRef const& name_ , StringRef const& tags_ ) noexcept : name( name_ ), tags( tags_ ) {}++    AutoReg::AutoReg( ITestInvoker* invoker, SourceLineInfo const& lineInfo, StringRef const& classOrMethod, NameAndTags const& nameAndTags ) noexcept {+        CATCH_TRY {+            getMutableRegistryHub()+                    .registerTest(+                        makeTestCase(+                            invoker,+                            extractClassName( classOrMethod ),+                            nameAndTags,+                            lineInfo));+        } CATCH_CATCH_ALL {+            // Do not throw when constructing global objects, instead register the exception to be processed later+            getMutableRegistryHub().registerStartupException();+        }+    }++    AutoReg::~AutoReg() = default;+}+// end catch_test_registry.cpp+// start catch_test_spec.cpp++#include <algorithm>+#include <string>+#include <vector>+#include <memory>++namespace Catch {++    TestSpec::Pattern::Pattern( std::string const& name )+    : m_name( name )+    {}++    TestSpec::Pattern::~Pattern() = default;++    std::string const& TestSpec::Pattern::name() const {+        return m_name;+    }++    TestSpec::NamePattern::NamePattern( std::string const& name, std::string const& filterString )+    : Pattern( filterString )+    , m_wildcardPattern( toLower( name ), CaseSensitive::No )+    {}++    bool TestSpec::NamePattern::matches( TestCaseInfo const& testCase ) const {+        return m_wildcardPattern.matches( testCase.name );+    }++    TestSpec::TagPattern::TagPattern( std::string const& tag, std::string const& filterString )+    : Pattern( filterString )+    , m_tag( toLower( tag ) )+    {}++    bool TestSpec::TagPattern::matches( TestCaseInfo const& testCase ) const {+        return std::find(begin(testCase.lcaseTags),+                         end(testCase.lcaseTags),+                         m_tag) != end(testCase.lcaseTags);+    }++    TestSpec::ExcludedPattern::ExcludedPattern( PatternPtr const& underlyingPattern )+    : Pattern( underlyingPattern->name() )+    , m_underlyingPattern( underlyingPattern )+    {}++    bool TestSpec::ExcludedPattern::matches( TestCaseInfo const& testCase ) const {+        return !m_underlyingPattern->matches( testCase );+    }++    bool TestSpec::Filter::matches( TestCaseInfo const& testCase ) const {+        return std::all_of( m_patterns.begin(), m_patterns.end(), [&]( PatternPtr const& p ){ return p->matches( testCase ); } );+    }++    std::string TestSpec::Filter::name() const {+        std::string name;+        for( auto const& p : m_patterns )+            name += p->name();+        return name;+    }++    bool TestSpec::hasFilters() const {+        return !m_filters.empty();+    }++    bool TestSpec::matches( TestCaseInfo const& testCase ) const {+        return std::any_of( m_filters.begin(), m_filters.end(), [&]( Filter const& f ){ return f.matches( testCase ); } );+    }++    TestSpec::Matches TestSpec::matchesByFilter( std::vector<TestCase> const& testCases, IConfig const& config ) const+    {+        Matches matches( m_filters.size() );+        std::transform( m_filters.begin(), m_filters.end(), matches.begin(), [&]( Filter const& filter ){+            std::vector<TestCase const*> currentMatches;+            for( auto const& test : testCases )+                if( isThrowSafe( test, config ) && filter.matches( test ) )+                    currentMatches.emplace_back( &test );+            return FilterMatch{ filter.name(), currentMatches };+        } );+        return matches;+    }++    const TestSpec::vectorStrings& TestSpec::getInvalidArgs() const{+        return  (m_invalidArgs);+    }++}+// end catch_test_spec.cpp+// start catch_test_spec_parser.cpp++namespace Catch {++    TestSpecParser::TestSpecParser( ITagAliasRegistry const& tagAliases ) : m_tagAliases( &tagAliases ) {}++    TestSpecParser& TestSpecParser::parse( std::string const& arg ) {+        m_mode = None;+        m_exclusion = false;+        m_arg = m_tagAliases->expandAliases( arg );+        m_escapeChars.clear();+        m_substring.reserve(m_arg.size());+        m_patternName.reserve(m_arg.size());+        m_realPatternPos = 0;++        for( m_pos = 0; m_pos < m_arg.size(); ++m_pos )+          //if visitChar fails+           if( !visitChar( m_arg[m_pos] ) ){+               m_testSpec.m_invalidArgs.push_back(arg);+               break;+           }+        endMode();+        return *this;+    }+    TestSpec TestSpecParser::testSpec() {+        addFilter();+        return m_testSpec;+    }+    bool TestSpecParser::visitChar( char c ) {+        if( (m_mode != EscapedName) && (c == '\\') ) {+            escape();+            addCharToPattern(c);+            return true;+        }else if((m_mode != EscapedName) && (c == ',') )  {+            return separate();+        }++        switch( m_mode ) {+        case None:+            if( processNoneChar( c ) )+                return true;+            break;+        case Name:+            processNameChar( c );+            break;+        case EscapedName:+            endMode();+            addCharToPattern(c);+            return true;+        default:+        case Tag:+        case QuotedName:+            if( processOtherChar( c ) )+                return true;+            break;+        }++        m_substring += c;+        if( !isControlChar( c ) ) {+            m_patternName += c;+            m_realPatternPos++;+        }+        return true;+    }+    // Two of the processing methods return true to signal the caller to return+    // without adding the given character to the current pattern strings+    bool TestSpecParser::processNoneChar( char c ) {+        switch( c ) {+        case ' ':+            return true;+        case '~':+            m_exclusion = true;+            return false;+        case '[':+            startNewMode( Tag );+            return false;+        case '"':+            startNewMode( QuotedName );+            return false;+        default:+            startNewMode( Name );+            return false;+        }+    }+    void TestSpecParser::processNameChar( char c ) {+        if( c == '[' ) {+            if( m_substring == "exclude:" )+                m_exclusion = true;+            else+                endMode();+            startNewMode( Tag );+        }+    }+    bool TestSpecParser::processOtherChar( char c ) {+        if( !isControlChar( c ) )+            return false;+        m_substring += c;+        endMode();+        return true;+    }+    void TestSpecParser::startNewMode( Mode mode ) {+        m_mode = mode;+    }+    void TestSpecParser::endMode() {+        switch( m_mode ) {+        case Name:+        case QuotedName:+            return addNamePattern();+        case Tag:+            return addTagPattern();+        case EscapedName:+            revertBackToLastMode();+            return;+        case None:+        default:+            return startNewMode( None );+        }+    }+    void TestSpecParser::escape() {+        saveLastMode();+        m_mode = EscapedName;+        m_escapeChars.push_back(m_realPatternPos);+    }+    bool TestSpecParser::isControlChar( char c ) const {+        switch( m_mode ) {+            default:+                return false;+            case None:+                return c == '~';+            case Name:+                return c == '[';+            case EscapedName:+                return true;+            case QuotedName:+                return c == '"';+            case Tag:+                return c == '[' || c == ']';+        }+    }++    void TestSpecParser::addFilter() {+        if( !m_currentFilter.m_patterns.empty() ) {+            m_testSpec.m_filters.push_back( m_currentFilter );+            m_currentFilter = TestSpec::Filter();+        }+    }++    void TestSpecParser::saveLastMode() {+      lastMode = m_mode;+    }++    void TestSpecParser::revertBackToLastMode() {+      m_mode = lastMode;+    }++    bool TestSpecParser::separate() {+      if( (m_mode==QuotedName) || (m_mode==Tag) ){+         //invalid argument, signal failure to previous scope.+         m_mode = None;+         m_pos = m_arg.size();+         m_substring.clear();+         m_patternName.clear();+         m_realPatternPos = 0;+         return false;+      }+      endMode();+      addFilter();+      return true; //success+    }++    std::string TestSpecParser::preprocessPattern() {+        std::string token = m_patternName;+        for (std::size_t i = 0; i < m_escapeChars.size(); ++i)+            token = token.substr(0, m_escapeChars[i] - i) + token.substr(m_escapeChars[i] - i + 1);+        m_escapeChars.clear();+        if (startsWith(token, "exclude:")) {+            m_exclusion = true;+            token = token.substr(8);+        }++        m_patternName.clear();+        m_realPatternPos = 0;++        return token;+    }++    void TestSpecParser::addNamePattern() {+        auto token = preprocessPattern();++        if (!token.empty()) {+            TestSpec::PatternPtr pattern = std::make_shared<TestSpec::NamePattern>(token, m_substring);+            if (m_exclusion)+                pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);+            m_currentFilter.m_patterns.push_back(pattern);+        }+        m_substring.clear();+        m_exclusion = false;+        m_mode = None;+    }++    void TestSpecParser::addTagPattern() {+        auto token = preprocessPattern();++        if (!token.empty()) {+            // If the tag pattern is the "hide and tag" shorthand (e.g. [.foo])+            // we have to create a separate hide tag and shorten the real one+            if (token.size() > 1 && token[0] == '.') {+                token.erase(token.begin());+                TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(".", m_substring);+                if (m_exclusion) {+                    pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);+                }+                m_currentFilter.m_patterns.push_back(pattern);+            }++            TestSpec::PatternPtr pattern = std::make_shared<TestSpec::TagPattern>(token, m_substring);++            if (m_exclusion) {+                pattern = std::make_shared<TestSpec::ExcludedPattern>(pattern);+            }+            m_currentFilter.m_patterns.push_back(pattern);+        }+        m_substring.clear();+        m_exclusion = false;+        m_mode = None;+    }++    TestSpec parseTestSpec( std::string const& arg ) {+        return TestSpecParser( ITagAliasRegistry::get() ).parse( arg ).testSpec();+    }++} // namespace Catch+// end catch_test_spec_parser.cpp+// start catch_timer.cpp++#include <chrono>++static const uint64_t nanosecondsInSecond = 1000000000;++namespace Catch {++    auto getCurrentNanosecondsSinceEpoch() -> uint64_t {+        return std::chrono::duration_cast<std::chrono::nanoseconds>( std::chrono::high_resolution_clock::now().time_since_epoch() ).count();+    }++    namespace {+        auto estimateClockResolution() -> uint64_t {+            uint64_t sum = 0;+            static const uint64_t iterations = 1000000;++            auto startTime = getCurrentNanosecondsSinceEpoch();++            for( std::size_t i = 0; i < iterations; ++i ) {++                uint64_t ticks;+                uint64_t baseTicks = getCurrentNanosecondsSinceEpoch();+                do {+                    ticks = getCurrentNanosecondsSinceEpoch();+                } while( ticks == baseTicks );++                auto delta = ticks - baseTicks;+                sum += delta;++                // If we have been calibrating for over 3 seconds -- the clock+                // is terrible and we should move on.+                // TBD: How to signal that the measured resolution is probably wrong?+                if (ticks > startTime + 3 * nanosecondsInSecond) {+                    return sum / ( i + 1u );+                }+            }++            // We're just taking the mean, here. To do better we could take the std. dev and exclude outliers+            // - and potentially do more iterations if there's a high variance.+            return sum/iterations;+        }+    }+    auto getEstimatedClockResolution() -> uint64_t {+        static auto s_resolution = estimateClockResolution();+        return s_resolution;+    }++    void Timer::start() {+       m_nanoseconds = getCurrentNanosecondsSinceEpoch();+    }+    auto Timer::getElapsedNanoseconds() const -> uint64_t {+        return getCurrentNanosecondsSinceEpoch() - m_nanoseconds;+    }+    auto Timer::getElapsedMicroseconds() const -> uint64_t {+        return getElapsedNanoseconds()/1000;+    }+    auto Timer::getElapsedMilliseconds() const -> unsigned int {+        return static_cast<unsigned int>(getElapsedMicroseconds()/1000);+    }+    auto Timer::getElapsedSeconds() const -> double {+        return getElapsedMicroseconds()/1000000.0;+    }++} // namespace Catch+// end catch_timer.cpp+// start catch_tostring.cpp++#if defined(__clang__)+#    pragma clang diagnostic push+#    pragma clang diagnostic ignored "-Wexit-time-destructors"+#    pragma clang diagnostic ignored "-Wglobal-constructors"+#endif++// Enable specific decls locally+#if !defined(CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER)+#define CATCH_CONFIG_ENABLE_CHRONO_STRINGMAKER+#endif++#include <cmath>+#include <iomanip>++namespace Catch {++namespace Detail {++    const std::string unprintableString = "{?}";++    namespace {+        const int hexThreshold = 255;++        struct Endianness {+            enum Arch { Big, Little };++            static Arch which() {+                int one = 1;+                // If the lowest byte we read is non-zero, we can assume+                // that little endian format is used.+                auto value = *reinterpret_cast<char*>(&one);+                return value ? Little : Big;+            }+        };+    }++    std::string rawMemoryToString( const void *object, std::size_t size ) {+        // Reverse order for little endian architectures+        int i = 0, end = static_cast<int>( size ), inc = 1;+        if( Endianness::which() == Endianness::Little ) {+            i = end-1;+            end = inc = -1;+        }++        unsigned char const *bytes = static_cast<unsigned char const *>(object);+        ReusableStringStream rss;+        rss << "0x" << std::setfill('0') << std::hex;+        for( ; i != end; i += inc )+             rss << std::setw(2) << static_cast<unsigned>(bytes[i]);+       return rss.str();+    }+}++template<typename T>+std::string fpToString( T value, int precision ) {+    if (Catch::isnan(value)) {+        return "nan";+    }++    ReusableStringStream rss;+    rss << std::setprecision( precision )+        << std::fixed+        << value;+    std::string d = rss.str();+    std::size_t i = d.find_last_not_of( '0' );+    if( i != std::string::npos && i != d.size()-1 ) {+        if( d[i] == '.' )+            i++;+        d = d.substr( 0, i+1 );+    }+    return d;+}++//// ======================================================= ////+//+//   Out-of-line defs for full specialization of StringMaker+//+//// ======================================================= ////++std::string StringMaker<std::string>::convert(const std::string& str) {+    if (!getCurrentContext().getConfig()->showInvisibles()) {+        return '"' + str + '"';+    }++    std::string s("\"");+    for (char c : str) {+        switch (c) {+        case '\n':+            s.append("\\n");+            break;+        case '\t':+            s.append("\\t");+            break;+        default:+            s.push_back(c);+            break;+        }+    }+    s.append("\"");+    return s;+}++#ifdef CATCH_CONFIG_CPP17_STRING_VIEW+std::string StringMaker<std::string_view>::convert(std::string_view str) {+    return ::Catch::Detail::stringify(std::string{ str });+}+#endif++std::string StringMaker<char const*>::convert(char const* str) {+    if (str) {+        return ::Catch::Detail::stringify(std::string{ str });+    } else {+        return{ "{null string}" };+    }+}+std::string StringMaker<char*>::convert(char* str) {+    if (str) {+        return ::Catch::Detail::stringify(std::string{ str });+    } else {+        return{ "{null string}" };+    }+}++#ifdef CATCH_CONFIG_WCHAR+std::string StringMaker<std::wstring>::convert(const std::wstring& wstr) {+    std::string s;+    s.reserve(wstr.size());+    for (auto c : wstr) {+        s += (c <= 0xff) ? static_cast<char>(c) : '?';+    }+    return ::Catch::Detail::stringify(s);+}++# ifdef CATCH_CONFIG_CPP17_STRING_VIEW+std::string StringMaker<std::wstring_view>::convert(std::wstring_view str) {+    return StringMaker<std::wstring>::convert(std::wstring(str));+}+# endif++std::string StringMaker<wchar_t const*>::convert(wchar_t const * str) {+    if (str) {+        return ::Catch::Detail::stringify(std::wstring{ str });+    } else {+        return{ "{null string}" };+    }+}+std::string StringMaker<wchar_t *>::convert(wchar_t * str) {+    if (str) {+        return ::Catch::Detail::stringify(std::wstring{ str });+    } else {+        return{ "{null string}" };+    }+}+#endif++#if defined(CATCH_CONFIG_CPP17_BYTE)+#include <cstddef>+std::string StringMaker<std::byte>::convert(std::byte value) {+    return ::Catch::Detail::stringify(std::to_integer<unsigned long long>(value));+}+#endif // defined(CATCH_CONFIG_CPP17_BYTE)++std::string StringMaker<int>::convert(int value) {+    return ::Catch::Detail::stringify(static_cast<long long>(value));+}+std::string StringMaker<long>::convert(long value) {+    return ::Catch::Detail::stringify(static_cast<long long>(value));+}+std::string StringMaker<long long>::convert(long long value) {+    ReusableStringStream rss;+    rss << value;+    if (value > Detail::hexThreshold) {+        rss << " (0x" << std::hex << value << ')';+    }+    return rss.str();+}++std::string StringMaker<unsigned int>::convert(unsigned int value) {+    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));+}+std::string StringMaker<unsigned long>::convert(unsigned long value) {+    return ::Catch::Detail::stringify(static_cast<unsigned long long>(value));+}+std::string StringMaker<unsigned long long>::convert(unsigned long long value) {+    ReusableStringStream rss;+    rss << value;+    if (value > Detail::hexThreshold) {+        rss << " (0x" << std::hex << value << ')';+    }+    return rss.str();+}++std::string StringMaker<bool>::convert(bool b) {+    return b ? "true" : "false";+}++std::string StringMaker<signed char>::convert(signed char value) {+    if (value == '\r') {+        return "'\\r'";+    } else if (value == '\f') {+        return "'\\f'";+    } else if (value == '\n') {+        return "'\\n'";+    } else if (value == '\t') {+        return "'\\t'";+    } else if ('\0' <= value && value < ' ') {+        return ::Catch::Detail::stringify(static_cast<unsigned int>(value));+    } else {+        char chstr[] = "' '";+        chstr[1] = value;+        return chstr;+    }+}+std::string StringMaker<char>::convert(char c) {+    return ::Catch::Detail::stringify(static_cast<signed char>(c));+}+std::string StringMaker<unsigned char>::convert(unsigned char c) {+    return ::Catch::Detail::stringify(static_cast<char>(c));+}++std::string StringMaker<std::nullptr_t>::convert(std::nullptr_t) {+    return "nullptr";+}++int StringMaker<float>::precision = 5;++std::string StringMaker<float>::convert(float value) {+    return fpToString(value, precision) + 'f';+}++int StringMaker<double>::precision = 10;++std::string StringMaker<double>::convert(double value) {+    return fpToString(value, precision);+}++std::string ratio_string<std::atto>::symbol() { return "a"; }+std::string ratio_string<std::femto>::symbol() { return "f"; }+std::string ratio_string<std::pico>::symbol() { return "p"; }+std::string ratio_string<std::nano>::symbol() { return "n"; }+std::string ratio_string<std::micro>::symbol() { return "u"; }+std::string ratio_string<std::milli>::symbol() { return "m"; }++} // end namespace Catch++#if defined(__clang__)+#    pragma clang diagnostic pop+#endif++// end catch_tostring.cpp+// start catch_totals.cpp++namespace Catch {++    Counts Counts::operator - ( Counts const& other ) const {+        Counts diff;+        diff.passed = passed - other.passed;+        diff.failed = failed - other.failed;+        diff.failedButOk = failedButOk - other.failedButOk;+        return diff;+    }++    Counts& Counts::operator += ( Counts const& other ) {+        passed += other.passed;+        failed += other.failed;+        failedButOk += other.failedButOk;+        return *this;+    }++    std::size_t Counts::total() const {+        return passed + failed + failedButOk;+    }+    bool Counts::allPassed() const {+        return failed == 0 && failedButOk == 0;+    }+    bool Counts::allOk() const {+        return failed == 0;+    }++    Totals Totals::operator - ( Totals const& other ) const {+        Totals diff;+        diff.assertions = assertions - other.assertions;+        diff.testCases = testCases - other.testCases;+        return diff;+    }++    Totals& Totals::operator += ( Totals const& other ) {+        assertions += other.assertions;+        testCases += other.testCases;+        return *this;+    }++    Totals Totals::delta( Totals const& prevTotals ) const {+        Totals diff = *this - prevTotals;+        if( diff.assertions.failed > 0 )+            ++diff.testCases.failed;+        else if( diff.assertions.failedButOk > 0 )+            ++diff.testCases.failedButOk;+        else+            ++diff.testCases.passed;+        return diff;+    }++}+// end catch_totals.cpp+// start catch_uncaught_exceptions.cpp++// start catch_config_uncaught_exceptions.hpp++//              Copyright Catch2 Authors+// Distributed under the Boost Software License, Version 1.0.+//   (See accompanying file LICENSE_1_0.txt or copy at+//        https://www.boost.org/LICENSE_1_0.txt)++// SPDX-License-Identifier: BSL-1.0++#ifndef CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP+#define CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP++#if defined(_MSC_VER)+#  if _MSC_VER >= 1900 // Visual Studio 2015 or newer+#    define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS+#  endif+#endif++#include <exception>++#if defined(__cpp_lib_uncaught_exceptions) \+    && !defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)++#  define CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS+#endif // __cpp_lib_uncaught_exceptions++#if defined(CATCH_INTERNAL_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS) \+    && !defined(CATCH_CONFIG_NO_CPP17_UNCAUGHT_EXCEPTIONS) \+    && !defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)++#  define CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS+#endif++#endif // CATCH_CONFIG_UNCAUGHT_EXCEPTIONS_HPP+// end catch_config_uncaught_exceptions.hpp+#include <exception>++namespace Catch {+    bool uncaught_exceptions() {+#if defined(CATCH_CONFIG_DISABLE_EXCEPTIONS)+        return false;+#elif defined(CATCH_CONFIG_CPP17_UNCAUGHT_EXCEPTIONS)+        return std::uncaught_exceptions() > 0;+#else+        return std::uncaught_exception();+#endif+  }+} // end namespace Catch+// end catch_uncaught_exceptions.cpp+// start catch_version.cpp++#include <ostream>++namespace Catch {++    Version::Version+        (   unsigned int _majorVersion,+            unsigned int _minorVersion,+            unsigned int _patchNumber,+            char const * const _branchName,+            unsigned int _buildNumber )+    :   majorVersion( _majorVersion ),+        minorVersion( _minorVersion ),+        patchNumber( _patchNumber ),+        branchName( _branchName ),+        buildNumber( _buildNumber )+    {}++    std::ostream& operator << ( std::ostream& os, Version const& version ) {+        os  << version.majorVersion << '.'+            << version.minorVersion << '.'+            << version.patchNumber;+        // branchName is never null -> 0th char is \0 if it is empty+        if (version.branchName[0]) {+            os << '-' << version.branchName+               << '.' << version.buildNumber;+        }+        return os;+    }++    Version const& libraryVersion() {+        static Version version( 2, 13, 7, "", 0 );+        return version;+    }++}+// end catch_version.cpp+// start catch_wildcard_pattern.cpp++namespace Catch {++    WildcardPattern::WildcardPattern( std::string const& pattern,+                                      CaseSensitive::Choice caseSensitivity )+    :   m_caseSensitivity( caseSensitivity ),+        m_pattern( normaliseString( pattern ) )+    {+        if( startsWith( m_pattern, '*' ) ) {+            m_pattern = m_pattern.substr( 1 );+            m_wildcard = WildcardAtStart;+        }+        if( endsWith( m_pattern, '*' ) ) {+            m_pattern = m_pattern.substr( 0, m_pattern.size()-1 );+            m_wildcard = static_cast<WildcardPosition>( m_wildcard | WildcardAtEnd );+        }+    }++    bool WildcardPattern::matches( std::string const& str ) const {+        switch( m_wildcard ) {+            case NoWildcard:+                return m_pattern == normaliseString( str );+            case WildcardAtStart:+                return endsWith( normaliseString( str ), m_pattern );+            case WildcardAtEnd:+                return startsWith( normaliseString( str ), m_pattern );+            case WildcardAtBothEnds:+                return contains( normaliseString( str ), m_pattern );+            default:+                CATCH_INTERNAL_ERROR( "Unknown enum" );+        }+    }++    std::string WildcardPattern::normaliseString( std::string const& str ) const {+        return trim( m_caseSensitivity == CaseSensitive::No ? toLower( str ) : str );+    }+}+// end catch_wildcard_pattern.cpp+// start catch_xmlwriter.cpp++#include <iomanip>+#include <type_traits>++namespace Catch {++namespace {++    size_t trailingBytes(unsigned char c) {+        if ((c & 0xE0) == 0xC0) {+            return 2;+        }+        if ((c & 0xF0) == 0xE0) {+            return 3;+        }+        if ((c & 0xF8) == 0xF0) {+            return 4;+        }+        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");+    }++    uint32_t headerValue(unsigned char c) {+        if ((c & 0xE0) == 0xC0) {+            return c & 0x1F;+        }+        if ((c & 0xF0) == 0xE0) {+            return c & 0x0F;+        }+        if ((c & 0xF8) == 0xF0) {+            return c & 0x07;+        }+        CATCH_INTERNAL_ERROR("Invalid multibyte utf-8 start byte encountered");+    }++    void hexEscapeChar(std::ostream& os, unsigned char c) {+        std::ios_base::fmtflags f(os.flags());+        os << "\\x"+            << std::uppercase << std::hex << std::setfill('0') << std::setw(2)+            << static_cast<int>(c);+        os.flags(f);+    }++    bool shouldNewline(XmlFormatting fmt) {+        return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Newline));+    }++    bool shouldIndent(XmlFormatting fmt) {+        return !!(static_cast<std::underlying_type<XmlFormatting>::type>(fmt & XmlFormatting::Indent));+    }++} // anonymous namespace++    XmlFormatting operator | (XmlFormatting lhs, XmlFormatting rhs) {+        return static_cast<XmlFormatting>(+            static_cast<std::underlying_type<XmlFormatting>::type>(lhs) |+            static_cast<std::underlying_type<XmlFormatting>::type>(rhs)+        );+    }++    XmlFormatting operator & (XmlFormatting lhs, XmlFormatting rhs) {+        return static_cast<XmlFormatting>(+            static_cast<std::underlying_type<XmlFormatting>::type>(lhs) &+            static_cast<std::underlying_type<XmlFormatting>::type>(rhs)+        );+    }++    XmlEncode::XmlEncode( std::string const& str, ForWhat forWhat )+    :   m_str( str ),+        m_forWhat( forWhat )+    {}++    void XmlEncode::encodeTo( std::ostream& os ) const {+        // Apostrophe escaping not necessary if we always use " to write attributes+        // (see: http://www.w3.org/TR/xml/#syntax)++        for( std::size_t idx = 0; idx < m_str.size(); ++ idx ) {+            unsigned char c = m_str[idx];+            switch (c) {+            case '<':   os << "&lt;"; break;+            case '&':   os << "&amp;"; break;++            case '>':+                // See: http://www.w3.org/TR/xml/#syntax+                if (idx > 2 && m_str[idx - 1] == ']' && m_str[idx - 2] == ']')+                    os << "&gt;";+                else+                    os << c;+                break;++            case '\"':+                if (m_forWhat == ForAttributes)+                    os << "&quot;";+                else+                    os << c;+                break;++            default:+                // Check for control characters and invalid utf-8++                // Escape control characters in standard ascii+                // see http://stackoverflow.com/questions/404107/why-are-control-characters-illegal-in-xml-1-0+                if (c < 0x09 || (c > 0x0D && c < 0x20) || c == 0x7F) {+                    hexEscapeChar(os, c);+                    break;+                }++                // Plain ASCII: Write it to stream+                if (c < 0x7F) {+                    os << c;+                    break;+                }++                // UTF-8 territory+                // Check if the encoding is valid and if it is not, hex escape bytes.+                // Important: We do not check the exact decoded values for validity, only the encoding format+                // First check that this bytes is a valid lead byte:+                // This means that it is not encoded as 1111 1XXX+                // Or as 10XX XXXX+                if (c <  0xC0 ||+                    c >= 0xF8) {+                    hexEscapeChar(os, c);+                    break;+                }++                auto encBytes = trailingBytes(c);+                // Are there enough bytes left to avoid accessing out-of-bounds memory?+                if (idx + encBytes - 1 >= m_str.size()) {+                    hexEscapeChar(os, c);+                    break;+                }+                // The header is valid, check data+                // The next encBytes bytes must together be a valid utf-8+                // This means: bitpattern 10XX XXXX and the extracted value is sane (ish)+                bool valid = true;+                uint32_t value = headerValue(c);+                for (std::size_t n = 1; n < encBytes; ++n) {+                    unsigned char nc = m_str[idx + n];+                    valid &= ((nc & 0xC0) == 0x80);+                    value = (value << 6) | (nc & 0x3F);+                }++                if (+                    // Wrong bit pattern of following bytes+                    (!valid) ||+                    // Overlong encodings+                    (value < 0x80) ||+                    (0x80 <= value && value < 0x800   && encBytes > 2) ||+                    (0x800 < value && value < 0x10000 && encBytes > 3) ||+                    // Encoded value out of range+                    (value >= 0x110000)+                    ) {+                    hexEscapeChar(os, c);+                    break;+                }++                // If we got here, this is in fact a valid(ish) utf-8 sequence+                for (std::size_t n = 0; n < encBytes; ++n) {+                    os << m_str[idx + n];+                }+                idx += encBytes - 1;+                break;+            }+        }+    }++    std::ostream& operator << ( std::ostream& os, XmlEncode const& xmlEncode ) {+        xmlEncode.encodeTo( os );+        return os;+    }++    XmlWriter::ScopedElement::ScopedElement( XmlWriter* writer, XmlFormatting fmt )+    :   m_writer( writer ),+        m_fmt(fmt)+    {}++    XmlWriter::ScopedElement::ScopedElement( ScopedElement&& other ) noexcept+    :   m_writer( other.m_writer ),+        m_fmt(other.m_fmt)+    {+        other.m_writer = nullptr;+        other.m_fmt = XmlFormatting::None;+    }+    XmlWriter::ScopedElement& XmlWriter::ScopedElement::operator=( ScopedElement&& other ) noexcept {+        if ( m_writer ) {+            m_writer->endElement();+        }+        m_writer = other.m_writer;+        other.m_writer = nullptr;+        m_fmt = other.m_fmt;+        other.m_fmt = XmlFormatting::None;+        return *this;+    }++    XmlWriter::ScopedElement::~ScopedElement() {+        if (m_writer) {+            m_writer->endElement(m_fmt);+        }+    }++    XmlWriter::ScopedElement& XmlWriter::ScopedElement::writeText( std::string const& text, XmlFormatting fmt ) {+        m_writer->writeText( text, fmt );+        return *this;+    }++    XmlWriter::XmlWriter( std::ostream& os ) : m_os( os )+    {+        writeDeclaration();+    }++    XmlWriter::~XmlWriter() {+        while (!m_tags.empty()) {+            endElement();+        }+        newlineIfNecessary();+    }++    XmlWriter& XmlWriter::startElement( std::string const& name, XmlFormatting fmt ) {+        ensureTagClosed();+        newlineIfNecessary();+        if (shouldIndent(fmt)) {+            m_os << m_indent;+            m_indent += "  ";+        }+        m_os << '<' << name;+        m_tags.push_back( name );+        m_tagIsOpen = true;+        applyFormatting(fmt);+        return *this;+    }++    XmlWriter::ScopedElement XmlWriter::scopedElement( std::string const& name, XmlFormatting fmt ) {+        ScopedElement scoped( this, fmt );+        startElement( name, fmt );+        return scoped;+    }++    XmlWriter& XmlWriter::endElement(XmlFormatting fmt) {+        m_indent = m_indent.substr(0, m_indent.size() - 2);++        if( m_tagIsOpen ) {+            m_os << "/>";+            m_tagIsOpen = false;+        } else {+            newlineIfNecessary();+            if (shouldIndent(fmt)) {+                m_os << m_indent;+            }+            m_os << "</" << m_tags.back() << ">";+        }+        m_os << std::flush;+        applyFormatting(fmt);+        m_tags.pop_back();+        return *this;+    }++    XmlWriter& XmlWriter::writeAttribute( std::string const& name, std::string const& attribute ) {+        if( !name.empty() && !attribute.empty() )+            m_os << ' ' << name << "=\"" << XmlEncode( attribute, XmlEncode::ForAttributes ) << '"';+        return *this;+    }++    XmlWriter& XmlWriter::writeAttribute( std::string const& name, bool attribute ) {+        m_os << ' ' << name << "=\"" << ( attribute ? "true" : "false" ) << '"';+        return *this;+    }++    XmlWriter& XmlWriter::writeText( std::string const& text, XmlFormatting fmt) {+        if( !text.empty() ){+            bool tagWasOpen = m_tagIsOpen;+            ensureTagClosed();+            if (tagWasOpen && shouldIndent(fmt)) {+                m_os << m_indent;+            }+            m_os << XmlEncode( text );+            applyFormatting(fmt);+        }+        return *this;+    }++    XmlWriter& XmlWriter::writeComment( std::string const& text, XmlFormatting fmt) {+        ensureTagClosed();+        if (shouldIndent(fmt)) {+            m_os << m_indent;+        }+        m_os << "<!--" << text << "-->";+        applyFormatting(fmt);+        return *this;+    }++    void XmlWriter::writeStylesheetRef( std::string const& url ) {+        m_os << "<?xml-stylesheet type=\"text/xsl\" href=\"" << url << "\"?>\n";+    }++    XmlWriter& XmlWriter::writeBlankLine() {+        ensureTagClosed();+        m_os << '\n';+        return *this;+    }++    void XmlWriter::ensureTagClosed() {+        if( m_tagIsOpen ) {+            m_os << '>' << std::flush;+            newlineIfNecessary();+            m_tagIsOpen = false;+        }+    }++    void XmlWriter::applyFormatting(XmlFormatting fmt) {+        m_needsNewline = shouldNewline(fmt);+    }++    void XmlWriter::writeDeclaration() {+        m_os << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";+    }++    void XmlWriter::newlineIfNecessary() {+        if( m_needsNewline ) {+            m_os << std::endl;+            m_needsNewline = false;+        }+    }+}+// end catch_xmlwriter.cpp+// start catch_reporter_bases.cpp++#include <cstring>+#include <cfloat>+#include <cstdio>+#include <cassert>+#include <memory>++namespace Catch {+    void prepareExpandedExpression(AssertionResult& result) {+        result.getExpandedExpression();+    }++    // Because formatting using c++ streams is stateful, drop down to C is required+    // Alternatively we could use stringstream, but its performance is... not good.+    std::string getFormattedDuration( double duration ) {+        // Max exponent + 1 is required to represent the whole part+        // + 1 for decimal point+        // + 3 for the 3 decimal places+        // + 1 for null terminator+        const std::size_t maxDoubleSize = DBL_MAX_10_EXP + 1 + 1 + 3 + 1;+        char buffer[maxDoubleSize];++        // Save previous errno, to prevent sprintf from overwriting it+        ErrnoGuard guard;+#ifdef _MSC_VER+        sprintf_s(buffer, "%.3f", duration);+#else+        std::sprintf(buffer, "%.3f", duration);+#endif+        return std::string(buffer);+    }++    bool shouldShowDuration( IConfig const& config, double duration ) {+        if ( config.showDurations() == ShowDurations::Always ) {+            return true;+        }+        if ( config.showDurations() == ShowDurations::Never ) {+            return false;+        }+        const double min = config.minDuration();+        return min >= 0 && duration >= min;+    }++    std::string serializeFilters( std::vector<std::string> const& container ) {+        ReusableStringStream oss;+        bool first = true;+        for (auto&& filter : container)+        {+            if (!first)+                oss << ' ';+            else+                first = false;++            oss << filter;+        }+        return oss.str();+    }++    TestEventListenerBase::TestEventListenerBase(ReporterConfig const & _config)+        :StreamingReporterBase(_config) {}++    std::set<Verbosity> TestEventListenerBase::getSupportedVerbosities() {+        return { Verbosity::Quiet, Verbosity::Normal, Verbosity::High };+    }++    void TestEventListenerBase::assertionStarting(AssertionInfo const &) {}++    bool TestEventListenerBase::assertionEnded(AssertionStats const &) {+        return false;+    }++} // end namespace Catch+// end catch_reporter_bases.cpp+// start catch_reporter_compact.cpp++namespace {++#ifdef CATCH_PLATFORM_MAC+    const char* failedString() { return "FAILED"; }+    const char* passedString() { return "PASSED"; }+#else+    const char* failedString() { return "failed"; }+    const char* passedString() { return "passed"; }+#endif++    // Colour::LightGrey+    Catch::Colour::Code dimColour() { return Catch::Colour::FileName; }++    std::string bothOrAll( std::size_t count ) {+        return count == 1 ? std::string() :+               count == 2 ? "both " : "all " ;+    }++} // anon namespace++namespace Catch {+namespace {+// Colour, message variants:+// - white: No tests ran.+// -   red: Failed [both/all] N test cases, failed [both/all] M assertions.+// - white: Passed [both/all] N test cases (no assertions).+// -   red: Failed N tests cases, failed M assertions.+// - green: Passed [both/all] N tests cases with M assertions.+void printTotals(std::ostream& out, const Totals& totals) {+    if (totals.testCases.total() == 0) {+        out << "No tests ran.";+    } else if (totals.testCases.failed == totals.testCases.total()) {+        Colour colour(Colour::ResultError);+        const std::string qualify_assertions_failed =+            totals.assertions.failed == totals.assertions.total() ?+            bothOrAll(totals.assertions.failed) : std::string();+        out <<+            "Failed " << bothOrAll(totals.testCases.failed)+            << pluralise(totals.testCases.failed, "test case") << ", "+            "failed " << qualify_assertions_failed <<+            pluralise(totals.assertions.failed, "assertion") << '.';+    } else if (totals.assertions.total() == 0) {+        out <<+            "Passed " << bothOrAll(totals.testCases.total())+            << pluralise(totals.testCases.total(), "test case")+            << " (no assertions).";+    } else if (totals.assertions.failed) {+        Colour colour(Colour::ResultError);+        out <<+            "Failed " << pluralise(totals.testCases.failed, "test case") << ", "+            "failed " << pluralise(totals.assertions.failed, "assertion") << '.';+    } else {+        Colour colour(Colour::ResultSuccess);+        out <<+            "Passed " << bothOrAll(totals.testCases.passed)+            << pluralise(totals.testCases.passed, "test case") <<+            " with " << pluralise(totals.assertions.passed, "assertion") << '.';+    }+}++// Implementation of CompactReporter formatting+class AssertionPrinter {+public:+    AssertionPrinter& operator= (AssertionPrinter const&) = delete;+    AssertionPrinter(AssertionPrinter const&) = delete;+    AssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)+        : stream(_stream)+        , result(_stats.assertionResult)+        , messages(_stats.infoMessages)+        , itMessage(_stats.infoMessages.begin())+        , printInfoMessages(_printInfoMessages) {}++    void print() {+        printSourceInfo();++        itMessage = messages.begin();++        switch (result.getResultType()) {+        case ResultWas::Ok:+            printResultType(Colour::ResultSuccess, passedString());+            printOriginalExpression();+            printReconstructedExpression();+            if (!result.hasExpression())+                printRemainingMessages(Colour::None);+            else+                printRemainingMessages();+            break;+        case ResultWas::ExpressionFailed:+            if (result.isOk())+                printResultType(Colour::ResultSuccess, failedString() + std::string(" - but was ok"));+            else+                printResultType(Colour::Error, failedString());+            printOriginalExpression();+            printReconstructedExpression();+            printRemainingMessages();+            break;+        case ResultWas::ThrewException:+            printResultType(Colour::Error, failedString());+            printIssue("unexpected exception with message:");+            printMessage();+            printExpressionWas();+            printRemainingMessages();+            break;+        case ResultWas::FatalErrorCondition:+            printResultType(Colour::Error, failedString());+            printIssue("fatal error condition with message:");+            printMessage();+            printExpressionWas();+            printRemainingMessages();+            break;+        case ResultWas::DidntThrowException:+            printResultType(Colour::Error, failedString());+            printIssue("expected exception, got none");+            printExpressionWas();+            printRemainingMessages();+            break;+        case ResultWas::Info:+            printResultType(Colour::None, "info");+            printMessage();+            printRemainingMessages();+            break;+        case ResultWas::Warning:+            printResultType(Colour::None, "warning");+            printMessage();+            printRemainingMessages();+            break;+        case ResultWas::ExplicitFailure:+            printResultType(Colour::Error, failedString());+            printIssue("explicitly");+            printRemainingMessages(Colour::None);+            break;+            // These cases are here to prevent compiler warnings+        case ResultWas::Unknown:+        case ResultWas::FailureBit:+        case ResultWas::Exception:+            printResultType(Colour::Error, "** internal error **");+            break;+        }+    }++private:+    void printSourceInfo() const {+        Colour colourGuard(Colour::FileName);+        stream << result.getSourceInfo() << ':';+    }++    void printResultType(Colour::Code colour, std::string const& passOrFail) const {+        if (!passOrFail.empty()) {+            {+                Colour colourGuard(colour);+                stream << ' ' << passOrFail;+            }+            stream << ':';+        }+    }++    void printIssue(std::string const& issue) const {+        stream << ' ' << issue;+    }++    void printExpressionWas() {+        if (result.hasExpression()) {+            stream << ';';+            {+                Colour colour(dimColour());+                stream << " expression was:";+            }+            printOriginalExpression();+        }+    }++    void printOriginalExpression() const {+        if (result.hasExpression()) {+            stream << ' ' << result.getExpression();+        }+    }++    void printReconstructedExpression() const {+        if (result.hasExpandedExpression()) {+            {+                Colour colour(dimColour());+                stream << " for: ";+            }+            stream << result.getExpandedExpression();+        }+    }++    void printMessage() {+        if (itMessage != messages.end()) {+            stream << " '" << itMessage->message << '\'';+            ++itMessage;+        }+    }++    void printRemainingMessages(Colour::Code colour = dimColour()) {+        if (itMessage == messages.end())+            return;++        const auto itEnd = messages.cend();+        const auto N = static_cast<std::size_t>(std::distance(itMessage, itEnd));++        {+            Colour colourGuard(colour);+            stream << " with " << pluralise(N, "message") << ':';+        }++        while (itMessage != itEnd) {+            // If this assertion is a warning ignore any INFO messages+            if (printInfoMessages || itMessage->type != ResultWas::Info) {+                printMessage();+                if (itMessage != itEnd) {+                    Colour colourGuard(dimColour());+                    stream << " and";+                }+                continue;+            }+            ++itMessage;+        }+    }++private:+    std::ostream& stream;+    AssertionResult const& result;+    std::vector<MessageInfo> messages;+    std::vector<MessageInfo>::const_iterator itMessage;+    bool printInfoMessages;+};++} // anon namespace++        std::string CompactReporter::getDescription() {+            return "Reports test results on a single line, suitable for IDEs";+        }++        void CompactReporter::noMatchingTestCases( std::string const& spec ) {+            stream << "No test cases matched '" << spec << '\'' << std::endl;+        }++        void CompactReporter::assertionStarting( AssertionInfo const& ) {}++        bool CompactReporter::assertionEnded( AssertionStats const& _assertionStats ) {+            AssertionResult const& result = _assertionStats.assertionResult;++            bool printInfoMessages = true;++            // Drop out if result was successful and we're not printing those+            if( !m_config->includeSuccessfulResults() && result.isOk() ) {+                if( result.getResultType() != ResultWas::Warning )+                    return false;+                printInfoMessages = false;+            }++            AssertionPrinter printer( stream, _assertionStats, printInfoMessages );+            printer.print();++            stream << std::endl;+            return true;+        }++        void CompactReporter::sectionEnded(SectionStats const& _sectionStats) {+            double dur = _sectionStats.durationInSeconds;+            if ( shouldShowDuration( *m_config, dur ) ) {+                stream << getFormattedDuration( dur ) << " s: " << _sectionStats.sectionInfo.name << std::endl;+            }+        }++        void CompactReporter::testRunEnded( TestRunStats const& _testRunStats ) {+            printTotals( stream, _testRunStats.totals );+            stream << '\n' << std::endl;+            StreamingReporterBase::testRunEnded( _testRunStats );+        }++        CompactReporter::~CompactReporter() {}++    CATCH_REGISTER_REPORTER( "compact", CompactReporter )++} // end namespace Catch+// end catch_reporter_compact.cpp+// start catch_reporter_console.cpp++#include <cfloat>+#include <cstdio>++#if defined(_MSC_VER)+#pragma warning(push)+#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch+ // Note that 4062 (not all labels are handled and default is missing) is enabled+#endif++#if defined(__clang__)+#  pragma clang diagnostic push+// For simplicity, benchmarking-only helpers are always enabled+#  pragma clang diagnostic ignored "-Wunused-function"+#endif++namespace Catch {++namespace {++// Formatter impl for ConsoleReporter+class ConsoleAssertionPrinter {+public:+    ConsoleAssertionPrinter& operator= (ConsoleAssertionPrinter const&) = delete;+    ConsoleAssertionPrinter(ConsoleAssertionPrinter const&) = delete;+    ConsoleAssertionPrinter(std::ostream& _stream, AssertionStats const& _stats, bool _printInfoMessages)+        : stream(_stream),+        stats(_stats),+        result(_stats.assertionResult),+        colour(Colour::None),+        message(result.getMessage()),+        messages(_stats.infoMessages),+        printInfoMessages(_printInfoMessages) {+        switch (result.getResultType()) {+        case ResultWas::Ok:+            colour = Colour::Success;+            passOrFail = "PASSED";+            //if( result.hasMessage() )+            if (_stats.infoMessages.size() == 1)+                messageLabel = "with message";+            if (_stats.infoMessages.size() > 1)+                messageLabel = "with messages";+            break;+        case ResultWas::ExpressionFailed:+            if (result.isOk()) {+                colour = Colour::Success;+                passOrFail = "FAILED - but was ok";+            } else {+                colour = Colour::Error;+                passOrFail = "FAILED";+            }+            if (_stats.infoMessages.size() == 1)+                messageLabel = "with message";+            if (_stats.infoMessages.size() > 1)+                messageLabel = "with messages";+            break;+        case ResultWas::ThrewException:+            colour = Colour::Error;+            passOrFail = "FAILED";+            messageLabel = "due to unexpected exception with ";+            if (_stats.infoMessages.size() == 1)+                messageLabel += "message";+            if (_stats.infoMessages.size() > 1)+                messageLabel += "messages";+            break;+        case ResultWas::FatalErrorCondition:+            colour = Colour::Error;+            passOrFail = "FAILED";+            messageLabel = "due to a fatal error condition";+            break;+        case ResultWas::DidntThrowException:+            colour = Colour::Error;+            passOrFail = "FAILED";+            messageLabel = "because no exception was thrown where one was expected";+            break;+        case ResultWas::Info:+            messageLabel = "info";+            break;+        case ResultWas::Warning:+            messageLabel = "warning";+            break;+        case ResultWas::ExplicitFailure:+            passOrFail = "FAILED";+            colour = Colour::Error;+            if (_stats.infoMessages.size() == 1)+                messageLabel = "explicitly with message";+            if (_stats.infoMessages.size() > 1)+                messageLabel = "explicitly with messages";+            break;+            // These cases are here to prevent compiler warnings+        case ResultWas::Unknown:+        case ResultWas::FailureBit:+        case ResultWas::Exception:+            passOrFail = "** internal error **";+            colour = Colour::Error;+            break;+        }+    }++    void print() const {+        printSourceInfo();+        if (stats.totals.assertions.total() > 0) {+            printResultType();+            printOriginalExpression();+            printReconstructedExpression();+        } else {+            stream << '\n';+        }+        printMessage();+    }++private:+    void printResultType() const {+        if (!passOrFail.empty()) {+            Colour colourGuard(colour);+            stream << passOrFail << ":\n";+        }+    }+    void printOriginalExpression() const {+        if (result.hasExpression()) {+            Colour colourGuard(Colour::OriginalExpression);+            stream << "  ";+            stream << result.getExpressionInMacro();+            stream << '\n';+        }+    }+    void printReconstructedExpression() const {+        if (result.hasExpandedExpression()) {+            stream << "with expansion:\n";+            Colour colourGuard(Colour::ReconstructedExpression);+            stream << Column(result.getExpandedExpression()).indent(2) << '\n';+        }+    }+    void printMessage() const {+        if (!messageLabel.empty())+            stream << messageLabel << ':' << '\n';+        for (auto const& msg : messages) {+            // If this assertion is a warning ignore any INFO messages+            if (printInfoMessages || msg.type != ResultWas::Info)+                stream << Column(msg.message).indent(2) << '\n';+        }+    }+    void printSourceInfo() const {+        Colour colourGuard(Colour::FileName);+        stream << result.getSourceInfo() << ": ";+    }++    std::ostream& stream;+    AssertionStats const& stats;+    AssertionResult const& result;+    Colour::Code colour;+    std::string passOrFail;+    std::string messageLabel;+    std::string message;+    std::vector<MessageInfo> messages;+    bool printInfoMessages;+};++std::size_t makeRatio(std::size_t number, std::size_t total) {+    std::size_t ratio = total > 0 ? CATCH_CONFIG_CONSOLE_WIDTH * number / total : 0;+    return (ratio == 0 && number > 0) ? 1 : ratio;+}++std::size_t& findMax(std::size_t& i, std::size_t& j, std::size_t& k) {+    if (i > j && i > k)+        return i;+    else if (j > k)+        return j;+    else+        return k;+}++struct ColumnInfo {+    enum Justification { Left, Right };+    std::string name;+    int width;+    Justification justification;+};+struct ColumnBreak {};+struct RowBreak {};++class Duration {+    enum class Unit {+        Auto,+        Nanoseconds,+        Microseconds,+        Milliseconds,+        Seconds,+        Minutes+    };+    static const uint64_t s_nanosecondsInAMicrosecond = 1000;+    static const uint64_t s_nanosecondsInAMillisecond = 1000 * s_nanosecondsInAMicrosecond;+    static const uint64_t s_nanosecondsInASecond = 1000 * s_nanosecondsInAMillisecond;+    static const uint64_t s_nanosecondsInAMinute = 60 * s_nanosecondsInASecond;++    double m_inNanoseconds;+    Unit m_units;++public:+    explicit Duration(double inNanoseconds, Unit units = Unit::Auto)+        : m_inNanoseconds(inNanoseconds),+        m_units(units) {+        if (m_units == Unit::Auto) {+            if (m_inNanoseconds < s_nanosecondsInAMicrosecond)+                m_units = Unit::Nanoseconds;+            else if (m_inNanoseconds < s_nanosecondsInAMillisecond)+                m_units = Unit::Microseconds;+            else if (m_inNanoseconds < s_nanosecondsInASecond)+                m_units = Unit::Milliseconds;+            else if (m_inNanoseconds < s_nanosecondsInAMinute)+                m_units = Unit::Seconds;+            else+                m_units = Unit::Minutes;+        }++    }++    auto value() const -> double {+        switch (m_units) {+        case Unit::Microseconds:+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMicrosecond);+        case Unit::Milliseconds:+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMillisecond);+        case Unit::Seconds:+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInASecond);+        case Unit::Minutes:+            return m_inNanoseconds / static_cast<double>(s_nanosecondsInAMinute);+        default:+            return m_inNanoseconds;+        }+    }+    auto unitsAsString() const -> std::string {+        switch (m_units) {+        case Unit::Nanoseconds:+            return "ns";+        case Unit::Microseconds:+            return "us";+        case Unit::Milliseconds:+            return "ms";+        case Unit::Seconds:+            return "s";+        case Unit::Minutes:+            return "m";+        default:+            return "** internal error **";+        }++    }+    friend auto operator << (std::ostream& os, Duration const& duration) -> std::ostream& {+        return os << duration.value() << ' ' << duration.unitsAsString();+    }+};+} // end anon namespace++class TablePrinter {+    std::ostream& m_os;+    std::vector<ColumnInfo> m_columnInfos;+    std::ostringstream m_oss;+    int m_currentColumn = -1;+    bool m_isOpen = false;++public:+    TablePrinter( std::ostream& os, std::vector<ColumnInfo> columnInfos )+    :   m_os( os ),+        m_columnInfos( std::move( columnInfos ) ) {}++    auto columnInfos() const -> std::vector<ColumnInfo> const& {+        return m_columnInfos;+    }++    void open() {+        if (!m_isOpen) {+            m_isOpen = true;+            *this << RowBreak();++			Columns headerCols;+			Spacer spacer(2);+			for (auto const& info : m_columnInfos) {+				headerCols += Column(info.name).width(static_cast<std::size_t>(info.width - 2));+				headerCols += spacer;+			}+			m_os << headerCols << '\n';++            m_os << Catch::getLineOfChars<'-'>() << '\n';+        }+    }+    void close() {+        if (m_isOpen) {+            *this << RowBreak();+            m_os << std::endl;+            m_isOpen = false;+        }+    }++    template<typename T>+    friend TablePrinter& operator << (TablePrinter& tp, T const& value) {+        tp.m_oss << value;+        return tp;+    }++    friend TablePrinter& operator << (TablePrinter& tp, ColumnBreak) {+        auto colStr = tp.m_oss.str();+        const auto strSize = colStr.size();+        tp.m_oss.str("");+        tp.open();+        if (tp.m_currentColumn == static_cast<int>(tp.m_columnInfos.size() - 1)) {+            tp.m_currentColumn = -1;+            tp.m_os << '\n';+        }+        tp.m_currentColumn++;++        auto colInfo = tp.m_columnInfos[tp.m_currentColumn];+        auto padding = (strSize + 1 < static_cast<std::size_t>(colInfo.width))+            ? std::string(colInfo.width - (strSize + 1), ' ')+            : std::string();+        if (colInfo.justification == ColumnInfo::Left)+            tp.m_os << colStr << padding << ' ';+        else+            tp.m_os << padding << colStr << ' ';+        return tp;+    }++    friend TablePrinter& operator << (TablePrinter& tp, RowBreak) {+        if (tp.m_currentColumn > 0) {+            tp.m_os << '\n';+            tp.m_currentColumn = -1;+        }+        return tp;+    }+};++ConsoleReporter::ConsoleReporter(ReporterConfig const& config)+    : StreamingReporterBase(config),+    m_tablePrinter(new TablePrinter(config.stream(),+        [&config]() -> std::vector<ColumnInfo> {+        if (config.fullConfig()->benchmarkNoAnalysis())+        {+            return{+                { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },+                { "     samples", 14, ColumnInfo::Right },+                { "  iterations", 14, ColumnInfo::Right },+                { "        mean", 14, ColumnInfo::Right }+            };+        }+        else+        {+            return{+                { "benchmark name", CATCH_CONFIG_CONSOLE_WIDTH - 43, ColumnInfo::Left },+                { "samples      mean       std dev", 14, ColumnInfo::Right },+                { "iterations   low mean   low std dev", 14, ColumnInfo::Right },+                { "estimated    high mean  high std dev", 14, ColumnInfo::Right }+            };+        }+    }())) {}+ConsoleReporter::~ConsoleReporter() = default;++std::string ConsoleReporter::getDescription() {+    return "Reports test results as plain lines of text";+}++void ConsoleReporter::noMatchingTestCases(std::string const& spec) {+    stream << "No test cases matched '" << spec << '\'' << std::endl;+}++void ConsoleReporter::reportInvalidArguments(std::string const&arg){+    stream << "Invalid Filter: " << arg << std::endl;+}++void ConsoleReporter::assertionStarting(AssertionInfo const&) {}++bool ConsoleReporter::assertionEnded(AssertionStats const& _assertionStats) {+    AssertionResult const& result = _assertionStats.assertionResult;++    bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();++    // Drop out if result was successful but we're not printing them.+    if (!includeResults && result.getResultType() != ResultWas::Warning)+        return false;++    lazyPrint();++    ConsoleAssertionPrinter printer(stream, _assertionStats, includeResults);+    printer.print();+    stream << std::endl;+    return true;+}++void ConsoleReporter::sectionStarting(SectionInfo const& _sectionInfo) {+    m_tablePrinter->close();+    m_headerPrinted = false;+    StreamingReporterBase::sectionStarting(_sectionInfo);+}+void ConsoleReporter::sectionEnded(SectionStats const& _sectionStats) {+    m_tablePrinter->close();+    if (_sectionStats.missingAssertions) {+        lazyPrint();+        Colour colour(Colour::ResultError);+        if (m_sectionStack.size() > 1)+            stream << "\nNo assertions in section";+        else+            stream << "\nNo assertions in test case";+        stream << " '" << _sectionStats.sectionInfo.name << "'\n" << std::endl;+    }+    double dur = _sectionStats.durationInSeconds;+    if (shouldShowDuration(*m_config, dur)) {+        stream << getFormattedDuration(dur) << " s: " << _sectionStats.sectionInfo.name << std::endl;+    }+    if (m_headerPrinted) {+        m_headerPrinted = false;+    }+    StreamingReporterBase::sectionEnded(_sectionStats);+}++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+void ConsoleReporter::benchmarkPreparing(std::string const& name) {+	lazyPrintWithoutClosingBenchmarkTable();++	auto nameCol = Column(name).width(static_cast<std::size_t>(m_tablePrinter->columnInfos()[0].width - 2));++	bool firstLine = true;+	for (auto line : nameCol) {+		if (!firstLine)+			(*m_tablePrinter) << ColumnBreak() << ColumnBreak() << ColumnBreak();+		else+			firstLine = false;++		(*m_tablePrinter) << line << ColumnBreak();+	}+}++void ConsoleReporter::benchmarkStarting(BenchmarkInfo const& info) {+    (*m_tablePrinter) << info.samples << ColumnBreak()+        << info.iterations << ColumnBreak();+    if (!m_config->benchmarkNoAnalysis())+        (*m_tablePrinter) << Duration(info.estimatedDuration) << ColumnBreak();+}+void ConsoleReporter::benchmarkEnded(BenchmarkStats<> const& stats) {+    if (m_config->benchmarkNoAnalysis())+    {+        (*m_tablePrinter) << Duration(stats.mean.point.count()) << ColumnBreak();+    }+    else+    {+        (*m_tablePrinter) << ColumnBreak()+            << Duration(stats.mean.point.count()) << ColumnBreak()+            << Duration(stats.mean.lower_bound.count()) << ColumnBreak()+            << Duration(stats.mean.upper_bound.count()) << ColumnBreak() << ColumnBreak()+            << Duration(stats.standardDeviation.point.count()) << ColumnBreak()+            << Duration(stats.standardDeviation.lower_bound.count()) << ColumnBreak()+            << Duration(stats.standardDeviation.upper_bound.count()) << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak() << ColumnBreak();+    }+}++void ConsoleReporter::benchmarkFailed(std::string const& error) {+	Colour colour(Colour::Red);+    (*m_tablePrinter)+        << "Benchmark failed (" << error << ')'+        << ColumnBreak() << RowBreak();+}+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++void ConsoleReporter::testCaseEnded(TestCaseStats const& _testCaseStats) {+    m_tablePrinter->close();+    StreamingReporterBase::testCaseEnded(_testCaseStats);+    m_headerPrinted = false;+}+void ConsoleReporter::testGroupEnded(TestGroupStats const& _testGroupStats) {+    if (currentGroupInfo.used) {+        printSummaryDivider();+        stream << "Summary for group '" << _testGroupStats.groupInfo.name << "':\n";+        printTotals(_testGroupStats.totals);+        stream << '\n' << std::endl;+    }+    StreamingReporterBase::testGroupEnded(_testGroupStats);+}+void ConsoleReporter::testRunEnded(TestRunStats const& _testRunStats) {+    printTotalsDivider(_testRunStats.totals);+    printTotals(_testRunStats.totals);+    stream << std::endl;+    StreamingReporterBase::testRunEnded(_testRunStats);+}+void ConsoleReporter::testRunStarting(TestRunInfo const& _testInfo) {+    StreamingReporterBase::testRunStarting(_testInfo);+    printTestFilters();+}++void ConsoleReporter::lazyPrint() {++    m_tablePrinter->close();+    lazyPrintWithoutClosingBenchmarkTable();+}++void ConsoleReporter::lazyPrintWithoutClosingBenchmarkTable() {++    if (!currentTestRunInfo.used)+        lazyPrintRunInfo();+    if (!currentGroupInfo.used)+        lazyPrintGroupInfo();++    if (!m_headerPrinted) {+        printTestCaseAndSectionHeader();+        m_headerPrinted = true;+    }+}+void ConsoleReporter::lazyPrintRunInfo() {+    stream << '\n' << getLineOfChars<'~'>() << '\n';+    Colour colour(Colour::SecondaryText);+    stream << currentTestRunInfo->name+        << " is a Catch v" << libraryVersion() << " host application.\n"+        << "Run with -? for options\n\n";++    if (m_config->rngSeed() != 0)+        stream << "Randomness seeded to: " << m_config->rngSeed() << "\n\n";++    currentTestRunInfo.used = true;+}+void ConsoleReporter::lazyPrintGroupInfo() {+    if (!currentGroupInfo->name.empty() && currentGroupInfo->groupsCounts > 1) {+        printClosedHeader("Group: " + currentGroupInfo->name);+        currentGroupInfo.used = true;+    }+}+void ConsoleReporter::printTestCaseAndSectionHeader() {+    assert(!m_sectionStack.empty());+    printOpenHeader(currentTestCaseInfo->name);++    if (m_sectionStack.size() > 1) {+        Colour colourGuard(Colour::Headers);++        auto+            it = m_sectionStack.begin() + 1, // Skip first section (test case)+            itEnd = m_sectionStack.end();+        for (; it != itEnd; ++it)+            printHeaderString(it->name, 2);+    }++    SourceLineInfo lineInfo = m_sectionStack.back().lineInfo;++    stream << getLineOfChars<'-'>() << '\n';+    Colour colourGuard(Colour::FileName);+    stream << lineInfo << '\n';+    stream << getLineOfChars<'.'>() << '\n' << std::endl;+}++void ConsoleReporter::printClosedHeader(std::string const& _name) {+    printOpenHeader(_name);+    stream << getLineOfChars<'.'>() << '\n';+}+void ConsoleReporter::printOpenHeader(std::string const& _name) {+    stream << getLineOfChars<'-'>() << '\n';+    {+        Colour colourGuard(Colour::Headers);+        printHeaderString(_name);+    }+}++// if string has a : in first line will set indent to follow it on+// subsequent lines+void ConsoleReporter::printHeaderString(std::string const& _string, std::size_t indent) {+    std::size_t i = _string.find(": ");+    if (i != std::string::npos)+        i += 2;+    else+        i = 0;+    stream << Column(_string).indent(indent + i).initialIndent(indent) << '\n';+}++struct SummaryColumn {++    SummaryColumn( std::string _label, Colour::Code _colour )+    :   label( std::move( _label ) ),+        colour( _colour ) {}+    SummaryColumn addRow( std::size_t count ) {+        ReusableStringStream rss;+        rss << count;+        std::string row = rss.str();+        for (auto& oldRow : rows) {+            while (oldRow.size() < row.size())+                oldRow = ' ' + oldRow;+            while (oldRow.size() > row.size())+                row = ' ' + row;+        }+        rows.push_back(row);+        return *this;+    }++    std::string label;+    Colour::Code colour;+    std::vector<std::string> rows;++};++void ConsoleReporter::printTotals( Totals const& totals ) {+    if (totals.testCases.total() == 0) {+        stream << Colour(Colour::Warning) << "No tests ran\n";+    } else if (totals.assertions.total() > 0 && totals.testCases.allPassed()) {+        stream << Colour(Colour::ResultSuccess) << "All tests passed";+        stream << " ("+            << pluralise(totals.assertions.passed, "assertion") << " in "+            << pluralise(totals.testCases.passed, "test case") << ')'+            << '\n';+    } else {++        std::vector<SummaryColumn> columns;+        columns.push_back(SummaryColumn("", Colour::None)+                          .addRow(totals.testCases.total())+                          .addRow(totals.assertions.total()));+        columns.push_back(SummaryColumn("passed", Colour::Success)+                          .addRow(totals.testCases.passed)+                          .addRow(totals.assertions.passed));+        columns.push_back(SummaryColumn("failed", Colour::ResultError)+                          .addRow(totals.testCases.failed)+                          .addRow(totals.assertions.failed));+        columns.push_back(SummaryColumn("failed as expected", Colour::ResultExpectedFailure)+                          .addRow(totals.testCases.failedButOk)+                          .addRow(totals.assertions.failedButOk));++        printSummaryRow("test cases", columns, 0);+        printSummaryRow("assertions", columns, 1);+    }+}+void ConsoleReporter::printSummaryRow(std::string const& label, std::vector<SummaryColumn> const& cols, std::size_t row) {+    for (auto col : cols) {+        std::string value = col.rows[row];+        if (col.label.empty()) {+            stream << label << ": ";+            if (value != "0")+                stream << value;+            else+                stream << Colour(Colour::Warning) << "- none -";+        } else if (value != "0") {+            stream << Colour(Colour::LightGrey) << " | ";+            stream << Colour(col.colour)+                << value << ' ' << col.label;+        }+    }+    stream << '\n';+}++void ConsoleReporter::printTotalsDivider(Totals const& totals) {+    if (totals.testCases.total() > 0) {+        std::size_t failedRatio = makeRatio(totals.testCases.failed, totals.testCases.total());+        std::size_t failedButOkRatio = makeRatio(totals.testCases.failedButOk, totals.testCases.total());+        std::size_t passedRatio = makeRatio(totals.testCases.passed, totals.testCases.total());+        while (failedRatio + failedButOkRatio + passedRatio < CATCH_CONFIG_CONSOLE_WIDTH - 1)+            findMax(failedRatio, failedButOkRatio, passedRatio)++;+        while (failedRatio + failedButOkRatio + passedRatio > CATCH_CONFIG_CONSOLE_WIDTH - 1)+            findMax(failedRatio, failedButOkRatio, passedRatio)--;++        stream << Colour(Colour::Error) << std::string(failedRatio, '=');+        stream << Colour(Colour::ResultExpectedFailure) << std::string(failedButOkRatio, '=');+        if (totals.testCases.allPassed())+            stream << Colour(Colour::ResultSuccess) << std::string(passedRatio, '=');+        else+            stream << Colour(Colour::Success) << std::string(passedRatio, '=');+    } else {+        stream << Colour(Colour::Warning) << std::string(CATCH_CONFIG_CONSOLE_WIDTH - 1, '=');+    }+    stream << '\n';+}+void ConsoleReporter::printSummaryDivider() {+    stream << getLineOfChars<'-'>() << '\n';+}++void ConsoleReporter::printTestFilters() {+    if (m_config->testSpec().hasFilters()) {+        Colour guard(Colour::BrightYellow);+        stream << "Filters: " << serializeFilters(m_config->getTestsOrTags()) << '\n';+    }+}++CATCH_REGISTER_REPORTER("console", ConsoleReporter)++} // end namespace Catch++#if defined(_MSC_VER)+#pragma warning(pop)+#endif++#if defined(__clang__)+#  pragma clang diagnostic pop+#endif+// end catch_reporter_console.cpp+// start catch_reporter_junit.cpp++#include <cassert>+#include <sstream>+#include <ctime>+#include <algorithm>+#include <iomanip>++namespace Catch {++    namespace {+        std::string getCurrentTimestamp() {+            // Beware, this is not reentrant because of backward compatibility issues+            // Also, UTC only, again because of backward compatibility (%z is C++11)+            time_t rawtime;+            std::time(&rawtime);+            auto const timeStampSize = sizeof("2017-01-16T17:06:45Z");++#ifdef _MSC_VER+            std::tm timeInfo = {};+            gmtime_s(&timeInfo, &rawtime);+#else+            std::tm* timeInfo;+            timeInfo = std::gmtime(&rawtime);+#endif++            char timeStamp[timeStampSize];+            const char * const fmt = "%Y-%m-%dT%H:%M:%SZ";++#ifdef _MSC_VER+            std::strftime(timeStamp, timeStampSize, fmt, &timeInfo);+#else+            std::strftime(timeStamp, timeStampSize, fmt, timeInfo);+#endif+            return std::string(timeStamp, timeStampSize-1);+        }++        std::string fileNameTag(const std::vector<std::string> &tags) {+            auto it = std::find_if(begin(tags),+                                   end(tags),+                                   [] (std::string const& tag) {return tag.front() == '#'; });+            if (it != tags.end())+                return it->substr(1);+            return std::string();+        }++        // Formats the duration in seconds to 3 decimal places.+        // This is done because some genius defined Maven Surefire schema+        // in a way that only accepts 3 decimal places, and tools like+        // Jenkins use that schema for validation JUnit reporter output.+        std::string formatDuration( double seconds ) {+            ReusableStringStream rss;+            rss << std::fixed << std::setprecision( 3 ) << seconds;+            return rss.str();+        }++    } // anonymous namespace++    JunitReporter::JunitReporter( ReporterConfig const& _config )+        :   CumulativeReporterBase( _config ),+            xml( _config.stream() )+        {+            m_reporterPrefs.shouldRedirectStdOut = true;+            m_reporterPrefs.shouldReportAllAssertions = true;+        }++    JunitReporter::~JunitReporter() {}++    std::string JunitReporter::getDescription() {+        return "Reports test results in an XML format that looks like Ant's junitreport target";+    }++    void JunitReporter::noMatchingTestCases( std::string const& /*spec*/ ) {}++    void JunitReporter::testRunStarting( TestRunInfo const& runInfo )  {+        CumulativeReporterBase::testRunStarting( runInfo );+        xml.startElement( "testsuites" );+    }++    void JunitReporter::testGroupStarting( GroupInfo const& groupInfo ) {+        suiteTimer.start();+        stdOutForSuite.clear();+        stdErrForSuite.clear();+        unexpectedExceptions = 0;+        CumulativeReporterBase::testGroupStarting( groupInfo );+    }++    void JunitReporter::testCaseStarting( TestCaseInfo const& testCaseInfo ) {+        m_okToFail = testCaseInfo.okToFail();+    }++    bool JunitReporter::assertionEnded( AssertionStats const& assertionStats ) {+        if( assertionStats.assertionResult.getResultType() == ResultWas::ThrewException && !m_okToFail )+            unexpectedExceptions++;+        return CumulativeReporterBase::assertionEnded( assertionStats );+    }++    void JunitReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {+        stdOutForSuite += testCaseStats.stdOut;+        stdErrForSuite += testCaseStats.stdErr;+        CumulativeReporterBase::testCaseEnded( testCaseStats );+    }++    void JunitReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {+        double suiteTime = suiteTimer.getElapsedSeconds();+        CumulativeReporterBase::testGroupEnded( testGroupStats );+        writeGroup( *m_testGroups.back(), suiteTime );+    }++    void JunitReporter::testRunEndedCumulative() {+        xml.endElement();+    }++    void JunitReporter::writeGroup( TestGroupNode const& groupNode, double suiteTime ) {+        XmlWriter::ScopedElement e = xml.scopedElement( "testsuite" );++        TestGroupStats const& stats = groupNode.value;+        xml.writeAttribute( "name", stats.groupInfo.name );+        xml.writeAttribute( "errors", unexpectedExceptions );+        xml.writeAttribute( "failures", stats.totals.assertions.failed-unexpectedExceptions );+        xml.writeAttribute( "tests", stats.totals.assertions.total() );+        xml.writeAttribute( "hostname", "tbd" ); // !TBD+        if( m_config->showDurations() == ShowDurations::Never )+            xml.writeAttribute( "time", "" );+        else+            xml.writeAttribute( "time", formatDuration( suiteTime ) );+        xml.writeAttribute( "timestamp", getCurrentTimestamp() );++        // Write properties if there are any+        if (m_config->hasTestFilters() || m_config->rngSeed() != 0) {+            auto properties = xml.scopedElement("properties");+            if (m_config->hasTestFilters()) {+                xml.scopedElement("property")+                    .writeAttribute("name", "filters")+                    .writeAttribute("value", serializeFilters(m_config->getTestsOrTags()));+            }+            if (m_config->rngSeed() != 0) {+                xml.scopedElement("property")+                    .writeAttribute("name", "random-seed")+                    .writeAttribute("value", m_config->rngSeed());+            }+        }++        // Write test cases+        for( auto const& child : groupNode.children )+            writeTestCase( *child );++        xml.scopedElement( "system-out" ).writeText( trim( stdOutForSuite ), XmlFormatting::Newline );+        xml.scopedElement( "system-err" ).writeText( trim( stdErrForSuite ), XmlFormatting::Newline );+    }++    void JunitReporter::writeTestCase( TestCaseNode const& testCaseNode ) {+        TestCaseStats const& stats = testCaseNode.value;++        // All test cases have exactly one section - which represents the+        // test case itself. That section may have 0-n nested sections+        assert( testCaseNode.children.size() == 1 );+        SectionNode const& rootSection = *testCaseNode.children.front();++        std::string className = stats.testInfo.className;++        if( className.empty() ) {+            className = fileNameTag(stats.testInfo.tags);+            if ( className.empty() )+                className = "global";+        }++        if ( !m_config->name().empty() )+            className = m_config->name() + "." + className;++        writeSection( className, "", rootSection, stats.testInfo.okToFail() );+    }++    void JunitReporter::writeSection( std::string const& className,+                                      std::string const& rootName,+                                      SectionNode const& sectionNode,+                                      bool testOkToFail) {+        std::string name = trim( sectionNode.stats.sectionInfo.name );+        if( !rootName.empty() )+            name = rootName + '/' + name;++        if( !sectionNode.assertions.empty() ||+            !sectionNode.stdOut.empty() ||+            !sectionNode.stdErr.empty() ) {+            XmlWriter::ScopedElement e = xml.scopedElement( "testcase" );+            if( className.empty() ) {+                xml.writeAttribute( "classname", name );+                xml.writeAttribute( "name", "root" );+            }+            else {+                xml.writeAttribute( "classname", className );+                xml.writeAttribute( "name", name );+            }+            xml.writeAttribute( "time", formatDuration( sectionNode.stats.durationInSeconds ) );+            // This is not ideal, but it should be enough to mimic gtest's+            // junit output.+            // Ideally the JUnit reporter would also handle `skipTest`+            // events and write those out appropriately.+            xml.writeAttribute( "status", "run" );++            if (sectionNode.stats.assertions.failedButOk) {+                xml.scopedElement("skipped")+                    .writeAttribute("message", "TEST_CASE tagged with !mayfail");+            }++            writeAssertions( sectionNode );++            if( !sectionNode.stdOut.empty() )+                xml.scopedElement( "system-out" ).writeText( trim( sectionNode.stdOut ), XmlFormatting::Newline );+            if( !sectionNode.stdErr.empty() )+                xml.scopedElement( "system-err" ).writeText( trim( sectionNode.stdErr ), XmlFormatting::Newline );+        }+        for( auto const& childNode : sectionNode.childSections )+            if( className.empty() )+                writeSection( name, "", *childNode, testOkToFail );+            else+                writeSection( className, name, *childNode, testOkToFail );+    }++    void JunitReporter::writeAssertions( SectionNode const& sectionNode ) {+        for( auto const& assertion : sectionNode.assertions )+            writeAssertion( assertion );+    }++    void JunitReporter::writeAssertion( AssertionStats const& stats ) {+        AssertionResult const& result = stats.assertionResult;+        if( !result.isOk() ) {+            std::string elementName;+            switch( result.getResultType() ) {+                case ResultWas::ThrewException:+                case ResultWas::FatalErrorCondition:+                    elementName = "error";+                    break;+                case ResultWas::ExplicitFailure:+                case ResultWas::ExpressionFailed:+                case ResultWas::DidntThrowException:+                    elementName = "failure";+                    break;++                // We should never see these here:+                case ResultWas::Info:+                case ResultWas::Warning:+                case ResultWas::Ok:+                case ResultWas::Unknown:+                case ResultWas::FailureBit:+                case ResultWas::Exception:+                    elementName = "internalError";+                    break;+            }++            XmlWriter::ScopedElement e = xml.scopedElement( elementName );++            xml.writeAttribute( "message", result.getExpression() );+            xml.writeAttribute( "type", result.getTestMacroName() );++            ReusableStringStream rss;+            if (stats.totals.assertions.total() > 0) {+                rss << "FAILED" << ":\n";+                if (result.hasExpression()) {+                    rss << "  ";+                    rss << result.getExpressionInMacro();+                    rss << '\n';+                }+                if (result.hasExpandedExpression()) {+                    rss << "with expansion:\n";+                    rss << Column(result.getExpandedExpression()).indent(2) << '\n';+                }+            } else {+                rss << '\n';+            }++            if( !result.getMessage().empty() )+                rss << result.getMessage() << '\n';+            for( auto const& msg : stats.infoMessages )+                if( msg.type == ResultWas::Info )+                    rss << msg.message << '\n';++            rss << "at " << result.getSourceInfo();+            xml.writeText( rss.str(), XmlFormatting::Newline );+        }+    }++    CATCH_REGISTER_REPORTER( "junit", JunitReporter )++} // end namespace Catch+// end catch_reporter_junit.cpp+// start catch_reporter_listening.cpp++#include <cassert>++namespace Catch {++    ListeningReporter::ListeningReporter() {+        // We will assume that listeners will always want all assertions+        m_preferences.shouldReportAllAssertions = true;+    }++    void ListeningReporter::addListener( IStreamingReporterPtr&& listener ) {+        m_listeners.push_back( std::move( listener ) );+    }++    void ListeningReporter::addReporter(IStreamingReporterPtr&& reporter) {+        assert(!m_reporter && "Listening reporter can wrap only 1 real reporter");+        m_reporter = std::move( reporter );+        m_preferences.shouldRedirectStdOut = m_reporter->getPreferences().shouldRedirectStdOut;+    }++    ReporterPreferences ListeningReporter::getPreferences() const {+        return m_preferences;+    }++    std::set<Verbosity> ListeningReporter::getSupportedVerbosities() {+        return std::set<Verbosity>{ };+    }++    void ListeningReporter::noMatchingTestCases( std::string const& spec ) {+        for ( auto const& listener : m_listeners ) {+            listener->noMatchingTestCases( spec );+        }+        m_reporter->noMatchingTestCases( spec );+    }++    void ListeningReporter::reportInvalidArguments(std::string const&arg){+        for ( auto const& listener : m_listeners ) {+            listener->reportInvalidArguments( arg );+        }+        m_reporter->reportInvalidArguments( arg );+    }++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+    void ListeningReporter::benchmarkPreparing( std::string const& name ) {+		for (auto const& listener : m_listeners) {+			listener->benchmarkPreparing(name);+		}+		m_reporter->benchmarkPreparing(name);+	}+    void ListeningReporter::benchmarkStarting( BenchmarkInfo const& benchmarkInfo ) {+        for ( auto const& listener : m_listeners ) {+            listener->benchmarkStarting( benchmarkInfo );+        }+        m_reporter->benchmarkStarting( benchmarkInfo );+    }+    void ListeningReporter::benchmarkEnded( BenchmarkStats<> const& benchmarkStats ) {+        for ( auto const& listener : m_listeners ) {+            listener->benchmarkEnded( benchmarkStats );+        }+        m_reporter->benchmarkEnded( benchmarkStats );+    }++	void ListeningReporter::benchmarkFailed( std::string const& error ) {+		for (auto const& listener : m_listeners) {+			listener->benchmarkFailed(error);+		}+		m_reporter->benchmarkFailed(error);+	}+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++    void ListeningReporter::testRunStarting( TestRunInfo const& testRunInfo ) {+        for ( auto const& listener : m_listeners ) {+            listener->testRunStarting( testRunInfo );+        }+        m_reporter->testRunStarting( testRunInfo );+    }++    void ListeningReporter::testGroupStarting( GroupInfo const& groupInfo ) {+        for ( auto const& listener : m_listeners ) {+            listener->testGroupStarting( groupInfo );+        }+        m_reporter->testGroupStarting( groupInfo );+    }++    void ListeningReporter::testCaseStarting( TestCaseInfo const& testInfo ) {+        for ( auto const& listener : m_listeners ) {+            listener->testCaseStarting( testInfo );+        }+        m_reporter->testCaseStarting( testInfo );+    }++    void ListeningReporter::sectionStarting( SectionInfo const& sectionInfo ) {+        for ( auto const& listener : m_listeners ) {+            listener->sectionStarting( sectionInfo );+        }+        m_reporter->sectionStarting( sectionInfo );+    }++    void ListeningReporter::assertionStarting( AssertionInfo const& assertionInfo ) {+        for ( auto const& listener : m_listeners ) {+            listener->assertionStarting( assertionInfo );+        }+        m_reporter->assertionStarting( assertionInfo );+    }++    // The return value indicates if the messages buffer should be cleared:+    bool ListeningReporter::assertionEnded( AssertionStats const& assertionStats ) {+        for( auto const& listener : m_listeners ) {+            static_cast<void>( listener->assertionEnded( assertionStats ) );+        }+        return m_reporter->assertionEnded( assertionStats );+    }++    void ListeningReporter::sectionEnded( SectionStats const& sectionStats ) {+        for ( auto const& listener : m_listeners ) {+            listener->sectionEnded( sectionStats );+        }+        m_reporter->sectionEnded( sectionStats );+    }++    void ListeningReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {+        for ( auto const& listener : m_listeners ) {+            listener->testCaseEnded( testCaseStats );+        }+        m_reporter->testCaseEnded( testCaseStats );+    }++    void ListeningReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {+        for ( auto const& listener : m_listeners ) {+            listener->testGroupEnded( testGroupStats );+        }+        m_reporter->testGroupEnded( testGroupStats );+    }++    void ListeningReporter::testRunEnded( TestRunStats const& testRunStats ) {+        for ( auto const& listener : m_listeners ) {+            listener->testRunEnded( testRunStats );+        }+        m_reporter->testRunEnded( testRunStats );+    }++    void ListeningReporter::skipTest( TestCaseInfo const& testInfo ) {+        for ( auto const& listener : m_listeners ) {+            listener->skipTest( testInfo );+        }+        m_reporter->skipTest( testInfo );+    }++    bool ListeningReporter::isMulti() const {+        return true;+    }++} // end namespace Catch+// end catch_reporter_listening.cpp+// start catch_reporter_xml.cpp++#if defined(_MSC_VER)+#pragma warning(push)+#pragma warning(disable:4061) // Not all labels are EXPLICITLY handled in switch+                              // Note that 4062 (not all labels are handled+                              // and default is missing) is enabled+#endif++namespace Catch {+    XmlReporter::XmlReporter( ReporterConfig const& _config )+    :   StreamingReporterBase( _config ),+        m_xml(_config.stream())+    {+        m_reporterPrefs.shouldRedirectStdOut = true;+        m_reporterPrefs.shouldReportAllAssertions = true;+    }++    XmlReporter::~XmlReporter() = default;++    std::string XmlReporter::getDescription() {+        return "Reports test results as an XML document";+    }++    std::string XmlReporter::getStylesheetRef() const {+        return std::string();+    }++    void XmlReporter::writeSourceInfo( SourceLineInfo const& sourceInfo ) {+        m_xml+            .writeAttribute( "filename", sourceInfo.file )+            .writeAttribute( "line", sourceInfo.line );+    }++    void XmlReporter::noMatchingTestCases( std::string const& s ) {+        StreamingReporterBase::noMatchingTestCases( s );+    }++    void XmlReporter::testRunStarting( TestRunInfo const& testInfo ) {+        StreamingReporterBase::testRunStarting( testInfo );+        std::string stylesheetRef = getStylesheetRef();+        if( !stylesheetRef.empty() )+            m_xml.writeStylesheetRef( stylesheetRef );+        m_xml.startElement( "Catch" );+        if( !m_config->name().empty() )+            m_xml.writeAttribute( "name", m_config->name() );+        if (m_config->testSpec().hasFilters())+            m_xml.writeAttribute( "filters", serializeFilters( m_config->getTestsOrTags() ) );+        if( m_config->rngSeed() != 0 )+            m_xml.scopedElement( "Randomness" )+                .writeAttribute( "seed", m_config->rngSeed() );+    }++    void XmlReporter::testGroupStarting( GroupInfo const& groupInfo ) {+        StreamingReporterBase::testGroupStarting( groupInfo );+        m_xml.startElement( "Group" )+            .writeAttribute( "name", groupInfo.name );+    }++    void XmlReporter::testCaseStarting( TestCaseInfo const& testInfo ) {+        StreamingReporterBase::testCaseStarting(testInfo);+        m_xml.startElement( "TestCase" )+            .writeAttribute( "name", trim( testInfo.name ) )+            .writeAttribute( "description", testInfo.description )+            .writeAttribute( "tags", testInfo.tagsAsString() );++        writeSourceInfo( testInfo.lineInfo );++        if ( m_config->showDurations() == ShowDurations::Always )+            m_testCaseTimer.start();+        m_xml.ensureTagClosed();+    }++    void XmlReporter::sectionStarting( SectionInfo const& sectionInfo ) {+        StreamingReporterBase::sectionStarting( sectionInfo );+        if( m_sectionDepth++ > 0 ) {+            m_xml.startElement( "Section" )+                .writeAttribute( "name", trim( sectionInfo.name ) );+            writeSourceInfo( sectionInfo.lineInfo );+            m_xml.ensureTagClosed();+        }+    }++    void XmlReporter::assertionStarting( AssertionInfo const& ) { }++    bool XmlReporter::assertionEnded( AssertionStats const& assertionStats ) {++        AssertionResult const& result = assertionStats.assertionResult;++        bool includeResults = m_config->includeSuccessfulResults() || !result.isOk();++        if( includeResults || result.getResultType() == ResultWas::Warning ) {+            // Print any info messages in <Info> tags.+            for( auto const& msg : assertionStats.infoMessages ) {+                if( msg.type == ResultWas::Info && includeResults ) {+                    m_xml.scopedElement( "Info" )+                            .writeText( msg.message );+                } else if ( msg.type == ResultWas::Warning ) {+                    m_xml.scopedElement( "Warning" )+                            .writeText( msg.message );+                }+            }+        }++        // Drop out if result was successful but we're not printing them.+        if( !includeResults && result.getResultType() != ResultWas::Warning )+            return true;++        // Print the expression if there is one.+        if( result.hasExpression() ) {+            m_xml.startElement( "Expression" )+                .writeAttribute( "success", result.succeeded() )+                .writeAttribute( "type", result.getTestMacroName() );++            writeSourceInfo( result.getSourceInfo() );++            m_xml.scopedElement( "Original" )+                .writeText( result.getExpression() );+            m_xml.scopedElement( "Expanded" )+                .writeText( result.getExpandedExpression() );+        }++        // And... Print a result applicable to each result type.+        switch( result.getResultType() ) {+            case ResultWas::ThrewException:+                m_xml.startElement( "Exception" );+                writeSourceInfo( result.getSourceInfo() );+                m_xml.writeText( result.getMessage() );+                m_xml.endElement();+                break;+            case ResultWas::FatalErrorCondition:+                m_xml.startElement( "FatalErrorCondition" );+                writeSourceInfo( result.getSourceInfo() );+                m_xml.writeText( result.getMessage() );+                m_xml.endElement();+                break;+            case ResultWas::Info:+                m_xml.scopedElement( "Info" )+                    .writeText( result.getMessage() );+                break;+            case ResultWas::Warning:+                // Warning will already have been written+                break;+            case ResultWas::ExplicitFailure:+                m_xml.startElement( "Failure" );+                writeSourceInfo( result.getSourceInfo() );+                m_xml.writeText( result.getMessage() );+                m_xml.endElement();+                break;+            default:+                break;+        }++        if( result.hasExpression() )+            m_xml.endElement();++        return true;+    }++    void XmlReporter::sectionEnded( SectionStats const& sectionStats ) {+        StreamingReporterBase::sectionEnded( sectionStats );+        if( --m_sectionDepth > 0 ) {+            XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResults" );+            e.writeAttribute( "successes", sectionStats.assertions.passed );+            e.writeAttribute( "failures", sectionStats.assertions.failed );+            e.writeAttribute( "expectedFailures", sectionStats.assertions.failedButOk );++            if ( m_config->showDurations() == ShowDurations::Always )+                e.writeAttribute( "durationInSeconds", sectionStats.durationInSeconds );++            m_xml.endElement();+        }+    }++    void XmlReporter::testCaseEnded( TestCaseStats const& testCaseStats ) {+        StreamingReporterBase::testCaseEnded( testCaseStats );+        XmlWriter::ScopedElement e = m_xml.scopedElement( "OverallResult" );+        e.writeAttribute( "success", testCaseStats.totals.assertions.allOk() );++        if ( m_config->showDurations() == ShowDurations::Always )+            e.writeAttribute( "durationInSeconds", m_testCaseTimer.getElapsedSeconds() );++        if( !testCaseStats.stdOut.empty() )+            m_xml.scopedElement( "StdOut" ).writeText( trim( testCaseStats.stdOut ), XmlFormatting::Newline );+        if( !testCaseStats.stdErr.empty() )+            m_xml.scopedElement( "StdErr" ).writeText( trim( testCaseStats.stdErr ), XmlFormatting::Newline );++        m_xml.endElement();+    }++    void XmlReporter::testGroupEnded( TestGroupStats const& testGroupStats ) {+        StreamingReporterBase::testGroupEnded( testGroupStats );+        // TODO: Check testGroupStats.aborting and act accordingly.+        m_xml.scopedElement( "OverallResults" )+            .writeAttribute( "successes", testGroupStats.totals.assertions.passed )+            .writeAttribute( "failures", testGroupStats.totals.assertions.failed )+            .writeAttribute( "expectedFailures", testGroupStats.totals.assertions.failedButOk );+        m_xml.scopedElement( "OverallResultsCases")+            .writeAttribute( "successes", testGroupStats.totals.testCases.passed )+            .writeAttribute( "failures", testGroupStats.totals.testCases.failed )+            .writeAttribute( "expectedFailures", testGroupStats.totals.testCases.failedButOk );+        m_xml.endElement();+    }++    void XmlReporter::testRunEnded( TestRunStats const& testRunStats ) {+        StreamingReporterBase::testRunEnded( testRunStats );+        m_xml.scopedElement( "OverallResults" )+            .writeAttribute( "successes", testRunStats.totals.assertions.passed )+            .writeAttribute( "failures", testRunStats.totals.assertions.failed )+            .writeAttribute( "expectedFailures", testRunStats.totals.assertions.failedButOk );+        m_xml.scopedElement( "OverallResultsCases")+            .writeAttribute( "successes", testRunStats.totals.testCases.passed )+            .writeAttribute( "failures", testRunStats.totals.testCases.failed )+            .writeAttribute( "expectedFailures", testRunStats.totals.testCases.failedButOk );+        m_xml.endElement();+    }++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+    void XmlReporter::benchmarkPreparing(std::string const& name) {+        m_xml.startElement("BenchmarkResults")+            .writeAttribute("name", name);+    }++    void XmlReporter::benchmarkStarting(BenchmarkInfo const &info) {+        m_xml.writeAttribute("samples", info.samples)+            .writeAttribute("resamples", info.resamples)+            .writeAttribute("iterations", info.iterations)+            .writeAttribute("clockResolution", info.clockResolution)+            .writeAttribute("estimatedDuration", info.estimatedDuration)+            .writeComment("All values in nano seconds");+    }++    void XmlReporter::benchmarkEnded(BenchmarkStats<> const& benchmarkStats) {+        m_xml.startElement("mean")+            .writeAttribute("value", benchmarkStats.mean.point.count())+            .writeAttribute("lowerBound", benchmarkStats.mean.lower_bound.count())+            .writeAttribute("upperBound", benchmarkStats.mean.upper_bound.count())+            .writeAttribute("ci", benchmarkStats.mean.confidence_interval);+        m_xml.endElement();+        m_xml.startElement("standardDeviation")+            .writeAttribute("value", benchmarkStats.standardDeviation.point.count())+            .writeAttribute("lowerBound", benchmarkStats.standardDeviation.lower_bound.count())+            .writeAttribute("upperBound", benchmarkStats.standardDeviation.upper_bound.count())+            .writeAttribute("ci", benchmarkStats.standardDeviation.confidence_interval);+        m_xml.endElement();+        m_xml.startElement("outliers")+            .writeAttribute("variance", benchmarkStats.outlierVariance)+            .writeAttribute("lowMild", benchmarkStats.outliers.low_mild)+            .writeAttribute("lowSevere", benchmarkStats.outliers.low_severe)+            .writeAttribute("highMild", benchmarkStats.outliers.high_mild)+            .writeAttribute("highSevere", benchmarkStats.outliers.high_severe);+        m_xml.endElement();+        m_xml.endElement();+    }++    void XmlReporter::benchmarkFailed(std::string const &error) {+        m_xml.scopedElement("failed").+            writeAttribute("message", error);+        m_xml.endElement();+    }+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++    CATCH_REGISTER_REPORTER( "xml", XmlReporter )++} // end namespace Catch++#if defined(_MSC_VER)+#pragma warning(pop)+#endif+// end catch_reporter_xml.cpp++namespace Catch {+    LeakDetector leakDetector;+}++#ifdef __clang__+#pragma clang diagnostic pop+#endif++// end catch_impl.hpp+#endif++#ifdef CATCH_CONFIG_MAIN+// start catch_default_main.hpp++#ifndef __OBJC__++#if defined(CATCH_CONFIG_WCHAR) && defined(CATCH_PLATFORM_WINDOWS) && defined(_UNICODE) && !defined(DO_NOT_USE_WMAIN)+// Standard C/C++ Win32 Unicode wmain entry point+extern "C" int wmain (int argc, wchar_t * argv[], wchar_t * []) {+#else+// Standard C/C++ main entry point+int main (int argc, char * argv[]) {+#endif++    return Catch::Session().run( argc, argv );+}++#else // __OBJC__++// Objective-C entry point+int main (int argc, char * const argv[]) {+#if !CATCH_ARC_ENABLED+    NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];+#endif++    Catch::registerTestMethods();+    int result = Catch::Session().run( argc, (char**)argv );++#if !CATCH_ARC_ENABLED+    [pool drain];+#endif++    return result;+}++#endif // __OBJC__++// end catch_default_main.hpp+#endif++#if !defined(CATCH_CONFIG_IMPL_ONLY)++#ifdef CLARA_CONFIG_MAIN_NOT_DEFINED+#  undef CLARA_CONFIG_MAIN+#endif++#if !defined(CATCH_CONFIG_DISABLE)+//////+// If this config identifier is defined then all CATCH macros are prefixed with CATCH_+#ifdef CATCH_CONFIG_PREFIX_ALL++#define CATCH_REQUIRE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__ )+#define CATCH_REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )++#define CATCH_REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "CATCH_REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )+#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )+#define CATCH_REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )+#endif// CATCH_CONFIG_DISABLE_MATCHERS+#define CATCH_REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )++#define CATCH_CHECK( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define CATCH_CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )+#define CATCH_CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CATCH_CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define CATCH_CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CATCH_CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define CATCH_CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CATCH_CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )++#define CATCH_CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CATCH_CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CATCH_CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )+#define CATCH_CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CATCH_CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CATCH_CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )+#endif // CATCH_CONFIG_DISABLE_MATCHERS+#define CATCH_CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CATCH_CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )++#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CATCH_CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )++#define CATCH_REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CATCH_REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )+#endif // CATCH_CONFIG_DISABLE_MATCHERS++#define CATCH_INFO( msg ) INTERNAL_CATCH_INFO( "CATCH_INFO", msg )+#define CATCH_UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "CATCH_UNSCOPED_INFO", msg )+#define CATCH_WARN( msg ) INTERNAL_CATCH_MSG( "CATCH_WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )+#define CATCH_CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CATCH_CAPTURE",__VA_ARGS__ )++#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )+#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define CATCH_METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )+#define CATCH_REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )+#define CATCH_SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )+#define CATCH_DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )+#define CATCH_FAIL( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )+#define CATCH_FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "CATCH_FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define CATCH_SUCCEED( ... ) INTERNAL_CATCH_MSG( "CATCH_SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )++#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )+#else+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )+#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )+#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )+#endif++#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)+#define CATCH_STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__ ,      #__VA_ARGS__ );     CATCH_SUCCEED( #__VA_ARGS__ )+#define CATCH_STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); CATCH_SUCCEED( #__VA_ARGS__ )+#else+#define CATCH_STATIC_REQUIRE( ... )       CATCH_REQUIRE( __VA_ARGS__ )+#define CATCH_STATIC_REQUIRE_FALSE( ... ) CATCH_REQUIRE_FALSE( __VA_ARGS__ )+#endif++// "BDD-style" convenience wrappers+#define CATCH_SCENARIO( ... ) CATCH_TEST_CASE( "Scenario: " __VA_ARGS__ )+#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )+#define CATCH_GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )+#define CATCH_AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )+#define CATCH_WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )+#define CATCH_AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )+#define CATCH_THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )+#define CATCH_AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+#define CATCH_BENCHMARK(...) \+    INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))+#define CATCH_BENCHMARK_ADVANCED(name) \+    INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name)+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required+#else++#define REQUIRE( ... ) INTERNAL_CATCH_TEST( "REQUIRE", Catch::ResultDisposition::Normal, __VA_ARGS__  )+#define REQUIRE_FALSE( ... ) INTERNAL_CATCH_TEST( "REQUIRE_FALSE", Catch::ResultDisposition::Normal | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )++#define REQUIRE_THROWS( ... ) INTERNAL_CATCH_THROWS( "REQUIRE_THROWS", Catch::ResultDisposition::Normal, __VA_ARGS__ )+#define REQUIRE_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "REQUIRE_THROWS_AS", exceptionType, Catch::ResultDisposition::Normal, expr )+#define REQUIRE_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "REQUIRE_THROWS_WITH", Catch::ResultDisposition::Normal, matcher, expr )+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "REQUIRE_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::Normal, matcher, expr )+#endif // CATCH_CONFIG_DISABLE_MATCHERS+#define REQUIRE_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "REQUIRE_NOTHROW", Catch::ResultDisposition::Normal, __VA_ARGS__ )++#define CHECK( ... ) INTERNAL_CATCH_TEST( "CHECK", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define CHECK_FALSE( ... ) INTERNAL_CATCH_TEST( "CHECK_FALSE", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::FalseTest, __VA_ARGS__ )+#define CHECKED_IF( ... ) INTERNAL_CATCH_IF( "CHECKED_IF", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define CHECKED_ELSE( ... ) INTERNAL_CATCH_ELSE( "CHECKED_ELSE", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define CHECK_NOFAIL( ... ) INTERNAL_CATCH_TEST( "CHECK_NOFAIL", Catch::ResultDisposition::ContinueOnFailure | Catch::ResultDisposition::SuppressFail, __VA_ARGS__ )++#define CHECK_THROWS( ... )  INTERNAL_CATCH_THROWS( "CHECK_THROWS", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define CHECK_THROWS_AS( expr, exceptionType ) INTERNAL_CATCH_THROWS_AS( "CHECK_THROWS_AS", exceptionType, Catch::ResultDisposition::ContinueOnFailure, expr )+#define CHECK_THROWS_WITH( expr, matcher ) INTERNAL_CATCH_THROWS_STR_MATCHES( "CHECK_THROWS_WITH", Catch::ResultDisposition::ContinueOnFailure, matcher, expr )+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) INTERNAL_CATCH_THROWS_MATCHES( "CHECK_THROWS_MATCHES", exceptionType, Catch::ResultDisposition::ContinueOnFailure, matcher, expr )+#endif // CATCH_CONFIG_DISABLE_MATCHERS+#define CHECK_NOTHROW( ... ) INTERNAL_CATCH_NO_THROW( "CHECK_NOTHROW", Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )++#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CHECK_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "CHECK_THAT", matcher, Catch::ResultDisposition::ContinueOnFailure, arg )++#define REQUIRE_THAT( arg, matcher ) INTERNAL_CHECK_THAT( "REQUIRE_THAT", matcher, Catch::ResultDisposition::Normal, arg )+#endif // CATCH_CONFIG_DISABLE_MATCHERS++#define INFO( msg ) INTERNAL_CATCH_INFO( "INFO", msg )+#define UNSCOPED_INFO( msg ) INTERNAL_CATCH_UNSCOPED_INFO( "UNSCOPED_INFO", msg )+#define WARN( msg ) INTERNAL_CATCH_MSG( "WARN", Catch::ResultWas::Warning, Catch::ResultDisposition::ContinueOnFailure, msg )+#define CAPTURE( ... ) INTERNAL_CATCH_CAPTURE( INTERNAL_CATCH_UNIQUE_NAME(capturer), "CAPTURE",__VA_ARGS__ )++#define TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE( __VA_ARGS__ )+#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define METHOD_AS_TEST_CASE( method, ... ) INTERNAL_CATCH_METHOD_AS_TEST_CASE( method, __VA_ARGS__ )+#define REGISTER_TEST_CASE( Function, ... ) INTERNAL_CATCH_REGISTER_TESTCASE( Function, __VA_ARGS__ )+#define SECTION( ... ) INTERNAL_CATCH_SECTION( __VA_ARGS__ )+#define DYNAMIC_SECTION( ... ) INTERNAL_CATCH_DYNAMIC_SECTION( __VA_ARGS__ )+#define FAIL( ... ) INTERNAL_CATCH_MSG( "FAIL", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::Normal, __VA_ARGS__ )+#define FAIL_CHECK( ... ) INTERNAL_CATCH_MSG( "FAIL_CHECK", Catch::ResultWas::ExplicitFailure, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define SUCCEED( ... ) INTERNAL_CATCH_MSG( "SUCCEED", Catch::ResultWas::Ok, Catch::ResultDisposition::ContinueOnFailure, __VA_ARGS__ )+#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE()++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ )+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ )+#define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE(__VA_ARGS__)+#define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ )+#else+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ ) )+#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG( __VA_ARGS__ ) )+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ ) )+#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE( __VA_ARGS__ ) )+#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( __VA_ARGS__ ) )+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, __VA_ARGS__ ) )+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, __VA_ARGS__ ) )+#define TEMPLATE_LIST_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE( __VA_ARGS__ ) )+#define TEMPLATE_LIST_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_LIST_TEST_CASE_METHOD( className, __VA_ARGS__ ) )+#endif++#if !defined(CATCH_CONFIG_RUNTIME_STATIC_REQUIRE)+#define STATIC_REQUIRE( ... )       static_assert(   __VA_ARGS__,  #__VA_ARGS__ ); SUCCEED( #__VA_ARGS__ )+#define STATIC_REQUIRE_FALSE( ... ) static_assert( !(__VA_ARGS__), "!(" #__VA_ARGS__ ")" ); SUCCEED( "!(" #__VA_ARGS__ ")" )+#else+#define STATIC_REQUIRE( ... )       REQUIRE( __VA_ARGS__ )+#define STATIC_REQUIRE_FALSE( ... ) REQUIRE_FALSE( __VA_ARGS__ )+#endif++#endif++#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION( signature )++// "BDD-style" convenience wrappers+#define SCENARIO( ... ) TEST_CASE( "Scenario: " __VA_ARGS__ )+#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TEST_CASE_METHOD( className, "Scenario: " __VA_ARGS__ )++#define GIVEN( desc )     INTERNAL_CATCH_DYNAMIC_SECTION( "    Given: " << desc )+#define AND_GIVEN( desc ) INTERNAL_CATCH_DYNAMIC_SECTION( "And given: " << desc )+#define WHEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     When: " << desc )+#define AND_WHEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( " And when: " << desc )+#define THEN( desc )      INTERNAL_CATCH_DYNAMIC_SECTION( "     Then: " << desc )+#define AND_THEN( desc )  INTERNAL_CATCH_DYNAMIC_SECTION( "      And: " << desc )++#if defined(CATCH_CONFIG_ENABLE_BENCHMARKING)+#define BENCHMARK(...) \+    INTERNAL_CATCH_BENCHMARK(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), INTERNAL_CATCH_GET_1_ARG(__VA_ARGS__,,), INTERNAL_CATCH_GET_2_ARG(__VA_ARGS__,,))+#define BENCHMARK_ADVANCED(name) \+    INTERNAL_CATCH_BENCHMARK_ADVANCED(INTERNAL_CATCH_UNIQUE_NAME(____C_A_T_C_H____B_E_N_C_H____), name)+#endif // CATCH_CONFIG_ENABLE_BENCHMARKING++using Catch::Detail::Approx;++#else // CATCH_CONFIG_DISABLE++//////+// If this config identifier is defined then all CATCH macros are prefixed with CATCH_+#ifdef CATCH_CONFIG_PREFIX_ALL++#define CATCH_REQUIRE( ... )        (void)(0)+#define CATCH_REQUIRE_FALSE( ... )  (void)(0)++#define CATCH_REQUIRE_THROWS( ... ) (void)(0)+#define CATCH_REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)+#define CATCH_REQUIRE_THROWS_WITH( expr, matcher )     (void)(0)+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CATCH_REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)+#endif// CATCH_CONFIG_DISABLE_MATCHERS+#define CATCH_REQUIRE_NOTHROW( ... ) (void)(0)++#define CATCH_CHECK( ... )         (void)(0)+#define CATCH_CHECK_FALSE( ... )   (void)(0)+#define CATCH_CHECKED_IF( ... )    if (__VA_ARGS__)+#define CATCH_CHECKED_ELSE( ... )  if (!(__VA_ARGS__))+#define CATCH_CHECK_NOFAIL( ... )  (void)(0)++#define CATCH_CHECK_THROWS( ... )  (void)(0)+#define CATCH_CHECK_THROWS_AS( expr, exceptionType ) (void)(0)+#define CATCH_CHECK_THROWS_WITH( expr, matcher )     (void)(0)+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CATCH_CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)+#endif // CATCH_CONFIG_DISABLE_MATCHERS+#define CATCH_CHECK_NOTHROW( ... ) (void)(0)++#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CATCH_CHECK_THAT( arg, matcher )   (void)(0)++#define CATCH_REQUIRE_THAT( arg, matcher ) (void)(0)+#endif // CATCH_CONFIG_DISABLE_MATCHERS++#define CATCH_INFO( msg )          (void)(0)+#define CATCH_UNSCOPED_INFO( msg ) (void)(0)+#define CATCH_WARN( msg )          (void)(0)+#define CATCH_CAPTURE( msg )       (void)(0)++#define CATCH_TEST_CASE( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))+#define CATCH_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))+#define CATCH_METHOD_AS_TEST_CASE( method, ... )+#define CATCH_REGISTER_TEST_CASE( Function, ... ) (void)(0)+#define CATCH_SECTION( ... )+#define CATCH_DYNAMIC_SECTION( ... )+#define CATCH_FAIL( ... ) (void)(0)+#define CATCH_FAIL_CHECK( ... ) (void)(0)+#define CATCH_SUCCEED( ... ) (void)(0)++#define CATCH_ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)+#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)+#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#else+#define CATCH_TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )+#define CATCH_TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )+#define CATCH_TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )+#define CATCH_TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) CATCH_TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define CATCH_TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) CATCH_TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#endif++// "BDD-style" convenience wrappers+#define CATCH_SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))+#define CATCH_SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )+#define CATCH_GIVEN( desc )+#define CATCH_AND_GIVEN( desc )+#define CATCH_WHEN( desc )+#define CATCH_AND_WHEN( desc )+#define CATCH_THEN( desc )+#define CATCH_AND_THEN( desc )++#define CATCH_STATIC_REQUIRE( ... )       (void)(0)+#define CATCH_STATIC_REQUIRE_FALSE( ... ) (void)(0)++// If CATCH_CONFIG_PREFIX_ALL is not defined then the CATCH_ prefix is not required+#else++#define REQUIRE( ... )       (void)(0)+#define REQUIRE_FALSE( ... ) (void)(0)++#define REQUIRE_THROWS( ... ) (void)(0)+#define REQUIRE_THROWS_AS( expr, exceptionType ) (void)(0)+#define REQUIRE_THROWS_WITH( expr, matcher ) (void)(0)+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define REQUIRE_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)+#endif // CATCH_CONFIG_DISABLE_MATCHERS+#define REQUIRE_NOTHROW( ... ) (void)(0)++#define CHECK( ... ) (void)(0)+#define CHECK_FALSE( ... ) (void)(0)+#define CHECKED_IF( ... ) if (__VA_ARGS__)+#define CHECKED_ELSE( ... ) if (!(__VA_ARGS__))+#define CHECK_NOFAIL( ... ) (void)(0)++#define CHECK_THROWS( ... )  (void)(0)+#define CHECK_THROWS_AS( expr, exceptionType ) (void)(0)+#define CHECK_THROWS_WITH( expr, matcher ) (void)(0)+#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CHECK_THROWS_MATCHES( expr, exceptionType, matcher ) (void)(0)+#endif // CATCH_CONFIG_DISABLE_MATCHERS+#define CHECK_NOTHROW( ... ) (void)(0)++#if !defined(CATCH_CONFIG_DISABLE_MATCHERS)+#define CHECK_THAT( arg, matcher ) (void)(0)++#define REQUIRE_THAT( arg, matcher ) (void)(0)+#endif // CATCH_CONFIG_DISABLE_MATCHERS++#define INFO( msg ) (void)(0)+#define UNSCOPED_INFO( msg ) (void)(0)+#define WARN( msg ) (void)(0)+#define CAPTURE( msg ) (void)(0)++#define TEST_CASE( ... )  INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))+#define TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))+#define METHOD_AS_TEST_CASE( method, ... )+#define REGISTER_TEST_CASE( Function, ... ) (void)(0)+#define SECTION( ... )+#define DYNAMIC_SECTION( ... )+#define FAIL( ... ) (void)(0)+#define FAIL_CHECK( ... ) (void)(0)+#define SUCCEED( ... ) (void)(0)+#define ANON_TEST_CASE() INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ))++#ifndef CATCH_CONFIG_TRADITIONAL_MSVC_PREPROCESSOR+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__)+#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__)+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__)+#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#else+#define TEMPLATE_TEST_CASE( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_NO_REGISTRATION(__VA_ARGS__) )+#define TEMPLATE_TEST_CASE_SIG( ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_SIG_NO_REGISTRATION(__VA_ARGS__) )+#define TEMPLATE_TEST_CASE_METHOD( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_NO_REGISTRATION(className, __VA_ARGS__ ) )+#define TEMPLATE_TEST_CASE_METHOD_SIG( className, ... ) INTERNAL_CATCH_EXPAND_VARGS( INTERNAL_CATCH_TEMPLATE_TEST_CASE_METHOD_SIG_NO_REGISTRATION(className, __VA_ARGS__ ) )+#define TEMPLATE_PRODUCT_TEST_CASE( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE_SIG( ... ) TEMPLATE_TEST_CASE( __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#define TEMPLATE_PRODUCT_TEST_CASE_METHOD_SIG( className, ... ) TEMPLATE_TEST_CASE_METHOD( className, __VA_ARGS__ )+#endif++#define STATIC_REQUIRE( ... )       (void)(0)+#define STATIC_REQUIRE_FALSE( ... ) (void)(0)++#endif++#define CATCH_TRANSLATE_EXCEPTION( signature ) INTERNAL_CATCH_TRANSLATE_EXCEPTION_NO_REG( INTERNAL_CATCH_UNIQUE_NAME( catch_internal_ExceptionTranslator ), signature )++// "BDD-style" convenience wrappers+#define SCENARIO( ... ) INTERNAL_CATCH_TESTCASE_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ) )+#define SCENARIO_METHOD( className, ... ) INTERNAL_CATCH_TESTCASE_METHOD_NO_REGISTRATION(INTERNAL_CATCH_UNIQUE_NAME( ____C_A_T_C_H____T_E_S_T____ ), className )++#define GIVEN( desc )+#define AND_GIVEN( desc )+#define WHEN( desc )+#define AND_WHEN( desc )+#define THEN( desc )+#define AND_THEN( desc )++using Catch::Detail::Approx;++#endif++#endif // ! CATCH_CONFIG_IMPL_ONLY++// start catch_reenable_warnings.h+++#ifdef __clang__+#    ifdef __ICC // icpc defines the __clang__ macro+#        pragma warning(pop)+#    else+#        pragma clang diagnostic pop+#    endif+#elif defined __GNUC__+#    pragma GCC diagnostic pop+#endif++// end catch_reenable_warnings.h+// end catch.hpp+#endif // TWOBLUECUBES_SINGLE_INCLUDE_CATCH_HPP_INCLUDED+
+ src/hs/Main.hs view
@@ -0,0 +1,6 @@+module Main where++import Sound.Tidal.Link (hello)++main :: IO ()+main = hello
+ src/hs/Sound/Tidal/Link.hsc view
@@ -0,0 +1,139 @@+{-# LANGUAGE ForeignFunctionInterface #-}++module Sound.Tidal.Link where++#include "abl_link.h"++import Foreign+import Foreign.C.Types+import Data.Int()++data AbletonLinkImpl+data SessionStateImpl++newtype AbletonLink = AbletonLink (Ptr AbletonLinkImpl)+newtype SessionState = SessionState (Ptr SessionStateImpl)++instance Show AbletonLink where+  show _ = "-unshowable-"++instance Show SessionState where+  show _ = "-unshowable-"++type Beat    = CDouble+type BPM     = CDouble+type Micros  = Int64+type Quantum = CDouble++instance Storable AbletonLink where+  alignment _ = #{alignment abl_link}+  sizeOf    _ = #{size abl_link}+  peek ptr = do+    impl <- #{peek abl_link,impl} ptr+    return (AbletonLink impl)+  poke ptr (AbletonLink impl) = do+    #{poke abl_link,impl} ptr impl++instance Storable SessionState where+  alignment _ = #{alignment abl_link_session_state}+  sizeOf    _ = #{size abl_link_session_state}+  peek ptr = do+    impl <- #{peek abl_link_session_state,impl} ptr+    return (SessionState impl)+  poke ptr (SessionState impl) = do+    #{poke abl_link_session_state,impl} ptr impl++foreign import ccall "abl_link.h abl_link_create"+  create :: BPM -> IO AbletonLink++foreign import ccall "abl_link.h abl_link_enable"+  abl_link_enable :: AbletonLink -> CBool -> IO ()++setEnabled :: Bool -> AbletonLink -> IO ()+setEnabled True al = abl_link_enable al (CBool 1)+setEnabled False al = abl_link_enable al (CBool 0)++enable :: AbletonLink -> IO ()+enable = setEnabled True++disable :: AbletonLink -> IO ()+disable = setEnabled False++foreign import ccall "abl_link.h abl_link_create_session_state"+  createSessionState :: IO SessionState++foreign import ccall "abl_link.h abl_link_capture_app_session_state"+  captureAppSessionState :: AbletonLink -> SessionState -> IO ()++createAndCaptureAppSessionState :: AbletonLink -> IO SessionState+createAndCaptureAppSessionState al = do+  sessionState <- createSessionState+  captureAppSessionState al sessionState+  return sessionState++foreign import ccall "abl_link.h abl_link_commit_app_session_state"+  commitAppSessionState :: AbletonLink -> SessionState -> IO ()++foreign import ccall "abl_link.h abl_link_destroy_session_state"+  destroySessionState :: SessionState -> IO ()++commitAndDestroyAppSessionState :: AbletonLink -> SessionState -> IO ()+commitAndDestroyAppSessionState al ss = do+  commitAppSessionState al ss+  destroySessionState ss++foreign import ccall "abl_link.h abl_link_clock_micros"+  clock :: AbletonLink -> IO Micros++foreign import ccall "abl_link.h abl_link_beat_at_time"+  beatAtTime :: SessionState -> Micros -> Quantum -> IO Beat++foreign import ccall "abl_link.h abl_link_time_at_beat"+  timeAtBeat :: SessionState -> Beat -> Quantum -> IO Micros++foreign import ccall "abl_link.h abl_link_tempo"+  getTempo :: SessionState -> IO BPM++foreign import ccall "abl_link.h abl_link_set_tempo"+  setTempo :: SessionState -> BPM -> Micros -> IO ()++foreign import ccall "abl_link.h abl_link_request_beat_at_time"+  requestBeatAtTime :: SessionState -> Beat -> Micros -> Quantum -> IO ()++foreign import ccall "abl_link.h abl_link_force_beat_at_time"+  forceBeatAtTime :: SessionState -> Beat -> Micros -> Quantum -> IO ()++-- |Test+hello :: IO ()+hello = do+    print "hello"+    link <- create 88+    print "Created link"+    _ <- getLine+    print "gotline"+    now <- clock link+    print $ "Now: " ++ show now+    print "gotline"+    enable link+    print "Link enabled"+    _ <- getLine+    print "gotline"+    sessionState <- createSessionState+    print "Created sessionState"+    _ <- getLine+    print "gotline"+    captureAppSessionState link sessionState+    _line_1 <- getLine+    print "gotline"+    setTempo sessionState 130 now+    beat <- beatAtTime sessionState now 1+    print $ "beat: " ++ show beat+    _line_2 <- getLine+    print "gotline"+    now' <- clock link+    print $ "Now': " ++ show now'+    beat' <- beatAtTime sessionState now' 1+    print $ "beat': " ++ show beat'+    commitAndDestroyAppSessionState link sessionState+    _line_3 <- getLine+    print $ "done"
+ tidal-link.cabal view
@@ -0,0 +1,87 @@+cabal-version:       2.4+name:                tidal-link+version:             1.0+synopsis:            Ableton Link integration for Tidal+-- description:+homepage:            http://tidalcycles.org/+license:             GPL-3.0-only+license-file:        LICENSE+author:              Pierre Krafft+maintainer:          Pierre Krafft <kpierre@outlook.com>, Alex McLean <alex@slab.org>+Stability:           Experimental+Copyright:           (c) Pierre Krafft and contributors, 2021+category:            Sound+build-type:          Simple+tested-with:         GHC == 9.2.4++extra-source-files:+  README.md+  link/**/*.hpp+  link/**/*.ipp+  link/**/*.h++description: Ableton Link integration for Tidal, to let Tidal sync with external clocks++library+  ghc-options: -Wall+  hs-source-dirs: src/hs++  default-language:    Haskell2010++  Exposed-modules:     Sound.Tidal.Link++  Build-depends:+      base >=4.8 && <5++  if os(windows)+    if impl(ghc >= 9.4.0)+      extra-libraries:+          c+++          iphlpapi+          winmm+          ws2_32+    else+      extra-libraries:+          stdc+++          iphlpapi+          winmm+          ws2_32+    cxx-options:+      -DLINK_PLATFORM_WINDOWS=1 -Wno-multichar -Wno-subobject-linkage+    cxx-sources: link/extensions/abl_link/src/abl_link.cpp+  elif os(darwin)+    extra-libraries:+        stdc+++    cxx-options:+      -DLINK_PLATFORM_MACOSX=1 -std=c++14 -Wno-multichar -Wno-subobject-linkage+    cxx-sources: link/extensions/abl_link/src/abl_link.cpp+  else+    extra-libraries:+        stdc+++    cxx-options:+      -DLINK_PLATFORM_LINUX=1 -std=c++14 -Wno-multichar -Wno-subobject-linkage+    cxx-sources: link/extensions/abl_link/src/abl_link.cpp++  Build-depends:+      base >=4.8 && <5++  include-dirs:+    link/include+    link/modules/asio-standalone/asio/include+    link/extensions/abl_link/include++source-repository head+  type:     git+  location: https://github.com/tidalcycles/Tidal++executable linktest+  ghc-options: -Wall+  hs-source-dirs:+                 src/hs+  main-is: Main.hs++  default-language:    Haskell2010++  Build-depends:+      base >=4.8 && <5,+      tidal-link