packages feed

tidal-link 1.0.1 → 1.0.2

raw patch · 789 files changed

+58261/−10101 lines, 789 files

Files

link/include/ableton/Link.ipp view
@@ -225,19 +225,33 @@   forceBeatAtTime(beat, time, quantum); } -template <typename Clock>-inline void BasicLink<Clock>::SessionState::forceBeatAtTime(-  const double beat, const std::chrono::microseconds time, const double quantum)+inline void forceBeatAtTimeImpl(link::Timeline& timeline,+  const link::Beats beat,+  const std::chrono::microseconds time,+  const link::Beats 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);+  const auto curBeatAtTime = link::toPhaseEncodedBeats(timeline, time, quantum);+  const auto closestInPhase = link::closestPhaseMatch(curBeatAtTime, beat, quantum);+  timeline = shiftClientTimeline(timeline, closestInPhase - curBeatAtTime);   // Now adjust the magnitude-  mState.timeline.beatOrigin =-    mState.timeline.beatOrigin + (link::Beats{beat} - closestInPhase);+  timeline.beatOrigin = timeline.beatOrigin + beat - closestInPhase;+}++template <typename Clock>+inline void BasicLink<Clock>::SessionState::forceBeatAtTime(+  const double beat, std::chrono::microseconds time, const double quantum)+{+  forceBeatAtTimeImpl(mState.timeline, link::Beats{beat}, time, link::Beats{quantum});++  // Due to quantization errors the resulting BeatTime at 'time' after forcing can be+  // bigger than 'beat' which then violates intended behavior of the API and can lead+  // i.e. to missing a downbeat. Thus we have to shift the timeline forwards.+  if (beatAtTime(time, quantum) > beat)+  {+    forceBeatAtTimeImpl(mState.timeline, link::Beats{beat}, ++time, link::Beats{quantum});+  } }  template <typename Clock>
+ link/include/ableton/discovery/AsioTypes.hpp view
@@ -0,0 +1,54 @@+/* Copyright 2023, 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>++namespace ableton+{+namespace discovery+{++using IpAddress = LINK_ASIO_NAMESPACE::ip::address;+using IpAddressV4 = LINK_ASIO_NAMESPACE::ip::address_v4;+using IpAddressV6 = LINK_ASIO_NAMESPACE::ip::address_v6;+using UdpSocket = LINK_ASIO_NAMESPACE::ip::udp::socket;+using UdpEndpoint = LINK_ASIO_NAMESPACE::ip::udp::endpoint;++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};+}++template <typename AsioAddrType>+AsioAddrType makeAddress(const char* pAddr, uint32_t scopeId)+{+  using namespace std;+  typename AsioAddrType::bytes_type bytes;+  copy(pAddr, pAddr + bytes.size(), begin(bytes));+  return AsioAddrType{bytes, scopeId};+}++} // namespace discovery+} // namespace ableton
link/include/ableton/discovery/InterfaceScanner.hpp view
@@ -19,7 +19,7 @@  #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/util/Injected.hpp> #include <chrono> #include <vector>@@ -29,7 +29,7 @@ namespace discovery { -// Callback takes a range of asio::ip:address which is+// Callback takes a range of IpAddress which is // guaranteed to be sorted and unique template <typename Callback, typename IoContext> class InterfaceScanner@@ -64,7 +64,7 @@     using namespace std;     debug(mIo->log()) << "Scanning network interfaces";     // Rescan the hardware for available network interface addresses-    vector<asio::ip::address> addrs = mIo->scanNetworkInterfaces();+    vector<IpAddress> 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));
+ link/include/ableton/discovery/IpInterface.hpp view
@@ -0,0 +1,130 @@+/* 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/AsioTypes.hpp>+#include <ableton/util/Injected.hpp>++namespace ableton+{+namespace discovery+{++inline UdpEndpoint multicastEndpointV4()+{+  return {IpAddressV4::from_string("224.76.78.75"), 20808};+}++inline UdpEndpoint multicastEndpointV6(uint64_t scopeId)+{+  // This is a non-permanently-assigned link-local multicast address (RFC4291)+  return {+    ::LINK_ASIO_NAMESPACE::ip::make_address("ff12::8080%" + std::to_string(scopeId)),+    20808};+}++// Type tags for dispatching between unicast and multicast packets+struct MulticastTag+{+};+struct UnicastTag+{+};++template <typename IoContext, std::size_t MaxPacketSize>+class IpInterface+{+public:+  using Socket = typename util::Injected<IoContext>::type::template Socket<MaxPacketSize>;++  IpInterface(util::Injected<IoContext> io, const IpAddress& addr)+    : mIo(std::move(io))+    , mMulticastReceiveSocket(mIo->template openMulticastSocket<MaxPacketSize>(addr))+    , mSendSocket(mIo->template openUnicastSocket<MaxPacketSize>(addr))+  {+  }++  IpInterface(const IpInterface&) = delete;+  IpInterface& operator=(const IpInterface&) = delete;++  IpInterface(IpInterface&& 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 UdpEndpoint& 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)));+  }++  UdpEndpoint 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 UdpEndpoint& 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>+IpInterface<IoContext, MaxPacketSize> makeIpInterface(+  util::Injected<IoContext> io, const IpAddress& addr)+{+  return {std::move(io), addr};+}++} // namespace discovery+} // namespace ableton
− link/include/ableton/discovery/IpV4Interface.hpp
@@ -1,123 +0,0 @@-/* 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/NetworkByteStreamSerializable.hpp view
@@ -19,7 +19,7 @@  #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #if defined(LINK_PLATFORM_MACOSX) #include <ableton/platforms/darwin/Darwin.hpp> #elif defined(LINK_PLATFORM_LINUX)
link/include/ableton/discovery/Payload.hpp view
@@ -82,6 +82,11 @@   template <typename It>   friend It toNetworkByteStream(const PayloadEntry& entry, It out)   {+    // Don't serialize Entry if its value is of size zero+    if (sizeInByteStream(entry.value) == 0)+    {+      return out;+    }     return toNetworkByteStream(       entry.value, toNetworkByteStream(entry.header, std::move(out)));   }
link/include/ableton/discovery/PeerGateway.hpp view
@@ -216,7 +216,7 @@ // IpV4 gateway types template <typename StateQuery, typename IoContext> using IpV4Messenger = UdpMessenger<-  IpV4Interface<typename util::Injected<IoContext>::type&, v1::kMaxMessageSize>,+  IpInterface<typename util::Injected<IoContext>::type&, v1::kMaxMessageSize>,   StateQuery,   IoContext>; @@ -226,11 +226,11 @@     PeerObserver,     IoContext>; -// Factory function to bind a PeerGateway to an IpV4Interface with the given address.+// Factory function to bind a PeerGateway to an IpInterface 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,+  const IpAddress& addr,   util::Injected<PeerObserver> observer,   NodeState state) {@@ -240,7 +240,7 @@   const uint8_t ttl = 5;   const uint8_t ttlRatio = 20; -  auto iface = makeIpV4Interface<v1::kMaxMessageSize>(injectRef(*io), addr);+  auto iface = makeIpInterface<v1::kMaxMessageSize>(injectRef(*io), addr);    auto messenger = makeUdpMessenger(     injectVal(std::move(iface)), std::move(state), injectRef(*io), ttl, ttlRatio);
link/include/ableton/discovery/PeerGateways.hpp view
@@ -19,8 +19,8 @@  #pragma once +#include <ableton/discovery/AsioTypes.hpp> #include <ableton/discovery/InterfaceScanner.hpp>-#include <ableton/platforms/asio/AsioWrapper.hpp> #include <map>  namespace ableton@@ -28,16 +28,17 @@ namespace discovery { -// GatewayFactory must have an operator()(NodeState, IoRef, asio::ip::address)+// GatewayFactory must have an operator()(NodeState, IoRef, IpAddress) // 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>;+  using Gateway = decltype(std::declval<GatewayFactory>()(std::declval<NodeState>(),+    std::declval<util::Injected<IoType&>>(),+    std::declval<IpAddress>()));+  using GatewayMap = std::map<IpAddress, Gateway>;    PeerGateways(const std::chrono::seconds rescanPeriod,     NodeState state,@@ -86,7 +87,7 @@    // 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)+  void repairGateway(const IpAddress& gatewayAddr)   {     if (mpScannerCallback->mGateways.erase(gatewayAddr))     {@@ -111,18 +112,18 @@     {       using namespace std;       // Get the set of current addresses.-      vector<asio::ip::address> curAddrs;+      vector<IpAddress> 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;+      vector<IpAddress> newAddrs;       set_difference(std::begin(range), std::end(range), std::begin(curAddrs),         std::end(curAddrs), back_inserter(newAddrs)); -      vector<asio::ip::address> staleAddrs;+      vector<IpAddress> staleAddrs;       set_difference(std::begin(curAddrs), std::end(curAddrs), std::begin(range),         std::end(range), back_inserter(staleAddrs)); @@ -137,12 +138,8 @@       {         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()));-          }+          info(mIo.log()) << "initializing peer gateway on interface " << addr;+          mGateways.emplace(addr, mFactory(mState, util::injectRef(mIo), addr));         }         catch (const runtime_error& e)         {
link/include/ableton/discovery/Service.hpp view
@@ -59,7 +59,7 @@   // 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)+  void repairGateway(const IpAddress& gatewayAddr)   {     mGateways.repairGateway(gatewayAddr);   }
link/include/ableton/discovery/UdpMessenger.hpp view
@@ -19,10 +19,10 @@  #pragma once -#include <ableton/discovery/IpV4Interface.hpp>+#include <ableton/discovery/AsioTypes.hpp>+#include <ableton/discovery/IpInterface.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>@@ -37,15 +37,23 @@ // interface through which the sending failed. struct UdpSendException : std::runtime_error {-  UdpSendException(const std::runtime_error& e, asio::ip::address ifAddr)+  UdpSendException(const std::runtime_error& e, IpAddress ifAddr)     : std::runtime_error(e.what())     , interfaceAddr(std::move(ifAddr))   {   } -  asio::ip::address interfaceAddr;+  IpAddress interfaceAddr; }; +template <typename Interface>+UdpEndpoint ipV6Endpoint(Interface& iface, const UdpEndpoint& endpoint)+{+  auto v6Address = endpoint.address().to_v6();+  v6Address.scope_id(iface.endpoint().address().to_v6().scope_id());+  return {v6Address, endpoint.port()};+}+ // Throws UdpSendException template <typename Interface, typename NodeId, typename Payload> void sendUdpMessage(Interface& iface,@@ -53,7 +61,7 @@   const uint8_t ttl,   const v1::MessageType messageType,   const Payload& payload,-  const asio::ip::udp::endpoint& to)+  const UdpEndpoint& to) {   using namespace std;   v1::MessageBuffer buffer;@@ -176,8 +184,16 @@      void sendByeBye()     {-      sendUdpMessage(-        *mInterface, mState.ident(), 0, v1::kByeBye, makePayload(), multicastEndpoint());+      if (mInterface->endpoint().address().is_v4())+      {+        sendUdpMessage(*mInterface, mState.ident(), 0, v1::kByeBye, makePayload(),+          multicastEndpointV4());+      }+      if (mInterface->endpoint().address().is_v6())+      {+        sendUdpMessage(*mInterface, mState.ident(), 0, v1::kByeBye, makePayload(),+          multicastEndpointV6(mInterface->endpoint().address().to_v6().scope_id()));+      }     }      void updateState(NodeState state)@@ -213,21 +229,29 @@       if (delay < milliseconds{1})       {         debug(mIo->log()) << "Broadcasting state";-        sendPeerState(v1::kAlive, multicastEndpoint());+        if (mInterface->endpoint().address().is_v4())+        {+          sendPeerState(v1::kAlive, multicastEndpointV4());+        }+        if (mInterface->endpoint().address().is_v6())+        {+          sendPeerState(v1::kAlive,+            multicastEndpointV6(mInterface->endpoint().address().to_v6().scope_id()));+        }       }     } -    void sendPeerState(-      const v1::MessageType messageType, const asio::ip::udp::endpoint& to)+    void sendPeerState(const v1::MessageType messageType, const UdpEndpoint& to)     {       sendUdpMessage(         *mInterface, mState.ident(), mTtl, messageType, toPayload(mState), to);       mLastBroadcastTime = mTimer.now();     } -    void sendResponse(const asio::ip::udp::endpoint& to)+    void sendResponse(const UdpEndpoint& to)     {-      sendPeerState(v1::kResponse, to);+      const auto endpoint = to.address().is_v4() ? to : ipV6Endpoint(*mInterface, to);+      sendPeerState(v1::kResponse, endpoint);     }      template <typename Tag>@@ -237,10 +261,8 @@     }      template <typename Tag, typename It>-    void operator()(Tag tag,-      const asio::ip::udp::endpoint& from,-      const It messageBegin,-      const It messageEnd)+    void operator()(+      Tag tag, const UdpEndpoint& from, const It messageBegin, const It messageEnd)     {       auto result = v1::parseMessageHeader<NodeId>(messageBegin, messageEnd); 
link/include/ableton/discovery/test/Interface.hpp view
@@ -31,9 +31,8 @@ class Interface { public:-  void send(const uint8_t* const bytes,-    const size_t numBytes,-    const asio::ip::udp::endpoint& endpoint)+  void send(+    const uint8_t* const bytes, const size_t numBytes, const UdpEndpoint& endpoint)   {     sentMessages.push_back(       std::make_pair(std::vector<uint8_t>{bytes, bytes + numBytes}, endpoint));@@ -42,31 +41,30 @@   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) {+    mCallback = [callback, tag](+                  const UdpEndpoint& 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)+  void incomingMessage(const UdpEndpoint& from, It messageBegin, It messageEnd)   {     std::vector<uint8_t> buffer{messageBegin, messageEnd};     mCallback(from, buffer);   } -  asio::ip::udp::endpoint endpoint() const+  UdpEndpoint endpoint() const   {-    return asio::ip::udp::endpoint({}, 0);+    return UdpEndpoint({}, 0);   } -  using SentMessage = std::pair<std::vector<uint8_t>, asio::ip::udp::endpoint>;+  using SentMessage = std::pair<std::vector<uint8_t>, UdpEndpoint>;   std::vector<SentMessage> sentMessages;  private:   using ReceiveCallback =-    std::function<void(const asio::ip::udp::endpoint&, const std::vector<uint8_t>&)>;+    std::function<void(const UdpEndpoint&, const std::vector<uint8_t>&)>;   ReceiveCallback mCallback; }; 
link/include/ableton/discovery/test/Socket.hpp view
@@ -19,7 +19,7 @@  #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/util/Log.hpp> #include <ableton/util/test/IoService.hpp> @@ -37,12 +37,12 @@   {   } -  friend void configureUnicastSocket(Socket&, const asio::ip::address_v4&)+  friend void configureUnicastSocket(Socket&, const IpAddressV4&)   {   }    std::size_t send(-    const uint8_t* const pData, const size_t numBytes, const asio::ip::udp::endpoint& to)+    const uint8_t* const pData, const size_t numBytes, const discovery::UdpEndpoint& to)   {     sentMessages.push_back(       std::make_pair(std::vector<uint8_t>{pData, pData + numBytes}, to));@@ -52,31 +52,29 @@   template <typename Handler>   void receive(Handler handler)   {-    mCallback = [handler](const asio::ip::udp::endpoint& from,-                  const std::vector<uint8_t>& buffer) {+    mCallback = [handler](const UdpEndpoint& 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)+  void incomingMessage(const UdpEndpoint& from, It messageBegin, It messageEnd)   {     std::vector<uint8_t> buffer{messageBegin, messageEnd};     mCallback(from, buffer);   } -  asio::ip::udp::endpoint endpoint() const+  UdpEndpoint endpoint() const   {-    return asio::ip::udp::endpoint({}, 0);+    return UdpEndpoint({}, 0);   } -  using SentMessage = std::pair<std::vector<uint8_t>, asio::ip::udp::endpoint>;+  using SentMessage = std::pair<std::vector<uint8_t>, UdpEndpoint>;   std::vector<SentMessage> sentMessages;  private:   using ReceiveCallback =-    std::function<void(const asio::ip::udp::endpoint&, const std::vector<uint8_t>&)>;+    std::function<void(const UdpEndpoint&, const std::vector<uint8_t>&)>;   ReceiveCallback mCallback; }; 
link/include/ableton/link/Controller.hpp view
@@ -717,18 +717,11 @@   {     GatewayPtr operator()(std::pair<NodeState, GhostXForm> state,       util::Injected<IoType&> io,-      const asio::ip::address& addr)+      const discovery::IpAddress& 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");-      }+      return GatewayPtr{new ControllerGateway{std::move(io), addr,+        util::injectVal(makeGatewayObserver(mController.mPeers, addr)),+        std::move(state.first), std::move(state.second), mController.mClock}};     }      Controller& mController;
link/include/ableton/link/Gateway.hpp view
@@ -33,7 +33,7 @@ { public:   Gateway(util::Injected<IoContext> io,-    asio::ip::address_v4 addr,+    discovery::IpAddress addr,     util::Injected<PeerObserver> observer,     NodeState nodeState,     GhostXForm ghostXForm,
link/include/ableton/link/Measurement.hpp view
@@ -45,7 +45,7 @@    Measurement(const PeerState& state,     Callback callback,-    asio::ip::address_v4 address,+    discovery::IpAddress address,     Clock clock,     util::Injected<IoContext> io)     : mIo(std::move(io))@@ -69,12 +69,11 @@      Impl(const PeerState& state,       Callback callback,-      asio::ip::address_v4 address,+      discovery::IpAddress 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())@@ -82,6 +81,17 @@       , mLog(channel(io->log(), "Measurement on gateway@" + address.to_string()))       , mSuccess(false)     {+      if (state.endpoint.address().is_v4())+      {+        mEndpoint = state.endpoint;+      }+      else+      {+        auto v6Address = state.endpoint.address().to_v6();+        v6Address.scope_id(address.to_v6().scope_id());+        mEndpoint = {v6Address, state.endpoint.port()};+      }+       const auto ht = HostTime{mClock.micros()};       sendPing(mEndpoint, discovery::makePayload(ht));       resetTimer();@@ -117,7 +127,7 @@     // 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)+      const discovery::UdpEndpoint& from, const It messageBegin, const It messageEnd)     {       using namespace std;       const auto result = v1::parseMessageHeader(messageBegin, messageEnd);@@ -197,7 +207,7 @@     }      template <typename Payload>-    void sendPing(asio::ip::udp::endpoint to, const Payload& payload)+    void sendPing(discovery::UdpEndpoint to, const Payload& payload)     {       v1::MessageBuffer buffer;       const auto msgBegin = std::begin(buffer);@@ -232,7 +242,7 @@      Socket mSocket;     SessionId mSessionId;-    asio::ip::udp::endpoint mEndpoint;+    discovery::UdpEndpoint mEndpoint;     std::vector<double> mData;     Callback mCallback;     Clock mClock;
link/include/ableton/link/MeasurementEndpointV4.hpp view
@@ -19,8 +19,9 @@  #pragma once +#include <ableton/discovery/AsioTypes.hpp> #include <ableton/discovery/NetworkByteStreamSerializable.hpp>-#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <cassert>  namespace ableton {@@ -35,6 +36,10 @@   // Model the NetworkByteStreamSerializable concept   friend std::uint32_t sizeInByteStream(const MeasurementEndpointV4 mep)   {+    if (mep.ep.address().is_v6())+    {+      return 0;+    }     return discovery::sizeInByteStream(              static_cast<std::uint32_t>(mep.ep.address().to_v4().to_ulong()))            + discovery::sizeInByteStream(mep.ep.port());@@ -43,6 +48,7 @@   template <typename It>   friend It toNetworkByteStream(const MeasurementEndpointV4 mep, It out)   {+    assert(mep.ep.address().is_v4());     return discovery::toNetworkByteStream(mep.ep.port(),       discovery::toNetworkByteStream(         static_cast<std::uint32_t>(mep.ep.address().to_v4().to_ulong()), std::move(out)));@@ -58,11 +64,11 @@       std::move(addrRes.second), end);     return make_pair(       MeasurementEndpointV4{-        {asio::ip::address_v4{std::move(addrRes.first)}, std::move(portRes.first)}},+        {discovery::IpAddressV4{std::move(addrRes.first)}, std::move(portRes.first)}},       std::move(portRes.second));   } -  asio::ip::udp::endpoint ep;+  discovery::UdpEndpoint ep; };  } // namespace link
+ link/include/ableton/link/MeasurementEndpointV6.hpp view
@@ -0,0 +1,75 @@+/* Copyright 2023, 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>+#include <cassert>++namespace ableton+{+namespace link+{++struct MeasurementEndpointV6+{+  static const std::int32_t key = 'mep6';+  static_assert(key == 0x6d657036, "Unexpected byte order");++  // Model the NetworkByteStreamSerializable concept+  friend std::uint32_t sizeInByteStream(const MeasurementEndpointV6 mep)+  {+    if (mep.ep.address().is_v4())+    {+      return 0;+    }+    return discovery::sizeInByteStream(mep.ep.address().to_v6().to_bytes())+           + discovery::sizeInByteStream(mep.ep.port());+  }++  template <typename It>+  friend It toNetworkByteStream(const MeasurementEndpointV6 mep, It out)+  {+    assert(mep.ep.address().is_v6());+    return discovery::toNetworkByteStream(+      mep.ep.port(), discovery::toNetworkByteStream(+                       mep.ep.address().to_v6().to_bytes(), std::move(out)));+  }++  template <typename It>+  static std::pair<MeasurementEndpointV6, It> fromNetworkByteStream(It begin, It end)+  {+    using namespace std;+    auto addrRes =+      discovery::Deserialize<discovery::IpAddressV6::bytes_type>::fromNetworkByteStream(+        std::move(begin), end);+    auto portRes = discovery::Deserialize<std::uint16_t>::fromNetworkByteStream(+      std::move(addrRes.second), end);+    return make_pair(+      MeasurementEndpointV6{+        {discovery::IpAddressV6{std::move(addrRes.first)}, std::move(portRes.first)}},+      std::move(portRes.second));+  }++  discovery::UdpEndpoint ep;+};++} // namespace link+} // namespace ableton
link/include/ableton/link/MeasurementService.hpp view
@@ -42,7 +42,7 @@   using IoType = util::Injected<IoContext>;   using MeasurementInstance = Measurement<Clock, IoContext>; -  MeasurementService(asio::ip::address_v4 address,+  MeasurementService(discovery::IpAddress address,     SessionId sessionId,     GhostXForm ghostXForm,     Clock clock,@@ -65,7 +65,7 @@     mPingResponder.updateNodeState(sessionId, xform);   } -  asio::ip::udp::endpoint endpoint() const+  discovery::UdpEndpoint endpoint() const   {     return mPingResponder.endpoint();   }@@ -77,7 +77,7 @@     using namespace std;      const auto nodeId = state.nodeState.nodeId;-    auto addr = mPingResponder.endpoint().address().to_v4();+    auto addr = mPingResponder.endpoint().address();     auto callback = CompletionCallback<Handler>{*this, nodeId, handler};      try
link/include/ableton/link/PeerState.hpp view
@@ -21,6 +21,7 @@  #include <ableton/discovery/Payload.hpp> #include <ableton/link/MeasurementEndpointV4.hpp>+#include <ableton/link/MeasurementEndpointV6.hpp> #include <ableton/link/NodeState.hpp>  namespace ableton@@ -61,12 +62,16 @@     return lhs.nodeState == rhs.nodeState && lhs.endpoint == rhs.endpoint;   } -  friend auto toPayload(const PeerState& state)-    -> decltype(std::declval<NodeState::Payload>()-                + discovery::makePayload(MeasurementEndpointV4{{}}))+  friend auto toPayload(const PeerState& state) -> decltype(+    std::declval<NodeState::Payload>() + discovery::makePayload(MeasurementEndpointV4{{}})+    + discovery::makePayload(MeasurementEndpointV6{{}}))   {+    // This implements a switch if either an IPv4 or IPv6 endpoint is serialized.+    // MeasurementEndpoints that contain an endpoint that does not match the IP protocol+    // version return a sizeInByteStream() of zero and won't be serialized.     return toPayload(state.nodeState)-           + discovery::makePayload(MeasurementEndpointV4{state.endpoint});+           + discovery::makePayload(MeasurementEndpointV4{state.endpoint})+           + discovery::makePayload(MeasurementEndpointV6{state.endpoint});   }    template <typename It>@@ -75,15 +80,16 @@     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);-      });+    discovery::parsePayload<MeasurementEndpointV4, MeasurementEndpointV6>(+      std::move(begin), std::move(end),+      [&peerState](MeasurementEndpointV4 me4) { peerState.endpoint = std::move(me4.ep); },+      [&peerState](+        MeasurementEndpointV6 me6) { peerState.endpoint = std::move(me6.ep); });     return peerState;   }    NodeState nodeState;-  asio::ip::udp::endpoint endpoint;+  discovery::UdpEndpoint endpoint; };  } // namespace link
link/include/ableton/link/Peers.hpp view
@@ -47,7 +47,7 @@   struct Impl;  public:-  using Peer = std::pair<PeerState, asio::ip::address>;+  using Peer = std::pair<PeerState, discovery::IpAddress>;    Peers(util::Injected<IoContext> io,     SessionMembershipCallback membership,@@ -119,7 +119,7 @@     using GatewayObserverNodeState = PeerState;     using GatewayObserverNodeId = NodeId; -    GatewayObserver(std::shared_ptr<Impl> pImpl, asio::ip::address addr)+    GatewayObserver(std::shared_ptr<Impl> pImpl, discovery::IpAddress addr)       : mpImpl(std::move(pImpl))       , mAddr(std::move(addr))     {@@ -165,11 +165,11 @@     }      std::shared_ptr<Impl> mpImpl;-    asio::ip::address mAddr;+    discovery::IpAddress mAddr;   };    // Factory function for the gateway observer-  friend GatewayObserver makeGatewayObserver(Peers& peers, asio::ip::address addr)+  friend GatewayObserver makeGatewayObserver(Peers& peers, discovery::IpAddress addr)   {     return GatewayObserver{peers.mpImpl, std::move(addr)};   }@@ -188,7 +188,7 @@     {     } -    void sawPeerOnGateway(PeerState peerState, asio::ip::address gatewayAddr)+    void sawPeerOnGateway(PeerState peerState, discovery::IpAddress gatewayAddr)     {       using namespace std; @@ -255,7 +255,7 @@       }     } -    void peerLeftGateway(const NodeId& nodeId, const asio::ip::address& gatewayAddr)+    void peerLeftGateway(const NodeId& nodeId, const discovery::IpAddress& gatewayAddr)     {       using namespace std; @@ -276,7 +276,7 @@       }     } -    void gatewayClosed(const asio::ip::address& gatewayAddr)+    void gatewayClosed(const discovery::IpAddress& gatewayAddr)     {       using namespace std; 
link/include/ableton/link/PingResponder.hpp view
@@ -40,7 +40,7 @@   using Socket = typename IoType::type::template Socket<v1::kMaxMessageSize>;  public:-  PingResponder(asio::ip::address_v4 address,+  PingResponder(discovery::IpAddress address,     SessionId sessionId,     GhostXForm ghostXForm,     Clock clock,@@ -64,12 +64,12 @@     mpImpl->mGhostXForm = std::move(xform);   } -  asio::ip::udp::endpoint endpoint() const+  discovery::UdpEndpoint endpoint() const   {     return mpImpl->mSocket.endpoint();   } -  asio::ip::address address() const+  discovery::IpAddress address() const   {     return endpoint().address();   }@@ -82,7 +82,7 @@ private:   struct Impl : std::enable_shared_from_this<Impl>   {-    Impl(asio::ip::address_v4 address,+    Impl(discovery::IpAddress address,       SessionId sessionId,       GhostXForm ghostXForm,       Clock clock,@@ -102,7 +102,7 @@      // 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)+    void operator()(const discovery::UdpEndpoint& from, const It begin, const It end)     {       using namespace discovery; @@ -136,7 +136,7 @@     }      template <typename It>-    void reply(It begin, It end, const asio::ip::udp::endpoint& to)+    void reply(It begin, It end, const discovery::UdpEndpoint& to)     {       using namespace discovery; 
link/include/ableton/link/SessionState.hpp view
@@ -23,6 +23,7 @@ #include <ableton/link/StartStopState.hpp> #include <ableton/link/Timeline.hpp> #include <ableton/link/TripleBuffer.hpp>+#include <mutex>  namespace ableton {
link/include/ableton/platforms/Config.hpp view
@@ -62,31 +62,33 @@ 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>;+using IoContext =+  platforms::LINK_ASIO_NAMESPACE::Context<platforms::windows::ScanIpIfAddrs,+    util::NullLog,+    platforms::windows::ThreadFactory>; #else using IoContext =-  platforms::asio::Context<platforms::windows::ScanIpIfAddrs, util::NullLog>;+  platforms::LINK_ASIO_NAMESPACE::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,+using IoContext = platforms::LINK_ASIO_NAMESPACE::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 Clock = platforms::linux_::ClockMonotonicRaw; using Random = platforms::stl::Random; #ifdef __linux__-using IoContext = platforms::asio::Context<platforms::posix::ScanIpIfAddrs,+using IoContext = platforms::LINK_ASIO_NAMESPACE::Context<platforms::posix::ScanIpIfAddrs,   util::NullLog,-  platforms::linux::ThreadFactory>;+  platforms::linux_::ThreadFactory>; #else using IoContext =-  platforms::asio::Context<platforms::posix::ScanIpIfAddrs, util::NullLog>;+  platforms::LINK_ASIO_NAMESPACE::Context<platforms::posix::ScanIpIfAddrs, util::NullLog>; #endif  #elif defined(ESP_PLATFORM)
link/include/ableton/platforms/asio/AsioTimer.hpp view
@@ -27,7 +27,7 @@ { namespace platforms {-namespace asio+namespace LINK_ASIO_NAMESPACE {  // This implementation is based on the boost::asio::system_timer concept.@@ -41,11 +41,14 @@ class AsioTimer { public:-  using ErrorCode = ::asio::error_code;+  using ErrorCode = ::LINK_ASIO_NAMESPACE::error_code;   using TimePoint = std::chrono::system_clock::time_point;+  using IoService = ::LINK_ASIO_NAMESPACE::io_service;+  using SystemTimer = ::LINK_ASIO_NAMESPACE::system_timer; -  AsioTimer(::asio::io_service& io)-    : mpTimer(new ::asio::system_timer(io))++  AsioTimer(IoService& io)+    : mpTimer(new SystemTimer(io))     , mpAsyncHandler(std::make_shared<AsyncHandler>())   {   }@@ -123,10 +126,10 @@     std::function<void(const ErrorCode)> mpHandler;   }; -  std::unique_ptr<::asio::system_timer> mpTimer;+  std::unique_ptr<SystemTimer> mpTimer;   std::shared_ptr<AsyncHandler> mpAsyncHandler; }; -} // namespace asio+} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton
link/include/ableton/platforms/asio/AsioWrapper.hpp view
@@ -26,12 +26,19 @@  * by Link.  */ -#if !defined(ESP_PLATFORM)+#if defined(ESP_PLATFORM)++#define LINK_ASIO_NAMESPACE asio++#else+ #pragma push_macro("ASIO_STANDALONE")-#define ASIO_STANDALONE 1  #pragma push_macro("ASIO_NO_TYPEID") #define ASIO_NO_TYPEID 1+#define asio link_asio_1_28_0+#define LINK_ASIO_NAMESPACE link_asio_1_28_0+#define ASIO_STANDALONE 1 #endif  #if defined(LINK_PLATFORM_WINDOWS)@@ -75,11 +82,6 @@ #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@@ -88,3 +90,5 @@ #if defined(__clang__) #pragma clang diagnostic pop #endif++#undef asio
link/include/ableton/platforms/asio/Context.hpp view
@@ -19,9 +19,8 @@  #pragma once -#include <ableton/discovery/IpV4Interface.hpp>+#include <ableton/discovery/IpInterface.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>@@ -31,7 +30,7 @@ { namespace platforms {-namespace asio+namespace LINK_ASIO_NAMESPACE { namespace {@@ -51,7 +50,7 @@ class Context { public:-  using Timer = AsioTimer;+  using Timer = LINK_ASIO_NAMESPACE::AsioTimer;   using Log = LogT;    template <typename Handler, typename Duration>@@ -59,7 +58,9 @@     LockFreeCallbackDispatcher<Handler, Duration, ThreadFactoryT>;    template <std::size_t BufferSize>-  using Socket = asio::Socket<BufferSize>;+  using Socket = Socket<BufferSize>;+  using IoService = ::LINK_ASIO_NAMESPACE::io_service;+  using Work = IoService::work;    Context()     : Context(DefaultHandler{})@@ -68,11 +69,11 @@    template <typename ExceptionHandler>   explicit Context(ExceptionHandler exceptHandler)-    : mpService(new ::asio::io_service())-    , mpWork(new ::asio::io_service::work(*mpService))+    : mpService(new IoService())+    , mpWork(new Work(*mpService))   {     mThread = ThreadFactoryT::makeThread("Link Main",-      [](::asio::io_service& service, ExceptionHandler handler) {+      [](IoService& service, ExceptionHandler handler) {         for (;;)         {           try@@ -121,34 +122,79 @@     template <std::size_t BufferSize>-  Socket<BufferSize> openUnicastSocket(const ::asio::ip::address_v4& addr)+  Socket<BufferSize> openUnicastSocket(const discovery::IpAddress addr)   {-    auto socket = Socket<BufferSize>{*mpService};+    auto socket =+      addr.is_v4() ? Socket<BufferSize>{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v4()}+                   : Socket<BufferSize>{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v6()};     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});+      ::LINK_ASIO_NAMESPACE::ip::multicast::enable_loopback(addr.is_loopback()));+    if (addr.is_v4())+    {+      socket.mpImpl->mSocket.set_option(+        ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(addr.to_v4()));+      socket.mpImpl->mSocket.bind(+        ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v4(), 0});+    }+    else if (addr.is_v6())+    {+      const auto scopeId = addr.to_v6().scope_id();+      socket.mpImpl->mSocket.set_option(+        ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(+          static_cast<unsigned int>(scopeId)));+      socket.mpImpl->mSocket.bind(+        ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v6(), 0});+    }+    else+    {+      throw(std::runtime_error("Unknown Protocol"));+    }     return socket;   }    template <std::size_t BufferSize>-  Socket<BufferSize> openMulticastSocket(const ::asio::ip::address_v4& addr)+  Socket<BufferSize> openMulticastSocket(const discovery::IpAddress& addr)   {-    auto socket = Socket<BufferSize>{*mpService};-    socket.mpImpl->mSocket.set_option(::asio::ip::udp::socket::reuse_address(true));+    auto socket =+      addr.is_v4() ? Socket<BufferSize>{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v4()}+                   : Socket<BufferSize>{*mpService, ::LINK_ASIO_NAMESPACE::ip::udp::v6()};+     socket.mpImpl->mSocket.set_option(-      ::asio::socket_base::broadcast(!addr.is_loopback()));+      ::LINK_ASIO_NAMESPACE::ip::udp::socket::reuse_address(true));     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));+      ::LINK_ASIO_NAMESPACE::socket_base::broadcast(!addr.is_loopback()));+    socket.mpImpl->mSocket.set_option(+      ::LINK_ASIO_NAMESPACE::ip::multicast::enable_loopback(addr.is_loopback()));++    if (addr.is_v4())+    {+      socket.mpImpl->mSocket.set_option(+        ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(addr.to_v4()));+      socket.mpImpl->mSocket.bind({::LINK_ASIO_NAMESPACE::ip::address_v4::any(),+        discovery::multicastEndpointV4().port()});+      socket.mpImpl->mSocket.set_option(::LINK_ASIO_NAMESPACE::ip::multicast::join_group(+        discovery::multicastEndpointV4().address().to_v4(), addr.to_v4()));+    }+    else if (addr.is_v6())+    {+      const auto scopeId = addr.to_v6().scope_id();+      socket.mpImpl->mSocket.set_option(+        ::LINK_ASIO_NAMESPACE::ip::multicast::outbound_interface(+          static_cast<unsigned int>(scopeId)));+      const auto multicastEndpoint = discovery::multicastEndpointV6(scopeId);+      socket.mpImpl->mSocket.bind(+        {::LINK_ASIO_NAMESPACE::ip::address_v6::any(), multicastEndpoint.port()});+      socket.mpImpl->mSocket.set_option(::LINK_ASIO_NAMESPACE::ip::multicast::join_group(+        multicastEndpoint.address().to_v6(), scopeId));+    }+    else+    {+      throw(std::runtime_error("Unknown Protocol"));+    }     return socket;   } -  std::vector<::asio::ip::address> scanNetworkInterfaces()+  std::vector<discovery::IpAddress> scanNetworkInterfaces()   {     return mScanIpIfAddrs();   }@@ -184,13 +230,13 @@     }   }; -  std::unique_ptr<::asio::io_service> mpService;-  std::unique_ptr<::asio::io_service::work> mpWork;+  std::unique_ptr<::LINK_ASIO_NAMESPACE::io_service> mpService;+  std::unique_ptr<::LINK_ASIO_NAMESPACE::io_service::work> mpWork;   std::thread mThread;   Log mLog;   ScanIpIfAddrs mScanIpIfAddrs; }; -} // namespace asio+} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton
link/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp view
@@ -27,7 +27,7 @@ { namespace platforms {-namespace asio+namespace LINK_ASIO_NAMESPACE {  // Utility to signal invocation of a callback on another thread in a lock free manner.@@ -83,6 +83,6 @@   std::thread mThread; }; -} // namespace asio+} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton
link/include/ableton/platforms/asio/Socket.hpp view
@@ -19,7 +19,7 @@  #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/util/SafeAsyncHandler.hpp> #include <array> #include <cassert>@@ -28,14 +28,14 @@ { namespace platforms {-namespace asio+namespace LINK_ASIO_NAMESPACE {  template <std::size_t MaxPacketSize> struct Socket {-  Socket(::asio::io_service& io)-    : mpImpl(std::make_shared<Impl>(io))+  Socket(::LINK_ASIO_NAMESPACE::io_service& io, ::LINK_ASIO_NAMESPACE::ip::udp protocol)+    : mpImpl(std::make_shared<Impl>(io, protocol))   {   } @@ -47,12 +47,11 @@   {   } -  std::size_t send(const uint8_t* const pData,-    const size_t numBytes,-    const ::asio::ip::udp::endpoint& to)+  std::size_t send(+    const uint8_t* const pData, const size_t numBytes, const discovery::UdpEndpoint& to)   {     assert(numBytes < MaxPacketSize);-    return mpImpl->mSocket.send_to(::asio::buffer(pData, numBytes), to);+    return mpImpl->mSocket.send_to(::LINK_ASIO_NAMESPACE::buffer(pData, numBytes), to);   }    template <typename Handler>@@ -60,19 +59,19 @@   {     mpImpl->mHandler = std::move(handler);     mpImpl->mSocket.async_receive_from(-      ::asio::buffer(mpImpl->mReceiveBuffer, MaxPacketSize), mpImpl->mSenderEndpoint,-      util::makeAsyncSafe(mpImpl));+      ::LINK_ASIO_NAMESPACE::buffer(mpImpl->mReceiveBuffer, MaxPacketSize),+      mpImpl->mSenderEndpoint, util::makeAsyncSafe(mpImpl));   } -  ::asio::ip::udp::endpoint endpoint() const+  discovery::UdpEndpoint endpoint() const   {     return mpImpl->mSocket.local_endpoint();   }    struct Impl   {-    Impl(::asio::io_service& io)-      : mSocket(io, ::asio::ip::udp::v4())+    Impl(::LINK_ASIO_NAMESPACE::io_service& io, ::LINK_ASIO_NAMESPACE::ip::udp protocol)+      : mSocket(io, protocol)     {     } @@ -80,12 +79,13 @@     {       // 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);+      ::LINK_ASIO_NAMESPACE::error_code ec;+      mSocket.shutdown(::LINK_ASIO_NAMESPACE::ip::udp::socket::shutdown_both, ec);       mSocket.close(ec);     } -    void operator()(const ::asio::error_code& error, const std::size_t numBytes)+    void operator()(+      const ::LINK_ASIO_NAMESPACE::error_code& error, const std::size_t numBytes)     {       if (!error && numBytes > 0 && numBytes <= MaxPacketSize)       {@@ -94,17 +94,17 @@       }     } -    ::asio::ip::udp::socket mSocket;-    ::asio::ip::udp::endpoint mSenderEndpoint;+    discovery::UdpSocket mSocket;+    discovery::UdpEndpoint 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::function<void(const discovery::UdpEndpoint&, ByteIt, ByteIt)> mHandler;   };    std::shared_ptr<Impl> mpImpl; }; -} // namespace asio+} // namespace LINK_ASIO_NAMESPACE } // namespace platforms } // namespace ableton
− link/include/ableton/platforms/asio/Util.hpp
@@ -1,43 +0,0 @@-/* 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
@@ -19,6 +19,7 @@  #pragma once +#include <cassert> #include <chrono> #include <mach/mach_time.h> @@ -49,6 +50,8 @@    Ticks microsToTicks(const Micros micros) const   {+    // Negative Micros can not be represented in Ticks+    assert(micros.count() >= 0);     return static_cast<Ticks>(micros.count() / mTicksToMicros);   } 
link/include/ableton/platforms/esp32/Context.hpp view
@@ -19,12 +19,12 @@  #pragma once -#include <ableton/discovery/IpV4Interface.hpp>+#include <ableton/discovery/AsioTypes.hpp>+#include <ableton/discovery/IpInterface.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 <driver/gptimer.h> #include <freertos/FreeRTOS.h> #include <freertos/task.h> @@ -40,7 +40,6 @@ {   class ServiceRunner   {-     static void run(void* userParams)     {       auto runner = static_cast<ServiceRunner*>(userParams);@@ -60,11 +59,7 @@     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);+      vTaskNotifyGiveFromISR(*((TaskHandle_t*)userParam), &xHigherPriorityTaskWoken);       if (xHigherPriorityTaskWoken)       {         portYIELD_FROM_ISR();@@ -79,24 +74,21 @@       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);+      const esp_timer_create_args_t timerArgs = {+        .callback = &timerIsr,+        .arg = (void*)&mTaskHandle,+        .dispatch_method = ESP_TIMER_TASK,+        .name = "link",+        .skip_unhandled_events = true,+      }; -      timer_start(TIMER_GROUP_0, TIMER_1);+      ESP_ERROR_CHECK(esp_timer_create(&timerArgs, &mTimer));+      ESP_ERROR_CHECK(esp_timer_start_periodic(mTimer, 100));     }      ~ServiceRunner()     {+      esp_timer_delete(mTimer);       vTaskDelete(mTaskHandle);     } @@ -113,6 +105,7 @@    private:     TaskHandle_t mTaskHandle;+    esp_timer_handle_t mTimer;     std::unique_ptr<::asio::io_service> mpService;     std::unique_ptr<::asio::io_service::work> mpWork;   };@@ -150,30 +143,72 @@   }    template <std::size_t BufferSize>-  Socket<BufferSize> openUnicastSocket(const ::asio::ip::address_v4& addr)+  Socket<BufferSize> openUnicastSocket(const ::asio::ip::address& addr)   {-    auto socket = Socket<BufferSize>{serviceRunner().service()};+    auto socket =+      addr.is_v4() ? Socket<BufferSize>{serviceRunner().service(), ::asio::ip::udp::v4()}+                   : Socket<BufferSize>{serviceRunner().service(), ::asio::ip::udp::v6()};     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});+    if (addr.is_v4())+    {+      socket.mpImpl->mSocket.set_option(+        ::asio::ip::multicast::outbound_interface(addr.to_v4()));+      socket.mpImpl->mSocket.bind(+        ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v4(), 0});+    }+    else if (addr.is_v6())+    {+      const auto scopeId = addr.to_v6().scope_id();+      socket.mpImpl->mSocket.set_option(+        ::asio::ip::multicast::outbound_interface(static_cast<unsigned int>(scopeId)));+      socket.mpImpl->mSocket.bind(+        ::LINK_ASIO_NAMESPACE::ip::udp::endpoint{addr.to_v6(), 0});+    }+    else+    {+      throw(std::runtime_error("Unknown Protocol"));+    }     return socket;   }    template <std::size_t BufferSize>-  Socket<BufferSize> openMulticastSocket(const ::asio::ip::address_v4& addr)+  Socket<BufferSize> openMulticastSocket(const ::asio::ip::address& addr)   {-    auto socket = Socket<BufferSize>{serviceRunner().service()};+    auto socket =+      addr.is_v4() ? Socket<BufferSize>{serviceRunner().service(), ::asio::ip::udp::v4()}+                   : Socket<BufferSize>{serviceRunner().service(), ::asio::ip::udp::v6()};+     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));++    if (addr.is_v4())+    {+      socket.mpImpl->mSocket.set_option(+        ::asio::ip::multicast::outbound_interface(addr.to_v4()));+      socket.mpImpl->mSocket.bind(+        {::asio::ip::address_v4::any(), discovery::multicastEndpointV4().port()});+      socket.mpImpl->mSocket.set_option(::asio::ip::multicast::join_group(+        discovery::multicastEndpointV4().address().to_v4(), addr.to_v4()));+    }+    else if (addr.is_v6())+    {+      const auto scopeId = addr.to_v6().scope_id();+      socket.mpImpl->mSocket.set_option(+        ::asio::ip::multicast::outbound_interface(static_cast<unsigned int>(scopeId)));+      const auto multicastEndpoint = discovery::multicastEndpointV6(scopeId);+      socket.mpImpl->mSocket.bind(+        {::asio::ip::address_v6::any(), multicastEndpoint.port()});+      socket.mpImpl->mSocket.set_option(+        ::asio::ip::multicast::join_group(multicastEndpoint.address().to_v6(), scopeId));+    }+    else+    {+      throw(std::runtime_error("Unknown Protocol"));+    }     return socket;   } 
link/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp view
@@ -17,7 +17,7 @@  #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <arpa/inet.h> #include <esp_netif.h> #include <net/if.h>@@ -33,9 +33,9 @@ // ESP32 implementation of ip interface address scanner struct ScanIpIfAddrs {-  std::vector<::asio::ip::address> operator()()+  std::vector<discovery::IpAddress> operator()()   {-    std::vector<::asio::ip::address> addrs;+    std::vector<discovery::IpAddress> addrs;     // Get first network interface     esp_netif_t* esp_netif = esp_netif_next(NULL);     while (esp_netif)
link/include/ableton/platforms/linux/Clock.hpp view
@@ -28,15 +28,11 @@ namespace platforms { -#ifdef linux-#undef linux-#endif- #if defined(__FreeBSD_kernel__) #define CLOCK_MONOTONIC_RAW CLOCK_MONOTONIC #endif -namespace linux+namespace linux_ {  template <clockid_t CLOCK>@@ -55,6 +51,6 @@ using ClockMonotonic = Clock<CLOCK_MONOTONIC>; using ClockMonotonicRaw = Clock<CLOCK_MONOTONIC_RAW>; -} // namespace linux+} // namespace linux_ } // namespace platforms } // namespace ableton
link/include/ableton/platforms/linux/ThreadFactory.hpp view
@@ -26,7 +26,7 @@ { namespace platforms {-namespace linux+namespace linux_ {  struct ThreadFactory@@ -40,6 +40,6 @@   } }; -} // namespace linux+} // namespace linux_ } // namespace platforms } // namespace ableton
link/include/ableton/platforms/posix/ScanIpIfAddrs.hpp view
@@ -19,11 +19,12 @@  #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>-#include <ableton/platforms/asio/Util.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <arpa/inet.h> #include <ifaddrs.h>+#include <map> #include <net/if.h>+#include <string> #include <vector>  namespace ableton@@ -75,34 +76,49 @@ {   // Scan active network interfaces and return corresponding addresses   // for all ip-based interfaces.-  std::vector<::asio::ip::address> operator()()+  std::vector<discovery::IpAddress> operator()()   {-    std::vector<::asio::ip::address> addrs;+    std::vector<discovery::IpAddress> addrs;+    std::map<std::string, discovery::IpAddress> IpInterfaceNames;      detail::GetIfAddrs getIfAddrs;-    getIfAddrs.withIfAddrs([&addrs](const struct ifaddrs& interfaces) {+    getIfAddrs.withIfAddrs([&addrs, &IpInterfaceNames](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 && interface->ifa_flags & IFF_RUNNING && addr->sin_family == AF_INET)         {-          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 bytes = reinterpret_cast<const char*>(&addr->sin_addr);+          auto address = discovery::makeAddress<discovery::IpAddressV4>(bytes);+          addrs.emplace_back(std::move(address));+          IpInterfaceNames.insert(std::make_pair(interface->ifa_name, address));+        }+      }+    });++    getIfAddrs.withIfAddrs([&addrs, &IpInterfaceNames](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_RUNNING && addr->sin_family == AF_INET6)+        {+          auto addr6 = reinterpret_cast<const struct sockaddr_in6*>(addr);+          auto bytes = reinterpret_cast<const char*>(&addr6->sin6_addr);+          auto scopeId = addr6->sin6_scope_id;+          auto address = discovery::makeAddress<discovery::IpAddressV6>(bytes, scopeId);+          if (IpInterfaceNames.find(interface->ifa_name) != IpInterfaceNames.end()+              && !address.is_loopback() && address.is_link_local())           {-            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));+            addrs.emplace_back(std::move(address));           }         }       }     });+     return addrs;-  }+  }; };  } // namespace posix
link/include/ableton/platforms/windows/ScanIpIfAddrs.hpp view
@@ -19,10 +19,11 @@  #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>-#include <ableton/platforms/asio/Util.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <iphlpapi.h>+#include <map> #include <stdio.h>+#include <string> #include <vector> #include <winsock2.h> #include <ws2tcpip.h>@@ -99,12 +100,13 @@ {   // Scan active network interfaces and return corresponding addresses   // for all ip-based interfaces.-  std::vector<::asio::ip::address> operator()()+  std::vector<discovery::IpAddress> operator()()   {-    std::vector<::asio::ip::address> addrs;+    std::vector<discovery::IpAddress> addrs;+    std::map<std::string, discovery::IpAddress> IpInterfaceNames;      detail::GetIfAddrs getIfAddrs;-    getIfAddrs.withIfAddrs([&addrs](const IP_ADAPTER_ADDRESSES& interfaces) {+    getIfAddrs.withIfAddrs([&](const IP_ADAPTER_ADDRESSES& interfaces) {       const IP_ADAPTER_ADDRESSES* networkInterface;       for (networkInterface = &interfaces; networkInterface;            networkInterface = networkInterface->Next)@@ -119,18 +121,41 @@             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));+            auto ipv4address = discovery::makeAddress<discovery::IpAddressV4>(bytes);+            addrs.emplace_back(ipv4address);+            IpInterfaceNames.insert(+              std::make_pair(networkInterface->AdapterName, ipv4address));           }-          else if (AF_INET6 == family)+        }+      }+    });++    getIfAddrs.withIfAddrs([&](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_INET6 == family+              && IpInterfaceNames.find(networkInterface->AdapterName)+                   != IpInterfaceNames.end())           {-            SOCKADDR_IN6* addr6 =+            SOCKADDR_IN6* sockAddr =               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));+            auto bytes = reinterpret_cast<const char*>(&sockAddr->sin6_addr);+            auto addr6 = discovery::makeAddress<discovery::IpAddressV6>(bytes);+            if (!addr6.is_loopback() && addr6.is_link_local())+            {+              addrs.emplace_back(addr6);+            }           }         }       }     });+     return addrs;   } };
link/include/ableton/test/serial_io/Context.hpp view
@@ -19,7 +19,7 @@  #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/test/serial_io/SchedulerTree.hpp> #include <ableton/test/serial_io/Timer.hpp> #include <ableton/util/Log.hpp>@@ -37,7 +37,7 @@ { public:   Context(const SchedulerTree::TimePoint& now,-    const std::vector<::asio::ip::address>& ifAddrs,+    const std::vector<discovery::IpAddress>& ifAddrs,     std::shared_ptr<SchedulerTree> pScheduler)     : mNow(now)     , mIfAddrs(ifAddrs)@@ -91,14 +91,14 @@     return mLog;   } -  std::vector<::asio::ip::address> scanNetworkInterfaces()+  std::vector<discovery::IpAddress> scanNetworkInterfaces()   {     return mIfAddrs;   }  private:   const SchedulerTree::TimePoint& mNow;-  const std::vector<::asio::ip::address>& mIfAddrs;+  const std::vector<discovery::IpAddress>& mIfAddrs;   std::shared_ptr<SchedulerTree> mpScheduler;   Log mLog;   SchedulerTree::TimerId mNextTimerId;
link/include/ableton/test/serial_io/Fixture.hpp view
@@ -19,7 +19,7 @@  #pragma once -#include <ableton/platforms/asio/AsioWrapper.hpp>+#include <ableton/discovery/AsioTypes.hpp> #include <ableton/test/serial_io/Context.hpp> #include <chrono> #include <memory>@@ -50,7 +50,7 @@   Fixture(Fixture&&) = delete;   Fixture& operator=(Fixture&&) = delete; -  void setNetworkInterfaces(std::vector<::asio::ip::address> ifAddrs)+  void setNetworkInterfaces(std::vector<discovery::IpAddress> ifAddrs)   {     mIfAddrs = std::move(ifAddrs);   }@@ -84,7 +84,7 @@ private:   std::shared_ptr<SchedulerTree> mpScheduler;   SchedulerTree::TimePoint mNow;-  std::vector<::asio::ip::address> mIfAddrs;+  std::vector<discovery::IpAddress> mIfAddrs; };  } // namespace serial_io
link/modules/asio-standalone/asio/include/asio.hpp view
@@ -2,7 +2,7 @@ // asio.hpp // ~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,14 +15,25 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) +#include "asio/any_completion_executor.hpp"+#include "asio/any_completion_handler.hpp"+#include "asio/any_io_executor.hpp"+#include "asio/append.hpp"+#include "asio/as_tuple.hpp" #include "asio/associated_allocator.hpp"+#include "asio/associated_cancellation_slot.hpp" #include "asio/associated_executor.hpp"+#include "asio/associated_immediate_executor.hpp"+#include "asio/associator.hpp" #include "asio/async_result.hpp" #include "asio/awaitable.hpp" #include "asio/basic_datagram_socket.hpp" #include "asio/basic_deadline_timer.hpp"+#include "asio/basic_file.hpp" #include "asio/basic_io_object.hpp"+#include "asio/basic_random_access_file.hpp" #include "asio/basic_raw_socket.hpp"+#include "asio/basic_readable_pipe.hpp" #include "asio/basic_seq_packet_socket.hpp" #include "asio/basic_serial_port.hpp" #include "asio/basic_signal_set.hpp"@@ -30,11 +41,17 @@ #include "asio/basic_socket_acceptor.hpp" #include "asio/basic_socket_iostream.hpp" #include "asio/basic_socket_streambuf.hpp"+#include "asio/basic_stream_file.hpp" #include "asio/basic_stream_socket.hpp" #include "asio/basic_streambuf.hpp" #include "asio/basic_waitable_timer.hpp"+#include "asio/basic_writable_pipe.hpp"+#include "asio/bind_allocator.hpp"+#include "asio/bind_cancellation_slot.hpp" #include "asio/bind_executor.hpp"+#include "asio/bind_immediate_executor.hpp" #include "asio/buffer.hpp"+#include "asio/buffer_registration.hpp" #include "asio/buffered_read_stream_fwd.hpp" #include "asio/buffered_read_stream.hpp" #include "asio/buffered_stream_fwd.hpp"@@ -42,13 +59,19 @@ #include "asio/buffered_write_stream_fwd.hpp" #include "asio/buffered_write_stream.hpp" #include "asio/buffers_iterator.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/cancellation_type.hpp" #include "asio/co_spawn.hpp" #include "asio/completion_condition.hpp" #include "asio/compose.hpp" #include "asio/connect.hpp"+#include "asio/connect_pipe.hpp"+#include "asio/consign.hpp" #include "asio/coroutine.hpp" #include "asio/deadline_timer.hpp" #include "asio/defer.hpp"+#include "asio/deferred.hpp" #include "asio/detached.hpp" #include "asio/dispatch.hpp" #include "asio/error.hpp"@@ -84,6 +107,7 @@ #include "asio/execution_context.hpp" #include "asio/executor.hpp" #include "asio/executor_work_guard.hpp"+#include "asio/file_base.hpp" #include "asio/generic/basic_endpoint.hpp" #include "asio/generic/datagram_protocol.hpp" #include "asio/generic/raw_protocol.hpp"@@ -122,12 +146,14 @@ #include "asio/ip/unicast.hpp" #include "asio/ip/v6_only.hpp" #include "asio/is_applicable_property.hpp"+#include "asio/is_contiguous_iterator.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/seq_packet_protocol.hpp" #include "asio/local/stream_protocol.hpp" #include "asio/multiple_exceptions.hpp" #include "asio/packaged_task.hpp"@@ -139,20 +165,27 @@ #include "asio/posix/stream_descriptor.hpp" #include "asio/post.hpp" #include "asio/prefer.hpp"+#include "asio/prepend.hpp" #include "asio/query.hpp"+#include "asio/random_access_file.hpp" #include "asio/read.hpp" #include "asio/read_at.hpp" #include "asio/read_until.hpp"+#include "asio/readable_pipe.hpp"+#include "asio/recycling_allocator.hpp" #include "asio/redirect_error.hpp"+#include "asio/registered_buffer.hpp" #include "asio/require.hpp" #include "asio/require_concept.hpp" #include "asio/serial_port.hpp" #include "asio/serial_port_base.hpp" #include "asio/signal_set.hpp"+#include "asio/signal_set_base.hpp" #include "asio/socket_base.hpp" #include "asio/static_thread_pool.hpp" #include "asio/steady_timer.hpp" #include "asio/strand.hpp"+#include "asio/stream_file.hpp" #include "asio/streambuf.hpp" #include "asio/system_context.hpp" #include "asio/system_error.hpp"@@ -176,6 +209,7 @@ #include "asio/windows/overlapped_ptr.hpp" #include "asio/windows/random_access_handle.hpp" #include "asio/windows/stream_handle.hpp"+#include "asio/writable_pipe.hpp" #include "asio/write.hpp" #include "asio/write_at.hpp" 
+ link/modules/asio-standalone/asio/include/asio/any_completion_executor.hpp view
@@ -0,0 +1,342 @@+//+// any_completion_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_COMPLETION_EXECUTOR_HPP+#define ASIO_ANY_COMPLETION_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"+#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_completion_executor;++#else // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++/// Polymorphic executor type for use with I/O objects.+/**+ * The @c any_completion_executor type is a polymorphic executor that supports+ * the set of properties required for the execution of completion handlers. It+ * is defined as the execution::any_executor class template parameterised as+ * follows:+ * @code execution::any_executor<+ *   execution::prefer_only<execution::outstanding_work_t::tracked_t>,+ *   execution::prefer_only<execution::outstanding_work_t::untracked_t>+ *   execution::prefer_only<execution::relationship_t::fork_t>,+ *   execution::prefer_only<execution::relationship_t::continuation_t>+ * > @endcode+ */+class any_completion_executor :+#if defined(GENERATING_DOCUMENTATION)+  public execution::any_executor<...>+#else // defined(GENERATING_DOCUMENTATION)+  public execution::any_executor<+      execution::prefer_only<execution::outstanding_work_t::tracked_t>,+      execution::prefer_only<execution::outstanding_work_t::untracked_t>,+      execution::prefer_only<execution::relationship_t::fork_t>,+      execution::prefer_only<execution::relationship_t::continuation_t>+    >+#endif // defined(GENERATING_DOCUMENTATION)+{+public:+#if !defined(GENERATING_DOCUMENTATION)+  typedef execution::any_executor<+      execution::prefer_only<execution::outstanding_work_t::tracked_t>,+      execution::prefer_only<execution::outstanding_work_t::untracked_t>,+      execution::prefer_only<execution::relationship_t::fork_t>,+      execution::prefer_only<execution::relationship_t::continuation_t>+    > base_type;++  typedef void supportable_properties_type(+      execution::prefer_only<execution::outstanding_work_t::tracked_t>,+      execution::prefer_only<execution::outstanding_work_t::untracked_t>,+      execution::prefer_only<execution::relationship_t::fork_t>,+      execution::prefer_only<execution::relationship_t::continuation_t>+    );+#endif // !defined(GENERATING_DOCUMENTATION)++  /// Default constructor.+  ASIO_DECL any_completion_executor() ASIO_NOEXCEPT;++  /// Construct in an empty state. Equivalent effects to default constructor.+  ASIO_DECL any_completion_executor(nullptr_t) ASIO_NOEXCEPT;++  /// Copy constructor.+  ASIO_DECL any_completion_executor(+      const any_completion_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  ASIO_DECL any_completion_executor(+      any_completion_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Construct to point to the same target as another any_executor.+#if defined(GENERATING_DOCUMENTATION)+  template <class... OtherSupportableProperties>+    any_completion_executor(+        execution::any_executor<OtherSupportableProperties...> e);+#else // defined(GENERATING_DOCUMENTATION)+  template <typename OtherAnyExecutor>+  any_completion_executor(OtherAnyExecutor e,+      typename constraint<+        conditional<+          !is_same<OtherAnyExecutor, any_completion_executor>::value+            && is_base_of<execution::detail::any_executor_base,+              OtherAnyExecutor>::value,+          typename execution::detail::supportable_properties<+            0, supportable_properties_type>::template+              is_valid_target<OtherAnyExecutor>,+          false_type+        >::type::value+      >::type = 0)+    : base_type(ASIO_MOVE_CAST(OtherAnyExecutor)(e))+  {+  }+#endif // defined(GENERATING_DOCUMENTATION)++  /// Construct to point to the same target as another any_executor.+#if defined(GENERATING_DOCUMENTATION)+  template <class... OtherSupportableProperties>+    any_completion_executor(std::nothrow_t,+      execution::any_executor<OtherSupportableProperties...> e);+#else // defined(GENERATING_DOCUMENTATION)+  template <typename OtherAnyExecutor>+  any_completion_executor(std::nothrow_t, OtherAnyExecutor e,+      typename constraint<+        conditional<+          !is_same<OtherAnyExecutor, any_completion_executor>::value+            && is_base_of<execution::detail::any_executor_base,+              OtherAnyExecutor>::value,+          typename execution::detail::supportable_properties<+            0, supportable_properties_type>::template+              is_valid_target<OtherAnyExecutor>,+          false_type+        >::type::value+      >::type = 0) ASIO_NOEXCEPT+    : base_type(std::nothrow, ASIO_MOVE_CAST(OtherAnyExecutor)(e))+  {+  }+#endif // defined(GENERATING_DOCUMENTATION)++  /// Construct to point to the same target as another any_executor.+  ASIO_DECL any_completion_executor(std::nothrow_t,+      const any_completion_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Construct to point to the same target as another any_executor.+  ASIO_DECL any_completion_executor(std::nothrow_t,+      any_completion_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Construct a polymorphic wrapper for the specified executor.+#if defined(GENERATING_DOCUMENTATION)+  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_completion_executor(Executor e);+#else // defined(GENERATING_DOCUMENTATION)+  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_completion_executor(Executor e,+      typename constraint<+        conditional<+          !is_same<Executor, any_completion_executor>::value+            && !is_base_of<execution::detail::any_executor_base,+              Executor>::value,+          execution::detail::is_valid_target_executor<+            Executor, supportable_properties_type>,+          false_type+        >::type::value+      >::type = 0)+    : base_type(ASIO_MOVE_CAST(Executor)(e))+  {+  }+#endif // defined(GENERATING_DOCUMENTATION)++  /// Construct a polymorphic wrapper for the specified executor.+#if defined(GENERATING_DOCUMENTATION)+  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_completion_executor(std::nothrow_t, Executor e);+#else // defined(GENERATING_DOCUMENTATION)+  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_completion_executor(std::nothrow_t, Executor e,+      typename constraint<+        conditional<+          !is_same<Executor, any_completion_executor>::value+            && !is_base_of<execution::detail::any_executor_base,+              Executor>::value,+          execution::detail::is_valid_target_executor<+            Executor, supportable_properties_type>,+          false_type+        >::type::value+      >::type = 0) ASIO_NOEXCEPT+    : base_type(std::nothrow, ASIO_MOVE_CAST(Executor)(e))+  {+  }+#endif // defined(GENERATING_DOCUMENTATION)++  /// Assignment operator.+  ASIO_DECL any_completion_executor& operator=(+      const any_completion_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move assignment operator.+  ASIO_DECL any_completion_executor& operator=(+      any_completion_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Assignment operator that sets the polymorphic wrapper to the empty state.+  ASIO_DECL any_completion_executor& operator=(nullptr_t);++  /// Destructor.+  ASIO_DECL ~any_completion_executor();++  /// Swap targets with another polymorphic wrapper.+  ASIO_DECL void swap(any_completion_executor& other) ASIO_NOEXCEPT;++  /// Obtain a polymorphic wrapper with the specified property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require and asio::prefer customisation points.+   *+   * For example:+   * @code any_completion_executor ex = ...;+   * auto ex2 = asio::require(ex, execution::relationship.fork); @endcode+   */+  template <typename Property>+  any_completion_executor require(const Property& p,+      typename constraint<+        traits::require_member<const base_type&, const Property&>::is_valid+      >::type = 0) const+  {+    return static_cast<const base_type&>(*this).require(p);+  }++  /// Obtain a polymorphic wrapper with the specified property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::prefer customisation point.+   *+   * For example:+   * @code any_completion_executor ex = ...;+   * auto ex2 = asio::prefer(ex, execution::relationship.fork); @endcode+   */+  template <typename Property>+  any_completion_executor prefer(const Property& p,+      typename constraint<+        traits::prefer_member<const base_type&, const Property&>::is_valid+      >::type = 0) const+  {+    return static_cast<const base_type&>(*this).prefer(p);+  }+};++#if !defined(GENERATING_DOCUMENTATION)++template <>+ASIO_DECL any_completion_executor any_completion_executor::prefer(+    const execution::outstanding_work_t::tracked_t&, int) const;++template <>+ASIO_DECL any_completion_executor any_completion_executor::prefer(+    const execution::outstanding_work_t::untracked_t&, int) const;++template <>+ASIO_DECL any_completion_executor any_completion_executor::prefer(+    const execution::relationship_t::fork_t&, int) const;++template <>+ASIO_DECL any_completion_executor any_completion_executor::prefer(+    const execution::relationship_t::continuation_t&, int) const;++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <>+struct equality_comparable<any_completion_executor>+{+  static const bool is_valid = true;+  static const bool is_noexcept = true;+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename F>+struct execute_member<any_completion_executor, F>+{+  static const bool is_valid = true;+  static const bool is_noexcept = false;+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename Prop>+struct query_member<any_completion_executor, Prop> :+  query_member<any_completion_executor::base_type, Prop>+{+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Prop>+struct require_member<any_completion_executor, Prop> :+  require_member<any_completion_executor::base_type, Prop>+{+  typedef any_completion_executor result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++template <typename Prop>+struct prefer_member<any_completion_executor, Prop> :+  prefer_member<any_completion_executor::base_type, Prop>+{+  typedef any_completion_executor result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++} // namespace traits++#endif // !defined(GENERATING_DOCUMENTATION)++#endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY) \+  && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+# include "asio/impl/any_completion_executor.ipp"+#endif // defined(ASIO_HEADER_ONLY)+       //   && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#endif // ASIO_ANY_COMPLETION_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/any_completion_handler.hpp view
@@ -0,0 +1,762 @@+//+// any_completion_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_COMPLETION_HANDLER_HPP+#define ASIO_ANY_COMPLETION_HANDLER_HPP++#include "asio/detail/config.hpp"++#if (defined(ASIO_HAS_STD_TUPLE) \+    && defined(ASIO_HAS_MOVE) \+    && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+  || defined(GENERATING_DOCUMENTATION)++#include <cstring>+#include <functional>+#include <memory>+#include <utility>+#include "asio/any_completion_executor.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/associated_executor.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/recycling_allocator.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class any_completion_handler_impl_base+{+public:+  template <typename S>+  explicit any_completion_handler_impl_base(S&& slot)+    : cancel_state_(ASIO_MOVE_CAST(S)(slot), enable_total_cancellation())+  {+  }++  cancellation_slot get_cancellation_slot() const ASIO_NOEXCEPT+  {+    return cancel_state_.slot();+  }++private:+  cancellation_state cancel_state_;+};++template <typename Handler>+class any_completion_handler_impl :+  public any_completion_handler_impl_base+{+public:+  template <typename S, typename H>+  any_completion_handler_impl(S&& slot, H&& h)+    : any_completion_handler_impl_base(ASIO_MOVE_CAST(S)(slot)),+      handler_(ASIO_MOVE_CAST(H)(h))+  {+  }++  struct uninit_deleter+  {+    typename std::allocator_traits<+      associated_allocator_t<Handler,+        asio::recycling_allocator<void>>>::template+          rebind_alloc<any_completion_handler_impl> alloc;++    void operator()(any_completion_handler_impl* ptr)+    {+      std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1);+    }+  };++  struct deleter+  {+    typename std::allocator_traits<+      associated_allocator_t<Handler,+        asio::recycling_allocator<void>>>::template+          rebind_alloc<any_completion_handler_impl> alloc;++    void operator()(any_completion_handler_impl* ptr)+    {+      std::allocator_traits<decltype(alloc)>::destroy(alloc, ptr);+      std::allocator_traits<decltype(alloc)>::deallocate(alloc, ptr, 1);+    }+  };++  template <typename S, typename H>+  static any_completion_handler_impl* create(S&& slot, H&& h)+  {+    uninit_deleter d{+        (get_associated_allocator)(h,+          asio::recycling_allocator<void>())};++    std::unique_ptr<any_completion_handler_impl, uninit_deleter> uninit_ptr(+        std::allocator_traits<decltype(d.alloc)>::allocate(d.alloc, 1), d);++    any_completion_handler_impl* ptr =+      new (uninit_ptr.get()) any_completion_handler_impl(+        ASIO_MOVE_CAST(S)(slot), ASIO_MOVE_CAST(H)(h));++    uninit_ptr.release();+    return ptr;+  }++  void destroy()+  {+    deleter d{+        (get_associated_allocator)(handler_,+          asio::recycling_allocator<void>())};++    d(this);+  }++  any_completion_executor executor(+      const any_completion_executor& candidate) const ASIO_NOEXCEPT+  {+    return any_completion_executor(std::nothrow,+        (get_associated_executor)(handler_, candidate));+  }++  void* allocate(std::size_t size, std::size_t align) const+  {+    typename std::allocator_traits<+      associated_allocator_t<Handler,+        asio::recycling_allocator<void>>>::template+          rebind_alloc<unsigned char> alloc(+            (get_associated_allocator)(handler_,+              asio::recycling_allocator<void>()));++    std::size_t space = size + align - 1;+    unsigned char* base =+      std::allocator_traits<decltype(alloc)>::allocate(+        alloc, space + sizeof(std::ptrdiff_t));++    void* p = base;+    if (detail::align(align, size, p, space))+    {+      std::ptrdiff_t off = static_cast<unsigned char*>(p) - base;+      std::memcpy(static_cast<unsigned char*>(p) + size, &off, sizeof(off));+      return p;+    }++    std::bad_alloc ex;+    asio::detail::throw_exception(ex);+    return nullptr;+  }++  void deallocate(void* p, std::size_t size, std::size_t align) const+  {+    if (p)+    {+      typename std::allocator_traits<+        associated_allocator_t<Handler,+          asio::recycling_allocator<void>>>::template+            rebind_alloc<unsigned char> alloc(+              (get_associated_allocator)(handler_,+                asio::recycling_allocator<void>()));++      std::ptrdiff_t off;+      std::memcpy(&off, static_cast<unsigned char*>(p) + size, sizeof(off));+      unsigned char* base = static_cast<unsigned char*>(p) - off;++      std::allocator_traits<decltype(alloc)>::deallocate(+          alloc, base, size + align -1 + sizeof(std::ptrdiff_t));+    }+  }++  template <typename... Args>+  void call(Args&&... args)+  {+    deleter d{+        (get_associated_allocator)(handler_,+          asio::recycling_allocator<void>())};++    std::unique_ptr<any_completion_handler_impl, deleter> ptr(this, d);+    Handler handler(ASIO_MOVE_CAST(Handler)(handler_));+    ptr.reset();++    ASIO_MOVE_CAST(Handler)(handler)(+        ASIO_MOVE_CAST(Args)(args)...);+  }++private:+  Handler handler_;+};++template <typename Signature>+class any_completion_handler_call_fn;++template <typename R, typename... Args>+class any_completion_handler_call_fn<R(Args...)>+{+public:+  using type = void(*)(any_completion_handler_impl_base*, Args...);++  constexpr any_completion_handler_call_fn(type fn)+    : call_fn_(fn)+  {+  }++  void call(any_completion_handler_impl_base* impl, Args... args) const+  {+    call_fn_(impl, ASIO_MOVE_CAST(Args)(args)...);+  }++  template <typename Handler>+  static void impl(any_completion_handler_impl_base* impl, Args... args)+  {+    static_cast<any_completion_handler_impl<Handler>*>(impl)->call(+        ASIO_MOVE_CAST(Args)(args)...);+  }++private:+  type call_fn_;+};++template <typename... Signatures>+class any_completion_handler_call_fns;++template <typename Signature>+class any_completion_handler_call_fns<Signature> :+  public any_completion_handler_call_fn<Signature>+{+public:+  using any_completion_handler_call_fn<+    Signature>::any_completion_handler_call_fn;+  using any_completion_handler_call_fn<Signature>::call;+};++template <typename Signature, typename... Signatures>+class any_completion_handler_call_fns<Signature, Signatures...> :+  public any_completion_handler_call_fn<Signature>,+  public any_completion_handler_call_fns<Signatures...>+{+public:+  template <typename CallFn, typename... CallFns>+  constexpr any_completion_handler_call_fns(CallFn fn, CallFns... fns)+    : any_completion_handler_call_fn<Signature>(fn),+      any_completion_handler_call_fns<Signatures...>(fns...)+  {+  }++  using any_completion_handler_call_fn<Signature>::call;+  using any_completion_handler_call_fns<Signatures...>::call;+};++class any_completion_handler_destroy_fn+{+public:+  using type = void(*)(any_completion_handler_impl_base*);++  constexpr any_completion_handler_destroy_fn(type fn)+    : destroy_fn_(fn)+  {+  }++  void destroy(any_completion_handler_impl_base* impl) const+  {+    destroy_fn_(impl);+  }++  template <typename Handler>+  static void impl(any_completion_handler_impl_base* impl)+  {+    static_cast<any_completion_handler_impl<Handler>*>(impl)->destroy();+  }++private:+  type destroy_fn_;+};++class any_completion_handler_executor_fn+{+public:+  using type = any_completion_executor(*)(+      any_completion_handler_impl_base*, const any_completion_executor&);++  constexpr any_completion_handler_executor_fn(type fn)+    : executor_fn_(fn)+  {+  }++  any_completion_executor executor(any_completion_handler_impl_base* impl,+      const any_completion_executor& candidate) const+  {+    return executor_fn_(impl, candidate);+  }++  template <typename Handler>+  static any_completion_executor impl(any_completion_handler_impl_base* impl,+      const any_completion_executor& candidate)+  {+    return static_cast<any_completion_handler_impl<Handler>*>(impl)->executor(+        candidate);+  }++private:+  type executor_fn_;+};++class any_completion_handler_allocate_fn+{+public:+  using type = void*(*)(any_completion_handler_impl_base*,+      std::size_t, std::size_t);++  constexpr any_completion_handler_allocate_fn(type fn)+    : allocate_fn_(fn)+  {+  }++  void* allocate(any_completion_handler_impl_base* impl,+      std::size_t size, std::size_t align) const+  {+    return allocate_fn_(impl, size, align);+  }++  template <typename Handler>+  static void* impl(any_completion_handler_impl_base* impl,+      std::size_t size, std::size_t align)+  {+    return static_cast<any_completion_handler_impl<Handler>*>(impl)->allocate(+        size, align);+  }++private:+  type allocate_fn_;+};++class any_completion_handler_deallocate_fn+{+public:+  using type = void(*)(any_completion_handler_impl_base*,+      void*, std::size_t, std::size_t);++  constexpr any_completion_handler_deallocate_fn(type fn)+    : deallocate_fn_(fn)+  {+  }++  void deallocate(any_completion_handler_impl_base* impl,+      void* p, std::size_t size, std::size_t align) const+  {+    deallocate_fn_(impl, p, size, align);+  }++  template <typename Handler>+  static void impl(any_completion_handler_impl_base* impl,+      void* p, std::size_t size, std::size_t align)+  {+    static_cast<any_completion_handler_impl<Handler>*>(impl)->deallocate(+        p, size, align);+  }++private:+  type deallocate_fn_;+};++template <typename... Signatures>+class any_completion_handler_fn_table+  : private any_completion_handler_destroy_fn,+    private any_completion_handler_executor_fn,+    private any_completion_handler_allocate_fn,+    private any_completion_handler_deallocate_fn,+    private any_completion_handler_call_fns<Signatures...>+{+public:+  template <typename... CallFns>+  constexpr any_completion_handler_fn_table(+      any_completion_handler_destroy_fn::type destroy_fn,+      any_completion_handler_executor_fn::type executor_fn,+      any_completion_handler_allocate_fn::type allocate_fn,+      any_completion_handler_deallocate_fn::type deallocate_fn,+      CallFns... call_fns)+    : any_completion_handler_destroy_fn(destroy_fn),+      any_completion_handler_executor_fn(executor_fn),+      any_completion_handler_allocate_fn(allocate_fn),+      any_completion_handler_deallocate_fn(deallocate_fn),+      any_completion_handler_call_fns<Signatures...>(call_fns...)+  {+  }++  using any_completion_handler_destroy_fn::destroy;+  using any_completion_handler_executor_fn::executor;+  using any_completion_handler_allocate_fn::allocate;+  using any_completion_handler_deallocate_fn::deallocate;+  using any_completion_handler_call_fns<Signatures...>::call;+};++template <typename Handler, typename... Signatures>+struct any_completion_handler_fn_table_instance+{+  static constexpr any_completion_handler_fn_table<Signatures...>+    value = any_completion_handler_fn_table<Signatures...>(+        &any_completion_handler_destroy_fn::impl<Handler>,+        &any_completion_handler_executor_fn::impl<Handler>,+        &any_completion_handler_allocate_fn::impl<Handler>,+        &any_completion_handler_deallocate_fn::impl<Handler>,+        &any_completion_handler_call_fn<Signatures>::template impl<Handler>...);+};++template <typename Handler, typename... Signatures>+constexpr any_completion_handler_fn_table<Signatures...>+any_completion_handler_fn_table_instance<Handler, Signatures...>::value;++} // namespace detail++template <typename... Signatures>+class any_completion_handler;++/// An allocator type that forwards memory allocation operations through an+/// instance of @c any_completion_handler.+template <typename T, typename... Signatures>+class any_completion_handler_allocator+{+private:+  template <typename...>+  friend class any_completion_handler;++  template <typename, typename...>+  friend class any_completion_handler_allocator;++  const detail::any_completion_handler_fn_table<Signatures...>* fn_table_;+  detail::any_completion_handler_impl_base* impl_;++  constexpr any_completion_handler_allocator(int,+      const any_completion_handler<Signatures...>& h) ASIO_NOEXCEPT+    : fn_table_(h.fn_table_),+      impl_(h.impl_)+  {+  }++public:+  /// The type of objects that may be allocated by the allocator.+  typedef T value_type;++  /// Rebinds an allocator to another value type.+  template <typename U>+  struct rebind+  {+    /// Specifies the type of the rebound allocator.+    typedef any_completion_handler_allocator<U, Signatures...> other;+  };++  /// Construct from another @c any_completion_handler_allocator.+  template <typename U>+  constexpr any_completion_handler_allocator(+      const any_completion_handler_allocator<U, Signatures...>& a)+    ASIO_NOEXCEPT+    : fn_table_(a.fn_table_),+      impl_(a.impl_)+  {+  }++  /// Equality operator.+  constexpr bool operator==(+      const any_completion_handler_allocator& other) const ASIO_NOEXCEPT+  {+    return fn_table_ == other.fn_table_ && impl_ == other.impl_;+  }++  /// Inequality operator.+  constexpr bool operator!=(+      const any_completion_handler_allocator& other) const ASIO_NOEXCEPT+  {+    return fn_table_ != other.fn_table_ || impl_ != other.impl_;+  }++  /// Allocate space for @c n objects of the allocator's value type.+  T* allocate(std::size_t n) const+  {+    return static_cast<T*>(+        fn_table_->allocate(+          impl_, sizeof(T) * n, alignof(T)));+  }++  /// Deallocate space for @c n objects of the allocator's value type.+  void deallocate(T* p, std::size_t n) const+  {+    fn_table_->deallocate(impl_, p, sizeof(T) * n, alignof(T));+  }+};++/// A protoco-allocator type that may be rebound to obtain an allocator that+/// forwards memory allocation operations through an instance of+/// @c any_completion_handler.+template <typename... Signatures>+class any_completion_handler_allocator<void, Signatures...>+{+private:+  template <typename...>+  friend class any_completion_handler;++  template <typename, typename...>+  friend class any_completion_handler_allocator;++  const detail::any_completion_handler_fn_table<Signatures...>* fn_table_;+  detail::any_completion_handler_impl_base* impl_;++  constexpr any_completion_handler_allocator(int,+      const any_completion_handler<Signatures...>& h) ASIO_NOEXCEPT+    : fn_table_(h.fn_table_),+      impl_(h.impl_)+  {+  }++public:+  /// @c void as no objects can be allocated through a proto-allocator.+  typedef void value_type;++  /// Rebinds an allocator to another value type.+  template <typename U>+  struct rebind+  {+    /// Specifies the type of the rebound allocator.+    typedef any_completion_handler_allocator<U, Signatures...> other;+  };++  /// Construct from another @c any_completion_handler_allocator.+  template <typename U>+  constexpr any_completion_handler_allocator(+      const any_completion_handler_allocator<U, Signatures...>& a)+    ASIO_NOEXCEPT+    : fn_table_(a.fn_table_),+      impl_(a.impl_)+  {+  }++  /// Equality operator.+  constexpr bool operator==(+      const any_completion_handler_allocator& other) const ASIO_NOEXCEPT+  {+    return fn_table_ == other.fn_table_ && impl_ == other.impl_;+  }++  /// Inequality operator.+  constexpr bool operator!=(+      const any_completion_handler_allocator& other) const ASIO_NOEXCEPT+  {+    return fn_table_ != other.fn_table_ || impl_ != other.impl_;+  }+};++/// Polymorphic wrapper for completion handlers.+/**+ * The @c any_completion_handler class template is a polymorphic wrapper for+ * completion handlers that propagates the associated executor, associated+ * allocator, and associated cancellation slot through a type-erasing interface.+ *+ * When using @c any_completion_handler, specify one or more completion+ * signatures as template parameters. These will dictate the arguments that may+ * be passed to the handler through the polymorphic interface.+ *+ * Typical uses for @c any_completion_handler include:+ *+ * @li Separate compilation of asynchronous operation implementations.+ *+ * @li Enabling interoperability between asynchronous operations and virtual+ *     functions.+ */+template <typename... Signatures>+class any_completion_handler+{+#if !defined(GENERATING_DOCUMENTATION)+private:+  template <typename, typename...>+  friend class any_completion_handler_allocator;++  template <typename, typename>+  friend struct associated_executor;++  const detail::any_completion_handler_fn_table<Signatures...>* fn_table_;+  detail::any_completion_handler_impl_base* impl_;+#endif // !defined(GENERATING_DOCUMENTATION)++public:+  /// The associated allocator type.+  using allocator_type = any_completion_handler_allocator<void, Signatures...>;++  /// The associated cancellation slot type.+  using cancellation_slot_type = cancellation_slot;++  /// Construct an @c any_completion_handler in an empty state, without a target+  /// object.+  constexpr any_completion_handler()+    : fn_table_(nullptr),+      impl_(nullptr)+  {+  }++  /// Construct an @c any_completion_handler in an empty state, without a target+  /// object.+  constexpr any_completion_handler(nullptr_t)+    : fn_table_(nullptr),+      impl_(nullptr)+  {+  }++  /// Construct an @c any_completion_handler to contain the specified target.+  template <typename H, typename Handler = typename decay<H>::type>+  any_completion_handler(H&& h,+      typename constraint<+        !is_same<typename decay<H>::type, any_completion_handler>::value+      >::type = 0)+    : fn_table_(+        &detail::any_completion_handler_fn_table_instance<+          Handler, Signatures...>::value),+      impl_(detail::any_completion_handler_impl<Handler>::create(+            (get_associated_cancellation_slot)(h), ASIO_MOVE_CAST(H)(h)))+  {+  }++  /// Move-construct an @c any_completion_handler from another.+  /**+   * After the operation, the moved-from object @c other has no target.+   */+  any_completion_handler(any_completion_handler&& other) ASIO_NOEXCEPT+    : fn_table_(other.fn_table_),+      impl_(other.impl_)+  {+    other.fn_table_ = nullptr;+    other.impl_ = nullptr;+  }++  /// Move-assign an @c any_completion_handler from another.+  /**+   * After the operation, the moved-from object @c other has no target.+   */+  any_completion_handler& operator=(+      any_completion_handler&& other) ASIO_NOEXCEPT+  {+    any_completion_handler(+        ASIO_MOVE_CAST(any_completion_handler)(other)).swap(*this);+    return *this;+  }++  /// Assignment operator that sets the polymorphic wrapper to the empty state.+  any_completion_handler& operator=(nullptr_t) ASIO_NOEXCEPT+  {+    any_completion_handler().swap(*this);+    return *this;+  }++  /// Destructor.+  ~any_completion_handler()+  {+    if (impl_)+      fn_table_->destroy(impl_);+  }++  /// Test if the polymorphic wrapper is empty.+  constexpr explicit operator bool() const ASIO_NOEXCEPT+  {+    return impl_ != nullptr;+  }++  /// Test if the polymorphic wrapper is non-empty.+  constexpr bool operator!() const ASIO_NOEXCEPT+  {+    return impl_ == nullptr;+  }++  /// Swap the content of an @c any_completion_handler with another.+  void swap(any_completion_handler& other) ASIO_NOEXCEPT+  {+    std::swap(fn_table_, other.fn_table_);+    std::swap(impl_, other.impl_);+  }++  /// Get the associated allocator.+  allocator_type get_allocator() const ASIO_NOEXCEPT+  {+    return allocator_type(0, *this);+  }++  /// Get the associated cancellation slot.+  cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+  {+    return impl_->get_cancellation_slot();+  }++  /// Function call operator.+  /**+   * Invokes target completion handler with the supplied arguments.+   *+   * This function may only be called once, as the target handler is moved from.+   * The polymorphic wrapper is left in an empty state.+   *+   * Throws @c std::bad_function_call if the polymorphic wrapper is empty.+   */+  template <typename... Args>+  auto operator()(Args&&... args)+    -> decltype(fn_table_->call(impl_, ASIO_MOVE_CAST(Args)(args)...))+  {+    if (detail::any_completion_handler_impl_base* impl = impl_)+    {+      impl_ = nullptr;+      return fn_table_->call(impl, ASIO_MOVE_CAST(Args)(args)...);+    }+    std::bad_function_call ex;+    asio::detail::throw_exception(ex);+  }++  /// Equality operator.+  friend constexpr bool operator==(+      const any_completion_handler& a, nullptr_t) ASIO_NOEXCEPT+  {+    return a.impl_ == nullptr;+  }++  /// Equality operator.+  friend constexpr bool operator==(+      nullptr_t, const any_completion_handler& b) ASIO_NOEXCEPT+  {+    return nullptr == b.impl_;+  }++  /// Inequality operator.+  friend constexpr bool operator!=(+      const any_completion_handler& a, nullptr_t) ASIO_NOEXCEPT+  {+    return a.impl_ != nullptr;+  }++  /// Inequality operator.+  friend constexpr bool operator!=(+      nullptr_t, const any_completion_handler& b) ASIO_NOEXCEPT+  {+    return nullptr != b.impl_;+  }+};++template <typename... Signatures, typename Candidate>+struct associated_executor<any_completion_handler<Signatures...>, Candidate>+{+  using type = any_completion_executor;++  static type get(const any_completion_handler<Signatures...>& handler,+      const Candidate& candidate = Candidate()) ASIO_NOEXCEPT+  {+    return handler.fn_table_->executor(handler.impl_,+        any_completion_executor(std::nothrow, candidate));+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+       //     && defined(ASIO_HAS_MOVE)+       //     && defined(ASIO_HAS_VARIADIC_TEMPLATES))+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_ANY_COMPLETION_HANDLER_HPP
link/modules/asio-standalone/asio/include/asio/any_io_executor.hpp view
@@ -2,7 +2,7 @@ // any_io_executor.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -48,24 +48,312 @@  *   execution::prefer_only<execution::relationship_t::continuation_t>  * > @endcode  */+class any_io_executor : #if defined(GENERATING_DOCUMENTATION)-typedef execution::any_executor<...> any_io_executor;+  public execution::any_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;+  public execution::any_executor<+      execution::context_as_t<execution_context&>,+      execution::blocking_t::never_t,+      execution::prefer_only<execution::blocking_t::possibly_t>,+      execution::prefer_only<execution::outstanding_work_t::tracked_t>,+      execution::prefer_only<execution::outstanding_work_t::untracked_t>,+      execution::prefer_only<execution::relationship_t::fork_t>,+      execution::prefer_only<execution::relationship_t::continuation_t>+    > #endif // defined(GENERATING_DOCUMENTATION)+{+public:+#if !defined(GENERATING_DOCUMENTATION)+  typedef execution::any_executor<+      execution::context_as_t<execution_context&>,+      execution::blocking_t::never_t,+      execution::prefer_only<execution::blocking_t::possibly_t>,+      execution::prefer_only<execution::outstanding_work_t::tracked_t>,+      execution::prefer_only<execution::outstanding_work_t::untracked_t>,+      execution::prefer_only<execution::relationship_t::fork_t>,+      execution::prefer_only<execution::relationship_t::continuation_t>+    > base_type; +  typedef void supportable_properties_type(+      execution::context_as_t<execution_context&>,+      execution::blocking_t::never_t,+      execution::prefer_only<execution::blocking_t::possibly_t>,+      execution::prefer_only<execution::outstanding_work_t::tracked_t>,+      execution::prefer_only<execution::outstanding_work_t::untracked_t>,+      execution::prefer_only<execution::relationship_t::fork_t>,+      execution::prefer_only<execution::relationship_t::continuation_t>+    );+#endif // !defined(GENERATING_DOCUMENTATION)++  /// Default constructor.+  ASIO_DECL any_io_executor() ASIO_NOEXCEPT;++  /// Construct in an empty state. Equivalent effects to default constructor.+  ASIO_DECL any_io_executor(nullptr_t) ASIO_NOEXCEPT;++  /// Copy constructor.+  ASIO_DECL any_io_executor(const any_io_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  ASIO_DECL any_io_executor(any_io_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Construct to point to the same target as another any_executor.+#if defined(GENERATING_DOCUMENTATION)+  template <class... OtherSupportableProperties>+    any_io_executor(execution::any_executor<OtherSupportableProperties...> e);+#else // defined(GENERATING_DOCUMENTATION)+  template <typename OtherAnyExecutor>+  any_io_executor(OtherAnyExecutor e,+      typename constraint<+        conditional<+          !is_same<OtherAnyExecutor, any_io_executor>::value+            && is_base_of<execution::detail::any_executor_base,+              OtherAnyExecutor>::value,+          typename execution::detail::supportable_properties<+            0, supportable_properties_type>::template+              is_valid_target<OtherAnyExecutor>,+          false_type+        >::type::value+      >::type = 0)+    : base_type(ASIO_MOVE_CAST(OtherAnyExecutor)(e))+  {+  }+#endif // defined(GENERATING_DOCUMENTATION)++  /// Construct to point to the same target as another any_executor.+#if defined(GENERATING_DOCUMENTATION)+  template <class... OtherSupportableProperties>+    any_io_executor(std::nothrow_t,+      execution::any_executor<OtherSupportableProperties...> e);+#else // defined(GENERATING_DOCUMENTATION)+  template <typename OtherAnyExecutor>+  any_io_executor(std::nothrow_t, OtherAnyExecutor e,+      typename constraint<+        conditional<+          !is_same<OtherAnyExecutor, any_io_executor>::value+            && is_base_of<execution::detail::any_executor_base,+              OtherAnyExecutor>::value,+          typename execution::detail::supportable_properties<+            0, supportable_properties_type>::template+              is_valid_target<OtherAnyExecutor>,+          false_type+        >::type::value+      >::type = 0) ASIO_NOEXCEPT+    : base_type(std::nothrow, ASIO_MOVE_CAST(OtherAnyExecutor)(e))+  {+  }+#endif // defined(GENERATING_DOCUMENTATION)++  /// Construct to point to the same target as another any_executor.+  ASIO_DECL any_io_executor(std::nothrow_t,+      const any_io_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Construct to point to the same target as another any_executor.+  ASIO_DECL any_io_executor(std::nothrow_t,+      any_io_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Construct a polymorphic wrapper for the specified executor.+#if defined(GENERATING_DOCUMENTATION)+  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_io_executor(Executor e);+#else // defined(GENERATING_DOCUMENTATION)+  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_io_executor(Executor e,+      typename constraint<+        conditional<+          !is_same<Executor, any_io_executor>::value+            && !is_base_of<execution::detail::any_executor_base,+              Executor>::value,+          execution::detail::is_valid_target_executor<+            Executor, supportable_properties_type>,+          false_type+        >::type::value+      >::type = 0)+    : base_type(ASIO_MOVE_CAST(Executor)(e))+  {+  }+#endif // defined(GENERATING_DOCUMENTATION)++  /// Construct a polymorphic wrapper for the specified executor.+#if defined(GENERATING_DOCUMENTATION)+  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_io_executor(std::nothrow_t, Executor e);+#else // defined(GENERATING_DOCUMENTATION)+  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_io_executor(std::nothrow_t, Executor e,+      typename constraint<+        conditional<+          !is_same<Executor, any_io_executor>::value+            && !is_base_of<execution::detail::any_executor_base,+              Executor>::value,+          execution::detail::is_valid_target_executor<+            Executor, supportable_properties_type>,+          false_type+        >::type::value+      >::type = 0) ASIO_NOEXCEPT+    : base_type(std::nothrow, ASIO_MOVE_CAST(Executor)(e))+  {+  }+#endif // defined(GENERATING_DOCUMENTATION)++  /// Assignment operator.+  ASIO_DECL any_io_executor& operator=(+      const any_io_executor& e) ASIO_NOEXCEPT;++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move assignment operator.+  ASIO_DECL any_io_executor& operator=(+      any_io_executor&& e) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Assignment operator that sets the polymorphic wrapper to the empty state.+  ASIO_DECL any_io_executor& operator=(nullptr_t);++  /// Destructor.+  ASIO_DECL ~any_io_executor();++  /// Swap targets with another polymorphic wrapper.+  ASIO_DECL void swap(any_io_executor& other) ASIO_NOEXCEPT;++  /// Obtain a polymorphic wrapper with the specified property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::require and asio::prefer customisation points.+   *+   * For example:+   * @code any_io_executor ex = ...;+   * auto ex2 = asio::require(ex, execution::blocking.possibly); @endcode+   */+  template <typename Property>+  any_io_executor require(const Property& p,+      typename constraint<+        traits::require_member<const base_type&, const Property&>::is_valid+      >::type = 0) const+  {+    return static_cast<const base_type&>(*this).require(p);+  }++  /// Obtain a polymorphic wrapper with the specified property.+  /**+   * Do not call this function directly. It is intended for use with the+   * asio::prefer customisation point.+   *+   * For example:+   * @code any_io_executor ex = ...;+   * auto ex2 = asio::prefer(ex, execution::blocking.possibly); @endcode+   */+  template <typename Property>+  any_io_executor prefer(const Property& p,+      typename constraint<+        traits::prefer_member<const base_type&, const Property&>::is_valid+      >::type = 0) const+  {+    return static_cast<const base_type&>(*this).prefer(p);+  }+};++#if !defined(GENERATING_DOCUMENTATION)++template <>+ASIO_DECL any_io_executor any_io_executor::require(+    const execution::blocking_t::never_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+    const execution::blocking_t::possibly_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+    const execution::outstanding_work_t::tracked_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+    const execution::outstanding_work_t::untracked_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+    const execution::relationship_t::fork_t&, int) const;++template <>+ASIO_DECL any_io_executor any_io_executor::prefer(+    const execution::relationship_t::continuation_t&, int) const;++namespace traits {++#if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++template <>+struct equality_comparable<any_io_executor>+{+  static const bool is_valid = true;+  static const bool is_noexcept = true;+};++#endif // !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++template <typename F>+struct execute_member<any_io_executor, F>+{+  static const bool is_valid = true;+  static const bool is_noexcept = false;+  typedef void result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename Prop>+struct query_member<any_io_executor, Prop> :+  query_member<any_io_executor::base_type, Prop>+{+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++template <typename Prop>+struct require_member<any_io_executor, Prop> :+  require_member<any_io_executor::base_type, Prop>+{+  typedef any_io_executor result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++template <typename Prop>+struct prefer_member<any_io_executor, Prop> :+  prefer_member<any_io_executor::base_type, Prop>+{+  typedef any_io_executor result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)++} // namespace traits++#endif // !defined(GENERATING_DOCUMENTATION)+ #endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)  } // namespace asio  #include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY) \+  && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+# include "asio/impl/any_io_executor.ipp"+#endif // defined(ASIO_HEADER_ONLY)+       //   && !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)  #endif // ASIO_ANY_IO_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/append.hpp view
@@ -0,0 +1,78 @@+//+// append.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_APPEND_HPP+#define ASIO_APPEND_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_TUPLE) \+    && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+  || defined(GENERATING_DOCUMENTATION)++#include <tuple>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Completion token type used to specify that the completion handler+/// arguments should be passed additional values after the results of the+/// operation.+template <typename CompletionToken, typename... Values>+class append_t+{+public:+  /// Constructor.+  template <typename T, typename... V>+  ASIO_CONSTEXPR explicit append_t(+      ASIO_MOVE_ARG(T) completion_token,+      ASIO_MOVE_ARG(V)... values)+    : token_(ASIO_MOVE_CAST(T)(completion_token)),+      values_(ASIO_MOVE_CAST(V)(values)...)+  {+  }++//private:+  CompletionToken token_;+  std::tuple<Values...> values_;+};++/// Completion token type used to specify that the completion handler+/// arguments should be passed additional values after the results of the+/// operation.+template <typename CompletionToken, typename... Values>+ASIO_NODISCARD inline ASIO_CONSTEXPR append_t<+  typename decay<CompletionToken>::type, typename decay<Values>::type...>+append(ASIO_MOVE_ARG(CompletionToken) completion_token,+    ASIO_MOVE_ARG(Values)... values)+{+  return append_t<+    typename decay<CompletionToken>::type, typename decay<Values>::type...>(+      ASIO_MOVE_CAST(CompletionToken)(completion_token),+      ASIO_MOVE_CAST(Values)(values)...);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/append.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+       //     && defined(ASIO_HAS_VARIADIC_TEMPLATES))+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_APPEND_HPP
+ link/modules/asio-standalone/asio/include/asio/as_tuple.hpp view
@@ -0,0 +1,139 @@+//+// as_tuple.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_AS_TUPLE_HPP+#define ASIO_AS_TUPLE_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_TUPLE) \+    && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// A @ref completion_token adapter used to specify that the completion handler+/// arguments should be combined into a single tuple argument.+/**+ * The as_tuple_t class is used to indicate that any arguments to the+ * completion handler should be combined and passed as a single tuple argument.+ * The arguments are first moved into a @c std::tuple and that tuple is then+ * passed to the completion handler.+ */+template <typename CompletionToken>+class as_tuple_t+{+public:+  /// Tag type used to prevent the "default" constructor from being used for+  /// conversions.+  struct default_constructor_tag {};++  /// Default constructor.+  /**+   * This constructor is only valid if the underlying completion token is+   * default constructible and move constructible. The underlying completion+   * token is itself defaulted as an argument to allow it to capture a source+   * location.+   */+  ASIO_CONSTEXPR as_tuple_t(+      default_constructor_tag = default_constructor_tag(),+      CompletionToken token = CompletionToken())+    : token_(ASIO_MOVE_CAST(CompletionToken)(token))+  {+  }++  /// Constructor.+  template <typename T>+  ASIO_CONSTEXPR explicit as_tuple_t(+      ASIO_MOVE_ARG(T) completion_token)+    : token_(ASIO_MOVE_CAST(T)(completion_token))+  {+  }++  /// Adapts an executor to add the @c as_tuple_t completion token as the+  /// default.+  template <typename InnerExecutor>+  struct executor_with_default : InnerExecutor+  {+    /// Specify @c as_tuple_t as the default completion token type.+    typedef as_tuple_t default_completion_token_type;++    /// Construct the adapted executor from the inner executor type.+    template <typename InnerExecutor1>+    executor_with_default(const InnerExecutor1& ex,+        typename constraint<+          conditional<+            !is_same<InnerExecutor1, executor_with_default>::value,+            is_convertible<InnerExecutor1, InnerExecutor>,+            false_type+          >::type::value+        >::type = 0) ASIO_NOEXCEPT+      : InnerExecutor(ex)+    {+    }+  };++  /// Type alias to adapt an I/O object to use @c as_tuple_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 as_tuple_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));+  }++//private:+  CompletionToken token_;+};++/// Adapt a @ref completion_token to specify that the completion handler+/// arguments should be combined into a single tuple argument.+template <typename CompletionToken>+ASIO_NODISCARD inline+ASIO_CONSTEXPR as_tuple_t<typename decay<CompletionToken>::type>+as_tuple(ASIO_MOVE_ARG(CompletionToken) completion_token)+{+  return as_tuple_t<typename decay<CompletionToken>::type>(+      ASIO_MOVE_CAST(CompletionToken)(completion_token));+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/as_tuple.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+       //     && defined(ASIO_HAS_VARIADIC_TEMPLATES))+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_AS_TUPLE_HPP
link/modules/asio-standalone/asio/include/asio/associated_allocator.hpp view
@@ -2,7 +2,7 @@ // associated_allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,36 +17,81 @@  #include "asio/detail/config.hpp" #include <memory>+#include "asio/associator.hpp"+#include "asio/detail/functional.hpp" #include "asio/detail/type_traits.hpp"  #include "asio/detail/push_options.hpp"  namespace asio {++template <typename T, typename Allocator>+struct associated_allocator;+ namespace detail { -template <typename T, typename E, typename = void>+template <typename T, typename = void>+struct has_allocator_type : false_type+{+};++template <typename T>+struct has_allocator_type<T,+  typename void_type<typename T::allocator_type>::type>+    : true_type+{+};++template <typename T, typename A, typename = void, typename = void> struct associated_allocator_impl {-  typedef E type;+  typedef void asio_associated_allocator_is_unspecialised; -  static type get(const T&, const E& e) ASIO_NOEXCEPT+  typedef A type;++  static type get(const T&) ASIO_NOEXCEPT   {-    return e;+    return type();   }++  static const type& get(const T&, const A& a) ASIO_NOEXCEPT+  {+    return a;+  } }; -template <typename T, typename E>-struct associated_allocator_impl<T, E,+template <typename T, typename A>+struct associated_allocator_impl<T, A,   typename void_type<typename T::allocator_type>::type> {   typedef typename T::allocator_type type; -  static type get(const T& t, const E&) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const T& t) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_allocator()))   {     return t.get_allocator();   }++  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const T& t, const A&) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_allocator()))+  {+    return t.get_allocator();+  } }; +template <typename T, typename A>+struct associated_allocator_impl<T, A,+  typename enable_if<+    !has_allocator_type<T>::value+  >::type,+  typename void_type<+    typename associator<associated_allocator, T, A>::type+  >::type> : associator<associated_allocator, T, A>+{+};+ } // namespace detail  /// Traits type used to obtain the allocator associated with an object.@@ -63,29 +108,32 @@  * Allocator requirements.  *  * @li Provide a noexcept static member function named @c get, callable as @c- * get(t) and with return type @c type.+ * get(t) and with return type @c type or a (possibly const) reference to @c+ * type.  *  * @li Provide a noexcept static member function named @c get, callable as @c- * get(t,a) and with return type @c type.+ * get(t,a) and with return type @c type or a (possibly const) reference to @c+ * type.  */ template <typename T, typename Allocator = std::allocator<void> > struct associated_allocator+#if !defined(GENERATING_DOCUMENTATION)+  : detail::associated_allocator_impl<T, Allocator>+#endif // !defined(GENERATING_DOCUMENTATION) {+#if defined(GENERATING_DOCUMENTATION)   /// 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 type().+  static decltype(auto) get(const T& t) ASIO_NOEXCEPT;++  /// 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);-  }+  static decltype(auto) get(const T& t, const Allocator& a) ASIO_NOEXCEPT;+#endif // defined(GENERATING_DOCUMENTATION) };  /// Helper function to obtain an object's associated allocator.@@ -93,7 +141,7 @@  * @returns <tt>associated_allocator<T>::get(t)</tt>  */ template <typename T>-inline typename associated_allocator<T>::type+ASIO_NODISCARD inline typename associated_allocator<T>::type get_associated_allocator(const T& t) ASIO_NOEXCEPT {   return associated_allocator<T>::get(t);@@ -104,8 +152,11 @@  * @returns <tt>associated_allocator<T, Allocator>::get(t, a)</tt>  */ template <typename T, typename Allocator>-inline typename associated_allocator<T, Allocator>::type+ASIO_NODISCARD inline ASIO_AUTO_RETURN_TYPE_PREFIX2(+    typename associated_allocator<T, Allocator>::type) get_associated_allocator(const T& t, const Allocator& a) ASIO_NOEXCEPT+  ASIO_AUTO_RETURN_TYPE_SUFFIX((+    associated_allocator<T, Allocator>::get(t, a))) {   return associated_allocator<T, Allocator>::get(t, a); }@@ -117,6 +168,63 @@   = typename associated_allocator<T, Allocator>::type;  #endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++namespace detail {++template <typename T, typename A, typename = void>+struct associated_allocator_forwarding_base+{+};++template <typename T, typename A>+struct associated_allocator_forwarding_base<T, A,+    typename enable_if<+      is_same<+        typename associated_allocator<T,+          A>::asio_associated_allocator_is_unspecialised,+        void+      >::value+    >::type>+{+  typedef void asio_associated_allocator_is_unspecialised;+};++} // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \+  || defined(GENERATING_DOCUMENTATION)++/// Specialisation of associated_allocator for @c std::reference_wrapper.+template <typename T, typename Allocator>+struct associated_allocator<reference_wrapper<T>, Allocator>+#if !defined(GENERATING_DOCUMENTATION)+  : detail::associated_allocator_forwarding_base<T, Allocator>+#endif // !defined(GENERATING_DOCUMENTATION)+{+  /// Forwards @c type to the associator specialisation for the unwrapped type+  /// @c T.+  typedef typename associated_allocator<T, Allocator>::type type;++  /// Forwards the request to get the allocator to the associator specialisation+  /// for the unwrapped type @c T.+  static type get(reference_wrapper<T> t) ASIO_NOEXCEPT+  {+    return associated_allocator<T, Allocator>::get(t.get());+  }++  /// Forwards the request to get the allocator to the associator specialisation+  /// for the unwrapped type @c T.+  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      reference_wrapper<T> t, const Allocator& a) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      associated_allocator<T, Allocator>::get(t.get(), a)))+  {+    return associated_allocator<T, Allocator>::get(t.get(), a);+  }+};++#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+       //   || defined(GENERATING_DOCUMENTATION)  } // namespace asio 
+ link/modules/asio-standalone/asio/include/asio/associated_cancellation_slot.hpp view
@@ -0,0 +1,238 @@+//+// associated_cancellation_slot.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP+#define ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associator.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/detail/functional.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename T, typename CancellationSlot>+struct associated_cancellation_slot;++namespace detail {++template <typename T, typename = void>+struct has_cancellation_slot_type : false_type+{+};++template <typename T>+struct has_cancellation_slot_type<T,+  typename void_type<typename T::cancellation_slot_type>::type>+    : true_type+{+};++template <typename T, typename S, typename = void, typename = void>+struct associated_cancellation_slot_impl+{+  typedef void asio_associated_cancellation_slot_is_unspecialised;++  typedef S type;++  static type get(const T&) ASIO_NOEXCEPT+  {+    return type();+  }++  static const type& get(const T&, const S& s) ASIO_NOEXCEPT+  {+    return s;+  }+};++template <typename T, typename S>+struct associated_cancellation_slot_impl<T, S,+  typename void_type<typename T::cancellation_slot_type>::type>+{+  typedef typename T::cancellation_slot_type type;++  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const T& t) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_cancellation_slot()))+  {+    return t.get_cancellation_slot();+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const T& t, const S&) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_cancellation_slot()))+  {+    return t.get_cancellation_slot();+  }+};++template <typename T, typename S>+struct associated_cancellation_slot_impl<T, S,+  typename enable_if<+    !has_cancellation_slot_type<T>::value+  >::type,+  typename void_type<+    typename associator<associated_cancellation_slot, T, S>::type+  >::type> : associator<associated_cancellation_slot, T, S>+{+};++} // namespace detail++/// Traits type used to obtain the cancellation_slot associated with an object.+/**+ * A program may specialise this traits type if the @c T template parameter in+ * the specialisation is a user-defined type. The template parameter @c+ * CancellationSlot shall be a type meeting the CancellationSlot requirements.+ *+ * Specialisations shall meet the following requirements, where @c t is a const+ * reference to an object of type @c T, and @c s is an object of type @c+ * CancellationSlot.+ *+ * @li Provide a nested typedef @c type that identifies a type meeting the+ * CancellationSlot requirements.+ *+ * @li Provide a noexcept static member function named @c get, callable as @c+ * get(t) and with return type @c type or a (possibly const) reference to @c+ * type.+ *+ * @li Provide a noexcept static member function named @c get, callable as @c+ * get(t,s) and with return type @c type or a (possibly const) reference to @c+ * type.+ */+template <typename T, typename CancellationSlot = cancellation_slot>+struct associated_cancellation_slot+#if !defined(GENERATING_DOCUMENTATION)+  : detail::associated_cancellation_slot_impl<T, CancellationSlot>+#endif // !defined(GENERATING_DOCUMENTATION)+{+#if defined(GENERATING_DOCUMENTATION)+  /// If @c T has a nested type @c cancellation_slot_type,+  /// <tt>T::cancellation_slot_type</tt>. Otherwise+  /// @c CancellationSlot.+  typedef see_below type;++  /// If @c T has a nested type @c cancellation_slot_type, returns+  /// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c type().+  static decltype(auto) get(const T& t) ASIO_NOEXCEPT;++  /// If @c T has a nested type @c cancellation_slot_type, returns+  /// <tt>t.get_cancellation_slot()</tt>. Otherwise returns @c s.+  static decltype(auto) get(const T& t,+      const CancellationSlot& s) ASIO_NOEXCEPT;+#endif // defined(GENERATING_DOCUMENTATION)+};++/// Helper function to obtain an object's associated cancellation_slot.+/**+ * @returns <tt>associated_cancellation_slot<T>::get(t)</tt>+ */+template <typename T>+ASIO_NODISCARD inline typename associated_cancellation_slot<T>::type+get_associated_cancellation_slot(const T& t) ASIO_NOEXCEPT+{+  return associated_cancellation_slot<T>::get(t);+}++/// Helper function to obtain an object's associated cancellation_slot.+/**+ * @returns <tt>associated_cancellation_slot<T,+ * CancellationSlot>::get(t, st)</tt>+ */+template <typename T, typename CancellationSlot>+ASIO_NODISCARD inline ASIO_AUTO_RETURN_TYPE_PREFIX2(+    typename associated_cancellation_slot<T, CancellationSlot>::type)+get_associated_cancellation_slot(const T& t,+    const CancellationSlot& st) ASIO_NOEXCEPT+  ASIO_AUTO_RETURN_TYPE_SUFFIX((+    associated_cancellation_slot<T, CancellationSlot>::get(t, st)))+{+  return associated_cancellation_slot<T, CancellationSlot>::get(t, st);+}++#if defined(ASIO_HAS_ALIAS_TEMPLATES)++template <typename T, typename CancellationSlot = cancellation_slot>+using associated_cancellation_slot_t =+  typename associated_cancellation_slot<T, CancellationSlot>::type;++#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++namespace detail {++template <typename T, typename S, typename = void>+struct associated_cancellation_slot_forwarding_base+{+};++template <typename T, typename S>+struct associated_cancellation_slot_forwarding_base<T, S,+    typename enable_if<+      is_same<+        typename associated_cancellation_slot<T,+          S>::asio_associated_cancellation_slot_is_unspecialised,+        void+      >::value+    >::type>+{+  typedef void asio_associated_cancellation_slot_is_unspecialised;+};++} // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \+  || defined(GENERATING_DOCUMENTATION)++/// Specialisation of associated_cancellation_slot for @c+/// std::reference_wrapper.+template <typename T, typename CancellationSlot>+struct associated_cancellation_slot<reference_wrapper<T>, CancellationSlot>+#if !defined(GENERATING_DOCUMENTATION)+  : detail::associated_cancellation_slot_forwarding_base<T, CancellationSlot>+#endif // !defined(GENERATING_DOCUMENTATION)+{+  /// Forwards @c type to the associator specialisation for the unwrapped type+  /// @c T.+  typedef typename associated_cancellation_slot<T, CancellationSlot>::type type;++  /// Forwards the request to get the cancellation slot to the associator+  /// specialisation for the unwrapped type @c T.+  static type get(reference_wrapper<T> t) ASIO_NOEXCEPT+  {+    return associated_cancellation_slot<T, CancellationSlot>::get(t.get());+  }++  /// Forwards the request to get the cancellation slot to the associator+  /// specialisation for the unwrapped type @c T.+  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(reference_wrapper<T> t,+      const CancellationSlot& s) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      associated_cancellation_slot<T, CancellationSlot>::get(t.get(), s)))+  {+    return associated_cancellation_slot<T, CancellationSlot>::get(t.get(), s);+  }+};++#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+       //   || defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ASSOCIATED_CANCELLATION_SLOT_HPP
link/modules/asio-standalone/asio/include/asio/associated_executor.hpp view
@@ -2,7 +2,7 @@ // associated_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,8 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"+#include "asio/associator.hpp"+#include "asio/detail/functional.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp"@@ -24,17 +26,38 @@ #include "asio/detail/push_options.hpp"  namespace asio {++template <typename T, typename Executor>+struct associated_executor;+ namespace detail { -template <typename T, typename E, typename = void>+template <typename T, typename = void>+struct has_executor_type : false_type+{+};++template <typename T>+struct has_executor_type<T,+  typename void_type<typename T::executor_type>::type>+    : true_type+{+};++template <typename T, typename E, typename = void, typename = void> struct associated_executor_impl {   typedef void asio_associated_executor_is_unspecialised;    typedef E type; -  static type get(const T&, const E& e = E()) ASIO_NOEXCEPT+  static type get(const T&) ASIO_NOEXCEPT   {+    return type();+  }++  static const type& get(const T&, const E& e) ASIO_NOEXCEPT+  {     return e;   } };@@ -45,12 +68,32 @@ {   typedef typename T::executor_type type; -  static type get(const T& t, const E& = E()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const T& t) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_executor()))   {     return t.get_executor();   }++  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const T& t, const E&) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_executor()))+  {+    return t.get_executor();+  } }; +template <typename T, typename E>+struct associated_executor_impl<T, E,+  typename enable_if<+    !has_executor_type<T>::value+  >::type,+  typename void_type<+    typename associator<associated_executor, T, E>::type+  >::type> : associator<associated_executor, T, E>+{+};+ } // namespace detail  /// Traits type used to obtain the executor associated with an object.@@ -67,10 +110,12 @@  * Executor requirements.  *  * @li Provide a noexcept static member function named @c get, callable as @c- * get(t) and with return type @c type.+ * get(t) and with return type @c type or a (possibly const) reference to @c+ * type.  *  * @li Provide a noexcept static member function named @c get, callable as @c- * get(t,e) and with return type @c type.+ * get(t,e) and with return type @c type or a (possibly const) reference to @c+ * type.  */ template <typename T, typename Executor = system_executor> struct associated_executor@@ -84,9 +129,12 @@   typedef see_below type;    /// If @c T has a nested type @c executor_type, returns+  /// <tt>t.get_executor()</tt>. Otherwise returns @c type().+  static decltype(auto) get(const T& t) ASIO_NOEXCEPT;++  /// 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;+  static decltype(auto) get(const T& t, const Executor& ex) ASIO_NOEXCEPT; #endif // defined(GENERATING_DOCUMENTATION) }; @@ -95,7 +143,7 @@  * @returns <tt>associated_executor<T>::get(t)</tt>  */ template <typename T>-inline typename associated_executor<T>::type+ASIO_NODISCARD inline typename associated_executor<T>::type get_associated_executor(const T& t) ASIO_NOEXCEPT {   return associated_executor<T>::get(t);@@ -106,11 +154,14 @@  * @returns <tt>associated_executor<T, Executor>::get(t, ex)</tt>  */ template <typename T, typename Executor>-inline typename associated_executor<T, Executor>::type+ASIO_NODISCARD inline ASIO_AUTO_RETURN_TYPE_PREFIX2(+    typename associated_executor<T, Executor>::type) get_associated_executor(const T& t, const Executor& ex,-    typename enable_if<+    typename constraint<       is_executor<Executor>::value || execution::is_executor<Executor>::value-    >::type* = 0) ASIO_NOEXCEPT+    >::type = 0) ASIO_NOEXCEPT+  ASIO_AUTO_RETURN_TYPE_SUFFIX((+    associated_executor<T, Executor>::get(t, ex))) {   return associated_executor<T, Executor>::get(t, ex); }@@ -121,11 +172,11 @@  * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt>  */ template <typename T, typename ExecutionContext>-inline typename associated_executor<T,-  typename ExecutionContext::executor_type>::type+ASIO_NODISCARD 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+    typename constraint<is_convertible<ExecutionContext&,+      execution_context&>::value>::type = 0) ASIO_NOEXCEPT {   return associated_executor<T,     typename ExecutionContext::executor_type>::get(t, ctx.get_executor());@@ -159,6 +210,42 @@ };  } // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \+  || defined(GENERATING_DOCUMENTATION)++/// Specialisation of associated_executor for @c std::reference_wrapper.+template <typename T, typename Executor>+struct associated_executor<reference_wrapper<T>, Executor>+#if !defined(GENERATING_DOCUMENTATION)+  : detail::associated_executor_forwarding_base<T, Executor>+#endif // !defined(GENERATING_DOCUMENTATION)+{+  /// Forwards @c type to the associator specialisation for the unwrapped type+  /// @c T.+  typedef typename associated_executor<T, Executor>::type type;++  /// Forwards the request to get the executor to the associator specialisation+  /// for the unwrapped type @c T.+  static type get(reference_wrapper<T> t) ASIO_NOEXCEPT+  {+    return associated_executor<T, Executor>::get(t.get());+  }++  /// Forwards the request to get the executor to the associator specialisation+  /// for the unwrapped type @c T.+  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      reference_wrapper<T> t, const Executor& ex) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      associated_executor<T, Executor>::get(t.get(), ex)))+  {+    return associated_executor<T, Executor>::get(t.get(), ex);+  }+};++#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+       //   || defined(GENERATING_DOCUMENTATION)+ } // namespace asio  #include "asio/detail/pop_options.hpp"
+ link/modules/asio-standalone/asio/include/asio/associated_immediate_executor.hpp view
@@ -0,0 +1,297 @@+//+// associated_immediate_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_IMMEDIATE_EXECUTOR_HPP+#define ASIO_ASSOCIATED_IMMEDIATE_EXECUTOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associator.hpp"+#include "asio/detail/functional.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/execution/blocking.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution_context.hpp"+#include "asio/is_executor.hpp"+#include "asio/require.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename T, typename Executor>+struct associated_immediate_executor;++namespace detail {++template <typename T, typename = void>+struct has_immediate_executor_type : false_type+{+};++template <typename T>+struct has_immediate_executor_type<T,+  typename void_type<typename T::immediate_executor_type>::type>+    : true_type+{+};++template <typename E, typename = void, typename = void>+struct default_immediate_executor+{+  typedef typename require_result<E, execution::blocking_t::never_t>::type type;++  static type get(const E& e) ASIO_NOEXCEPT+  {+    return asio::require(e, execution::blocking.never);+  }+};++template <typename E>+struct default_immediate_executor<E,+  typename enable_if<+    !execution::is_executor<E>::value+  >::type,+  typename enable_if<+    is_executor<E>::value+  >::type>+{+  class type : public E+  {+  public:+    template <typename Executor1>+    explicit type(const Executor1& e,+        typename constraint<+          conditional<+            !is_same<Executor1, type>::value,+            is_convertible<Executor1, E>,+            false_type+          >::type::value+        >::type = 0) ASIO_NOEXCEPT+      : E(e)+    {+    }++    type(const type& other) ASIO_NOEXCEPT+      : E(static_cast<const E&>(other))+    {+    }++#if defined(ASIO_HAS_MOVE)+    type(type&& other) ASIO_NOEXCEPT+      : E(ASIO_MOVE_CAST(E)(other))+    {+    }+#endif // defined(ASIO_HAS_MOVE)++    template <typename Function, typename Allocator>+    void dispatch(ASIO_MOVE_ARG(Function) f, const Allocator& a) const+    {+      this->post(ASIO_MOVE_CAST(Function)(f), a);+    }++    friend bool operator==(const type& a, const type& b) ASIO_NOEXCEPT+    {+      return static_cast<const E&>(a) == static_cast<const E&>(b);+    }++    friend bool operator!=(const type& a, const type& b) ASIO_NOEXCEPT+    {+      return static_cast<const E&>(a) != static_cast<const E&>(b);+    }+  };++  static type get(const E& e) ASIO_NOEXCEPT+  {+    return type(e);+  }+};++template <typename T, typename E, typename = void, typename = void>+struct associated_immediate_executor_impl+{+  typedef void asio_associated_immediate_executor_is_unspecialised;++  typedef typename default_immediate_executor<E>::type type;++  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const T&, const E& e) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((default_immediate_executor<E>::get(e)))+  {+    return default_immediate_executor<E>::get(e);+  }+};++template <typename T, typename E>+struct associated_immediate_executor_impl<T, E,+  typename void_type<typename T::immediate_executor_type>::type>+{+  typedef typename T::immediate_executor_type type;++  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const T& t, const E&) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((t.get_immediate_executor()))+  {+    return t.get_immediate_executor();+  }+};++template <typename T, typename E>+struct associated_immediate_executor_impl<T, E,+  typename enable_if<+    !has_immediate_executor_type<T>::value+  >::type,+  typename void_type<+    typename associator<associated_immediate_executor, T, E>::type+  >::type> : associator<associated_immediate_executor, T, E>+{+};++} // namespace detail++/// Traits type used to obtain the immediate 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 or a (possibly const) reference to @c+ * type.+ *+ * @li Provide a noexcept static member function named @c get, callable as @c+ * get(t,e) and with return type @c type or a (possibly const) reference to @c+ * type.+ */+template <typename T, typename Executor>+struct associated_immediate_executor+#if !defined(GENERATING_DOCUMENTATION)+  : detail::associated_immediate_executor_impl<T, Executor>+#endif // !defined(GENERATING_DOCUMENTATION)+{+#if defined(GENERATING_DOCUMENTATION)+  /// If @c T has a nested type @c immediate_executor_type,+  // <tt>T::immediate_executor_type</tt>. Otherwise @c Executor.+  typedef see_below type;++  /// If @c T has a nested type @c immediate_executor_type, returns+  /// <tt>t.get_immediate_executor()</tt>. Otherwise returns+  /// <tt>asio::require(ex, asio::execution::blocking.never)</tt>.+  static decltype(auto) get(const T& t, const Executor& ex) ASIO_NOEXCEPT;+#endif // defined(GENERATING_DOCUMENTATION)+};++/// Helper function to obtain an object's associated executor.+/**+ * @returns <tt>associated_immediate_executor<T, Executor>::get(t, ex)</tt>+ */+template <typename T, typename Executor>+ASIO_NODISCARD inline ASIO_AUTO_RETURN_TYPE_PREFIX2(+    typename associated_immediate_executor<T, Executor>::type)+get_associated_immediate_executor(const T& t, const Executor& ex,+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type = 0) ASIO_NOEXCEPT+  ASIO_AUTO_RETURN_TYPE_SUFFIX((+    associated_immediate_executor<T, Executor>::get(t, ex)))+{+  return associated_immediate_executor<T, Executor>::get(t, ex);+}++/// Helper function to obtain an object's associated executor.+/**+ * @returns <tt>associated_immediate_executor<T, typename+ * ExecutionContext::executor_type>::get(t, ctx.get_executor())</tt>+ */+template <typename T, typename ExecutionContext>+ASIO_NODISCARD inline typename associated_immediate_executor<T,+    typename ExecutionContext::executor_type>::type+get_associated_immediate_executor(const T& t, ExecutionContext& ctx,+    typename constraint<is_convertible<ExecutionContext&,+      execution_context&>::value>::type = 0) ASIO_NOEXCEPT+{+  return associated_immediate_executor<T,+    typename ExecutionContext::executor_type>::get(t, ctx.get_executor());+}++#if defined(ASIO_HAS_ALIAS_TEMPLATES)++template <typename T, typename Executor>+using associated_immediate_executor_t =+  typename associated_immediate_executor<T, Executor>::type;++#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++namespace detail {++template <typename T, typename E, typename = void>+struct associated_immediate_executor_forwarding_base+{+};++template <typename T, typename E>+struct associated_immediate_executor_forwarding_base<T, E,+    typename enable_if<+      is_same<+        typename associated_immediate_executor<T,+          E>::asio_associated_immediate_executor_is_unspecialised,+        void+      >::value+    >::type>+{+  typedef void asio_associated_immediate_executor_is_unspecialised;+};++} // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER) \+  || defined(GENERATING_DOCUMENTATION)++/// Specialisation of associated_immediate_executor for+/// @c std::reference_wrapper.+template <typename T, typename Executor>+struct associated_immediate_executor<reference_wrapper<T>, Executor>+#if !defined(GENERATING_DOCUMENTATION)+  : detail::associated_immediate_executor_forwarding_base<T, Executor>+#endif // !defined(GENERATING_DOCUMENTATION)+{+  /// Forwards @c type to the associator specialisation for the unwrapped type+  /// @c T.+  typedef typename associated_immediate_executor<T, Executor>::type type;++  /// Forwards the request to get the executor to the associator specialisation+  /// for the unwrapped type @c T.+  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      reference_wrapper<T> t, const Executor& ex) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      associated_immediate_executor<T, Executor>::get(t.get(), ex)))+  {+    return associated_immediate_executor<T, Executor>::get(t.get(), ex);+  }+};++#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+       //   || defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ASSOCIATED_IMMEDIATE_EXECUTOR_HPP
+ link/modules/asio-standalone/asio/include/asio/associator.hpp view
@@ -0,0 +1,35 @@+//+// associator.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_ASSOCIATOR_HPP+#define ASIO_ASSOCIATOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Used to generically specialise associators for a type.+template <template <typename, typename> class Associator,+    typename T, typename DefaultCandidate>+struct associator+{+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_ASSOCIATOR_HPP
link/modules/asio-standalone/asio/include/asio/async_result.hpp view
@@ -2,513 +2,1602 @@ // 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)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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+{+};++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) &> : true_type+{+};++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) &&> : true_type+{+};++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) noexcept> : true_type+{+};++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) & noexcept> : true_type+{+};++template <typename R, typename... Args>+struct is_completion_signature<R(Args...) && noexcept> : true_type+{+};++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename... T>+struct are_completion_signatures : false_type+{+};++template <typename T0>+struct are_completion_signatures<T0>+  : is_completion_signature<T0>+{+};++template <typename T0, typename... TN>+struct are_completion_signatures<T0, TN...>+  : integral_constant<bool, (+      is_completion_signature<T0>::value+        && are_completion_signatures<TN...>::value)>+{+};++template <typename T, typename... Args>+ASIO_CONCEPT callable_with = requires(T&& t, Args&&... args)+{+  static_cast<T&&>(t)(static_cast<Args&&>(args)...);+};++template <typename T, typename... Signatures>+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...>)>+{+};++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) &>+  : integral_constant<bool, (callable_with<T&, Args...>)>+{+};++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) &&>+  : integral_constant<bool, (callable_with<T&&, Args...>)>+{+};++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) noexcept>+  : integral_constant<bool, (callable_with<T, Args...>)>+{+};++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) & noexcept>+  : integral_constant<bool, (callable_with<T&, Args...>)>+{+};++template <typename T, typename R, typename... Args>+struct is_completion_handler_for<T, R(Args...) && noexcept>+  : integral_constant<bool, (callable_with<T&&, Args...>)>+{+};++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename T, typename Signature0, typename... SignatureN>+struct is_completion_handler_for<T, Signature0, SignatureN...>+  : integral_constant<bool, (+      is_completion_handler_for<T, Signature0>::value+        && is_completion_handler_for<T, SignatureN...>::value)>+{+};++} // 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... Signatures>+ASIO_CONCEPT completion_handler_for =+  detail::are_completion_signatures<Signatures...>::value+    && detail::is_completion_handler_for<T, Signatures...>::value;++#define ASIO_COMPLETION_HANDLER_FOR(sig) \+  ::asio::completion_handler_for<sig>+#define ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) \+  ::asio::completion_handler_for<sig0, sig1>+#define ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) \+  ::asio::completion_handler_for<sig0, sig1, sig2>++#else // defined(ASIO_HAS_CONCEPTS)+      //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   && defined(ASIO_HAS_DECLTYPE)++#define ASIO_COMPLETION_SIGNATURE typename+#define ASIO_COMPLETION_HANDLER_FOR(sig) typename+#define ASIO_COMPLETION_HANDLER_FOR2(sig0, sig1) typename+#define ASIO_COMPLETION_HANDLER_FOR3(sig0, sig1, sig2) typename++#endif // defined(ASIO_HAS_CONCEPTS)+       //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   && defined(ASIO_HAS_DECLTYPE)++namespace detail {++template <typename T>+struct is_simple_completion_signature : false_type+{+};++template <typename T>+struct simple_completion_signature;++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename R, typename... Args>+struct is_simple_completion_signature<R(Args...)> : true_type+{+};++template <typename... Signatures>+struct are_simple_completion_signatures : false_type+{+};++template <typename Sig0>+struct are_simple_completion_signatures<Sig0>+  : is_simple_completion_signature<Sig0>+{+};++template <typename Sig0, typename... SigN>+struct are_simple_completion_signatures<Sig0, SigN...>+  : integral_constant<bool, (+      is_simple_completion_signature<Sig0>::value+        && are_simple_completion_signatures<SigN...>::value)>+{+};++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...)>+{+  typedef R type(Args...);+};++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) &>+{+  typedef R type(Args...);+};++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) &&>+{+  typedef R type(Args...);+};++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) noexcept>+{+  typedef R type(Args...);+};++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) & noexcept>+{+  typedef R type(Args...);+};++template <typename R, typename... Args>+struct simple_completion_signature<R(Args...) && noexcept>+{+  typedef R type(Args...);+};++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename R>+struct is_simple_completion_signature<R()> : true_type+{+};++#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct is_simple_completion_signature<R(ASIO_VARIADIC_TARGS(n))> \+    : true_type \+  { \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF)+#undef ASIO_PRIVATE_SIMPLE_SIG_DEF++template <typename Sig0 = void, typename Sig1 = void,+    typename Sig2 = void, typename = void>+struct are_simple_completion_signatures : false_type+{+};++template <typename Sig0>+struct are_simple_completion_signatures<Sig0>+  : is_simple_completion_signature<Sig0>+{+};++template <typename Sig0, typename Sig1>+struct are_simple_completion_signatures<Sig0, Sig1>+  : integral_constant<bool,+      (is_simple_completion_signature<Sig0>::value+        && is_simple_completion_signature<Sig1>::value)>+{+};++template <typename Sig0, typename Sig1, typename Sig2>+struct are_simple_completion_signatures<Sig0, Sig1, Sig2>+  : integral_constant<bool,+      (is_simple_completion_signature<Sig0>::value+        && is_simple_completion_signature<Sig1>::value+        && is_simple_completion_signature<Sig2>::value)>+{+};++template <>+struct simple_completion_signature<void>+{+  typedef void type;+};++template <typename R>+struct simple_completion_signature<R()>+{+  typedef R type();+};++#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct simple_completion_signature<R(ASIO_VARIADIC_TARGS(n))> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)); \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF)+#undef ASIO_PRIVATE_SIMPLE_SIG_DEF++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R>+struct simple_completion_signature<R() &>+{+  typedef R type();+};++template <typename R>+struct simple_completion_signature<R() &&>+{+  typedef R type();+};++#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct simple_completion_signature< \+    R(ASIO_VARIADIC_TARGS(n)) &> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)); \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct simple_completion_signature< \+    R(ASIO_VARIADIC_TARGS(n)) &&> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)); \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF)+#undef ASIO_PRIVATE_SIMPLE_SIG_DEF++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R>+struct simple_completion_signature<R() noexcept>+{+  typedef R type();+};++template <typename R>+struct simple_completion_signature<R() & noexcept>+{+  typedef R type();+};++template <typename R>+struct simple_completion_signature<R() && noexcept>+{+  typedef R type();+};++#define ASIO_PRIVATE_SIMPLE_SIG_DEF(n) \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct simple_completion_signature< \+    R(ASIO_VARIADIC_TARGS(n)) noexcept> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)); \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct simple_completion_signature< \+    R(ASIO_VARIADIC_TARGS(n)) & noexcept> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)); \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct simple_completion_signature< \+    R(ASIO_VARIADIC_TARGS(n)) && noexcept> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)); \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_SIMPLE_SIG_DEF)+#undef ASIO_PRIVATE_SIMPLE_SIG_DEF++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  || defined(GENERATING_DOCUMENTATION)++# define ASIO_COMPLETION_SIGNATURES_TPARAMS \+    ASIO_COMPLETION_SIGNATURE... Signatures++# define ASIO_COMPLETION_SIGNATURES_TSPECPARAMS \+    ASIO_COMPLETION_SIGNATURE... Signatures++# define ASIO_COMPLETION_SIGNATURES_TARGS Signatures...++# define ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS \+    typename asio::detail::simple_completion_signature< \+      Signatures>::type...++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   || defined(GENERATING_DOCUMENTATION)++# define ASIO_COMPLETION_SIGNATURES_TPARAMS \+    typename Sig0 = void, \+    typename Sig1 = void, \+    typename Sig2 = void++# define ASIO_COMPLETION_SIGNATURES_TSPECPARAMS \+    typename Sig0, \+    typename Sig1, \+    typename Sig2++# define ASIO_COMPLETION_SIGNATURES_TARGS Sig0, Sig1, Sig2++# define ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS \+    typename ::asio::detail::simple_completion_signature<Sig0>::type, \+    typename ::asio::detail::simple_completion_signature<Sig1>::type, \+    typename ::asio::detail::simple_completion_signature<Sig2>::type++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   || defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+class completion_handler_async_result+{+public:+  typedef CompletionToken completion_handler_type;+  typedef void return_type;++  explicit completion_handler_async_result(completion_handler_type&)+  {+  }++  return_type get()+  {+  }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation,+      ASIO_COMPLETION_HANDLER_FOR(Signatures...) 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, typename 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, \+      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)) \+  { \+    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:+  completion_handler_async_result(+      const completion_handler_async_result&) ASIO_DELETED;+  completion_handler_async_result& operator=(+      const completion_handler_async_result&) ASIO_DELETED;+};++} // namespace detail++#if defined(GENERATING_DOCUMENTATION)++/// 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_SIGNATURES_TPARAMS>+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);++  /// Obtain the value to be returned from the initiating function.+  return_type get();++  /// 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);++private:+  async_result(const async_result&) ASIO_DELETED;+  async_result& operator=(const async_result&) ASIO_DELETED;+};++#else // defined(GENERATING_DOCUMENTATION)++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+class async_result :+  public conditional<+      detail::are_simple_completion_signatures<+        ASIO_COMPLETION_SIGNATURES_TARGS>::value,+      detail::completion_handler_async_result<+        CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>,+      async_result<CompletionToken,+        ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS>+    >::type+{+public:+  typedef typename conditional<+      detail::are_simple_completion_signatures<+        ASIO_COMPLETION_SIGNATURES_TARGS>::value,+      detail::completion_handler_async_result<+        CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>,+      async_result<CompletionToken,+        ASIO_COMPLETION_SIGNATURES_TSIMPLEARGS>+    >::type base_type;++  using base_type::base_type;++private:+  async_result(const async_result&) ASIO_DELETED;+  async_result& operator=(const async_result&) ASIO_DELETED;+};++#else // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+class async_result :+  public detail::completion_handler_async_result<+    CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>+{+public:+  explicit async_result(CompletionToken& h)+    : detail::completion_handler_async_result<+        CompletionToken, ASIO_COMPLETION_SIGNATURES_TARGS>(h)+  {+  }++private:+  async_result(const async_result&) ASIO_DELETED;+  async_result& operator=(const async_result&) ASIO_DELETED;+};++#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <ASIO_COMPLETION_SIGNATURES_TSPECPARAMS>+class async_result<void, ASIO_COMPLETION_SIGNATURES_TARGS>+{+  // 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_SIGNATURES_TPARAMS>+struct async_completion+{+  /// The real handler type to be used for the asynchronous operation.+  typedef typename asio::async_result<+    typename decay<CompletionToken>::type,+      ASIO_COMPLETION_SIGNATURES_TARGS>::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,+    ASIO_COMPLETION_SIGNATURES_TARGS> result;+};++namespace detail {++template <typename CompletionToken, ASIO_COMPLETION_SIGNATURES_TPARAMS>+struct async_result_helper+  : async_result<typename decay<CompletionToken>::type,+      ASIO_COMPLETION_SIGNATURES_TARGS>+{+};++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, ASIO_COMPLETION_SIGNATURES_TPARAMS>+struct async_result_has_initiate_memfn+  : integral_constant<bool, sizeof(async_result_initiate_memfn_helper<+      async_result<typename decay<CompletionToken>::type,+        ASIO_COMPLETION_SIGNATURES_TARGS>+    >(0)) != 1>+{+};++} // namespace detail++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_INITFN_RESULT_TYPE(ct, sig) \+  void_or_deduced+# define ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1) \+  void_or_deduced+# define ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \+  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_INITFN_RESULT_TYPE2(ct, sig0, sig1) \+  typename ::asio::detail::async_result_helper< \+    ct, sig0, sig1>::return_type+# define ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \+  typename ::asio::detail::async_result_helper< \+    ct, sig0, sig1, sig2>::return_type+#define ASIO_HANDLER_TYPE(ct, sig) \+  typename ::asio::detail::async_result_helper< \+    ct, sig>::completion_handler_type+#define ASIO_HANDLER_TYPE2(ct, sig0, sig1) \+  typename ::asio::detail::async_result_helper< \+    ct, sig0, sig1>::completion_handler_type+#define ASIO_HANDLER_TYPE3(ct, sig0, sig1, sig2) \+  typename ::asio::detail::async_result_helper< \+    ct, sig0, sig1, sig2>::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_INITFN_RESULT_TYPE2(ct, sig0, sig1) \+  typename ::asio::async_result< \+    typename ::asio::decay<ct>::type, sig0, sig1>::return_type+# define ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2) \+  typename ::asio::async_result< \+    typename ::asio::decay<ct>::type, sig0, sig1, sig2>::return_type+#define ASIO_HANDLER_TYPE(ct, sig) \+  typename ::asio::async_result< \+    typename ::asio::decay<ct>::type, sig>::completion_handler_type+#define ASIO_HANDLER_TYPE2(ct, sig0, sig1) \+  typename ::asio::async_result< \+    typename ::asio::decay<ct>::type, \+      sig0, sig1>::completion_handler_type+#define ASIO_HANDLER_TYPE3(ct, sig0, sig1, sig2) \+  typename ::asio::async_result< \+    typename ::asio::decay<ct>::type, \+      sig0, sig1, sig2>::completion_handler_type+#endif++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \+  auto+#elif defined(ASIO_HAS_RETURN_TYPE_DEDUCTION)+# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \+  auto+#else+# define ASIO_INITFN_AUTO_RESULT_TYPE(ct, sig) \+  ASIO_INITFN_RESULT_TYPE(ct, sig)+# define ASIO_INITFN_AUTO_RESULT_TYPE2(ct, sig0, sig1) \+  ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1)+# define ASIO_INITFN_AUTO_RESULT_TYPE3(ct, sig0, sig1, sig2) \+  ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2)+#endif++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)+#elif defined(ASIO_HAS_RETURN_TYPE_DEDUCTION)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)+#elif defined(ASIO_HAS_DECLTYPE)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \+  auto+# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr) -> decltype expr+#else+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ct, sig) \+  ASIO_INITFN_RESULT_TYPE(ct, sig)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX2(ct, sig0, sig1) \+  ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1)+# define ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX3(ct, sig0, sig1, sig2) \+  ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2)+# define ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(expr)+#endif++#if defined(GENERATING_DOCUMENTATION)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \+  void_or_deduced+# define ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \+  void_or_deduced+# define ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \+  void_or_deduced+#elif defined(ASIO_HAS_DECLTYPE)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \+  decltype expr+# define ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \+  decltype expr+# define ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \+  decltype expr+#else+# define ASIO_INITFN_DEDUCED_RESULT_TYPE(ct, sig, expr) \+  ASIO_INITFN_RESULT_TYPE(ct, sig)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE2(ct, sig0, sig1, expr) \+  ASIO_INITFN_RESULT_TYPE2(ct, sig0, sig1)+# define ASIO_INITFN_DEDUCED_RESULT_TYPE3(ct, sig0, sig1, sig2, expr) \+  ASIO_INITFN_RESULT_TYPE3(ct, sig0, sig1, sig2)+#endif++#if defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken,+    completion_signature... Signatures,+    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... Signatures,+    typename Initiation, typename... Args>+inline typename constraint<+    detail::async_result_has_initiate_memfn<+      CompletionToken, Signatures...>::value,+    ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signatures...,+      (async_result<typename decay<CompletionToken>::type,+        Signatures...>::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,+    Signatures...>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+      ASIO_MOVE_CAST(CompletionToken)(token),+      ASIO_MOVE_CAST(Args)(args)...);+}++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE... Signatures,+    typename Initiation, typename... Args>+inline typename constraint<+    !detail::async_result_has_initiate_memfn<+      CompletionToken, Signatures...>::value,+    ASIO_INITFN_RESULT_TYPE(CompletionToken, Signatures...)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,+    ASIO_MOVE_ARG(Args)... args)+{+  async_completion<CompletionToken, Signatures...> completion(token);++  ASIO_MOVE_CAST(Initiation)(initiation)(+      ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,+        Signatures...))(completion.completion_handler),+      ASIO_MOVE_CAST(Args)(args)...);++  return completion.result.get();+}++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Sig0,+    typename Initiation>+inline typename constraint<+    detail::async_result_has_initiate_memfn<+      CompletionToken, Sig0>::value,+    ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Sig0,+      (async_result<typename decay<CompletionToken>::type,+        Sig0>::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,+    Sig0>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+      ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Sig0,+    ASIO_COMPLETION_SIGNATURE Sig1,+    typename Initiation>+inline typename constraint<+    detail::async_result_has_initiate_memfn<+      CompletionToken, Sig0, Sig1>::value,+    ASIO_INITFN_DEDUCED_RESULT_TYPE2(CompletionToken, Sig0, Sig1,+      (async_result<typename decay<CompletionToken>::type,+        Sig0, Sig1>::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,+    Sig0, Sig1>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+      ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Sig0,+    ASIO_COMPLETION_SIGNATURE Sig1,+    ASIO_COMPLETION_SIGNATURE Sig2,+    typename Initiation>+inline typename constraint<+    detail::async_result_has_initiate_memfn<+      CompletionToken, Sig0, Sig1, Sig2>::value,+    ASIO_INITFN_DEDUCED_RESULT_TYPE3(CompletionToken, Sig0, Sig1, Sig2,+      (async_result<typename decay<CompletionToken>::type,+        Sig0, Sig1, Sig2>::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,+    Sig0, Sig1, Sig2>::initiate(ASIO_MOVE_CAST(Initiation)(initiation),+      ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Sig0,+    typename Initiation>+inline typename constraint<+    !detail::async_result_has_initiate_memfn<+      CompletionToken, Sig0>::value,+    ASIO_INITFN_RESULT_TYPE(CompletionToken, Sig0)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+  async_completion<CompletionToken, Sig0> completion(token);++  ASIO_MOVE_CAST(Initiation)(initiation)(+      ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken,+        Sig0))(completion.completion_handler));++  return completion.result.get();+}++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Sig0,+    ASIO_COMPLETION_SIGNATURE Sig1,+    typename Initiation>+inline typename constraint<+    !detail::async_result_has_initiate_memfn<+      CompletionToken, Sig0, Sig1>::value,+    ASIO_INITFN_RESULT_TYPE2(CompletionToken, Sig0, Sig1)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+  async_completion<CompletionToken, Sig0, Sig1> completion(token);++  ASIO_MOVE_CAST(Initiation)(initiation)(+      ASIO_MOVE_CAST(ASIO_HANDLER_TYPE2(CompletionToken,+        Sig0, Sig1))(completion.completion_handler));++  return completion.result.get();+}++template <typename CompletionToken,+    ASIO_COMPLETION_SIGNATURE Sig0,+    ASIO_COMPLETION_SIGNATURE Sig1,+    ASIO_COMPLETION_SIGNATURE Sig2,+    typename Initiation>+inline typename constraint<+    !detail::async_result_has_initiate_memfn<+      CompletionToken, Sig0, Sig1, Sig2>::value,+    ASIO_INITFN_RESULT_TYPE3(CompletionToken, Sig0, Sig1, Sig2)>::type+async_initiate(ASIO_MOVE_ARG(Initiation) initiation,+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+{+  async_completion<CompletionToken, Sig0, Sig1, Sig2> completion(token);++  ASIO_MOVE_CAST(Initiation)(initiation)(+      ASIO_MOVE_CAST(ASIO_HANDLER_TYPE3(CompletionToken,+        Sig0, Sig1, Sig2))(completion.completion_handler));++  return completion.result.get();+}++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename CompletionToken, \+      ASIO_COMPLETION_SIGNATURE Sig0, \+      typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  inline typename constraint< \+      detail::async_result_has_initiate_memfn< \+        CompletionToken, Sig0>::value, \+      ASIO_INITFN_DEDUCED_RESULT_TYPE( \+        CompletionToken, Sig0, \+        (async_result<typename decay<CompletionToken>::type, \+          Sig0>::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, \+      Sig0>::initiate( \+        ASIO_MOVE_CAST(Initiation)(initiation), \+        ASIO_MOVE_CAST(CompletionToken)(token), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <typename CompletionToken, \+      ASIO_COMPLETION_SIGNATURE Sig0, \+      ASIO_COMPLETION_SIGNATURE Sig1, \+      typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  inline typename constraint< \+      detail::async_result_has_initiate_memfn< \+        CompletionToken, Sig0, Sig1>::value, \+      ASIO_INITFN_DEDUCED_RESULT_TYPE2( \+        CompletionToken, Sig0, Sig1, \+        (async_result<typename decay<CompletionToken>::type, \+          Sig0, Sig1>::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, \+      Sig0, Sig1>::initiate( \+        ASIO_MOVE_CAST(Initiation)(initiation), \+        ASIO_MOVE_CAST(CompletionToken)(token), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <typename CompletionToken, \+      ASIO_COMPLETION_SIGNATURE Sig0, \+      ASIO_COMPLETION_SIGNATURE Sig1, \+      ASIO_COMPLETION_SIGNATURE Sig2, \+      typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  inline typename constraint< \+      detail::async_result_has_initiate_memfn< \+        CompletionToken, Sig0, Sig1, Sig2>::value, \+      ASIO_INITFN_DEDUCED_RESULT_TYPE3( \+        CompletionToken, Sig0, Sig1, Sig2, \+        (async_result<typename decay<CompletionToken>::type, \+          Sig0, Sig1, Sig2>::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, \+      Sig0, Sig1, Sig2>::initiate( \+        ASIO_MOVE_CAST(Initiation)(initiation), \+        ASIO_MOVE_CAST(CompletionToken)(token), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <typename CompletionToken, \+      ASIO_COMPLETION_SIGNATURE Sig0, \+      typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  inline typename constraint< \+      !detail::async_result_has_initiate_memfn< \+        CompletionToken, Sig0>::value, \+      ASIO_INITFN_RESULT_TYPE(CompletionToken, Sig0)>::type \+  async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    async_completion<CompletionToken, \+      Sig0> completion(token); \+  \+    ASIO_MOVE_CAST(Initiation)(initiation)( \+        ASIO_MOVE_CAST(ASIO_HANDLER_TYPE(CompletionToken, \+          Sig0))(completion.completion_handler), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  \+    return completion.result.get(); \+  } \+  \+  template <typename CompletionToken, \+      ASIO_COMPLETION_SIGNATURE Sig0, \+      ASIO_COMPLETION_SIGNATURE Sig1, \+      typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  inline typename constraint< \+      !detail::async_result_has_initiate_memfn< \+        CompletionToken, Sig0, Sig1>::value, \+      ASIO_INITFN_RESULT_TYPE2(CompletionToken, Sig0, Sig1)>::type \+  async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    async_completion<CompletionToken, \+      Sig0, Sig1> completion(token); \+  \+    ASIO_MOVE_CAST(Initiation)(initiation)( \+        ASIO_MOVE_CAST(ASIO_HANDLER_TYPE2(CompletionToken, \+          Sig0, Sig1))(completion.completion_handler), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \+  \+    return completion.result.get(); \+  } \+  \+  template <typename CompletionToken, \+      ASIO_COMPLETION_SIGNATURE Sig0, \+      ASIO_COMPLETION_SIGNATURE Sig1, \+      ASIO_COMPLETION_SIGNATURE Sig2, \+      typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  inline typename constraint< \+      !detail::async_result_has_initiate_memfn< \+        CompletionToken, Sig0, Sig1, Sig2>::value, \+      ASIO_INITFN_RESULT_TYPE3(CompletionToken, Sig0, Sig1, Sig2)>::type \+  async_initiate(ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    async_completion<CompletionToken, \+      Sig0, Sig1, Sig2> completion(token); \+  \+    ASIO_MOVE_CAST(Initiation)(initiation)( \+        ASIO_MOVE_CAST(ASIO_HANDLER_TYPE3(CompletionToken, \+          Sig0, Sig1, Sig2))(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... Signatures>+struct initiation_archetype+{+  template <completion_handler_for<Signatures...> CompletionHandler>+  void operator()(CompletionHandler&&) const+  {+  }+};++} // namespace detail++template <typename T, typename... Signatures>+ASIO_CONCEPT completion_token_for =+  detail::are_completion_signatures<Signatures...>::value+  &&+  requires(T&& t)+  {+    async_initiate<T, Signatures...>(+        detail::initiation_archetype<Signatures...>{}, t);+  };++#define ASIO_COMPLETION_TOKEN_FOR(sig) \+  ::asio::completion_token_for<sig>+#define ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) \+  ::asio::completion_token_for<sig0, sig1>+#define ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) \+  ::asio::completion_token_for<sig0, sig1, sig2>++#else // defined(ASIO_HAS_CONCEPTS)+      //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   && defined(ASIO_HAS_DECLTYPE)++#define ASIO_COMPLETION_TOKEN_FOR(sig) typename+#define ASIO_COMPLETION_TOKEN_FOR2(sig0, sig1) typename+#define ASIO_COMPLETION_TOKEN_FOR3(sig0, sig1, sig2) typename++#endif // defined(ASIO_HAS_CONCEPTS)+       //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   && defined(ASIO_HAS_DECLTYPE)++namespace detail {++struct async_operation_probe {};+struct async_operation_probe_result {};++template <typename Call, typename = void>+struct is_async_operation_call : false_type+{+};++template <typename Call>+struct is_async_operation_call<Call,+    typename void_type<+      typename enable_if<+        is_same<+          typename result_of<Call>::type,+          async_operation_probe_result+        >::value+      >::type+    >::type> : true_type+{+};++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... Signatures>+class async_result<detail::async_operation_probe, Signatures...>+{+public:+  typedef detail::async_operation_probe_result return_type;++  template <typename Initiation, typename... InitArgs>+  static return_type initiate(ASIO_MOVE_ARG(Initiation),+      detail::async_operation_probe, ASIO_MOVE_ARG(InitArgs)...)+  {+    return return_type();+  }+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++namespace detail {++struct async_result_probe_base+{+  typedef detail::async_operation_probe_result return_type;++  template <typename Initiation>+  static return_type initiate(ASIO_MOVE_ARG(Initiation),+      detail::async_operation_probe)+  {+    return return_type();+  }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  static return_type initiate(ASIO_MOVE_ARG(Initiation), \+      detail::async_operation_probe, \+      ASIO_VARIADIC_UNNAMED_MOVE_PARAMS(n)) \+  { \+    return return_type(); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF+};++} // namespace detail++template <typename Sig0>+class async_result<detail::async_operation_probe, Sig0>+  : public detail::async_result_probe_base {};++template <typename Sig0, typename Sig1>+class async_result<detail::async_operation_probe, Sig0, Sig1>+  : public detail::async_result_probe_base {};++template <typename Sig0, typename Sig1, typename Sig2>+class async_result<detail::async_operation_probe, Sig0, Sig1, Sig2>+  : public detail::async_result_probe_base {};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(GENERATING_DOCUMENTATION)++#if defined(GENERATING_DOCUMENTATION)++/// The is_async_operation trait detects whether a type @c T and arguments+/// @c Args... may be used to initiate an asynchronous operation.+/**+ * Class template @c is_async_operation is a trait is derived from @c true_type+ * if the expression <tt>T(Args..., token)</tt> initiates an asynchronous+ * operation, where @c token is an unspecified completion token type. Otherwise,+ * @c is_async_operation is derived from @c false_type.+ */+template <typename T, typename... Args>+struct is_async_operation : integral_constant<bool, automatically_determined>+{+};++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Args>+struct is_async_operation :+  detail::is_async_operation_call<+    T(Args..., detail::async_operation_probe)>+{+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void, typename = void,+    typename = void, typename = void>+struct is_async_operation;++template <typename T>+struct is_async_operation<T> :+  detail::is_async_operation_call<+    T(detail::async_operation_probe)>+{+};++#define ASIO_PRIVATE_IS_ASYNC_OP_DEF(n) \+  template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+  struct is_async_operation<T, ASIO_VARIADIC_TARGS(n)> : \+    detail::is_async_operation_call< \+      T(ASIO_VARIADIC_TARGS(n), detail::async_operation_probe)> \+  { \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_IS_ASYNC_OP_DEF)+#undef ASIO_PRIVATE_IS_ASYNC_OP_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++#if defined(ASIO_HAS_CONCEPTS) \+  && defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Args>+ASIO_CONCEPT async_operation = is_async_operation<T, Args...>::value;++#define ASIO_ASYNC_OPERATION(t) \+  ::asio::async_operation<t>+#define ASIO_ASYNC_OPERATION1(t, a0) \+  ::asio::async_operation<t, a0>+#define ASIO_ASYNC_OPERATION2(t, a0, a1) \+  ::asio::async_operation<t, a0, a1>+#define ASIO_ASYNC_OPERATION3(t, a0, a1, a2) \+  ::asio::async_operation<t, a0, a1, a2>++#else // defined(ASIO_HAS_CONCEPTS)+      //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)++#define ASIO_ASYNC_OPERATION(t) typename+#define ASIO_ASYNC_OPERATION1(t, a0) typename+#define ASIO_ASYNC_OPERATION2(t, a0, a1) typename+#define ASIO_ASYNC_OPERATION3(t, a0, a1, a2) typename++#endif // defined(ASIO_HAS_CONCEPTS)+       //   && defined(ASIO_HAS_VARIADIC_TEMPLATES)++namespace detail {++struct completion_signature_probe {};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... T>+struct completion_signature_probe_result+{+  template <template <typename...> class Op>+  struct apply+  {+    typedef Op<T...> type;+  };+};++template <typename T>+struct completion_signature_probe_result<T>+{+  typedef T type;++  template <template <typename...> class Op>+  struct apply+  {+    typedef Op<T> type;+  };+};++template <>+struct completion_signature_probe_result<void>+{+  template <template <typename...> class Op>+  struct apply+  {+    typedef Op<> type;+  };+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T>+struct completion_signature_probe_result+{+  typedef T type;+};++template <>+struct completion_signature_probe_result<void>+{+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename... Signatures>+class async_result<detail::completion_signature_probe, Signatures...>+{+public:+  typedef detail::completion_signature_probe_result<Signatures...> return_type;++  template <typename Initiation, typename... InitArgs>+  static return_type initiate(ASIO_MOVE_ARG(Initiation),+      detail::completion_signature_probe, ASIO_MOVE_ARG(InitArgs)...)+  {+    return return_type();+  }+};++template <typename Signature>+class async_result<detail::completion_signature_probe, Signature>+{+public:+  typedef detail::completion_signature_probe_result<Signature> return_type;++  template <typename Initiation, typename... InitArgs>+  static return_type initiate(ASIO_MOVE_ARG(Initiation),+      detail::completion_signature_probe, ASIO_MOVE_ARG(InitArgs)...)+  {+    return return_type();+  }+};++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++namespace detail {++template <typename Signature>+class async_result_sig_probe_base+{+public:+  typedef detail::completion_signature_probe_result<Signature> return_type;++  template <typename Initiation>+  static return_type initiate(ASIO_MOVE_ARG(Initiation),+      detail::async_operation_probe)+  {+    return return_type();+  }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  static return_type initiate(ASIO_MOVE_ARG(Initiation), \+      detail::completion_signature_probe, \+      ASIO_VARIADIC_UNNAMED_MOVE_PARAMS(n)) \+  { \+    return return_type(); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF+};++} // namespace detail++template <>+class async_result<detail::completion_signature_probe>+  : public detail::async_result_sig_probe_base<void> {};++template <typename Sig0>+class async_result<detail::completion_signature_probe, Sig0>+  : public detail::async_result_sig_probe_base<Sig0> {};++template <typename Sig0, typename Sig1>+class async_result<detail::completion_signature_probe, Sig0, Sig1>+  : public detail::async_result_sig_probe_base<void> {};++template <typename Sig0, typename Sig1, typename Sig2>+class async_result<detail::completion_signature_probe, Sig0, Sig1, Sig2>+  : public detail::async_result_sig_probe_base<void> {};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+#endif // !defined(GENERATING_DOCUMENTATION)++#if defined(GENERATING_DOCUMENTATION)++/// The completion_signature_of trait determines the completion signature+/// of an asynchronous operation.+/**+ * Class template @c completion_signature_of is a trait with a member type+ * alias @c type that denotes the completion signature of the asynchronous+ * operation initiated by the expression <tt>T(Args..., token)</tt> operation,+ * where @c token is an unspecified completion token type. If the asynchronous+ * operation does not have exactly one completion signature, the instantion of+ * the trait is well-formed but the member type alias @c type is omitted. If+ * the expression <tt>T(Args..., token)</tt> is not an asynchronous operation+ * then use of the trait is ill-formed.+ */+template <typename T, typename... Args>+struct completion_signature_of+{+  typedef automatically_determined type;+};++template <typename T, typename... Args>+using completion_signature_of_t =+  typename completion_signature_of<T, Args...>::type;++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename... Args>+struct completion_signature_of :+  result_of<T(Args..., detail::completion_signature_probe)>::type+{+};++#if defined(ASIO_HAS_ALIAS_TEMPLATES)+template <typename T, typename... Args>+using completion_signature_of_t =+  typename completion_signature_of<T, Args...>::type;+#endif // defined(ASIO_HAS_ALIAS_TEMPLATES)++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <typename T, typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void, typename = void,+    typename = void, typename = void>+struct completion_signature_of;++template <typename T>+struct completion_signature_of<T> :+  result_of<T(detail::completion_signature_probe)>::type+{+};++#define ASIO_PRIVATE_COMPLETION_SIG_OF_DEF(n) \+  template <typename T, ASIO_VARIADIC_TPARAMS(n)> \+  struct completion_signature_of<T, ASIO_VARIADIC_TARGS(n)> : \+    result_of< \+      T(ASIO_VARIADIC_TARGS(n), \+        detail::completion_signature_probe)>::type \+  { \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_COMPLETION_SIG_OF_DEF)+#undef ASIO_PRIVATE_COMPLETION_SIG_OF_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)  namespace detail { 
link/modules/asio-standalone/asio/include/asio/awaitable.hpp view
@@ -2,7 +2,7 @@ // awaitable.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,6 +25,7 @@ # include <experimental/coroutine> #endif // defined(ASIO_HAS_STD_COROUTINE) +#include <utility> #include "asio/any_io_executor.hpp"  #include "asio/detail/push_options.hpp"@@ -47,7 +48,7 @@  /// The return type of a coroutine or asynchronous operation. template <typename T, typename Executor = any_io_executor>-class awaitable+class ASIO_NODISCARD awaitable { public:   /// The type of the awaited value.@@ -73,6 +74,14 @@   {     if (frame_)       frame_->destroy();+  }++  /// Move assignment.+  awaitable& operator=(awaitable&& other) noexcept+  {+    if (this != &other)+      frame_ = std::exchange(other.frame_, nullptr);+    return *this;   }    /// Checks if the awaitable refers to a future result.
link/modules/asio-standalone/asio/include/asio/basic_datagram_socket.hpp view
@@ -2,7 +2,7 @@ // basic_datagram_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -45,11 +45,24 @@  * @par Thread Safety  * @e Distinct @e objects: Safe.@n  * @e Shared @e objects: Unsafe.+ *+ * Synchronous @c send, @c send_to, @c receive, @c receive_from, @c connect,+ * and @c shutdown operations are thread safe with respect to each other, if+ * the underlying operating system calls are also thread safe. This means that+ * it is permitted to perform concurrent calls to these synchronous operations+ * on a single socket object. Other synchronous operations, such as @c open or+ * @c close, are not thread safe.  */ template <typename Protocol, typename Executor> class basic_datagram_socket   : public basic_socket<Protocol, Executor> {+private:+  class initiate_async_send;+  class initiate_async_send_to;+  class initiate_async_receive;+  class initiate_async_receive_from;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -100,9 +113,9 @@    */   template <typename ExecutionContext>   explicit basic_datagram_socket(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context)   {   }@@ -138,9 +151,10 @@   template <typename ExecutionContext>   basic_datagram_socket(ExecutionContext& context,       const protocol_type& protocol,-      typename enable_if<-        is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())     : basic_socket<Protocol, Executor>(context, protocol)   {   }@@ -184,9 +198,9 @@   template <typename ExecutionContext>   basic_datagram_socket(ExecutionContext& context,       const endpoint_type& endpoint,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context, endpoint)   {   }@@ -229,9 +243,9 @@   template <typename ExecutionContext>   basic_datagram_socket(ExecutionContext& context,       const protocol_type& protocol, const native_handle_type& native_socket,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context, protocol, native_socket)   {   }@@ -285,10 +299,10 @@    */   template <typename Protocol1, typename Executor1>   basic_datagram_socket(basic_datagram_socket<Protocol1, Executor1>&& other,-      typename enable_if<+      typename constraint<         is_convertible<Protocol1, Protocol>::value           && is_convertible<Executor1, Executor>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(std::move(other))   {   }@@ -307,7 +321,7 @@    * constructor.    */   template <typename Protocol1, typename Executor1>-  typename enable_if<+  typename constraint<     is_convertible<Protocol1, Protocol>::value       && is_convertible<Executor1, Executor>::value,     basic_datagram_socket&@@ -415,25 +429,31 @@   /// 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.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more data buffers to be sent on the socket. Although    * the buffers object may be copied as necessary, ownership of the underlying    * memory blocks is retained by the caller, which must guarantee that they-   * remain valid until the handler is called.+   * remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes. Potential+   * completion tokens include @ref use_future, @ref use_awaitable, @ref+   * yield_context, or a function object with the correct completion signature.+   * The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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.@@ -446,65 +466,100 @@    * See the @ref buffer documentation for information on sending multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_send(const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send>(), token,+          buffers, socket_base::message_flags(0))))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send(this), handler,+        initiate_async_send(this), token,         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.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more data buffers to be sent on the socket. Although    * the buffers object may be copied as necessary, ownership of the underlying    * memory blocks is retained by the caller, which must guarantee that they-   * remain valid until the handler is called.+   * remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes. Potential+   * completion tokens include @ref use_future, @ref use_awaitable, @ref+   * yield_context, or a function object with the correct completion signature.+   * The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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 Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_send(const ConstBufferSequence& buffers,       socket_base::message_flags flags,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send>(), token, buffers, flags)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send(this), handler, buffers, flags);+        initiate_async_send(this), token, buffers, flags);   }    /// Send a datagram to the specified endpoint.@@ -598,28 +653,34 @@   /// Start an asynchronous send.   /**    * This function is used to asynchronously send a datagram to the specified-   * remote endpoint. The function call always returns immediately.+   * remote endpoint. It is an initiating function for an @ref+   * asynchronous_operation, and 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.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes. Potential+   * completion tokens include @ref use_future, @ref use_awaitable, @ref+   * yield_context, or a function object with the correct completion signature.+   * The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @par Example    * To send a single data buffer use the @ref buffer function as follows:    * @code@@ -631,65 +692,102 @@    * See the @ref buffer documentation for information on sending multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_send_to(const ConstBufferSequence& buffers,       const endpoint_type& destination,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send_to>(), token, buffers,+          destination, socket_base::message_flags(0))))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send_to(this), handler, buffers,+        initiate_async_send_to(this), token, 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.+   * remote endpoint. It is an initiating function for an @ref+   * asynchronous_operation, and 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.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes. Potential+   * completion tokens include @ref use_future, @ref use_awaitable, @ref+   * yield_context, or a function object with the correct completion signature.+   * The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       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_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send_to>(), token,+          buffers, destination, flags)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send_to(this), handler, buffers, destination, flags);+        initiate_async_send_to(this), token,+        buffers, destination, flags);   }    /// Receive some data on a connected socket.@@ -784,25 +882,31 @@   /// 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.+   * socket. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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.@@ -816,65 +920,100 @@    * See the @ref buffer documentation for information on receiving into    * multiple buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive(const MutableBufferSequence& buffers,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive>(), token,+          buffers, socket_base::message_flags(0))))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive(this), handler,+        initiate_async_receive(this), token,         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.+   * socket. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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 Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive(const MutableBufferSequence& buffers,       socket_base::message_flags flags,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive>(), token, buffers, flags)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive(this), handler, buffers, flags);+        initiate_async_receive(this), token, buffers, flags);   }    /// Receive a datagram with the endpoint of the sender.@@ -968,31 +1107,37 @@    /// Start an asynchronous receive.   /**-   * This function is used to asynchronously receive a datagram. The function-   * call always returns immediately.+   * This function is used to asynchronously receive a datagram. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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.+   * completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @par Example    * To receive into a single data buffer use the @ref buffer function as    * follows:@@ -1001,67 +1146,103 @@    * See the @ref buffer documentation for information on receiving into    * multiple buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive_from(const MutableBufferSequence& buffers,       endpoint_type& sender_endpoint,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive_from>(), token, buffers,+          &sender_endpoint, socket_base::message_flags(0))))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive_from(this), handler, buffers,+        initiate_async_receive_from(this), token, 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.+   * This function is used to asynchronously receive a datagram. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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.+   * completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       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_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive_from>(), token,+          buffers, &sender_endpoint, flags)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive_from(this), handler,+        initiate_async_receive_from(this), token,         buffers, &sender_endpoint, flags);   } @@ -1081,7 +1262,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -1115,7 +1296,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -1149,7 +1330,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -1183,7 +1364,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
link/modules/asio-standalone/asio/include/asio/basic_deadline_timer.hpp view
@@ -2,7 +2,7 @@ // basic_deadline_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -128,6 +128,9 @@     typename Executor = any_io_executor> class basic_deadline_timer {+private:+  class initiate_async_wait;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -159,7 +162,7 @@    * dispatch handlers for any asynchronous operations performed on the timer.    */   explicit basic_deadline_timer(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -175,10 +178,10 @@    */   template <typename ExecutionContext>   explicit basic_deadline_timer(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {   } @@ -193,7 +196,7 @@    * as an absolute time.    */   basic_deadline_timer(const executor_type& ex, const time_type& expiry_time)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);@@ -213,10 +216,10 @@    */   template <typename ExecutionContext>   basic_deadline_timer(ExecutionContext& context, const time_type& expiry_time,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);@@ -235,7 +238,7 @@    */   basic_deadline_timer(const executor_type& ex,       const duration_type& expiry_time)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().expires_from_now(@@ -257,10 +260,10 @@   template <typename ExecutionContext>   basic_deadline_timer(ExecutionContext& context,       const duration_type& expiry_time,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().expires_from_now(@@ -314,7 +317,7 @@   }    /// Get the executor associated with the object.-  executor_type get_executor() ASIO_NOEXCEPT+  const executor_type& get_executor() ASIO_NOEXCEPT   {     return impl_.get_executor();   }@@ -607,38 +610,57 @@   /// Start an asynchronous wait on the timer.   /**    * This function may be used to initiate an asynchronous wait against the-   * timer. It always returns immediately.+   * timer. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *-   * For each call to async_wait(), the supplied handler will be called exactly-   * once. The handler will be called when:+   * For each call to async_wait(), the completion handler will be called+   * exactly once. The completion handler will be called when:    *    * @li The timer has expired.    *    * @li The timer was cancelled, in which case the handler is passed the error    * code asio::error::operation_aborted.    *-   * @param 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the timer expires. Potential+   * completion tokens include @ref use_future, @ref use_awaitable, @ref+   * yield_context, or a function object with the correct completion signature.+   * The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error // Result of operation.    * ); @endcode    * Regardless of whether the asynchronous operation completes immediately or-   * not, the handler will not be invoked from within this function. On-   * immediate completion, invocation of the handler will be performed in a+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+        WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken,       void (asio::error_code))   async_wait(-      ASIO_MOVE_ARG(WaitHandler) handler+      ASIO_MOVE_ARG(WaitToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WaitToken, void (asio::error_code)>(+          declval<initiate_async_wait>(), token)))   {-    return async_initiate<WaitHandler, void (asio::error_code)>(-        initiate_async_wait(this), handler);+    return async_initiate<WaitToken, void (asio::error_code)>(+        initiate_async_wait(this), token);   }  private:@@ -657,7 +679,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
+ link/modules/asio-standalone/asio/include/asio/basic_file.hpp view
@@ -0,0 +1,829 @@+//+// basic_file.hpp+// ~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_FILE_HPP+#define ASIO_BASIC_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+  || defined(GENERATING_DOCUMENTATION)++#include <string>+#include "asio/any_io_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/cstdint.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/io_object_impl.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/post.hpp"+#include "asio/file_base.hpp"+#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_file_service.hpp"+#elif defined(ASIO_HAS_IO_URING)+# include "asio/detail/io_uring_file_service.hpp"+#endif++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_BASIC_FILE_FWD_DECL)+#define ASIO_BASIC_FILE_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Executor = any_io_executor>+class basic_file;++#endif // !defined(ASIO_BASIC_FILE_FWD_DECL)++/// Provides file functionality.+/**+ * The basic_file class template provides functionality that is common to both+ * stream-oriented and random-access files.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor>+class basic_file+  : public file_base+{+public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the file type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The file type when rebound to the specified executor.+    typedef basic_file<Executor1> other;+  };++  /// The native representation of a file.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#elif defined(ASIO_HAS_IOCP)+  typedef detail::win_iocp_file_service::native_handle_type native_handle_type;+#elif defined(ASIO_HAS_IO_URING)+  typedef detail::io_uring_file_service::native_handle_type native_handle_type;+#endif++  /// Construct a basic_file without opening it.+  /**+   * This constructor initialises a file without opening it.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   */+  explicit basic_file(const executor_type& ex)+    : impl_(0, ex)+  {+  }++  /// Construct a basic_file without opening it.+  /**+   * This constructor initialises a file without opening it.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   */+  template <typename ExecutionContext>+  explicit basic_file(ExecutionContext& context,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)+  {+  }++  /// Construct and open a basic_file.+  /**+   * This constructor initialises a file and opens it.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   */+  explicit basic_file(const executor_type& ex,+      const char* path, file_base::flags open_flags)+    : impl_(0, ex)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct a basic_file without opening it.+  /**+   * This constructor initialises a file and opens it.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   */+  template <typename ExecutionContext>+  explicit basic_file(ExecutionContext& context,+      const char* path, file_base::flags open_flags,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct and open a basic_file.+  /**+   * This constructor initialises a file and opens it.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   */+  explicit basic_file(const executor_type& ex,+      const std::string& path, file_base::flags open_flags)+    : impl_(0, ex)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(),+        path.c_str(), open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct a basic_file without opening it.+  /**+   * This constructor initialises a file and opens it.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   */+  template <typename ExecutionContext>+  explicit basic_file(ExecutionContext& context,+      const std::string& path, file_base::flags open_flags,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(),+        path.c_str(), open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct a basic_file on an existing native file handle.+  /**+   * This constructor initialises a file object to hold an existing native file.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   *+   * @param native_file A native file handle.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_file(const executor_type& ex, const native_handle_type& native_file)+    : impl_(0, ex)+  {+    asio::error_code ec;+    impl_.get_service().assign(+        impl_.get_implementation(), native_file, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Construct a basic_file on an existing native file.+  /**+   * This constructor initialises a file object to hold an existing native file.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   *+   * @param native_file A native file.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_file(ExecutionContext& context, const native_handle_type& native_file,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)+  {+    asio::error_code ec;+    impl_.get_service().assign(+        impl_.get_implementation(), native_file, ec);+    asio::detail::throw_error(ec, "assign");+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_file from another.+  /**+   * This constructor moves a file from one object to another.+   *+   * @param other The other basic_file object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_file(const executor_type&) constructor.+   */+  basic_file(basic_file&& other) ASIO_NOEXCEPT+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_file from another.+  /**+   * This assignment operator moves a file from one object to another.+   *+   * @param other The other basic_file object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_file(const executor_type&) constructor.+   */+  basic_file& operator=(basic_file&& other)+  {+    impl_ = std::move(other.impl_);+    return *this;+  }++  // All files have access to each other's implementations.+  template <typename Executor1>+  friend class basic_file;++  /// Move-construct a basic_file from a file of another executor type.+  /**+   * This constructor moves a file from one object to another.+   *+   * @param other The other basic_file object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_file(const executor_type&) constructor.+   */+  template <typename Executor1>+  basic_file(basic_file<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_file from a file of another executor type.+  /**+   * This assignment operator moves a file from one object to another.+   *+   * @param other The other basic_file object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_file(const executor_type&) constructor.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_file&+  >::type operator=(basic_file<Executor1>&& other)+  {+    basic_file tmp(std::move(other));+    impl_ = std::move(tmp.impl_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Get the executor associated with the object.+  const executor_type& get_executor() ASIO_NOEXCEPT+  {+    return impl_.get_executor();+  }++  /// Open the file using the specified path.+  /**+   * This function opens the file so that it will use the specified path.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::stream_file file(my_context);+   * file.open("/path/to/my/file", asio::stream_file::read_only);+   * @endcode+   */+  void open(const char* path, file_base::flags open_flags)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Open the file using the specified path.+  /**+   * This function opens the file so that it will use the specified path.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::stream_file file(my_context);+   * asio::error_code ec;+   * file.open("/path/to/my/file", asio::stream_file::read_only, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID open(const char* path,+      file_base::flags open_flags, asio::error_code& ec)+  {+    impl_.get_service().open(impl_.get_implementation(), path, open_flags, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Open the file using the specified path.+  /**+   * This function opens the file so that it will use the specified path.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @par Example+   * @code+   * asio::stream_file file(my_context);+   * file.open("/path/to/my/file", asio::stream_file::read_only);+   * @endcode+   */+  void open(const std::string& path, file_base::flags open_flags)+  {+    asio::error_code ec;+    impl_.get_service().open(impl_.get_implementation(),+        path.c_str(), open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Open the file using the specified path.+  /**+   * This function opens the file so that it will use the specified path.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @par Example+   * @code+   * asio::stream_file file(my_context);+   * asio::error_code ec;+   * file.open("/path/to/my/file", asio::stream_file::read_only, ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID open(const std::string& path,+      file_base::flags open_flags, asio::error_code& ec)+  {+    impl_.get_service().open(impl_.get_implementation(),+        path.c_str(), open_flags, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Assign an existing native file to the file.+  /*+   * This function opens the file to hold an existing native file.+   *+   * @param native_file A native file.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void assign(const native_handle_type& native_file)+  {+    asio::error_code ec;+    impl_.get_service().assign(+        impl_.get_implementation(), native_file, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Assign an existing native file to the file.+  /*+   * This function opens the file to hold an existing native file.+   *+   * @param native_file A native file.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID assign(const native_handle_type& native_file,+      asio::error_code& ec)+  {+    impl_.get_service().assign(+        impl_.get_implementation(), native_file, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Determine whether the file is open.+  bool is_open() const+  {+    return impl_.get_service().is_open(impl_.get_implementation());+  }++  /// Close the file.+  /**+   * This function is used to close the file. Any asynchronous read or write+   * operations will be cancelled immediately, and will complete with the+   * asio::error::operation_aborted error.+   *+   * @throws asio::system_error Thrown on failure. Note that, even if+   * the function indicates an error, the underlying descriptor is closed.+   */+  void close()+  {+    asio::error_code ec;+    impl_.get_service().close(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "close");+  }++  /// Close the file.+  /**+   * This function is used to close the file. Any asynchronous read or write+   * operations will be cancelled immediately, and will complete with the+   * asio::error::operation_aborted error.+   *+   * @param ec Set to indicate what error occurred, if any. Note that, even if+   * the function indicates an error, the underlying descriptor is closed.+   *+   * @par Example+   * @code+   * asio::stream_file file(my_context);+   * ...+   * asio::error_code ec;+   * file.close(ec);+   * if (ec)+   * {+   *   // An error occurred.+   * }+   * @endcode+   */+  ASIO_SYNC_OP_VOID close(asio::error_code& ec)+  {+    impl_.get_service().close(impl_.get_implementation(), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Release ownership of the underlying native file.+  /**+   * This function causes all outstanding asynchronous read and write+   * operations to finish immediately, and the handlers for cancelled+   * operations will be passed the asio::error::operation_aborted error.+   * Ownership of the native file is then transferred to the caller.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note This function is unsupported on Windows versions prior to Windows+   * 8.1, and will fail with asio::error::operation_not_supported on+   * these platforms.+   */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+  && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+  __declspec(deprecated("This function always fails with "+        "operation_not_supported when used on Windows versions "+        "prior to Windows 8.1."))+#endif+  native_handle_type release()+  {+    asio::error_code ec;+    native_handle_type s = impl_.get_service().release(+        impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "release");+    return s;+  }++  /// Release ownership of the underlying native file.+  /**+   * This function causes all outstanding asynchronous read and write+   * operations to finish immediately, and the handlers for cancelled+   * operations will be passed the asio::error::operation_aborted error.+   * Ownership of the native file is then transferred to the caller.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note This function is unsupported on Windows versions prior to Windows+   * 8.1, and will fail with asio::error::operation_not_supported on+   * these platforms.+   */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+  && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0603)+  __declspec(deprecated("This function always fails with "+        "operation_not_supported when used on Windows versions "+        "prior to Windows 8.1."))+#endif+  native_handle_type release(asio::error_code& ec)+  {+    return impl_.get_service().release(impl_.get_implementation(), ec);+  }++  /// Get the native file representation.+  /**+   * This function may be used to obtain the underlying representation of the+   * file. This is intended to allow access to native file functionality+   * that is not otherwise provided.+   */+  native_handle_type native_handle()+  {+    return impl_.get_service().native_handle(impl_.get_implementation());+  }++  /// Cancel all asynchronous operations associated with the file.+  /**+   * This function causes all outstanding asynchronous read and write+   * operations to finish immediately, and the handlers for cancelled+   * operations will be passed the asio::error::operation_aborted error.+   *+   * @throws asio::system_error Thrown on failure.+   *+   * @note Calls to cancel() will always fail with+   * asio::error::operation_not_supported when run on Windows XP, Windows+   * Server 2003, and earlier versions of Windows, unless+   * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has+   * two issues that should be considered before enabling its use:+   *+   * @li It will only cancel asynchronous operations that were initiated in the+   * current thread.+   *+   * @li It can appear to complete without error, but the request to cancel the+   * unfinished operations may be silently ignored by the operating system.+   * Whether it works or not seems to depend on the drivers that are installed.+   *+   * For portable cancellation, consider using the close() function to+   * simultaneously cancel the outstanding operations and close the file.+   *+   * When running on Windows Vista, Windows Server 2008, and later, the+   * CancelIoEx function is always used. This function does not have the+   * problems described above.+   */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+  && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \+  && !defined(ASIO_ENABLE_CANCELIO)+  __declspec(deprecated("By default, this function always fails with "+        "operation_not_supported when used on Windows XP, Windows Server 2003, "+        "or earlier. Consult documentation for details."))+#endif+  void cancel()+  {+    asio::error_code ec;+    impl_.get_service().cancel(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "cancel");+  }++  /// Cancel all asynchronous operations associated with the file.+  /**+   * This function causes all outstanding asynchronous read and write+   * operations to finish immediately, and the handlers for cancelled+   * operations will be passed the asio::error::operation_aborted error.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @note Calls to cancel() will always fail with+   * asio::error::operation_not_supported when run on Windows XP, Windows+   * Server 2003, and earlier versions of Windows, unless+   * ASIO_ENABLE_CANCELIO is defined. However, the CancelIo function has+   * two issues that should be considered before enabling its use:+   *+   * @li It will only cancel asynchronous operations that were initiated in the+   * current thread.+   *+   * @li It can appear to complete without error, but the request to cancel the+   * unfinished operations may be silently ignored by the operating system.+   * Whether it works or not seems to depend on the drivers that are installed.+   *+   * For portable cancellation, consider using the close() function to+   * simultaneously cancel the outstanding operations and close the file.+   *+   * When running on Windows Vista, Windows Server 2008, and later, the+   * CancelIoEx function is always used. This function does not have the+   * problems described above.+   */+#if defined(ASIO_MSVC) && (ASIO_MSVC >= 1400) \+  && (!defined(_WIN32_WINNT) || _WIN32_WINNT < 0x0600) \+  && !defined(ASIO_ENABLE_CANCELIO)+  __declspec(deprecated("By default, this function always fails with "+        "operation_not_supported when used on Windows XP, Windows Server 2003, "+        "or earlier. Consult documentation for details."))+#endif+  ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)+  {+    impl_.get_service().cancel(impl_.get_implementation(), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Get the size of the file.+  /**+   * This function determines the size of the file, in bytes.+   *+   * @throws asio::system_error Thrown on failure.+   */+  uint64_t size() const+  {+    asio::error_code ec;+    uint64_t s = impl_.get_service().size(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "size");+    return s;+  }++  /// Get the size of the file.+  /**+   * This function determines the size of the file, in bytes.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  uint64_t size(asio::error_code& ec) const+  {+    return impl_.get_service().size(impl_.get_implementation(), ec);+  }++  /// Alter the size of the file.+  /**+   * This function resizes the file to the specified size, in bytes. If the+   * current file size exceeds @c n then any extra data is discarded. If the+   * current size is less than @c n then the file is extended and filled with+   * zeroes.+   *+   * @param n The new size for the file.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void resize(uint64_t n)+  {+    asio::error_code ec;+    impl_.get_service().resize(impl_.get_implementation(), n, ec);+    asio::detail::throw_error(ec, "resize");+  }++  /// Alter the size of the file.+  /**+   * This function resizes the file to the specified size, in bytes. If the+   * current file size exceeds @c n then any extra data is discarded. If the+   * current size is less than @c n then the file is extended and filled with+   * zeroes.+   *+   * @param n The new size for the file.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID resize(uint64_t n, asio::error_code& ec)+  {+    impl_.get_service().resize(impl_.get_implementation(), n, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Synchronise the file to disk.+  /**+   * This function synchronises the file data and metadata to disk. Note that+   * the semantics of this synchronisation vary between operation systems.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void sync_all()+  {+    asio::error_code ec;+    impl_.get_service().sync_all(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "sync_all");+  }++  /// Synchronise the file to disk.+  /**+   * This function synchronises the file data and metadata to disk. Note that+   * the semantics of this synchronisation vary between operation systems.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID sync_all(asio::error_code& ec)+  {+    impl_.get_service().sync_all(impl_.get_implementation(), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Synchronise the file data to disk.+  /**+   * This function synchronises the file data to disk. Note that the semantics+   * of this synchronisation vary between operation systems.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void sync_data()+  {+    asio::error_code ec;+    impl_.get_service().sync_data(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "sync_data");+  }++  /// Synchronise the file data to disk.+  /**+   * This function synchronises the file data to disk. Note that the semantics+   * of this synchronisation vary between operation systems.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID sync_data(asio::error_code& ec)+  {+    impl_.get_service().sync_data(impl_.get_implementation(), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++protected:+  /// Protected destructor to prevent deletion through this type.+  /**+   * This function destroys the file, cancelling any outstanding asynchronous+   * operations associated with the file as if by calling @c cancel.+   */+  ~basic_file()+  {+  }++#if defined(ASIO_HAS_IOCP)+  detail::io_object_impl<detail::win_iocp_file_service, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING)+  detail::io_object_impl<detail::io_uring_file_service, Executor> impl_;+#endif++private:+  // Disallow copying and assignment.+  basic_file(const basic_file&) ASIO_DELETED;+  basic_file& operator=(const basic_file&) ASIO_DELETED;+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_FILE_HPP
link/modules/asio-standalone/asio/include/asio/basic_io_object.hpp view
@@ -2,7 +2,7 @@ // basic_io_object.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/basic_random_access_file.hpp view
@@ -0,0 +1,701 @@+//+// basic_random_access_file.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_RANDOM_ACCESS_FILE_HPP+#define ASIO_BASIC_RANDOM_ACCESS_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+  || defined(GENERATING_DOCUMENTATION)++#include <cstddef>+#include "asio/async_result.hpp"+#include "asio/basic_file.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)+#define ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Executor = any_io_executor>+class basic_random_access_file;++#endif // !defined(ASIO_BASIC_RANDOM_ACCESS_FILE_FWD_DECL)++/// Provides random-access file functionality.+/**+ * The basic_random_access_file class template provides asynchronous and+ * blocking random-access file functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * Synchronous @c read_some_at and @c write_some_at operations are thread safe+ * with respect to each other, if the underlying operating system calls are+ * also thread safe. This means that it is permitted to perform concurrent+ * calls to these synchronous operations on a single file object. Other+ * synchronous operations, such as @c open or @c close, are not thread safe.+ */+template <typename Executor>+class basic_random_access_file+  : public basic_file<Executor>+{+private:+  class initiate_async_write_some_at;+  class initiate_async_read_some_at;++public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the file type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The file type when rebound to the specified executor.+    typedef basic_random_access_file<Executor1> other;+  };++  /// The native representation of a file.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#else+  typedef typename basic_file<Executor>::native_handle_type native_handle_type;+#endif++  /// Construct a basic_random_access_file without opening it.+  /**+   * This constructor initialises a file without opening it. The file needs to+   * be opened before data can be read from or or written to it.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   */+  explicit basic_random_access_file(const executor_type& ex)+    : basic_file<Executor>(ex)+  {+  }++  /// Construct a basic_random_access_file without opening it.+  /**+   * This constructor initialises a file without opening it. The file needs to+   * be opened before data can be read from or or written to it.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   */+  template <typename ExecutionContext>+  explicit basic_random_access_file(ExecutionContext& context,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(context)+  {+  }++  /// Construct and open a basic_random_access_file.+  /**+   * This constructor initialises and opens a file.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_random_access_file(const executor_type& ex,+      const char* path, file_base::flags open_flags)+    : basic_file<Executor>(ex, path, open_flags)+  {+  }++  /// Construct and open a basic_random_access_file.+  /**+   * This constructor initialises and opens a file.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_random_access_file(ExecutionContext& context,+      const char* path, file_base::flags open_flags,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(context, path, open_flags)+  {+  }++  /// Construct and open a basic_random_access_file.+  /**+   * This constructor initialises and opens a file.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_random_access_file(const executor_type& ex,+      const std::string& path, file_base::flags open_flags)+    : basic_file<Executor>(ex, path, open_flags)+  {+  }++  /// Construct and open a basic_random_access_file.+  /**+   * This constructor initialises and opens a file.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_random_access_file(ExecutionContext& context,+      const std::string& path, file_base::flags open_flags,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(context, path, open_flags)+  {+  }++  /// Construct a basic_random_access_file on an existing native file.+  /**+   * This constructor initialises a random-access file object to hold an+   * existing native file.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   *+   * @param native_file The new underlying file implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_random_access_file(const executor_type& ex,+      const native_handle_type& native_file)+    : basic_file<Executor>(ex, native_file)+  {+  }++  /// Construct a basic_random_access_file on an existing native file.+  /**+   * This constructor initialises a random-access file object to hold an+   * existing native file.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   *+   * @param native_file The new underlying file implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_random_access_file(ExecutionContext& context,+      const native_handle_type& native_file,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(context, native_file)+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_random_access_file from another.+  /**+   * This constructor moves a random-access file from one object to another.+   *+   * @param other The other basic_random_access_file object from which the move+   * will occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_random_access_file(const executor_type&)+   * constructor.+   */+  basic_random_access_file(basic_random_access_file&& other) ASIO_NOEXCEPT+    : basic_file<Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_random_access_file from another.+  /**+   * This assignment operator moves a random-access file from one object to+   * another.+   *+   * @param other The other basic_random_access_file object from which the move+   * will occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_random_access_file(const executor_type&)+   * constructor.+   */+  basic_random_access_file& operator=(basic_random_access_file&& other)+  {+    basic_file<Executor>::operator=(std::move(other));+    return *this;+  }++  /// Move-construct a basic_random_access_file from a file of another executor+  /// type.+  /**+   * This constructor moves a random-access file from one object to another.+   *+   * @param other The other basic_random_access_file object from which the move+   * will occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_random_access_file(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  basic_random_access_file(basic_random_access_file<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_random_access_file from a file of another executor+  /// type.+  /**+   * This assignment operator moves a random-access file from one object to+   * another.+   *+   * @param other The other basic_random_access_file object from which the move+   * will occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_random_access_file(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_random_access_file&+  >::type operator=(basic_random_access_file<Executor1>&& other)+  {+    basic_file<Executor>::operator=(std::move(other));+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destroys the file.+  /**+   * This function destroys the file, cancelling any outstanding asynchronous+   * operations associated with the file as if by calling @c cancel.+   */+  ~basic_random_access_file()+  {+  }++  /// Write some data to the handle at the specified offset.+  /**+   * This function is used to write data to the random-access handle. The+   * function call will block until one or more bytes of the data has been+   * written successfully, or until an error occurs.+   *+   * @param offset The offset at which the data will be written.+   *+   * @param buffers One or more data buffers to be written to the handle.+   *+   * @returns The number of bytes written.+   *+   * @throws asio::system_error Thrown on failure. An error code of+   * asio::error::eof indicates that the end of the file was reached.+   *+   * @note The write_some_at operation may not write all of the data. Consider+   * using the @ref write_at function if you need to ensure that all data is+   * written before the blocking operation completes.+   *+   * @par Example+   * To write a single data buffer use the @ref buffer function as follows:+   * @code+   * handle.write_some_at(42, asio::buffer(data, size));+   * @endcode+   * See the @ref buffer documentation for information on writing multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   */+  template <typename ConstBufferSequence>+  std::size_t write_some_at(uint64_t offset,+      const ConstBufferSequence& buffers)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().write_some_at(+        this->impl_.get_implementation(), offset, buffers, ec);+    asio::detail::throw_error(ec, "write_some_at");+    return s;+  }++  /// Write some data to the handle at the specified offset.+  /**+   * This function is used to write data to the random-access handle. The+   * function call will block until one or more bytes of the data has been+   * written successfully, or until an error occurs.+   *+   * @param offset The offset at which the data will be written.+   *+   * @param buffers One or more data buffers to be written to the handle.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes written. Returns 0 if an error occurred.+   *+   * @note The write_some operation may not write all of the data to the+   * file. Consider using the @ref write_at function if you need to ensure that+   * all data is written before the blocking operation completes.+   */+  template <typename ConstBufferSequence>+  std::size_t write_some_at(uint64_t offset,+      const ConstBufferSequence& buffers, asio::error_code& ec)+  {+    return this->impl_.get_service().write_some_at(+        this->impl_.get_implementation(), offset, buffers, ec);+  }++  /// Start an asynchronous write at the specified offset.+  /**+   * This function is used to asynchronously write data to the random-access+   * handle. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.+   *+   * @param offset The offset at which the data will be written.+   *+   * @param buffers One or more data buffers to be written to the handle.+   * Although the buffers object may be copied as necessary, ownership of the+   * underlying memory blocks is retained by the caller, which must guarantee+   * that they remain valid until the completion handler is called.+   *+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the write completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   std::size_t bytes_transferred // Number of bytes written.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @note The write operation may not write all of the data to the file.+   * Consider using the @ref async_write_at function if you need to ensure that+   * all data is written before the asynchronous operation completes.+   *+   * @par Example+   * To write a single data buffer use the @ref buffer function as follows:+   * @code+   * handle.async_write_some_at(42, asio::buffer(data, size), handler);+   * @endcode+   * See the @ref buffer documentation for information on writing multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total+   */+  template <typename ConstBufferSequence,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        std::size_t)) WriteToken+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,+      void (asio::error_code, std::size_t))+  async_write_some_at(uint64_t offset,+      const ConstBufferSequence& buffers,+      ASIO_MOVE_ARG(WriteToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_write_some_at>(), token, offset, buffers)))+  {+    return async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        initiate_async_write_some_at(this), token, offset, buffers);+  }++  /// Read some data from the handle at the specified offset.+  /**+   * This function is used to read data from the random-access handle. The+   * function call will block until one or more bytes of data has been read+   * successfully, or until an error occurs.+   *+   * @param offset The offset at which the data will be read.+   *+   * @param buffers One or more buffers into which the data will be read.+   *+   * @returns The number of bytes read.+   *+   * @throws asio::system_error Thrown on failure. An error code of+   * asio::error::eof indicates that the end of the file was reached.+   *+   * @note The read_some operation may not read all of the requested number of+   * bytes. Consider using the @ref read_at function if you need to ensure that+   * the requested amount of data is read before the blocking operation+   * completes.+   *+   * @par Example+   * To read into a single data buffer use the @ref buffer function as follows:+   * @code+   * handle.read_some_at(42, asio::buffer(data, size));+   * @endcode+   * See the @ref buffer documentation for information on reading into multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   */+  template <typename MutableBufferSequence>+  std::size_t read_some_at(uint64_t offset,+      const MutableBufferSequence& buffers)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().read_some_at(+        this->impl_.get_implementation(), offset, buffers, ec);+    asio::detail::throw_error(ec, "read_some_at");+    return s;+  }++  /// Read some data from the handle at the specified offset.+  /**+   * This function is used to read data from the random-access handle. The+   * function call will block until one or more bytes of data has been read+   * successfully, or until an error occurs.+   *+   * @param offset The offset at which the data will be read.+   *+   * @param buffers One or more buffers into which the data will be read.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes read. Returns 0 if an error occurred.+   *+   * @note The read_some operation may not read all of the requested number of+   * bytes. Consider using the @ref read_at function if you need to ensure that+   * the requested amount of data is read before the blocking operation+   * completes.+   */+  template <typename MutableBufferSequence>+  std::size_t read_some_at(uint64_t offset,+      const MutableBufferSequence& buffers, asio::error_code& ec)+  {+    return this->impl_.get_service().read_some_at(+        this->impl_.get_implementation(), offset, buffers, ec);+  }++  /// Start an asynchronous read at the specified offset.+  /**+   * This function is used to asynchronously read data from the random-access+   * handle. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.+   *+   * @param offset The offset at which the data will be read.+   *+   * @param buffers One or more buffers into which the data will be read.+   * Although the buffers object may be copied as necessary, ownership of the+   * underlying memory blocks is retained by the caller, which must guarantee+   * that they remain valid until the completion handler is called.+   *+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the read completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   std::size_t bytes_transferred // Number of bytes read.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @note The read operation may not read all of the requested number of bytes.+   * Consider using the @ref async_read_at function if you need to ensure that+   * the requested amount of data is read before the asynchronous operation+   * completes.+   *+   * @par Example+   * To read into a single data buffer use the @ref buffer function as follows:+   * @code+   * handle.async_read_some_at(42, asio::buffer(data, size), handler);+   * @endcode+   * See the @ref buffer documentation for information on reading into multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total+   */+  template <typename MutableBufferSequence,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        std::size_t)) ReadToken+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,+      void (asio::error_code, std::size_t))+  async_read_some_at(uint64_t offset,+      const MutableBufferSequence& buffers,+      ASIO_MOVE_ARG(ReadToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_read_some_at>(), token, offset, buffers)))+  {+    return async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        initiate_async_read_some_at(this), token, offset, buffers);+  }++private:+  // Disallow copying and assignment.+  basic_random_access_file(const basic_random_access_file&) ASIO_DELETED;+  basic_random_access_file& operator=(+      const basic_random_access_file&) ASIO_DELETED;++  class initiate_async_write_some_at+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_write_some_at(basic_random_access_file* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename WriteHandler, typename ConstBufferSequence>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        uint64_t offset, const ConstBufferSequence& buffers) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a WriteHandler.+      ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;++      detail::non_const_lvalue<WriteHandler> handler2(handler);+      self_->impl_.get_service().async_write_some_at(+          self_->impl_.get_implementation(), offset, buffers,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_random_access_file* self_;+  };++  class initiate_async_read_some_at+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_read_some_at(basic_random_access_file* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename ReadHandler, typename MutableBufferSequence>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        uint64_t offset, const MutableBufferSequence& buffers) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a ReadHandler.+      ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;++      detail::non_const_lvalue<ReadHandler> handler2(handler);+      self_->impl_.get_service().async_read_some_at(+          self_->impl_.get_implementation(), offset, buffers,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_random_access_file* self_;+  };+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_RANDOM_ACCESS_FILE_HPP
link/modules/asio-standalone/asio/include/asio/basic_raw_socket.hpp view
@@ -2,7 +2,7 @@ // basic_raw_socket.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -45,11 +45,24 @@  * @par Thread Safety  * @e Distinct @e objects: Safe.@n  * @e Shared @e objects: Unsafe.+ *+ * Synchronous @c send, @c send_to, @c receive, @c receive_from, @c connect,+ * and @c shutdown operations are thread safe with respect to each other, if+ * the underlying operating system calls are also thread safe. This means that+ * it is permitted to perform concurrent calls to these synchronous operations+ * on a single socket object. Other synchronous operations, such as @c open or+ * @c close, are not thread safe.  */ template <typename Protocol, typename Executor> class basic_raw_socket   : public basic_socket<Protocol, Executor> {+private:+  class initiate_async_send;+  class initiate_async_send_to;+  class initiate_async_receive;+  class initiate_async_receive_from;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -100,9 +113,9 @@    */   template <typename ExecutionContext>   explicit basic_raw_socket(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context)   {   }@@ -137,9 +150,10 @@    */   template <typename ExecutionContext>   basic_raw_socket(ExecutionContext& context, const protocol_type& protocol,-      typename enable_if<-        is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())     : basic_socket<Protocol, Executor>(context, protocol)   {   }@@ -182,9 +196,9 @@    */   template <typename ExecutionContext>   basic_raw_socket(ExecutionContext& context, const endpoint_type& endpoint,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context, endpoint)   {   }@@ -227,9 +241,9 @@   template <typename ExecutionContext>   basic_raw_socket(ExecutionContext& context,       const protocol_type& protocol, const native_handle_type& native_socket,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context, protocol, native_socket)   {   }@@ -282,10 +296,10 @@    */   template <typename Protocol1, typename Executor1>   basic_raw_socket(basic_raw_socket<Protocol1, Executor1>&& other,-      typename enable_if<+      typename constraint<         is_convertible<Protocol1, Protocol>::value           && is_convertible<Executor1, Executor>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(std::move(other))   {   }@@ -302,7 +316,7 @@    * constructor.    */   template <typename Protocol1, typename Executor1>-  typename enable_if<+  typename constraint<     is_convertible<Protocol1, Protocol>::value       && is_convertible<Executor1, Executor>::value,     basic_raw_socket&@@ -406,26 +420,32 @@    /// 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.+   * This function is used to asynchronously send data on the raw socket. It is+   * an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more data buffers to be sent on the socket. Although    * the buffers object may be copied as necessary, ownership of the underlying    * memory blocks is retained by the caller, which must guarantee that they-   * remain valid until the handler is called.+   * remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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.@@ -438,65 +458,100 @@    * See the @ref buffer documentation for information on sending multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_send(const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send>(), token,+          buffers, socket_base::message_flags(0))))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send(this), handler,+        initiate_async_send(this), token,         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.+   * This function is used to asynchronously send data on the raw socket. It is+   * an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more data buffers to be sent on the socket. Although    * the buffers object may be copied as necessary, ownership of the underlying    * memory blocks is retained by the caller, which must guarantee that they-   * remain valid until the handler is called.+   * remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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 Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_send(const ConstBufferSequence& buffers,       socket_base::message_flags flags,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send>(), token, buffers, flags)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send(this), handler, buffers, flags);+        initiate_async_send(this), token, buffers, flags);   }    /// Send raw data to the specified endpoint.@@ -590,28 +645,34 @@   /// Start an asynchronous send.   /**    * This function is used to asynchronously send raw data to the specified-   * remote endpoint. The function call always returns immediately.+   * remote endpoint. It is an initiating function for an @ref+   * asynchronous_operation, and 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.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @par Example    * To send a single data buffer use the @ref buffer function as follows:    * @code@@ -623,65 +684,102 @@    * See the @ref buffer documentation for information on sending multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_send_to(const ConstBufferSequence& buffers,       const endpoint_type& destination,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send_to>(), token, buffers,+          destination, socket_base::message_flags(0))))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send_to(this), handler, buffers,+        initiate_async_send_to(this), token, 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.+   * remote endpoint. It is an initiating function for an @ref+   * asynchronous_operation, and 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.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       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_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send_to>(), token,+          buffers, destination, flags)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send_to(this), handler, buffers, destination, flags);+        initiate_async_send_to(this), token,+        buffers, destination, flags);   }    /// Receive some data on a connected socket.@@ -776,25 +874,31 @@   /// 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.+   * socket. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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.@@ -808,65 +912,100 @@    * See the @ref buffer documentation for information on receiving into    * multiple buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive(const MutableBufferSequence& buffers,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive>(), token,+          buffers, socket_base::message_flags(0))))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive(this), handler,+        initiate_async_receive(this), token,         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.+   * socket. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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 Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive(const MutableBufferSequence& buffers,       socket_base::message_flags flags,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive>(), token, buffers, flags)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive(this), handler, buffers, flags);+        initiate_async_receive(this), token, buffers, flags);   }    /// Receive raw data with the endpoint of the sender.@@ -960,31 +1099,37 @@    /// Start an asynchronous receive.   /**-   * This function is used to asynchronously receive raw data. The function-   * call always returns immediately.+   * This function is used to asynchronously receive raw data. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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.+   * completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @par Example    * To receive into a single data buffer use the @ref buffer function as    * follows:@@ -993,67 +1138,103 @@    * See the @ref buffer documentation for information on receiving into    * multiple buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive_from(const MutableBufferSequence& buffers,       endpoint_type& sender_endpoint,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive_from>(), token, buffers,+          &sender_endpoint, socket_base::message_flags(0))))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive_from(this), handler, buffers,+        initiate_async_receive_from(this), token, 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.+   * This function is used to asynchronously receive raw data. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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.+   * completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       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_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive_from>(), token,+          buffers, &sender_endpoint, flags)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive_from(this), handler,+        initiate_async_receive_from(this), token,         buffers, &sender_endpoint, flags);   } @@ -1072,7 +1253,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -1106,7 +1287,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -1140,7 +1321,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -1174,7 +1355,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
+ link/modules/asio-standalone/asio/include/asio/basic_readable_pipe.hpp view
@@ -0,0 +1,635 @@+//+// basic_readable_pipe.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_READABLE_PIPE_HPP+#define ASIO_BASIC_READABLE_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+  || defined(GENERATING_DOCUMENTATION)++#include <string>+#include "asio/any_io_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/io_object_impl.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_handle_service.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_descriptor_service.hpp"+#else+# include "asio/detail/reactive_descriptor_service.hpp"+#endif++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {++/// Provides pipe functionality.+/**+ * The basic_readable_pipe class provides a wrapper over pipe+ * functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor = any_io_executor>+class basic_readable_pipe+{+private:+  class initiate_async_read_some;++public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the pipe type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The pipe type when rebound to the specified executor.+    typedef basic_readable_pipe<Executor1> other;+  };++  /// The native representation of a pipe.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#elif defined(ASIO_HAS_IOCP)+  typedef detail::win_iocp_handle_service::native_handle_type+    native_handle_type;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  typedef detail::io_uring_descriptor_service::native_handle_type+    native_handle_type;+#else+  typedef detail::reactive_descriptor_service::native_handle_type+    native_handle_type;+#endif++  /// A basic_readable_pipe is always the lowest layer.+  typedef basic_readable_pipe lowest_layer_type;++  /// Construct a basic_readable_pipe without opening it.+  /**+   * This constructor creates a pipe without opening it.+   *+   * @param ex The I/O executor that the pipe will use, by default, to dispatch+   * handlers for any asynchronous operations performed on the pipe.+   */+  explicit basic_readable_pipe(const executor_type& ex)+    : impl_(0, ex)+  {+  }++  /// Construct a basic_readable_pipe without opening it.+  /**+   * This constructor creates a pipe without opening it.+   *+   * @param context An execution context which provides the I/O executor that+   * the pipe will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the pipe.+   */+  template <typename ExecutionContext>+  explicit basic_readable_pipe(ExecutionContext& context,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)+  {+  }++  /// Construct a basic_readable_pipe on an existing native pipe.+  /**+   * This constructor creates a pipe object to hold an existing native+   * pipe.+   *+   * @param ex The I/O executor that the pipe will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * pipe.+   *+   * @param native_pipe A native pipe.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_readable_pipe(const executor_type& ex,+      const native_handle_type& native_pipe)+    : impl_(0, ex)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        native_pipe, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Construct a basic_readable_pipe on an existing native pipe.+  /**+   * This constructor creates a pipe object to hold an existing native+   * pipe.+   *+   * @param context An execution context which provides the I/O executor that+   * the pipe will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the pipe.+   *+   * @param native_pipe A native pipe.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_readable_pipe(ExecutionContext& context,+      const native_handle_type& native_pipe,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type = 0)+    : impl_(0, 0, context)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        native_pipe, ec);+    asio::detail::throw_error(ec, "assign");+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_readable_pipe from another.+  /**+   * This constructor moves a pipe from one object to another.+   *+   * @param other The other basic_readable_pipe object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_readable_pipe(const executor_type&)+   * constructor.+   */+  basic_readable_pipe(basic_readable_pipe&& other)+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_readable_pipe from another.+  /**+   * This assignment operator moves a pipe from one object to another.+   *+   * @param other The other basic_readable_pipe object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_readable_pipe(const executor_type&)+   * constructor.+   */+  basic_readable_pipe& operator=(basic_readable_pipe&& other)+  {+    impl_ = std::move(other.impl_);+    return *this;+  }++  // All pipes have access to each other's implementations.+  template <typename Executor1>+  friend class basic_readable_pipe;++  /// Move-construct a basic_readable_pipe from a pipe of another executor type.+  /**+   * This constructor moves a pipe from one object to another.+   *+   * @param other The other basic_readable_pipe object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_readable_pipe(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  basic_readable_pipe(basic_readable_pipe<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_readable_pipe from a pipe of another executor type.+  /**+   * This assignment operator moves a pipe from one object to another.+   *+   * @param other The other basic_readable_pipe object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_readable_pipe(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_readable_pipe&+  >::type operator=(basic_readable_pipe<Executor1>&& other)+  {+    basic_readable_pipe tmp(std::move(other));+    impl_ = std::move(tmp.impl_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destroys the pipe.+  /**+   * This function destroys the pipe, cancelling any outstanding+   * asynchronous wait operations associated with the pipe as if by+   * calling @c cancel.+   */+  ~basic_readable_pipe()+  {+  }++  /// Get the executor associated with the object.+  const executor_type& get_executor() ASIO_NOEXCEPT+  {+    return impl_.get_executor();+  }++  /// Get a reference to the lowest layer.+  /**+   * This function returns a reference to the lowest layer in a stack of+   * layers. Since a basic_readable_pipe cannot contain any further layers, it+   * simply returns a reference to itself.+   *+   * @return A reference to the lowest layer in the stack of layers. Ownership+   * is not transferred to the caller.+   */+  lowest_layer_type& lowest_layer()+  {+    return *this;+  }++  /// Get a const reference to the lowest layer.+  /**+   * This function returns a const reference to the lowest layer in a stack of+   * layers. Since a basic_readable_pipe cannot contain any further layers, it+   * simply returns a reference to itself.+   *+   * @return A const reference to the lowest layer in the stack of layers.+   * Ownership is not transferred to the caller.+   */+  const lowest_layer_type& lowest_layer() const+  {+    return *this;+  }++  /// Assign an existing native pipe to the pipe.+  /*+   * This function opens the pipe to hold an existing native pipe.+   *+   * @param native_pipe A native pipe.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void assign(const native_handle_type& native_pipe)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Assign an existing native pipe to the pipe.+  /*+   * This function opens the pipe to hold an existing native pipe.+   *+   * @param native_pipe A native pipe.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe,+      asio::error_code& ec)+  {+    impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Determine whether the pipe is open.+  bool is_open() const+  {+    return impl_.get_service().is_open(impl_.get_implementation());+  }++  /// Close the pipe.+  /**+   * This function is used to close the pipe. Any asynchronous read operations+   * will be cancelled immediately, and will complete with the+   * asio::error::operation_aborted error.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void close()+  {+    asio::error_code ec;+    impl_.get_service().close(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "close");+  }++  /// Close the pipe.+  /**+   * This function is used to close the pipe. Any asynchronous read operations+   * will be cancelled immediately, and will complete with the+   * asio::error::operation_aborted error.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID close(asio::error_code& ec)+  {+    impl_.get_service().close(impl_.get_implementation(), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Release ownership of the underlying native pipe.+  /**+   * This function causes all outstanding asynchronous read operations to+   * finish immediately, and the handlers for cancelled operations will be+   * passed the asio::error::operation_aborted error. Ownership of the+   * native pipe 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 pipe.+  /**+   * This function causes all outstanding asynchronous read operations to+   * finish immediately, and the handlers for cancelled operations will be+   * passed the asio::error::operation_aborted error. Ownership of the+   * native pipe 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 pipe representation.+  /**+   * This function may be used to obtain the underlying representation of the+   * pipe. This is intended to allow access to native pipe+   * functionality that is not otherwise provided.+   */+  native_handle_type native_handle()+  {+    return impl_.get_service().native_handle(impl_.get_implementation());+  }++  /// Cancel all asynchronous operations associated with the pipe.+  /**+   * This function causes all outstanding asynchronous read operations to finish+   * immediately, and the handlers for cancelled operations will be passed the+   * asio::error::operation_aborted error.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void cancel()+  {+    asio::error_code ec;+    impl_.get_service().cancel(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "cancel");+  }++  /// Cancel all asynchronous operations associated with the pipe.+  /**+   * This function causes all outstanding asynchronous read operations to finish+   * immediately, and the handlers for cancelled operations will be passed the+   * asio::error::operation_aborted error.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)+  {+    impl_.get_service().cancel(impl_.get_implementation(), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Read some data from the pipe.+  /**+   * This function is used to read data from the pipe. The function call will+   * block until one or more bytes of data has been read successfully, or until+   * an error occurs.+   *+   * @param buffers One or more buffers into which the data will be read.+   *+   * @returns The number of bytes read.+   *+   * @throws asio::system_error Thrown on failure. An error code of+   * asio::error::eof indicates that the connection was closed by the+   * peer.+   *+   * @note The read_some operation may not read all of the requested number of+   * bytes. Consider using the @ref read function if you need to ensure that+   * the requested amount of data is read before the blocking operation+   * completes.+   *+   * @par Example+   * To read into a single data buffer use the @ref buffer function as follows:+   * @code+   * basic_readable_pipe.read_some(asio::buffer(data, size));+   * @endcode+   * See the @ref buffer documentation for information on reading into multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   */+  template <typename MutableBufferSequence>+  std::size_t read_some(const MutableBufferSequence& buffers)+  {+    asio::error_code ec;+    std::size_t s = impl_.get_service().read_some(+        impl_.get_implementation(), buffers, ec);+    asio::detail::throw_error(ec, "read_some");+    return s;+  }++  /// Read some data from the pipe.+  /**+   * This function is used to read data from the pipe. The function call will+   * block until one or more bytes of data has been read successfully, or until+   * an error occurs.+   *+   * @param buffers One or more buffers into which the data will be read.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes read. Returns 0 if an error occurred.+   *+   * @note The read_some operation may not read all of the requested number of+   * bytes. Consider using the @ref read function if you need to ensure that+   * the requested amount of data is read before the blocking operation+   * completes.+   */+  template <typename MutableBufferSequence>+  std::size_t read_some(const MutableBufferSequence& buffers,+      asio::error_code& ec)+  {+    return impl_.get_service().read_some(+        impl_.get_implementation(), buffers, ec);+  }++  /// Start an asynchronous read.+  /**+   * This function is used to asynchronously read data from the pipe. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.+   *+   * @param buffers One or more buffers into which the data will be read.+   * Although the buffers object may be copied as necessary, ownership of the+   * underlying memory blocks is retained by the caller, which must guarantee+   * that they remain valid until the completion handler is called.+   *+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the read completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   std::size_t bytes_transferred // Number of bytes read.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @note The read operation may not read all of the requested number of bytes.+   * Consider using the @ref async_read function if you need to ensure that the+   * requested amount of data is read before the asynchronous operation+   * completes.+   *+   * @par Example+   * To read into a single data buffer use the @ref buffer function as follows:+   * @code+   * basic_readable_pipe.async_read_some(+   *     asio::buffer(data, size), handler);+   * @endcode+   * See the @ref buffer documentation for information on reading into multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   */+  template <typename MutableBufferSequence,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        std::size_t)) ReadToken+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,+      void (asio::error_code, std::size_t))+  async_read_some(const MutableBufferSequence& buffers,+      ASIO_MOVE_ARG(ReadToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_read_some>(), token, buffers)))+  {+    return async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        initiate_async_read_some(this), token, buffers);+  }++private:+  // Disallow copying and assignment.+  basic_readable_pipe(const basic_readable_pipe&) ASIO_DELETED;+  basic_readable_pipe& operator=(const basic_readable_pipe&) ASIO_DELETED;++  class initiate_async_read_some+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_read_some(basic_readable_pipe* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename ReadHandler, typename MutableBufferSequence>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        const MutableBufferSequence& buffers) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a ReadHandler.+      ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;++      detail::non_const_lvalue<ReadHandler> handler2(handler);+      self_->impl_.get_service().async_read_some(+          self_->impl_.get_implementation(), buffers,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_readable_pipe* self_;+  };++#if defined(ASIO_HAS_IOCP)+  detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;+#else+  detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;+#endif+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PIPE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_READABLE_PIPE_HPP
link/modules/asio-standalone/asio/include/asio/basic_seq_packet_socket.hpp view
@@ -2,7 +2,7 @@ // basic_seq_packet_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -43,11 +43,22 @@  * @par Thread Safety  * @e Distinct @e objects: Safe.@n  * @e Shared @e objects: Unsafe.+ *+ * Synchronous @c send, @c receive, @c connect, and @c shutdown operations are+ * thread safe with respect to each other, if the underlying operating system+ * calls are also thread safe. This means that it is permitted to perform+ * concurrent calls to these synchronous operations on a single socket object.+ * Other synchronous operations, such as @c open or @c close, are not thread+ * safe.  */ template <typename Protocol, typename Executor> class basic_seq_packet_socket   : public basic_socket<Protocol, Executor> {+private:+  class initiate_async_send;+  class initiate_async_receive_with_flags;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -100,9 +111,9 @@    */   template <typename ExecutionContext>   explicit basic_seq_packet_socket(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context)   {   }@@ -143,9 +154,10 @@   template <typename ExecutionContext>   basic_seq_packet_socket(ExecutionContext& context,       const protocol_type& protocol,-      typename enable_if<-        is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())     : basic_socket<Protocol, Executor>(context, protocol)   {   }@@ -190,9 +202,9 @@   template <typename ExecutionContext>   basic_seq_packet_socket(ExecutionContext& context,       const endpoint_type& endpoint,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context, endpoint)   {   }@@ -235,9 +247,9 @@   template <typename ExecutionContext>   basic_seq_packet_socket(ExecutionContext& context,       const protocol_type& protocol, const native_handle_type& native_socket,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context, protocol, native_socket)   {   }@@ -293,10 +305,10 @@    */   template <typename Protocol1, typename Executor1>   basic_seq_packet_socket(basic_seq_packet_socket<Protocol1, Executor1>&& other,-      typename enable_if<+      typename constraint<         is_convertible<Protocol1, Protocol>::value           && is_convertible<Executor1, Executor>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(std::move(other))   {   }@@ -315,7 +327,7 @@    * constructor.    */   template <typename Protocol1, typename Executor1>-  typename enable_if<+  typename constraint<     is_convertible<Protocol1, Protocol>::value       && is_convertible<Executor1, Executor>::value,     basic_seq_packet_socket&@@ -398,27 +410,33 @@   /// Start an asynchronous send.   /**    * This function is used to asynchronously send data on the sequenced packet-   * socket. The function call always returns immediately.+   * socket. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param buffers One or more data buffers to be sent on the socket. Although    * the buffers object may be copied as necessary, ownership of the underlying    * memory blocks is retained by the caller, which must guarantee that they-   * remain valid until the handler is called.+   * remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @par Example    * To send a single data buffer use the @ref buffer function as follows:    * @code@@ -427,21 +445,35 @@    * See the @ref buffer documentation for information on sending multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_send(const ConstBufferSequence& buffers,       socket_base::message_flags flags,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send>(), token, buffers, flags)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send(this), handler, buffers, flags);+        initiate_async_send(this), token, buffers, flags);   }    /// Receive some data on the socket.@@ -566,31 +598,37 @@   /// Start an asynchronous receive.   /**    * This function is used to asynchronously receive data from the sequenced-   * packet socket. The function call always returns immediately.+   * packet socket. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion handler is called.    *    * @param out_flags Once the asynchronous operation completes, contains flags    * associated with the received data. For example, if the    * socket_base::message_end_of_record bit is set then the received data marks    * the end of a record. The caller must guarantee that the referenced-   * variable remains valid until the handler is called.+   * variable remains valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @par Example    * To receive into a single data buffer use the @ref buffer function as    * follows:@@ -600,33 +638,49 @@    * See the @ref buffer documentation for information on receiving into    * multiple buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive(const MutableBufferSequence& buffers,       socket_base::message_flags& out_flags,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive_with_flags>(), token,+          buffers, socket_base::message_flags(0), &out_flags)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive_with_flags(this), handler,+        initiate_async_receive_with_flags(this), token,         buffers, socket_base::message_flags(0), &out_flags);   }    /// Start an asynchronous receive.   /**    * This function is used to asynchronously receive data from the sequenced-   * data socket. The function call always returns immediately.+   * data socket. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion handler is called.    *    * @param in_flags Flags specifying how the receive call is to be made.    *@@ -634,20 +688,25 @@    * 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.+   * variable remains valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @par Example    * To receive into a single data buffer use the @ref buffer function as    * follows:@@ -659,23 +718,38 @@    * See the @ref buffer documentation for information on receiving into    * multiple buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive(const MutableBufferSequence& buffers,       socket_base::message_flags in_flags,       socket_base::message_flags& out_flags,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive_with_flags>(),+          token, buffers, in_flags, &out_flags)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(         initiate_async_receive_with_flags(this),-        handler, buffers, in_flags, &out_flags);+        token, buffers, in_flags, &out_flags);   }  private:@@ -694,7 +768,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -728,7 +802,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
link/modules/asio-standalone/asio/include/asio/basic_serial_port.hpp view
@@ -2,7 +2,7 @@ // basic_serial_port.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -35,7 +35,7 @@ #if defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_serial_port_service.hpp" #else-# include "asio/detail/reactive_serial_port_service.hpp"+# include "asio/detail/posix_serial_port_service.hpp" #endif  #if defined(ASIO_HAS_MOVE)@@ -59,6 +59,10 @@ class basic_serial_port   : public serial_port_base {+private:+  class initiate_async_write_some;+  class initiate_async_read_some;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -78,7 +82,7 @@   typedef detail::win_iocp_serial_port_service::native_handle_type     native_handle_type; #else-  typedef detail::reactive_serial_port_service::native_handle_type+  typedef detail::posix_serial_port_service::native_handle_type     native_handle_type; #endif @@ -94,7 +98,7 @@    * serial port.    */   explicit basic_serial_port(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -108,11 +112,11 @@    */   template <typename ExecutionContext>   explicit basic_serial_port(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value,-        basic_serial_port-      >::type* = 0)-    : impl_(context)+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {   } @@ -129,7 +133,7 @@    * port.    */   basic_serial_port(const executor_type& ex, const char* device)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().open(impl_.get_implementation(), device, ec);@@ -150,10 +154,10 @@    */   template <typename ExecutionContext>   basic_serial_port(ExecutionContext& context, const char* device,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().open(impl_.get_implementation(), device, ec);@@ -173,7 +177,7 @@    * port.    */   basic_serial_port(const executor_type& ex, const std::string& device)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().open(impl_.get_implementation(), device, ec);@@ -194,10 +198,10 @@    */   template <typename ExecutionContext>   basic_serial_port(ExecutionContext& context, const std::string& device,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().open(impl_.get_implementation(), device, ec);@@ -219,7 +223,7 @@    */   basic_serial_port(const executor_type& ex,       const native_handle_type& native_serial_port)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(),@@ -243,10 +247,10 @@   template <typename ExecutionContext>   basic_serial_port(ExecutionContext& context,       const native_handle_type& native_serial_port,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(),@@ -287,6 +291,55 @@     impl_ = std::move(other.impl_);     return *this;   }++  // All serial ports have access to each other's implementations.+  template <typename Executor1>+  friend class basic_serial_port;++  /// Move-construct a basic_serial_port from a serial port of another executor+  /// type.+  /**+   * 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.+   */+  template <typename Executor1>+  basic_serial_port(basic_serial_port<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_serial_port from a serial port of another executor+  /// type.+  /**+   * 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.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_serial_port&+  >::type operator=(basic_serial_port<Executor1>&& other)+  {+    basic_serial_port tmp(std::move(other));+    impl_ = std::move(tmp.impl_);+    return *this;+  } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)    /// Destroys the serial port.@@ -300,7 +353,7 @@   }    /// Get the executor associated with the object.-  executor_type get_executor() ASIO_NOEXCEPT+  const executor_type& get_executor() ASIO_NOEXCEPT   {     return impl_.get_executor();   }@@ -656,25 +709,31 @@   /// Start an asynchronous write.   /**    * This function is used to asynchronously write data to the serial port.-   * The function call always returns immediately.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more data buffers to be written to the serial port.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the write completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes written.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The write operation may not transmit all of the data to the peer.    * Consider using the @ref async_write function if you need to ensure that all    * data is written before the asynchronous operation completes.@@ -688,20 +747,34 @@    * See the @ref buffer documentation for information on writing multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_write_some(const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_write_some>(), token, buffers)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_write_some(this), handler, buffers);+        initiate_async_write_some(this), token, buffers);   }    /// Read some data from the serial port.@@ -770,25 +843,31 @@   /// Start an asynchronous read.   /**    * This function is used to asynchronously read data from the serial port.-   * The function call always returns immediately.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more buffers into which the data will be read.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the read completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes read.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The read operation may not read all of the requested number of bytes.    * Consider using the @ref async_read function if you need to ensure that the    * requested amount of data is read before the asynchronous operation@@ -803,20 +882,34 @@    * See the @ref buffer documentation for information on reading into multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_read_some(const MutableBufferSequence& buffers,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_read_some>(), token, buffers)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_read_some(this), handler, buffers);+        initiate_async_read_some(this), token, buffers);   }  private:@@ -834,7 +927,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -867,7 +960,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -893,7 +986,7 @@ #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_;+  detail::io_object_impl<detail::posix_serial_port_service, Executor> impl_; #endif }; 
link/modules/asio-standalone/asio/include/asio/basic_signal_set.hpp view
@@ -2,7 +2,7 @@ // basic_signal_set.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -27,7 +27,10 @@ #include "asio/detail/type_traits.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp"+#include "asio/signal_set_base.hpp" +#include "asio/detail/push_options.hpp"+ namespace asio {  /// Provides signal functionality.@@ -91,8 +94,11 @@  * least one thread.  */ template <typename Executor = any_io_executor>-class basic_signal_set+class basic_signal_set : public signal_set_base {+private:+  class initiate_async_wait;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -114,7 +120,7 @@    * signal set.    */   explicit basic_signal_set(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -128,10 +134,11 @@    */   template <typename ExecutionContext>   explicit basic_signal_set(ExecutionContext& context,-      typename enable_if<-        is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {   } @@ -150,7 +157,7 @@    * signals.add(signal_number_1); @endcode    */   basic_signal_set(const executor_type& ex, int signal_number_1)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -173,10 +180,11 @@    */   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)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -202,7 +210,7 @@    */   basic_signal_set(const executor_type& ex, int signal_number_1,       int signal_number_2)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -231,10 +239,11 @@   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)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -265,7 +274,7 @@    */   basic_signal_set(const executor_type& ex, int signal_number_1,       int signal_number_2, int signal_number_3)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -299,10 +308,11 @@   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)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().add(impl_.get_implementation(), signal_number_1, ec);@@ -324,7 +334,7 @@   }    /// Get the executor associated with the object.-  executor_type get_executor() ASIO_NOEXCEPT+  const executor_type& get_executor() ASIO_NOEXCEPT   {     return impl_.get_executor();   }@@ -361,6 +371,58 @@     ASIO_SYNC_OP_VOID_RETURN(ec);   } +  /// Add a signal to a signal_set with the specified flags.+  /**+   * This function adds the specified signal to the set. It has no effect if the+   * signal is already in the set.+   *+   * Flags other than flags::dont_care require OS support for the @c sigaction+   * call, and this function will fail with @c error::operation_not_supported if+   * this is unavailable.+   *+   * The specified flags will conflict with a prior, active registration of the+   * same signal, if either specified a flags value other than flags::dont_care.+   * In this case, the @c add will fail with @c error::invalid_argument.+   *+   * @param signal_number The signal to be added to the set.+   *+   * @param f Flags to modify the behaviour of the specified signal.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void add(int signal_number, flags_t f)+  {+    asio::error_code ec;+    impl_.get_service().add(impl_.get_implementation(), signal_number, f, ec);+    asio::detail::throw_error(ec, "add");+  }++  /// Add a signal to a signal_set with the specified flags.+  /**+   * This function adds the specified signal to the set. It has no effect if the+   * signal is already in the set.+   *+   * Flags other than flags::dont_care require OS support for the @c sigaction+   * call, and this function will fail with @c error::operation_not_supported if+   * this is unavailable.+   *+   * The specified flags will conflict with a prior, active registration of the+   * same signal, if either specified a flags value other than flags::dont_care.+   * In this case, the @c add will fail with @c error::invalid_argument.+   *+   * @param signal_number The signal to be added to the set.+   *+   * @param f Flags to modify the behaviour of the specified signal.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID add(int signal_number, flags_t f,+      asio::error_code& ec)+  {+    impl_.get_service().add(impl_.get_implementation(), signal_number, f, 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@@ -488,39 +550,58 @@   /// 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.+   * signal set. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *-   * For each call to async_wait(), the supplied handler will be called exactly-   * once. The handler will be called when:+   * For each call to async_wait(), the completion handler will be called+   * exactly once. The completion handler will be called when:    *    * @li One of the registered signals in the signal set occurs; or    *    * @li The signal set was cancelled, in which case the handler is passed the    * error code asio::error::operation_aborted.    *-   * @param 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the wait completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.    *   int signal_number // Indicates which signal occurred.    * ); @endcode    * Regardless of whether the asynchronous operation completes immediately or-   * not, the handler will not be invoked from within this function. On-   * immediate completion, invocation of the handler will be performed in a+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, int) @endcode+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code, int))-      SignalHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(SignalHandler,+      SignalToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(SignalToken,       void (asio::error_code, int))   async_wait(-      ASIO_MOVE_ARG(SignalHandler) handler+      ASIO_MOVE_ARG(SignalToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<SignalToken, void (asio::error_code, int)>(+          declval<initiate_async_wait>(), token)))   {-    return async_initiate<SignalHandler, void (asio::error_code, int)>(-        initiate_async_wait(this), handler);+    return async_initiate<SignalToken, void (asio::error_code, int)>(+        initiate_async_wait(this), token);   }  private:@@ -538,7 +619,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -564,5 +645,7 @@ };  } // namespace asio++#include "asio/detail/pop_options.hpp"  #endif // ASIO_BASIC_SIGNAL_SET_HPP
link/modules/asio-standalone/asio/include/asio/basic_socket.hpp view
@@ -2,7 +2,7 @@ // basic_socket.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -32,6 +32,8 @@ # include "asio/detail/null_socket_service.hpp" #elif defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_socket_service.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_socket_service.hpp" #else # include "asio/detail/reactive_socket_service.hpp" #endif@@ -66,6 +68,10 @@ class basic_socket   : public socket_base {+private:+  class initiate_async_connect;+  class initiate_async_wait;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -87,6 +93,9 @@ #elif defined(ASIO_HAS_IOCP)   typedef typename detail::win_iocp_socket_service<     Protocol>::native_handle_type native_handle_type;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  typedef typename detail::io_uring_socket_service<+    Protocol>::native_handle_type native_handle_type; #else   typedef typename detail::reactive_socket_service<     Protocol>::native_handle_type native_handle_type;@@ -111,7 +120,7 @@    * dispatch handlers for any asynchronous operations performed on the socket.    */   explicit basic_socket(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -125,10 +134,10 @@    */   template <typename ExecutionContext>   explicit basic_socket(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {   } @@ -144,7 +153,7 @@    * @throws asio::system_error Thrown on failure.    */   basic_socket(const executor_type& ex, const protocol_type& protocol)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().open(impl_.get_implementation(), protocol, ec);@@ -165,10 +174,11 @@    */   template <typename ExecutionContext>   basic_socket(ExecutionContext& context, const protocol_type& protocol,-      typename enable_if<-        is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().open(impl_.get_implementation(), protocol, ec);@@ -191,7 +201,7 @@    * @throws asio::system_error Thrown on failure.    */   basic_socket(const executor_type& ex, const endpoint_type& endpoint)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     const protocol_type protocol = endpoint.protocol();@@ -219,10 +229,10 @@    */   template <typename ExecutionContext>   basic_socket(ExecutionContext& context, const endpoint_type& endpoint,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     const protocol_type protocol = endpoint.protocol();@@ -247,7 +257,7 @@    */   basic_socket(const executor_type& ex, const protocol_type& protocol,       const native_handle_type& native_socket)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(),@@ -272,10 +282,10 @@   template <typename ExecutionContext>   basic_socket(ExecutionContext& context, const protocol_type& protocol,       const native_handle_type& native_socket,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(),@@ -331,10 +341,10 @@    */   template <typename Protocol1, typename Executor1>   basic_socket(basic_socket<Protocol1, Executor1>&& other,-      typename enable_if<+      typename constraint<         is_convertible<Protocol1, Protocol>::value           && is_convertible<Executor1, Executor>::value-      >::type* = 0)+      >::type = 0)     : impl_(std::move(other.impl_))   {   }@@ -350,11 +360,11 @@    * constructed using the @c basic_socket(const executor_type&) constructor.    */   template <typename Protocol1, typename Executor1>-  typename enable_if<+  typename constraint<     is_convertible<Protocol1, Protocol>::value       && is_convertible<Executor1, Executor>::value,     basic_socket&-  >::type operator=(basic_socket<Protocol1, Executor1> && other)+  >::type operator=(basic_socket<Protocol1, Executor1>&& other)   {     basic_socket tmp(std::move(other));     impl_ = std::move(tmp.impl_);@@ -363,7 +373,7 @@ #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)    /// Get the executor associated with the object.-  executor_type get_executor() ASIO_NOEXCEPT+  const executor_type& get_executor() ASIO_NOEXCEPT   {     return impl_.get_executor();   }@@ -901,7 +911,8 @@   /// Start an asynchronous connect.   /**    * This function is used to asynchronously connect a socket to the specified-   * remote endpoint. The function call always returns immediately.+   * remote endpoint. It is an initiating function for an @ref+   * asynchronous_operation, and 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@@ -910,17 +921,22 @@    * @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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the connect completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(-   *   const asio::error_code& error // Result of operation+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *    * @par Example    * @code    * void connect_handler(const asio::error_code& error)@@ -938,15 +954,29 @@    *     asio::ip::address::from_string("1.2.3.4"), 12345);    * socket.async_connect(endpoint, connect_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        ConnectHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ConnectHandler,+        ConnectToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ConnectToken,       void (asio::error_code))   async_connect(const endpoint_type& peer_endpoint,-      ASIO_MOVE_ARG(ConnectHandler) handler+      ASIO_MOVE_ARG(ConnectToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ConnectToken, void (asio::error_code)>(+          declval<initiate_async_connect>(), token,+          peer_endpoint, declval<asio::error_code&>())))   {     asio::error_code open_ec;     if (!is_open())@@ -955,8 +985,8 @@       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);+    return async_initiate<ConnectToken, void (asio::error_code)>(+        initiate_async_connect(this), token, peer_endpoint, open_ec);   }    /// Set an option on the socket.@@ -1740,21 +1770,28 @@   /// 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.+   * a ready to read, write or error condition state. It is an initiating+   * function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * @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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the wait completes. Potential+   * completion tokens include @ref use_future, @ref use_awaitable, @ref+   * yield_context, or a function object with the correct completion signature.+   * The function signature of the completion handler must be:    * @code void handler(-   *   const asio::error_code& error // Result of operation+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *    * @par Example    * @code    * void wait_handler(const asio::error_code& error)@@ -1771,18 +1808,31 @@    * ...    * socket.async_wait(asio::ip::tcp::socket::wait_read, wait_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+        WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken,       void (asio::error_code))   async_wait(wait_type w,-      ASIO_MOVE_ARG(WaitHandler) handler+      ASIO_MOVE_ARG(WaitToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WaitToken, void (asio::error_code)>(+          declval<initiate_async_wait>(), token, w)))   {-    return async_initiate<WaitHandler, void (asio::error_code)>(-        initiate_async_wait(this), handler, w);+    return async_initiate<WaitToken, void (asio::error_code)>(+        initiate_async_wait(this), token, w);   }  protected:@@ -1801,6 +1851,9 @@ #elif defined(ASIO_HAS_IOCP)   detail::io_object_impl<     detail::win_iocp_socket_service<Protocol>, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  detail::io_object_impl<+    detail::io_uring_socket_service<Protocol>, Executor> impl_; #else   detail::io_object_impl<     detail::reactive_socket_service<Protocol>, Executor> impl_;@@ -1821,7 +1874,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -1864,7 +1917,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
link/modules/asio-standalone/asio/include/asio/basic_socket_acceptor.hpp view
@@ -2,7 +2,7 @@ // basic_socket_acceptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -31,6 +31,8 @@ # include "asio/detail/null_socket_service.hpp" #elif defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_socket_service.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_socket_service.hpp" #else # include "asio/detail/reactive_socket_service.hpp" #endif@@ -61,6 +63,12 @@  * @e Distinct @e objects: Safe.@n  * @e Shared @e objects: Unsafe.  *+ * Synchronous @c accept operations are thread safe, if the underlying+ * operating system calls are also thread safe. This means that it is permitted+ * to perform concurrent calls to synchronous @c accept operations on a single+ * socket object. Other synchronous operations, such as @c open or @c close, are+ * not thread safe.+ *  * @par Example  * Opening a socket acceptor with the SO_REUSEADDR option enabled:  * @code@@ -76,6 +84,11 @@ class basic_socket_acceptor   : public socket_base {+private:+  class initiate_async_wait;+  class initiate_async_accept;+  class initiate_async_move_accept;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -97,6 +110,9 @@ #elif defined(ASIO_HAS_IOCP)   typedef typename detail::win_iocp_socket_service<     Protocol>::native_handle_type native_handle_type;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  typedef typename detail::io_uring_socket_service<+    Protocol>::native_handle_type native_handle_type; #else   typedef typename detail::reactive_socket_service<     Protocol>::native_handle_type native_handle_type;@@ -119,7 +135,7 @@    * acceptor.    */   explicit basic_socket_acceptor(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -135,10 +151,10 @@    */   template <typename ExecutionContext>   explicit basic_socket_acceptor(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {   } @@ -155,7 +171,7 @@    * @throws asio::system_error Thrown on failure.    */   basic_socket_acceptor(const executor_type& ex, const protocol_type& protocol)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().open(impl_.get_implementation(), protocol, ec);@@ -177,10 +193,11 @@   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)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().open(impl_.get_implementation(), protocol, ec);@@ -216,7 +233,7 @@    */   basic_socket_acceptor(const executor_type& ex,       const endpoint_type& endpoint, bool reuse_addr = true)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     const protocol_type protocol = endpoint.protocol();@@ -265,10 +282,10 @@   template <typename ExecutionContext>   basic_socket_acceptor(ExecutionContext& context,       const endpoint_type& endpoint, bool reuse_addr = true,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     const protocol_type protocol = endpoint.protocol();@@ -304,7 +321,7 @@    */   basic_socket_acceptor(const executor_type& ex,       const protocol_type& protocol, const native_handle_type& native_acceptor)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(),@@ -330,10 +347,10 @@   template <typename ExecutionContext>   basic_socket_acceptor(ExecutionContext& context,       const protocol_type& protocol, const native_handle_type& native_acceptor,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(),@@ -393,10 +410,10 @@    */   template <typename Protocol1, typename Executor1>   basic_socket_acceptor(basic_socket_acceptor<Protocol1, Executor1>&& other,-      typename enable_if<+      typename constraint<         is_convertible<Protocol1, Protocol>::value           && is_convertible<Executor1, Executor>::value-      >::type* = 0)+      >::type = 0)     : impl_(std::move(other.impl_))   {   }@@ -414,7 +431,7 @@    * constructor.    */   template <typename Protocol1, typename Executor1>-  typename enable_if<+  typename constraint<     is_convertible<Protocol1, Protocol>::value       && is_convertible<Executor1, Executor>::value,     basic_socket_acceptor&@@ -437,7 +454,7 @@   }    /// Get the executor associated with the object.-  executor_type get_executor() ASIO_NOEXCEPT+  const executor_type& get_executor() ASIO_NOEXCEPT   {     return impl_.get_executor();   }@@ -1184,21 +1201,28 @@   /// 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.+   * enter a ready to read, write or error condition state. It is an initiating+   * function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * @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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the wait completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(-   *   const asio::error_code& error // Result of operation+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *    * @par Example    * @code    * void wait_handler(const asio::error_code& error)@@ -1217,18 +1241,31 @@    *     asio::ip::tcp::acceptor::wait_read,    *     wait_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+        WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken,       void (asio::error_code))   async_wait(wait_type w,-      ASIO_MOVE_ARG(WaitHandler) handler+      ASIO_MOVE_ARG(WaitToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WaitToken, void (asio::error_code)>(+          declval<initiate_async_wait>(), token, w)))   {-    return async_initiate<WaitHandler, void (asio::error_code)>(-        initiate_async_wait(this), handler, w);+    return async_initiate<WaitToken, void (asio::error_code)>(+        initiate_async_wait(this), token, w);   }  #if !defined(ASIO_NO_EXTENSIONS)@@ -1252,9 +1289,9 @@    */   template <typename Protocol1, typename Executor1>   void accept(basic_socket<Protocol1, Executor1>& peer,-      typename enable_if<+      typename constraint<         is_convertible<Protocol, Protocol1>::value-      >::type* = 0)+      >::type = 0)   {     asio::error_code ec;     impl_.get_service().accept(impl_.get_implementation(),@@ -1288,9 +1325,9 @@   template <typename Protocol1, typename Executor1>   ASIO_SYNC_OP_VOID accept(       basic_socket<Protocol1, Executor1>& peer, asio::error_code& ec,-      typename enable_if<+      typename constraint<         is_convertible<Protocol, Protocol1>::value-      >::type* = 0)+      >::type = 0)   {     impl_.get_service().accept(impl_.get_implementation(),         peer, static_cast<endpoint_type*>(0), ec);@@ -1300,23 +1337,30 @@   /// Start an asynchronous accept.   /**    * This function is used to asynchronously accept a new connection into a-   * socket. The function call always returns immediately.+   * socket, and additionally obtain the endpoint of the remote peer. It is an+   * initiating function for an @ref asynchronous_operation, and 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.+   * guarantee that it is valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the accept completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error // Result of operation.    * ); @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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *    * @par Example    * @code    * void accept_handler(const asio::error_code& error)@@ -1334,21 +1378,35 @@    * asio::ip::tcp::socket socket(my_context);    * acceptor.async_accept(socket, accept_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename 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,+        AcceptToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(AcceptToken,       void (asio::error_code))   async_accept(basic_socket<Protocol1, Executor1>& peer,-      ASIO_MOVE_ARG(AcceptHandler) handler+      ASIO_MOVE_ARG(AcceptToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),-      typename enable_if<+      typename constraint<         is_convertible<Protocol, Protocol1>::value-      >::type* = 0)+      >::type = 0)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<AcceptToken, void (asio::error_code)>(+          declval<initiate_async_accept>(), token,+          &peer, static_cast<endpoint_type*>(0))))   {-    return async_initiate<AcceptHandler, void (asio::error_code)>(-        initiate_async_accept(this), handler,+    return async_initiate<AcceptToken, void (asio::error_code)>(+        initiate_async_accept(this), token,         &peer, static_cast<endpoint_type*>(0));   } @@ -1425,41 +1483,60 @@   /// 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.+   * socket, and additionally obtain the endpoint of the remote peer. It is an+   * initiating function for an @ref asynchronous_operation, and 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.+   * guarantee that it is valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the accept completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error // Result of operation.    * ); @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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename Executor1,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        AcceptHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(AcceptHandler,+        AcceptToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(AcceptToken,       void (asio::error_code))   async_accept(basic_socket<protocol_type, Executor1>& peer,       endpoint_type& peer_endpoint,-      ASIO_MOVE_ARG(AcceptHandler) handler+      ASIO_MOVE_ARG(AcceptToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<AcceptToken, void (asio::error_code)>(+          declval<initiate_async_accept>(), token, &peer, &peer_endpoint)))   {-    return async_initiate<AcceptHandler, void (asio::error_code)>(-        initiate_async_accept(this), handler, &peer, &peer_endpoint);+    return async_initiate<AcceptToken, void (asio::error_code)>(+        initiate_async_accept(this), token, &peer, &peer_endpoint);   } #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1531,27 +1608,36 @@    /// Start an asynchronous accept.   /**-   * This function is used to asynchronously accept a new connection. The-   * function call always returns immediately.+   * This function is used to asynchronously accept a new connection. It is an+   * initiating function for an @ref asynchronous_operation, and 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the accept completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   // 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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code,+   *    typename Protocol::socket::template+   *      rebind_executor<executor_type>::other)) @endcode+   *    * @par Example    * @code    * void accept_handler(const asio::error_code& error,@@ -1569,24 +1655,42 @@    * ...    * acceptor.async_accept(accept_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         typename Protocol::socket::template rebind_executor<-          executor_type>::other)) MoveAcceptHandler+          executor_type>::other)) MoveAcceptToken             ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken,       void (asio::error_code,         typename Protocol::socket::template           rebind_executor<executor_type>::other))   async_accept(-      ASIO_MOVE_ARG(MoveAcceptHandler) handler+      ASIO_MOVE_ARG(MoveAcceptToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<MoveAcceptToken,+        void (asio::error_code, typename Protocol::socket::template+          rebind_executor<executor_type>::other)>(+            declval<initiate_async_move_accept>(), token,+            declval<executor_type>(), static_cast<endpoint_type*>(0),+            static_cast<typename Protocol::socket::template+              rebind_executor<executor_type>::other*>(0))))   {-    return async_initiate<MoveAcceptHandler,+    return async_initiate<MoveAcceptToken,       void (asio::error_code, typename Protocol::socket::template         rebind_executor<executor_type>::other)>(-          initiate_async_move_accept(this), handler,+          initiate_async_move_accept(this), token,           impl_.get_executor(), static_cast<endpoint_type*>(0),           static_cast<typename Protocol::socket::template             rebind_executor<executor_type>::other*>(0));@@ -1618,10 +1722,10 @@   template <typename Executor1>   typename Protocol::socket::template rebind_executor<Executor1>::other   accept(const Executor1& ex,-      typename enable_if<+      typename constraint<         is_executor<Executor1>::value           || execution::is_executor<Executor1>::value-      >::type* = 0)+      >::type = 0)   {     asio::error_code ec;     typename Protocol::socket::template@@ -1658,9 +1762,9 @@   typename Protocol::socket::template rebind_executor<       typename ExecutionContext::executor_type>::other   accept(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)   {     asio::error_code ec;     typename Protocol::socket::template rebind_executor<@@ -1701,10 +1805,10 @@   template <typename Executor1>   typename Protocol::socket::template rebind_executor<Executor1>::other   accept(const Executor1& ex, asio::error_code& ec,-      typename enable_if<+      typename constraint<         is_executor<Executor1>::value           || execution::is_executor<Executor1>::value-      >::type* = 0)+      >::type = 0)   {     typename Protocol::socket::template       rebind_executor<Executor1>::other peer(ex);@@ -1744,9 +1848,9 @@   typename Protocol::socket::template rebind_executor<       typename ExecutionContext::executor_type>::other   accept(ExecutionContext& context, asio::error_code& ec,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)   {     typename Protocol::socket::template rebind_executor<         typename ExecutionContext::executor_type>::other peer(context);@@ -1756,8 +1860,9 @@    /// Start an asynchronous accept.   /**-   * This function is used to asynchronously accept a new connection. The-   * function call always returns immediately.+   * This function is used to asynchronously accept a new connection. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * This overload requires that the Protocol template parameter satisfy the    * AcceptableProtocol type requirements.@@ -1765,19 +1870,29 @@    * @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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the accept completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(-   *   const asio::error_code& error, // Result of operation.+   *   // Result of operation.+   *   const asio::error_code& error,+   *+   *   // On success, the newly accepted socket.    *   typename Protocol::socket::template rebind_executor<-   *     Executor1>::other peer // On success, the newly accepted socket.+   *     Executor1>::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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code,+   *    typename Protocol::socket::template rebind_executor<+   *      Executor1>::other)) @endcode+   *    * @par Example    * @code    * void accept_handler(const asio::error_code& error,@@ -1795,38 +1910,60 @@    * ...    * acceptor.async_accept(my_context2, accept_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename 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,+          typename constraint<is_executor<Executor1>::value+            || execution::is_executor<Executor1>::value,+              Executor1>::type>::other)) MoveAcceptToken+                ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken,       void (asio::error_code,         typename Protocol::socket::template rebind_executor<           Executor1>::other))   async_accept(const Executor1& ex,-      ASIO_MOVE_ARG(MoveAcceptHandler) handler+      ASIO_MOVE_ARG(MoveAcceptToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),-      typename enable_if<+      typename constraint<         is_executor<Executor1>::value           || execution::is_executor<Executor1>::value-      >::type* = 0)+      >::type = 0)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<MoveAcceptToken,+        void (asio::error_code,+          typename Protocol::socket::template rebind_executor<+            Executor1>::other)>(+              declval<initiate_async_move_accept>(), token,+              ex, static_cast<endpoint_type*>(0),+              static_cast<typename Protocol::socket::template+                rebind_executor<Executor1>::other*>(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));+    return async_initiate<MoveAcceptToken,+      void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          Executor1>::other)>(+            initiate_async_move_accept(this), token,+            ex, static_cast<endpoint_type*>(0),+            static_cast<typename Protocol::socket::template+              rebind_executor<Executor1>::other*>(0));   }    /// Start an asynchronous accept.   /**-   * This function is used to asynchronously accept a new connection. The-   * function call always returns immediately.+   * This function is used to asynchronously accept a new connection. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * This overload requires that the Protocol template parameter satisfy the    * AcceptableProtocol type requirements.@@ -1834,20 +1971,29 @@    * @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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the accept completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(-   *   const asio::error_code& error, // Result of operation.+   *   // Result of operation.+   *   const asio::error_code& error,+   *+   *   // On success, the newly accepted socket.    *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code,+   *    typename Protocol::socket::template rebind_executor<+   *      typename ExecutionContext::executor_type>::other)) @endcode+   *    * @par Example    * @code    * void accept_handler(const asio::error_code& error,@@ -1865,31 +2011,50 @@    * ...    * acceptor.async_accept(my_context2, accept_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ExecutionContext,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         typename Protocol::socket::template rebind_executor<-          typename ExecutionContext::executor_type>::other)) MoveAcceptHandler+          typename ExecutionContext::executor_type>::other)) MoveAcceptToken             ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken,       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_MOVE_ARG(MoveAcceptToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<MoveAcceptToken,+        void (asio::error_code,+          typename Protocol::socket::template rebind_executor<+            typename ExecutionContext::executor_type>::other)>(+              declval<initiate_async_move_accept>(), token,+              context.get_executor(), static_cast<endpoint_type*>(0),+              static_cast<typename Protocol::socket::template rebind_executor<+                typename ExecutionContext::executor_type>::other*>(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));+    return async_initiate<MoveAcceptToken,+      void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          typename ExecutionContext::executor_type>::other)>(+            initiate_async_move_accept(this), token,+            context.get_executor(), static_cast<endpoint_type*>(0),+            static_cast<typename Protocol::socket::template rebind_executor<+              typename ExecutionContext::executor_type>::other*>(0));   }    /// Accept a new connection.@@ -1969,8 +2134,9 @@    /// Start an asynchronous accept.   /**-   * This function is used to asynchronously accept a new connection. The-   * function call always returns immediately.+   * This function is used to asynchronously accept a new connection. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * This overload requires that the Protocol template parameter satisfy the    * AcceptableProtocol type requirements.@@ -1978,23 +2144,31 @@    * @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.+   * completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the accept completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   // 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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code,+   *    typename Protocol::socket::template+   *      rebind_executor<executor_type>::other)) @endcode+   *    * @par Example    * @code    * void accept_handler(const asio::error_code& error,@@ -2013,24 +2187,42 @@    * asio::ip::tcp::endpoint endpoint;    * acceptor.async_accept(endpoint, accept_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         typename Protocol::socket::template rebind_executor<-          executor_type>::other)) MoveAcceptHandler+          executor_type>::other)) MoveAcceptToken             ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken,       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_MOVE_ARG(MoveAcceptToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<MoveAcceptToken,+        void (asio::error_code, typename Protocol::socket::template+          rebind_executor<executor_type>::other)>(+            declval<initiate_async_move_accept>(), token,+            declval<executor_type>(), &peer_endpoint,+            static_cast<typename Protocol::socket::template+              rebind_executor<executor_type>::other*>(0))))   {-    return async_initiate<MoveAcceptHandler,+    return async_initiate<MoveAcceptToken,       void (asio::error_code, typename Protocol::socket::template         rebind_executor<executor_type>::other)>(-          initiate_async_move_accept(this), handler,+          initiate_async_move_accept(this), token,           impl_.get_executor(), &peer_endpoint,           static_cast<typename Protocol::socket::template             rebind_executor<executor_type>::other*>(0));@@ -2067,10 +2259,10 @@   template <typename Executor1>   typename Protocol::socket::template rebind_executor<Executor1>::other   accept(const Executor1& ex, endpoint_type& peer_endpoint,-      typename enable_if<+      typename constraint<         is_executor<Executor1>::value           || execution::is_executor<Executor1>::value-      >::type* = 0)+      >::type = 0)   {     asio::error_code ec;     typename Protocol::socket::template@@ -2113,9 +2305,9 @@   typename Protocol::socket::template rebind_executor<       typename ExecutionContext::executor_type>::other   accept(ExecutionContext& context, endpoint_type& peer_endpoint,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)   {     asio::error_code ec;     typename Protocol::socket::template rebind_executor<@@ -2163,10 +2355,10 @@   typename Protocol::socket::template rebind_executor<Executor1>::other   accept(const executor_type& ex,       endpoint_type& peer_endpoint, asio::error_code& ec,-      typename enable_if<+      typename constraint<         is_executor<Executor1>::value           || execution::is_executor<Executor1>::value-      >::type* = 0)+      >::type = 0)   {     typename Protocol::socket::template       rebind_executor<Executor1>::other peer(ex);@@ -2213,9 +2405,9 @@       typename ExecutionContext::executor_type>::other   accept(ExecutionContext& context,       endpoint_type& peer_endpoint, asio::error_code& ec,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)   {     typename Protocol::socket::template rebind_executor<         typename ExecutionContext::executor_type>::other peer(context);@@ -2226,8 +2418,9 @@    /// Start an asynchronous accept.   /**-   * This function is used to asynchronously accept a new connection. The-   * function call always returns immediately.+   * This function is used to asynchronously accept a new connection. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * This overload requires that the Protocol template parameter satisfy the    * AcceptableProtocol type requirements.@@ -2238,21 +2431,31 @@    * @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.+   * completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the accept completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(-   *   const asio::error_code& error, // Result of operation.+   *   // Result of operation.+   *   const asio::error_code& error,+   *+   *   // On success, the newly accepted socket.    *   typename Protocol::socket::template rebind_executor<-   *     Executor1>::other peer // On success, the newly accepted socket.+   *     Executor1>::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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code,+   *    typename Protocol::socket::template rebind_executor<+   *      Executor1>::other)) @endcode+   *    * @par Example    * @code    * void accept_handler(const asio::error_code& error,@@ -2271,38 +2474,58 @@    * asio::ip::tcp::endpoint endpoint;    * acceptor.async_accept(my_context2, endpoint, accept_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename 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,+          typename constraint<is_executor<Executor1>::value+            || execution::is_executor<Executor1>::value,+              Executor1>::type>::other)) MoveAcceptToken+                ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken,       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_MOVE_ARG(MoveAcceptToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),-      typename enable_if<+      typename constraint<         is_executor<Executor1>::value           || execution::is_executor<Executor1>::value-      >::type* = 0)+      >::type = 0)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<MoveAcceptToken,+        void (asio::error_code,+          typename Protocol::socket::template rebind_executor<+            Executor1>::other)>(+          declval<initiate_async_move_accept>(), token, ex, &peer_endpoint,+          static_cast<typename Protocol::socket::template+            rebind_executor<Executor1>::other*>(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));+    return async_initiate<MoveAcceptToken,+      void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          Executor1>::other)>(+            initiate_async_move_accept(this), token, ex, &peer_endpoint,+            static_cast<typename Protocol::socket::template+              rebind_executor<Executor1>::other*>(0));   }    /// Start an asynchronous accept.   /**-   * This function is used to asynchronously accept a new connection. The-   * function call always returns immediately.+   * This function is used to asynchronously accept a new connection. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * This overload requires that the Protocol template parameter satisfy the    * AcceptableProtocol type requirements.@@ -2313,22 +2536,31 @@    * @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.+   * completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the accept completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(-   *   const asio::error_code& error, // Result of operation.+   *   // Result of operation.+   *   const asio::error_code& error,+   *+   *   // On success, the newly accepted socket.    *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code,+   *    typename Protocol::socket::template rebind_executor<+   *      typename ExecutionContext::executor_type>::other)) @endcode+   *    * @par Example    * @code    * void accept_handler(const asio::error_code& error,@@ -2347,32 +2579,51 @@    * asio::ip::tcp::endpoint endpoint;    * acceptor.async_accept(my_context2, endpoint, accept_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ExecutionContext,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         typename Protocol::socket::template rebind_executor<-          typename ExecutionContext::executor_type>::other)) MoveAcceptHandler+          typename ExecutionContext::executor_type>::other)) MoveAcceptToken             ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(MoveAcceptHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(MoveAcceptToken,       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_MOVE_ARG(MoveAcceptToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type),-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<MoveAcceptToken,+        void (asio::error_code,+          typename Protocol::socket::template rebind_executor<+            typename ExecutionContext::executor_type>::other)>(+              declval<initiate_async_move_accept>(), token,+              context.get_executor(), &peer_endpoint,+              static_cast<typename Protocol::socket::template rebind_executor<+                typename ExecutionContext::executor_type>::other*>(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));+    return async_initiate<MoveAcceptToken,+      void (asio::error_code,+        typename Protocol::socket::template rebind_executor<+          typename ExecutionContext::executor_type>::other)>(+            initiate_async_move_accept(this), token,+            context.get_executor(), &peer_endpoint,+            static_cast<typename Protocol::socket::template rebind_executor<+              typename ExecutionContext::executor_type>::other*>(0));   } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -2392,7 +2643,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -2424,7 +2675,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -2458,7 +2709,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -2488,6 +2739,9 @@ #elif defined(ASIO_HAS_IOCP)   detail::io_object_impl<     detail::win_iocp_socket_service<Protocol>, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  detail::io_object_impl<+    detail::io_uring_socket_service<Protocol>, Executor> impl_; #else   detail::io_object_impl<     detail::reactive_socket_service<Protocol>, Executor> impl_;
link/modules/asio-standalone/asio/include/asio/basic_socket_iostream.hpp view
@@ -2,7 +2,7 @@ // basic_socket_iostream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/basic_socket_streambuf.hpp view
@@ -2,7 +2,7 @@ // basic_socket_streambuf.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/basic_stream_file.hpp view
@@ -0,0 +1,754 @@+//+// basic_stream_file.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_STREAM_FILE_HPP+#define ASIO_BASIC_STREAM_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+  || defined(GENERATING_DOCUMENTATION)++#include <cstddef>+#include "asio/async_result.hpp"+#include "asio/basic_file.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(ASIO_BASIC_STREAM_FILE_FWD_DECL)+#define ASIO_BASIC_STREAM_FILE_FWD_DECL++// Forward declaration with defaulted arguments.+template <typename Executor = any_io_executor>+class basic_stream_file;++#endif // !defined(ASIO_BASIC_STREAM_FILE_FWD_DECL)++/// Provides stream-oriented file functionality.+/**+ * The basic_stream_file class template provides asynchronous and blocking+ * stream-oriented file functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * @par Concepts:+ * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.+ */+template <typename Executor>+class basic_stream_file+  : public basic_file<Executor>+{+private:+  class initiate_async_write_some;+  class initiate_async_read_some;++public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the file type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The file type when rebound to the specified executor.+    typedef basic_stream_file<Executor1> other;+  };++  /// The native representation of a file.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#else+  typedef typename basic_file<Executor>::native_handle_type native_handle_type;+#endif++  /// Construct a basic_stream_file without opening it.+  /**+   * This constructor initialises a file without opening it. The file needs to+   * be opened before data can be read from or or written to it.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   */+  explicit basic_stream_file(const executor_type& ex)+    : basic_file<Executor>(ex)+  {+    this->impl_.get_service().set_is_stream(+        this->impl_.get_implementation(), true);+  }++  /// Construct a basic_stream_file without opening it.+  /**+   * This constructor initialises a file without opening it. The file needs to+   * be opened before data can be read from or or written to it.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   */+  template <typename ExecutionContext>+  explicit basic_stream_file(ExecutionContext& context,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(context)+  {+    this->impl_.get_service().set_is_stream(+        this->impl_.get_implementation(), true);+  }++  /// Construct and open a basic_stream_file.+  /**+   * This constructor initialises and opens a file.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_stream_file(const executor_type& ex,+      const char* path, file_base::flags open_flags)+    : basic_file<Executor>(ex)+  {+    asio::error_code ec;+    this->impl_.get_service().set_is_stream(+        this->impl_.get_implementation(), true);+    this->impl_.get_service().open(+        this->impl_.get_implementation(),+        path, open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct and open a basic_stream_file.+  /**+   * This constructor initialises and opens a file.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_stream_file(ExecutionContext& context,+      const char* path, file_base::flags open_flags,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(context)+  {+    asio::error_code ec;+    this->impl_.get_service().set_is_stream(+        this->impl_.get_implementation(), true);+    this->impl_.get_service().open(+        this->impl_.get_implementation(),+        path, open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct and open a basic_stream_file.+  /**+   * This constructor initialises and opens a file.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_stream_file(const executor_type& ex,+      const std::string& path, file_base::flags open_flags)+    : basic_file<Executor>(ex)+  {+    asio::error_code ec;+    this->impl_.get_service().set_is_stream(+        this->impl_.get_implementation(), true);+    this->impl_.get_service().open(+        this->impl_.get_implementation(),+        path.c_str(), open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct and open a basic_stream_file.+  /**+   * This constructor initialises and opens a file.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   *+   * @param path The path name identifying the file to be opened.+   *+   * @param open_flags A set of flags that determine how the file should be+   * opened.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_stream_file(ExecutionContext& context,+      const std::string& path, file_base::flags open_flags,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(context)+  {+    asio::error_code ec;+    this->impl_.get_service().set_is_stream(+        this->impl_.get_implementation(), true);+    this->impl_.get_service().open(+        this->impl_.get_implementation(),+        path.c_str(), open_flags, ec);+    asio::detail::throw_error(ec, "open");+  }++  /// Construct a basic_stream_file on an existing native file.+  /**+   * This constructor initialises a stream file object to hold an existing+   * native file.+   *+   * @param ex The I/O executor that the file will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the file.+   *+   * @param native_file The new underlying file implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_stream_file(const executor_type& ex,+      const native_handle_type& native_file)+    : basic_file<Executor>(ex, native_file)+  {+    this->impl_.get_service().set_is_stream(+        this->impl_.get_implementation(), true);+  }++  /// Construct a basic_stream_file on an existing native file.+  /**+   * This constructor initialises a stream file object to hold an existing+   * native file.+   *+   * @param context An execution context which provides the I/O executor that+   * the file will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the file.+   *+   * @param native_file The new underlying file implementation.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_stream_file(ExecutionContext& context,+      const native_handle_type& native_file,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(context, native_file)+  {+    this->impl_.get_service().set_is_stream(+        this->impl_.get_implementation(), true);+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_stream_file from another.+  /**+   * This constructor moves a stream file from one object to another.+   *+   * @param other The other basic_stream_file object from which the move+   * will occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_stream_file(const executor_type&)+   * constructor.+   */+  basic_stream_file(basic_stream_file&& other) ASIO_NOEXCEPT+    : basic_file<Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_stream_file from another.+  /**+   * This assignment operator moves a stream file from one object to another.+   *+   * @param other The other basic_stream_file object from which the move+   * will occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_stream_file(const executor_type&)+   * constructor.+   */+  basic_stream_file& operator=(basic_stream_file&& other)+  {+    basic_file<Executor>::operator=(std::move(other));+    return *this;+  }++  /// Move-construct a basic_stream_file from a file of another executor+  /// type.+  /**+   * This constructor moves a stream file from one object to another.+   *+   * @param other The other basic_stream_file object from which the move+   * will occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_stream_file(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  basic_stream_file(basic_stream_file<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_file<Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_stream_file from a file of another executor type.+  /**+   * This assignment operator moves a stream file from one object to another.+   *+   * @param other The other basic_stream_file object from which the move+   * will occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_stream_file(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_stream_file&+  >::type operator=(basic_stream_file<Executor1>&& other)+  {+    basic_file<Executor>::operator=(std::move(other));+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destroys the file.+  /**+   * This function destroys the file, cancelling any outstanding asynchronous+   * operations associated with the file as if by calling @c cancel.+   */+  ~basic_stream_file()+  {+  }++  /// Seek to a position in the file.+  /**+   * This function updates the current position in the file.+   *+   * @param offset The requested position in the file, relative to @c whence.+   *+   * @param whence One of @c seek_set, @c seek_cur or @c seek_end.+   *+   * @returns The new position relative to the beginning of the file.+   *+   * @throws asio::system_error Thrown on failure.+   */+  uint64_t seek(int64_t offset, file_base::seek_basis whence)+  {+    asio::error_code ec;+    uint64_t n = this->impl_.get_service().seek(+        this->impl_.get_implementation(), offset, whence, ec);+    asio::detail::throw_error(ec, "seek");+    return n;+  }++  /// Seek to a position in the file.+  /**+   * This function updates the current position in the file.+   *+   * @param offset The requested position in the file, relative to @c whence.+   *+   * @param whence One of @c seek_set, @c seek_cur or @c seek_end.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The new position relative to the beginning of the file.+   */+  uint64_t seek(int64_t offset, file_base::seek_basis whence,+      asio::error_code& ec)+  {+    return this->impl_.get_service().seek(+        this->impl_.get_implementation(), offset, whence, ec);+  }++  /// Write some data to the file.+  /**+   * This function is used to write data to the stream file. The function call+   * will block until one or more bytes of the data has been written+   * successfully, or until an error occurs.+   *+   * @param buffers One or more data buffers to be written to the file.+   *+   * @returns The number of bytes written.+   *+   * @throws asio::system_error Thrown on failure. An error code of+   * asio::error::eof indicates that the end of the file was reached.+   *+   * @note The write_some operation may not transmit all of the data to the+   * peer. Consider using the @ref write function if you need to ensure that+   * all data is written before the blocking operation completes.+   *+   * @par Example+   * To write a single data buffer use the @ref buffer function as follows:+   * @code+   * file.write_some(asio::buffer(data, size));+   * @endcode+   * See the @ref buffer documentation for information on writing multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   */+  template <typename ConstBufferSequence>+  std::size_t write_some(const ConstBufferSequence& buffers)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().write_some(+        this->impl_.get_implementation(), buffers, ec);+    asio::detail::throw_error(ec, "write_some");+    return s;+  }++  /// Write some data to the file.+  /**+   * This function is used to write data to the stream file. The function call+   * will block until one or more bytes of the data has been written+   * successfully, or until an error occurs.+   *+   * @param buffers One or more data buffers to be written to the file.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes written. Returns 0 if an error occurred.+   *+   * @note The write_some operation may not transmit all of the data to the+   * peer. Consider using the @ref write function if you need to ensure that+   * all data is written before the blocking operation completes.+   */+  template <typename ConstBufferSequence>+  std::size_t write_some(const ConstBufferSequence& buffers,+      asio::error_code& ec)+  {+    return this->impl_.get_service().write_some(+        this->impl_.get_implementation(), buffers, ec);+  }++  /// Start an asynchronous write.+  /**+   * This function is used to asynchronously write data to the stream file.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.+   *+   * @param buffers One or more data buffers to be written to the file.+   * Although the buffers object may be copied as necessary, ownership of the+   * underlying memory blocks is retained by the caller, which must guarantee+   * that they remain valid until the completion handler is called.+   *+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the write completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   std::size_t bytes_transferred // Number of bytes written.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @note The write operation may not transmit all of the data to the peer.+   * Consider using the @ref async_write function if you need to ensure that all+   * data is written before the asynchronous operation completes.+   *+   * @par Example+   * To write a single data buffer use the @ref buffer function as follows:+   * @code+   * file.async_write_some(asio::buffer(data, size), handler);+   * @endcode+   * See the @ref buffer documentation for information on writing multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total+   */+  template <typename ConstBufferSequence,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        std::size_t)) WriteToken+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,+      void (asio::error_code, std::size_t))+  async_write_some(const ConstBufferSequence& buffers,+      ASIO_MOVE_ARG(WriteToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_write_some>(), token, buffers)))+  {+    return async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        initiate_async_write_some(this), token, buffers);+  }++  /// Read some data from the file.+  /**+   * This function is used to read data from the stream file. The function+   * call will block until one or more bytes of data has been read successfully,+   * or until an error occurs.+   *+   * @param buffers One or more buffers into which the data will be read.+   *+   * @returns The number of bytes read.+   *+   * @throws asio::system_error Thrown on failure. An error code of+   * asio::error::eof indicates that the end of the file was reached.+   *+   * @note The read_some operation may not read all of the requested number of+   * bytes. Consider using the @ref read function if you need to ensure that+   * the requested amount of data is read before the blocking operation+   * completes.+   *+   * @par Example+   * To read into a single data buffer use the @ref buffer function as follows:+   * @code+   * file.read_some(asio::buffer(data, size));+   * @endcode+   * See the @ref buffer documentation for information on reading into multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   */+  template <typename MutableBufferSequence>+  std::size_t read_some(const MutableBufferSequence& buffers)+  {+    asio::error_code ec;+    std::size_t s = this->impl_.get_service().read_some(+        this->impl_.get_implementation(), buffers, ec);+    asio::detail::throw_error(ec, "read_some");+    return s;+  }++  /// Read some data from the file.+  /**+   * This function is used to read data from the stream file. The function+   * call will block until one or more bytes of data has been read successfully,+   * or until an error occurs.+   *+   * @param buffers One or more buffers into which the data will be read.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes read. Returns 0 if an error occurred.+   *+   * @note The read_some operation may not read all of the requested number of+   * bytes. Consider using the @ref read function if you need to ensure that+   * the requested amount of data is read before the blocking operation+   * completes.+   */+  template <typename MutableBufferSequence>+  std::size_t read_some(const MutableBufferSequence& buffers,+      asio::error_code& ec)+  {+    return this->impl_.get_service().read_some(+        this->impl_.get_implementation(), buffers, ec);+  }++  /// Start an asynchronous read.+  /**+   * This function is used to asynchronously read data from the stream file.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.+   *+   * @param buffers One or more buffers into which the data will be read.+   * Although the buffers object may be copied as necessary, ownership of the+   * underlying memory blocks is retained by the caller, which must guarantee+   * that they remain valid until the completion handler is called.+   *+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the read completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   std::size_t bytes_transferred // Number of bytes read.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @note The read operation may not read all of the requested number of bytes.+   * Consider using the @ref async_read function if you need to ensure that the+   * requested amount of data is read before the asynchronous operation+   * completes.+   *+   * @par Example+   * To read into a single data buffer use the @ref buffer function as follows:+   * @code+   * file.async_read_some(asio::buffer(data, size), handler);+   * @endcode+   * See the @ref buffer documentation for information on reading into multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total+   */+  template <typename MutableBufferSequence,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        std::size_t)) ReadToken+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,+      void (asio::error_code, std::size_t))+  async_read_some(const MutableBufferSequence& buffers,+      ASIO_MOVE_ARG(ReadToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_read_some>(), token, buffers)))+  {+    return async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        initiate_async_read_some(this), token, buffers);+  }++private:+  // Disallow copying and assignment.+  basic_stream_file(const basic_stream_file&) ASIO_DELETED;+  basic_stream_file& operator=(const basic_stream_file&) ASIO_DELETED;++  class initiate_async_write_some+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_write_some(basic_stream_file* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename WriteHandler, typename ConstBufferSequence>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        const ConstBufferSequence& buffers) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a WriteHandler.+      ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;++      detail::non_const_lvalue<WriteHandler> handler2(handler);+      self_->impl_.get_service().async_write_some(+          self_->impl_.get_implementation(), buffers,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_stream_file* self_;+  };++  class initiate_async_read_some+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_read_some(basic_stream_file* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename ReadHandler, typename MutableBufferSequence>+    void operator()(ASIO_MOVE_ARG(ReadHandler) handler,+        const MutableBufferSequence& buffers) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a ReadHandler.+      ASIO_READ_HANDLER_CHECK(ReadHandler, handler) type_check;++      detail::non_const_lvalue<ReadHandler> handler2(handler);+      self_->impl_.get_service().async_read_some(+          self_->impl_.get_implementation(), buffers,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_stream_file* self_;+  };+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_STREAM_FILE_HPP
link/modules/asio-standalone/asio/include/asio/basic_stream_socket.hpp view
@@ -2,7 +2,7 @@ // basic_stream_socket.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -46,6 +46,13 @@  * @e Distinct @e objects: Safe.@n  * @e Shared @e objects: Unsafe.  *+ * Synchronous @c send, @c receive, @c connect, and @c shutdown operations are+ * thread safe with respect to each other, if the underlying operating system+ * calls are also thread safe. This means that it is permitted to perform+ * concurrent calls to these synchronous operations on a single socket object.+ * Other synchronous operations, such as @c open or @c close, are not thread+ * safe.+ *  * @par Concepts:  * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.  */@@ -53,6 +60,10 @@ class basic_stream_socket   : public basic_socket<Protocol, Executor> {+private:+  class initiate_async_send;+  class initiate_async_receive;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -105,9 +116,9 @@    */   template <typename ExecutionContext>   explicit basic_stream_socket(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context)   {   }@@ -144,9 +155,10 @@    */   template <typename ExecutionContext>   basic_stream_socket(ExecutionContext& context, const protocol_type& protocol,-      typename enable_if<-        is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())     : basic_socket<Protocol, Executor>(context, protocol)   {   }@@ -189,9 +201,9 @@    */   template <typename ExecutionContext>   basic_stream_socket(ExecutionContext& context, const endpoint_type& endpoint,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context, endpoint)   {   }@@ -234,9 +246,9 @@   template <typename ExecutionContext>   basic_stream_socket(ExecutionContext& context,       const protocol_type& protocol, const native_handle_type& native_socket,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(context, protocol, native_socket)   {   }@@ -289,10 +301,10 @@    */   template <typename Protocol1, typename Executor1>   basic_stream_socket(basic_stream_socket<Protocol1, Executor1>&& other,-      typename enable_if<+      typename constraint<         is_convertible<Protocol1, Protocol>::value           && is_convertible<Executor1, Executor>::value-      >::type* = 0)+      >::type = 0)     : basic_socket<Protocol, Executor>(std::move(other))   {   }@@ -309,7 +321,7 @@    * constructor.    */   template <typename Protocol1, typename Executor1>-  typename enable_if<+  typename constraint<     is_convertible<Protocol1, Protocol>::value       && is_convertible<Executor1, Executor>::value,     basic_stream_socket&@@ -431,25 +443,31 @@   /// Start an asynchronous send.   /**    * This function is used to asynchronously send data on the stream socket.-   * The function call always returns immediately.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more data buffers to be sent on the socket. Although    * the buffers object may be copied as necessary, ownership of the underlying    * memory blocks is retained by the caller, which must guarantee that they-   * remain valid until the handler is called.+   * remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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.@@ -462,47 +480,68 @@    * See the @ref buffer documentation for information on sending multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_send(const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send>(), token,+          buffers, socket_base::message_flags(0))))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send(this), handler,+        initiate_async_send(this), token,         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.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more data buffers to be sent on the socket. Although    * the buffers object may be copied as necessary, ownership of the underlying    * memory blocks is retained by the caller, which must guarantee that they-   * remain valid until the handler is called.+   * remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the send completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes sent.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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.@@ -515,21 +554,35 @@    * See the @ref buffer documentation for information on sending multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_send(const ConstBufferSequence& buffers,       socket_base::message_flags flags,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send>(), token, buffers, flags)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send(this), handler, buffers, flags);+        initiate_async_send(this), token, buffers, flags);   }    /// Receive some data on the socket.@@ -640,25 +693,31 @@   /// Start an asynchronous receive.   /**    * This function is used to asynchronously receive data from the stream-   * socket. The function call always returns immediately.+   * socket. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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@@ -673,47 +732,68 @@    * See the @ref buffer documentation for information on receiving into    * multiple buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive(const MutableBufferSequence& buffers,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive>(), token,+          buffers, socket_base::message_flags(0))))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive(this), handler,+        initiate_async_receive(this), token,         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.+   * socket. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param buffers One or more buffers into which the data will be received.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the receive completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes received.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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@@ -728,21 +808,35 @@    * See the @ref buffer documentation for information on receiving into    * multiple buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_receive(const MutableBufferSequence& buffers,       socket_base::message_flags flags,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive>(), token, buffers, flags)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive(this), handler, buffers, flags);+        initiate_async_receive(this), token, buffers, flags);   }    /// Write some data to the socket.@@ -809,25 +903,31 @@   /// Start an asynchronous write.   /**    * This function is used to asynchronously write data to the stream socket.-   * The function call always returns immediately.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more data buffers to be written to the 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.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the write completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes written.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The write operation may not transmit all of the data to the peer.    * Consider using the @ref async_write function if you need to ensure that all    * data is written before the asynchronous operation completes.@@ -840,20 +940,35 @@    * See the @ref buffer documentation for information on writing multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_write_some(const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_send>(), token,+          buffers, socket_base::message_flags(0))))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_send(this), handler,+        initiate_async_send(this), token,         buffers, socket_base::message_flags(0));   } @@ -923,25 +1038,31 @@   /// Start an asynchronous read.   /**    * This function is used to asynchronously read data from the stream socket.-   * The function call always returns immediately.+   * socket. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param buffers One or more buffers into which the data will be 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.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the read completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes read.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The read operation may not read all of the requested number of bytes.    * Consider using the @ref async_read function if you need to ensure that the    * requested amount of data is read before the asynchronous operation@@ -955,20 +1076,35 @@    * See the @ref buffer documentation for information on reading into multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * On POSIX or Windows operating systems, this asynchronous operation supports+   * cancellation for the following asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_read_some(const MutableBufferSequence& buffers,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_receive>(), token,+          buffers, socket_base::message_flags(0))))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_receive(this), handler,+        initiate_async_receive(this), token,         buffers, socket_base::message_flags(0));   } @@ -987,7 +1123,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -1021,7 +1157,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
link/modules/asio-standalone/asio/include/asio/basic_streambuf.hpp view
@@ -2,7 +2,7 @@ // basic_streambuf.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/basic_streambuf_fwd.hpp view
@@ -2,7 +2,7 @@ // basic_streambuf_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/basic_waitable_timer.hpp view
@@ -2,7 +2,7 @@ // basic_waitable_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -141,6 +141,9 @@ template <typename Clock, typename WaitTraits, typename Executor> class basic_waitable_timer {+private:+  class initiate_async_wait;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -175,7 +178,7 @@    * dispatch handlers for any asynchronous operations performed on the timer.    */   explicit basic_waitable_timer(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -191,10 +194,10 @@    */   template <typename ExecutionContext>   explicit basic_waitable_timer(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {   } @@ -209,7 +212,7 @@    * as an absolute time.    */   basic_waitable_timer(const executor_type& ex, const time_point& expiry_time)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);@@ -230,10 +233,10 @@   template <typename ExecutionContext>   explicit basic_waitable_timer(ExecutionContext& context,       const time_point& expiry_time,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().expires_at(impl_.get_implementation(), expiry_time, ec);@@ -251,7 +254,7 @@    * now.    */   basic_waitable_timer(const executor_type& ex, const duration& expiry_time)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().expires_after(@@ -273,10 +276,10 @@   template <typename ExecutionContext>   explicit basic_waitable_timer(ExecutionContext& context,       const duration& expiry_time,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().expires_after(@@ -337,9 +340,9 @@   template <typename Executor1>   basic_waitable_timer(       basic_waitable_timer<Clock, WaitTraits, Executor1>&& other,-      typename enable_if<-          is_convertible<Executor1, Executor>::value-      >::type* = 0)+      typename constraint<+        is_convertible<Executor1, Executor>::value+      >::type = 0)     : impl_(std::move(other.impl_))   {   }@@ -357,7 +360,7 @@    * constructor.    */   template <typename Executor1>-  typename enable_if<+  typename constraint<     is_convertible<Executor1, Executor>::value,     basic_waitable_timer&   >::type operator=(basic_waitable_timer<Clock, WaitTraits, Executor1>&& other)@@ -378,7 +381,7 @@   }    /// Get the executor associated with the object.-  executor_type get_executor() ASIO_NOEXCEPT+  const executor_type& get_executor() ASIO_NOEXCEPT   {     return impl_.get_executor();   }@@ -726,38 +729,57 @@   /// Start an asynchronous wait on the timer.   /**    * This function may be used to initiate an asynchronous wait against the-   * timer. It always returns immediately.+   * timer. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *-   * For each call to async_wait(), the supplied handler will be called exactly-   * once. The handler will be called when:+   * For each call to async_wait(), the completion handler will be called+   * exactly once. The completion handler will be called when:    *    * @li The timer has expired.    *    * @li The timer was cancelled, in which case the handler is passed the error    * code asio::error::operation_aborted.    *-   * @param 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the timer expires. Potential+   * completion tokens include @ref use_future, @ref use_awaitable, @ref+   * yield_context, or a function object with the correct completion signature.+   * The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error // Result of operation.    * ); @endcode    * Regardless of whether the asynchronous operation completes immediately or-   * not, the handler will not be invoked from within this function. On-   * immediate completion, invocation of the handler will be performed in a+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,-      void (asio::error_code))+        WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(+      WaitToken, void (asio::error_code))   async_wait(-      ASIO_MOVE_ARG(WaitHandler) handler+      ASIO_MOVE_ARG(WaitToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WaitToken, void (asio::error_code)>(+          declval<initiate_async_wait>(), token)))   {-    return async_initiate<WaitHandler, void (asio::error_code)>(-        initiate_async_wait(this), handler);+    return async_initiate<WaitToken, void (asio::error_code)>(+        initiate_async_wait(this), token);   }  private:@@ -776,7 +798,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
+ link/modules/asio-standalone/asio/include/asio/basic_writable_pipe.hpp view
@@ -0,0 +1,631 @@+//+// basic_writable_pipe.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BASIC_WRITABLE_PIPE_HPP+#define ASIO_BASIC_WRITABLE_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+  || defined(GENERATING_DOCUMENTATION)++#include <string>+#include "asio/any_io_executor.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/handler_type_requirements.hpp"+#include "asio/detail/io_object_impl.hpp"+#include "asio/detail/non_const_lvalue.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#if defined(ASIO_HAS_IOCP)+# include "asio/detail/win_iocp_handle_service.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_descriptor_service.hpp"+#else+# include "asio/detail/reactive_descriptor_service.hpp"+#endif++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {++/// Provides pipe functionality.+/**+ * The basic_writable_pipe class provides a wrapper over pipe+ * functionality.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ */+template <typename Executor = any_io_executor>+class basic_writable_pipe+{+private:+  class initiate_async_write_some;++public:+  /// The type of the executor associated with the object.+  typedef Executor executor_type;++  /// Rebinds the pipe type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The pipe type when rebound to the specified executor.+    typedef basic_writable_pipe<Executor1> other;+  };++  /// The native representation of a pipe.+#if defined(GENERATING_DOCUMENTATION)+  typedef implementation_defined native_handle_type;+#elif defined(ASIO_HAS_IOCP)+  typedef detail::win_iocp_handle_service::native_handle_type+    native_handle_type;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  typedef detail::io_uring_descriptor_service::native_handle_type+    native_handle_type;+#else+  typedef detail::reactive_descriptor_service::native_handle_type+    native_handle_type;+#endif++  /// A basic_writable_pipe is always the lowest layer.+  typedef basic_writable_pipe lowest_layer_type;++  /// Construct a basic_writable_pipe without opening it.+  /**+   * This constructor creates a pipe without opening it.+   *+   * @param ex The I/O executor that the pipe will use, by default, to dispatch+   * handlers for any asynchronous operations performed on the pipe.+   */+  explicit basic_writable_pipe(const executor_type& ex)+    : impl_(0, ex)+  {+  }++  /// Construct a basic_writable_pipe without opening it.+  /**+   * This constructor creates a pipe without opening it.+   *+   * @param context An execution context which provides the I/O executor that+   * the pipe will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the pipe.+   */+  template <typename ExecutionContext>+  explicit basic_writable_pipe(ExecutionContext& context,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)+  {+  }++  /// Construct a basic_writable_pipe on an existing native pipe.+  /**+   * This constructor creates a pipe object to hold an existing native+   * pipe.+   *+   * @param ex The I/O executor that the pipe will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the+   * pipe.+   *+   * @param native_pipe A native pipe.+   *+   * @throws asio::system_error Thrown on failure.+   */+  basic_writable_pipe(const executor_type& ex,+      const native_handle_type& native_pipe)+    : impl_(0, ex)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        native_pipe, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Construct a basic_writable_pipe on an existing native pipe.+  /**+   * This constructor creates a pipe object to hold an existing native+   * pipe.+   *+   * @param context An execution context which provides the I/O executor that+   * the pipe will use, by default, to dispatch handlers for any+   * asynchronous operations performed on the pipe.+   *+   * @param native_pipe A native pipe.+   *+   * @throws asio::system_error Thrown on failure.+   */+  template <typename ExecutionContext>+  basic_writable_pipe(ExecutionContext& context,+      const native_handle_type& native_pipe,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type = 0)+    : impl_(0, 0, context)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(),+        native_pipe, ec);+    asio::detail::throw_error(ec, "assign");+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_writable_pipe from another.+  /**+   * This constructor moves a pipe from one object to another.+   *+   * @param other The other basic_writable_pipe object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_writable_pipe(const executor_type&)+   * constructor.+   */+  basic_writable_pipe(basic_writable_pipe&& other)+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_writable_pipe from another.+  /**+   * This assignment operator moves a pipe from one object to another.+   *+   * @param other The other basic_writable_pipe object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_writable_pipe(const executor_type&)+   * constructor.+   */+  basic_writable_pipe& operator=(basic_writable_pipe&& other)+  {+    impl_ = std::move(other.impl_);+    return *this;+  }++  // All pipes have access to each other's implementations.+  template <typename Executor1>+  friend class basic_writable_pipe;++  /// Move-construct a basic_writable_pipe from a pipe of another executor type.+  /**+   * This constructor moves a pipe from one object to another.+   *+   * @param other The other basic_writable_pipe object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_writable_pipe(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  basic_writable_pipe(basic_writable_pipe<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_writable_pipe from a pipe of another executor type.+  /**+   * This assignment operator moves a pipe from one object to another.+   *+   * @param other The other basic_writable_pipe object from which the move will+   * occur.+   *+   * @note Following the move, the moved-from object is in the same state as if+   * constructed using the @c basic_writable_pipe(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_writable_pipe&+  >::type operator=(basic_writable_pipe<Executor1>&& other)+  {+    basic_writable_pipe tmp(std::move(other));+    impl_ = std::move(tmp.impl_);+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destroys the pipe.+  /**+   * This function destroys the pipe, cancelling any outstanding+   * asynchronous wait operations associated with the pipe as if by+   * calling @c cancel.+   */+  ~basic_writable_pipe()+  {+  }++  /// Get the executor associated with the object.+  const executor_type& get_executor() ASIO_NOEXCEPT+  {+    return impl_.get_executor();+  }++  /// Get a reference to the lowest layer.+  /**+   * This function returns a reference to the lowest layer in a stack of+   * layers. Since a basic_writable_pipe cannot contain any further layers, it+   * simply returns a reference to itself.+   *+   * @return A reference to the lowest layer in the stack of layers. Ownership+   * is not transferred to the caller.+   */+  lowest_layer_type& lowest_layer()+  {+    return *this;+  }++  /// Get a const reference to the lowest layer.+  /**+   * This function returns a const reference to the lowest layer in a stack of+   * layers. Since a basic_writable_pipe cannot contain any further layers, it+   * simply returns a reference to itself.+   *+   * @return A const reference to the lowest layer in the stack of layers.+   * Ownership is not transferred to the caller.+   */+  const lowest_layer_type& lowest_layer() const+  {+    return *this;+  }++  /// Assign an existing native pipe to the pipe.+  /*+   * This function opens the pipe to hold an existing native pipe.+   *+   * @param native_pipe A native pipe.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void assign(const native_handle_type& native_pipe)+  {+    asio::error_code ec;+    impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);+    asio::detail::throw_error(ec, "assign");+  }++  /// Assign an existing native pipe to the pipe.+  /*+   * This function opens the pipe to hold an existing native pipe.+   *+   * @param native_pipe A native pipe.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID assign(const native_handle_type& native_pipe,+      asio::error_code& ec)+  {+    impl_.get_service().assign(impl_.get_implementation(), native_pipe, ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Determine whether the pipe is open.+  bool is_open() const+  {+    return impl_.get_service().is_open(impl_.get_implementation());+  }++  /// Close the pipe.+  /**+   * This function is used to close the pipe. Any asynchronous write operations+   * will be cancelled immediately, and will complete with the+   * asio::error::operation_aborted error.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void close()+  {+    asio::error_code ec;+    impl_.get_service().close(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "close");+  }++  /// Close the pipe.+  /**+   * This function is used to close the pipe. Any asynchronous write operations+   * will be cancelled immediately, and will complete with the+   * asio::error::operation_aborted error.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID close(asio::error_code& ec)+  {+    impl_.get_service().close(impl_.get_implementation(), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Release ownership of the underlying native pipe.+  /**+   * This function causes all outstanding asynchronous write operations to+   * finish immediately, and the handlers for cancelled operations will be+   * passed the asio::error::operation_aborted error. Ownership of the+   * native pipe 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 pipe.+  /**+   * This function causes all outstanding asynchronous write operations to+   * finish immediately, and the handlers for cancelled operations will be+   * passed the asio::error::operation_aborted error. Ownership of the+   * native pipe 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 pipe representation.+  /**+   * This function may be used to obtain the underlying representation of the+   * pipe. This is intended to allow access to native pipe+   * functionality that is not otherwise provided.+   */+  native_handle_type native_handle()+  {+    return impl_.get_service().native_handle(impl_.get_implementation());+  }++  /// Cancel all asynchronous operations associated with the pipe.+  /**+   * This function causes all outstanding asynchronous write operations to+   * finish immediately, and the handlers for cancelled operations will be+   * passed the asio::error::operation_aborted error.+   *+   * @throws asio::system_error Thrown on failure.+   */+  void cancel()+  {+    asio::error_code ec;+    impl_.get_service().cancel(impl_.get_implementation(), ec);+    asio::detail::throw_error(ec, "cancel");+  }++  /// Cancel all asynchronous operations associated with the pipe.+  /**+   * This function causes all outstanding asynchronous write operations to+   * finish immediately, and the handlers for cancelled operations will be+   * passed the asio::error::operation_aborted error.+   *+   * @param ec Set to indicate what error occurred, if any.+   */+  ASIO_SYNC_OP_VOID cancel(asio::error_code& ec)+  {+    impl_.get_service().cancel(impl_.get_implementation(), ec);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Write some data to the pipe.+  /**+   * This function is used to write data to the pipe. The function call will+   * block until one or more bytes of the data has been written successfully,+   * or until an error occurs.+   *+   * @param buffers One or more data buffers to be written to the pipe.+   *+   * @returns The number of bytes written.+   *+   * @throws asio::system_error Thrown on failure. An error code of+   * asio::error::eof indicates that the connection was closed by the+   * peer.+   *+   * @note The write_some operation may not transmit all of the data to the+   * peer. Consider using the @ref write function if you need to ensure that+   * all data is written before the blocking operation completes.+   *+   * @par Example+   * To write a single data buffer use the @ref buffer function as follows:+   * @code+   * pipe.write_some(asio::buffer(data, size));+   * @endcode+   * See the @ref buffer documentation for information on writing multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   */+  template <typename ConstBufferSequence>+  std::size_t write_some(const ConstBufferSequence& buffers)+  {+    asio::error_code ec;+    std::size_t s = impl_.get_service().write_some(+        impl_.get_implementation(), buffers, ec);+    asio::detail::throw_error(ec, "write_some");+    return s;+  }++  /// Write some data to the pipe.+  /**+   * This function is used to write data to the pipe. The function call will+   * block until one or more bytes of the data has been written successfully,+   * or until an error occurs.+   *+   * @param buffers One or more data buffers to be written to the pipe.+   *+   * @param ec Set to indicate what error occurred, if any.+   *+   * @returns The number of bytes written. Returns 0 if an error occurred.+   *+   * @note The write_some operation may not transmit all of the data to the+   * peer. Consider using the @ref write function if you need to ensure that+   * all data is written before the blocking operation completes.+   */+  template <typename ConstBufferSequence>+  std::size_t write_some(const ConstBufferSequence& buffers,+      asio::error_code& ec)+  {+    return impl_.get_service().write_some(+        impl_.get_implementation(), buffers, ec);+  }++  /// Start an asynchronous write.+  /**+   * This function is used to asynchronously write data to the pipe. It is an+   * initiating function for an @ref asynchronous_operation, and always returns+   * immediately.+   *+   * @param buffers One or more data buffers to be written to the pipe.+   * Although the buffers object may be copied as necessary, ownership of the+   * underlying memory blocks is retained by the caller, which must guarantee+   * that they remain valid until the completion handler is called.+   *+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the write completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:+   * @code void handler(+   *   const asio::error_code& error, // Result of operation.+   *   std::size_t bytes_transferred // Number of bytes written.+   * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @note The write operation may not transmit all of the data to the peer.+   * Consider using the @ref async_write function if you need to ensure that all+   * data is written before the asynchronous operation completes.+   *+   * @par Example+   * To write a single data buffer use the @ref buffer function as follows:+   * @code+   * pipe.async_write_some(asio::buffer(data, size), handler);+   * @endcode+   * See the @ref buffer documentation for information on writing multiple+   * buffers in one go, and how to use it with arrays, boost::array or+   * std::vector.+   */+  template <typename ConstBufferSequence,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,+        std::size_t)) WriteToken+          ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,+      void (asio::error_code, std::size_t))+  async_write_some(const ConstBufferSequence& buffers,+      ASIO_MOVE_ARG(WriteToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_write_some>(), token, buffers)))+  {+    return async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        initiate_async_write_some(this), token, buffers);+  }++private:+  // Disallow copying and assignment.+  basic_writable_pipe(const basic_writable_pipe&) ASIO_DELETED;+  basic_writable_pipe& operator=(const basic_writable_pipe&) ASIO_DELETED;++  class initiate_async_write_some+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_write_some(basic_writable_pipe* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename WriteHandler, typename ConstBufferSequence>+    void operator()(ASIO_MOVE_ARG(WriteHandler) handler,+        const ConstBufferSequence& buffers) const+    {+      // If you get an error on the following line it means that your handler+      // does not meet the documented type requirements for a WriteHandler.+      ASIO_WRITE_HANDLER_CHECK(WriteHandler, handler) type_check;++      detail::non_const_lvalue<WriteHandler> handler2(handler);+      self_->impl_.get_service().async_write_some(+          self_->impl_.get_implementation(), buffers,+          handler2.value, self_->impl_.get_executor());+    }++  private:+    basic_writable_pipe* self_;+  };++#if defined(ASIO_HAS_IOCP)+  detail::io_object_impl<detail::win_iocp_handle_service, Executor> impl_;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;+#else+  detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;+#endif+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PIPE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_BASIC_WRITABLE_PIPE_HPP
+ link/modules/asio-standalone/asio/include/asio/bind_allocator.hpp view
@@ -0,0 +1,733 @@+//+// bind_allocator.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BIND_ALLOCATOR_HPP+#define ASIO_BIND_ALLOCATOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/associated_allocator.hpp"+#include "asio/associator.hpp"+#include "asio/async_result.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper to automatically define nested typedef result_type.++template <typename T, typename = void>+struct allocator_binder_result_type+{+protected:+  typedef void result_type_or_void;+};++template <typename T>+struct allocator_binder_result_type<T,+  typename void_type<typename T::result_type>::type>+{+  typedef typename T::result_type result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R>+struct allocator_binder_result_type<R(*)()>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R>+struct allocator_binder_result_type<R(&)()>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct allocator_binder_result_type<R(*)(A1)>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct allocator_binder_result_type<R(&)(A1)>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct allocator_binder_result_type<R(*)(A1, A2)>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct allocator_binder_result_type<R(&)(A1, A2)>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++// Helper to automatically define nested typedef argument_type.++template <typename T, typename = void>+struct allocator_binder_argument_type {};++template <typename T>+struct allocator_binder_argument_type<T,+  typename void_type<typename T::argument_type>::type>+{+  typedef typename T::argument_type argument_type;+};++template <typename R, typename A1>+struct allocator_binder_argument_type<R(*)(A1)>+{+  typedef A1 argument_type;+};++template <typename R, typename A1>+struct allocator_binder_argument_type<R(&)(A1)>+{+  typedef A1 argument_type;+};++// Helper to automatically define nested typedefs first_argument_type and+// second_argument_type.++template <typename T, typename = void>+struct allocator_binder_argument_types {};++template <typename T>+struct allocator_binder_argument_types<T,+  typename void_type<typename T::first_argument_type>::type>+{+  typedef typename T::first_argument_type first_argument_type;+  typedef typename T::second_argument_type second_argument_type;+};++template <typename R, typename A1, typename A2>+struct allocator_binder_argument_type<R(*)(A1, A2)>+{+  typedef A1 first_argument_type;+  typedef A2 second_argument_type;+};++template <typename R, typename A1, typename A2>+struct allocator_binder_argument_type<R(&)(A1, A2)>+{+  typedef A1 first_argument_type;+  typedef A2 second_argument_type;+};++// Helper to enable SFINAE on zero-argument operator() below.++template <typename T, typename = void>+struct allocator_binder_result_of0+{+  typedef void type;+};++template <typename T>+struct allocator_binder_result_of0<T,+  typename void_type<typename result_of<T()>::type>::type>+{+  typedef typename result_of<T()>::type type;+};++} // namespace detail++/// A call wrapper type to bind an allocator of type @c Allocator+/// to an object of type @c T.+template <typename T, typename Allocator>+class allocator_binder+#if !defined(GENERATING_DOCUMENTATION)+  : public detail::allocator_binder_result_type<T>,+    public detail::allocator_binder_argument_type<T>,+    public detail::allocator_binder_argument_types<T>+#endif // !defined(GENERATING_DOCUMENTATION)+{+public:+  /// The type of the target object.+  typedef T target_type;++  /// The type of the associated allocator.+  typedef Allocator allocator_type;++#if defined(GENERATING_DOCUMENTATION)+  /// The return type if a function.+  /**+   * The type of @c result_type is based on the type @c T of the wrapper's+   * target object:+   *+   * @li if @c T is a pointer to function type, @c result_type is a synonym for+   * the return type of @c T;+   *+   * @li if @c T is a class type with a member type @c result_type, then @c+   * result_type is a synonym for @c T::result_type;+   *+   * @li otherwise @c result_type is not defined.+   */+  typedef see_below result_type;++  /// The type of the function's argument.+  /**+   * The type of @c argument_type is based on the type @c T of the wrapper's+   * target object:+   *+   * @li if @c T is a pointer to a function type accepting a single argument,+   * @c argument_type is a synonym for the return type of @c T;+   *+   * @li if @c T is a class type with a member type @c argument_type, then @c+   * argument_type is a synonym for @c T::argument_type;+   *+   * @li otherwise @c argument_type is not defined.+   */+  typedef see_below argument_type;++  /// The type of the function's first argument.+  /**+   * The type of @c first_argument_type is based on the type @c T of the+   * wrapper's target object:+   *+   * @li if @c T is a pointer to a function type accepting two arguments, @c+   * first_argument_type is a synonym for the return type of @c T;+   *+   * @li if @c T is a class type with a member type @c first_argument_type,+   * then @c first_argument_type is a synonym for @c T::first_argument_type;+   *+   * @li otherwise @c first_argument_type is not defined.+   */+  typedef see_below first_argument_type;++  /// The type of the function's second argument.+  /**+   * The type of @c second_argument_type is based on the type @c T of the+   * wrapper's target object:+   *+   * @li if @c T is a pointer to a function type accepting two arguments, @c+   * second_argument_type is a synonym for the return type of @c T;+   *+   * @li if @c T is a class type with a member type @c first_argument_type,+   * then @c second_argument_type is a synonym for @c T::second_argument_type;+   *+   * @li otherwise @c second_argument_type is not defined.+   */+  typedef see_below second_argument_type;+#endif // defined(GENERATING_DOCUMENTATION)++  /// Construct an allocator wrapper for the specified object.+  /**+   * This constructor is only valid if the type @c T is constructible from type+   * @c U.+   */+  template <typename U>+  allocator_binder(const allocator_type& s,+      ASIO_MOVE_ARG(U) u)+    : allocator_(s),+      target_(ASIO_MOVE_CAST(U)(u))+  {+  }++  /// Copy constructor.+  allocator_binder(const allocator_binder& other)+    : allocator_(other.get_allocator()),+      target_(other.get())+  {+  }++  /// Construct a copy, but specify a different allocator.+  allocator_binder(const allocator_type& s,+      const allocator_binder& other)+    : allocator_(s),+      target_(other.get())+  {+  }++  /// Construct a copy of a different allocator wrapper type.+  /**+   * This constructor is only valid if the @c Allocator type is+   * constructible from type @c OtherAllocator, and the type @c T is+   * constructible from type @c U.+   */+  template <typename U, typename OtherAllocator>+  allocator_binder(+      const allocator_binder<U, OtherAllocator>& other)+    : allocator_(other.get_allocator()),+      target_(other.get())+  {+  }++  /// Construct a copy of a different allocator wrapper type, but+  /// specify a different allocator.+  /**+   * This constructor is only valid if the type @c T is constructible from type+   * @c U.+   */+  template <typename U, typename OtherAllocator>+  allocator_binder(const allocator_type& s,+      const allocator_binder<U, OtherAllocator>& other)+    : allocator_(s),+      target_(other.get())+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Move constructor.+  allocator_binder(allocator_binder&& other)+    : allocator_(ASIO_MOVE_CAST(allocator_type)(+          other.get_allocator())),+      target_(ASIO_MOVE_CAST(T)(other.get()))+  {+  }++  /// Move construct the target object, but specify a different allocator.+  allocator_binder(const allocator_type& s,+      allocator_binder&& other)+    : allocator_(s),+      target_(ASIO_MOVE_CAST(T)(other.get()))+  {+  }++  /// Move construct from a different allocator wrapper type.+  template <typename U, typename OtherAllocator>+  allocator_binder(+      allocator_binder<U, OtherAllocator>&& other)+    : allocator_(ASIO_MOVE_CAST(OtherAllocator)(+          other.get_allocator())),+      target_(ASIO_MOVE_CAST(U)(other.get()))+  {+  }++  /// Move construct from a different allocator wrapper type, but+  /// specify a different allocator.+  template <typename U, typename OtherAllocator>+  allocator_binder(const allocator_type& s,+      allocator_binder<U, OtherAllocator>&& other)+    : allocator_(s),+      target_(ASIO_MOVE_CAST(U)(other.get()))+  {+  }++#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  ~allocator_binder()+  {+  }++  /// Obtain a reference to the target object.+  target_type& get() ASIO_NOEXCEPT+  {+    return target_;+  }++  /// Obtain a reference to the target object.+  const target_type& get() const ASIO_NOEXCEPT+  {+    return target_;+  }++  /// Obtain the associated allocator.+  allocator_type get_allocator() const ASIO_NOEXCEPT+  {+    return allocator_;+  }++#if defined(GENERATING_DOCUMENTATION)++  template <typename... Args> auto operator()(Args&& ...);+  template <typename... Args> auto operator()(Args&& ...) const;++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++  /// Forwarding function call operator.+  template <typename... Args>+  typename result_of<T(Args...)>::type operator()(+      ASIO_MOVE_ARG(Args)... args)+  {+    return target_(ASIO_MOVE_CAST(Args)(args)...);+  }++  /// Forwarding function call operator.+  template <typename... Args>+  typename result_of<T(Args...)>::type operator()(+      ASIO_MOVE_ARG(Args)... args) const+  {+    return target_(ASIO_MOVE_CAST(Args)(args)...);+  }++#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++  typename detail::allocator_binder_result_of0<T>::type operator()()+  {+    return target_();+  }++  typename detail::allocator_binder_result_of0<T>::type+  operator()() const+  {+    return target_();+  }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) const \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++  typedef typename detail::allocator_binder_result_type<+    T>::result_type_or_void result_type_or_void;++  result_type_or_void operator()()+  {+    return target_();+  }++  result_type_or_void operator()() const+  {+    return target_();+  }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  result_type_or_void operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  result_type_or_void operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) const \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++private:+  Allocator allocator_;+  T target_;+};++/// Associate an object of type @c T with an allocator of type+/// @c Allocator.+template <typename Allocator, typename T>+ASIO_NODISCARD inline allocator_binder<typename decay<T>::type, Allocator>+bind_allocator(const Allocator& s, ASIO_MOVE_ARG(T) t)+{+  return allocator_binder<+    typename decay<T>::type, Allocator>(+      s, ASIO_MOVE_CAST(T)(t));+}++#if !defined(GENERATING_DOCUMENTATION)++namespace detail {++template <typename TargetAsyncResult,+  typename Allocator, typename = void>+struct allocator_binder_async_result_completion_handler_type+{+};++template <typename TargetAsyncResult, typename Allocator>+struct allocator_binder_async_result_completion_handler_type<+  TargetAsyncResult, Allocator,+  typename void_type<+    typename TargetAsyncResult::completion_handler_type+  >::type>+{+  typedef allocator_binder<+    typename TargetAsyncResult::completion_handler_type, Allocator>+      completion_handler_type;+};++template <typename TargetAsyncResult, typename = void>+struct allocator_binder_async_result_return_type+{+};++template <typename TargetAsyncResult>+struct allocator_binder_async_result_return_type<+  TargetAsyncResult,+  typename void_type<+    typename TargetAsyncResult::return_type+  >::type>+{+  typedef typename TargetAsyncResult::return_type return_type;+};++} // namespace detail++template <typename T, typename Allocator, typename Signature>+class async_result<allocator_binder<T, Allocator>, Signature> :+  public detail::allocator_binder_async_result_completion_handler_type<+    async_result<T, Signature>, Allocator>,+  public detail::allocator_binder_async_result_return_type<+    async_result<T, Signature> >+{+public:+  explicit async_result(allocator_binder<T, Allocator>& b)+    : target_(b.get())+  {+  }++  typename async_result<T, Signature>::return_type get()+  {+    return target_.get();+  }++  template <typename Initiation>+  struct init_wrapper+  {+    template <typename Init>+    init_wrapper(const Allocator& allocator, ASIO_MOVE_ARG(Init) init)+      : allocator_(allocator),+        initiation_(ASIO_MOVE_CAST(Init)(init))+    {+    }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          allocator_binder<+            typename decay<Handler>::type, Allocator>(+              allocator_, ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args) const+    {+      initiation_(+          allocator_binder<+            typename decay<Handler>::type, Allocator>(+              allocator_, ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++    template <typename Handler>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          allocator_binder<+            typename decay<Handler>::type, Allocator>(+              allocator_, ASIO_MOVE_CAST(Handler)(handler)));+    }++    template <typename Handler>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler) const+    {+      initiation_(+          allocator_binder<+            typename decay<Handler>::type, Allocator>(+              allocator_, ASIO_MOVE_CAST(Handler)(handler)));+    }++#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \+    template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+    void operator()( \+        ASIO_MOVE_ARG(Handler) handler, \+        ASIO_VARIADIC_MOVE_PARAMS(n)) \+    { \+      ASIO_MOVE_CAST(Initiation)(initiation_)( \+          allocator_binder< \+            typename decay<Handler>::type, Allocator>( \+              allocator_, ASIO_MOVE_CAST(Handler)(handler)), \+          ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    \+    template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+    void operator()( \+        ASIO_MOVE_ARG(Handler) handler, \+        ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    { \+      initiation_( \+          allocator_binder< \+            typename decay<Handler>::type, Allocator>( \+              allocator_, ASIO_MOVE_CAST(Handler)(handler)), \+          ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    /**/+    ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)+#undef ASIO_PRIVATE_INIT_WRAPPER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++    Allocator allocator_;+    Initiation initiation_;+  };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+    (async_initiate<T, Signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<RawCompletionToken>().get(),+        declval<ASIO_MOVE_ARG(Args)>()...)))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+  {+    return async_initiate<T, Signature>(+        init_wrapper<typename decay<Initiation>::type>(+          token.get_allocator(),+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.get(), ASIO_MOVE_CAST(Args)(args)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+    (async_initiate<T, Signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<RawCompletionToken>().get())))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token)+  {+    return async_initiate<T, Signature>(+        init_wrapper<typename decay<Initiation>::type>(+          token.get_allocator(),+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.get());+  }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, typename RawCompletionToken, \+      ASIO_VARIADIC_TPARAMS(n)> \+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \+    (async_initiate<T, Signature>( \+        declval<init_wrapper<typename decay<Initiation>::type> >(), \+        declval<RawCompletionToken>().get(), \+        ASIO_VARIADIC_MOVE_DECLVAL(n)))) \+  initiate( \+      ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_MOVE_ARG(RawCompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return async_initiate<T, Signature>( \+        init_wrapper<typename decay<Initiation>::type>( \+          token.get_allocator(), \+          ASIO_MOVE_CAST(Initiation)(initiation)), \+        token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++private:+  async_result(const async_result&) ASIO_DELETED;+  async_result& operator=(const async_result&) ASIO_DELETED;++  async_result<T, Signature> target_;+};++template <template <typename, typename> class Associator,+    typename T, typename Allocator, typename DefaultCandidate>+struct associator<Associator,+    allocator_binder<T, Allocator>,+    DefaultCandidate>+  : Associator<T, DefaultCandidate>+{+  static typename Associator<T, DefaultCandidate>::type+  get(const allocator_binder<T, Allocator>& b) ASIO_NOEXCEPT+  {+    return Associator<T, DefaultCandidate>::get(b.get());+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<T, DefaultCandidate>::type)+  get(const allocator_binder<T, Allocator>& b,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<T, DefaultCandidate>::get(b.get(), c)))+  {+    return Associator<T, DefaultCandidate>::get(b.get(), c);+  }+};++template <typename T, typename Allocator, typename Allocator1>+struct associated_allocator<+    allocator_binder<T, Allocator>,+    Allocator1>+{+  typedef Allocator type;++  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const allocator_binder<T, Allocator>& b,+      const Allocator1& = Allocator1()) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((b.get_allocator()))+  {+    return b.get_allocator();+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BIND_ALLOCATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/bind_cancellation_slot.hpp view
@@ -0,0 +1,736 @@+//+// bind_cancellation_slot.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BIND_CANCELLATION_SLOT_HPP+#define ASIO_BIND_CANCELLATION_SLOT_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/associator.hpp"+#include "asio/async_result.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper to automatically define nested typedef result_type.++template <typename T, typename = void>+struct cancellation_slot_binder_result_type+{+protected:+  typedef void result_type_or_void;+};++template <typename T>+struct cancellation_slot_binder_result_type<T,+  typename void_type<typename T::result_type>::type>+{+  typedef typename T::result_type result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R>+struct cancellation_slot_binder_result_type<R(*)()>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R>+struct cancellation_slot_binder_result_type<R(&)()>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct cancellation_slot_binder_result_type<R(*)(A1)>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct cancellation_slot_binder_result_type<R(&)(A1)>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct cancellation_slot_binder_result_type<R(*)(A1, A2)>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1, typename A2>+struct cancellation_slot_binder_result_type<R(&)(A1, A2)>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++// Helper to automatically define nested typedef argument_type.++template <typename T, typename = void>+struct cancellation_slot_binder_argument_type {};++template <typename T>+struct cancellation_slot_binder_argument_type<T,+  typename void_type<typename T::argument_type>::type>+{+  typedef typename T::argument_type argument_type;+};++template <typename R, typename A1>+struct cancellation_slot_binder_argument_type<R(*)(A1)>+{+  typedef A1 argument_type;+};++template <typename R, typename A1>+struct cancellation_slot_binder_argument_type<R(&)(A1)>+{+  typedef A1 argument_type;+};++// Helper to automatically define nested typedefs first_argument_type and+// second_argument_type.++template <typename T, typename = void>+struct cancellation_slot_binder_argument_types {};++template <typename T>+struct cancellation_slot_binder_argument_types<T,+  typename void_type<typename T::first_argument_type>::type>+{+  typedef typename T::first_argument_type first_argument_type;+  typedef typename T::second_argument_type second_argument_type;+};++template <typename R, typename A1, typename A2>+struct cancellation_slot_binder_argument_type<R(*)(A1, A2)>+{+  typedef A1 first_argument_type;+  typedef A2 second_argument_type;+};++template <typename R, typename A1, typename A2>+struct cancellation_slot_binder_argument_type<R(&)(A1, A2)>+{+  typedef A1 first_argument_type;+  typedef A2 second_argument_type;+};++// Helper to enable SFINAE on zero-argument operator() below.++template <typename T, typename = void>+struct cancellation_slot_binder_result_of0+{+  typedef void type;+};++template <typename T>+struct cancellation_slot_binder_result_of0<T,+  typename void_type<typename result_of<T()>::type>::type>+{+  typedef typename result_of<T()>::type type;+};++} // namespace detail++/// A call wrapper type to bind a cancellation slot of type @c CancellationSlot+/// to an object of type @c T.+template <typename T, typename CancellationSlot>+class cancellation_slot_binder+#if !defined(GENERATING_DOCUMENTATION)+  : public detail::cancellation_slot_binder_result_type<T>,+    public detail::cancellation_slot_binder_argument_type<T>,+    public detail::cancellation_slot_binder_argument_types<T>+#endif // !defined(GENERATING_DOCUMENTATION)+{+public:+  /// The type of the target object.+  typedef T target_type;++  /// The type of the associated cancellation slot.+  typedef CancellationSlot cancellation_slot_type;++#if defined(GENERATING_DOCUMENTATION)+  /// The return type if a function.+  /**+   * The type of @c result_type is based on the type @c T of the wrapper's+   * target object:+   *+   * @li if @c T is a pointer to function type, @c result_type is a synonym for+   * the return type of @c T;+   *+   * @li if @c T is a class type with a member type @c result_type, then @c+   * result_type is a synonym for @c T::result_type;+   *+   * @li otherwise @c result_type is not defined.+   */+  typedef see_below result_type;++  /// The type of the function's argument.+  /**+   * The type of @c argument_type is based on the type @c T of the wrapper's+   * target object:+   *+   * @li if @c T is a pointer to a function type accepting a single argument,+   * @c argument_type is a synonym for the return type of @c T;+   *+   * @li if @c T is a class type with a member type @c argument_type, then @c+   * argument_type is a synonym for @c T::argument_type;+   *+   * @li otherwise @c argument_type is not defined.+   */+  typedef see_below argument_type;++  /// The type of the function's first argument.+  /**+   * The type of @c first_argument_type is based on the type @c T of the+   * wrapper's target object:+   *+   * @li if @c T is a pointer to a function type accepting two arguments, @c+   * first_argument_type is a synonym for the return type of @c T;+   *+   * @li if @c T is a class type with a member type @c first_argument_type,+   * then @c first_argument_type is a synonym for @c T::first_argument_type;+   *+   * @li otherwise @c first_argument_type is not defined.+   */+  typedef see_below first_argument_type;++  /// The type of the function's second argument.+  /**+   * The type of @c second_argument_type is based on the type @c T of the+   * wrapper's target object:+   *+   * @li if @c T is a pointer to a function type accepting two arguments, @c+   * second_argument_type is a synonym for the return type of @c T;+   *+   * @li if @c T is a class type with a member type @c first_argument_type,+   * then @c second_argument_type is a synonym for @c T::second_argument_type;+   *+   * @li otherwise @c second_argument_type is not defined.+   */+  typedef see_below second_argument_type;+#endif // defined(GENERATING_DOCUMENTATION)++  /// Construct a cancellation slot wrapper for the specified object.+  /**+   * This constructor is only valid if the type @c T is constructible from type+   * @c U.+   */+  template <typename U>+  cancellation_slot_binder(const cancellation_slot_type& s,+      ASIO_MOVE_ARG(U) u)+    : slot_(s),+      target_(ASIO_MOVE_CAST(U)(u))+  {+  }++  /// Copy constructor.+  cancellation_slot_binder(const cancellation_slot_binder& other)+    : slot_(other.get_cancellation_slot()),+      target_(other.get())+  {+  }++  /// Construct a copy, but specify a different cancellation slot.+  cancellation_slot_binder(const cancellation_slot_type& s,+      const cancellation_slot_binder& other)+    : slot_(s),+      target_(other.get())+  {+  }++  /// Construct a copy of a different cancellation slot wrapper type.+  /**+   * This constructor is only valid if the @c CancellationSlot type is+   * constructible from type @c OtherCancellationSlot, and the type @c T is+   * constructible from type @c U.+   */+  template <typename U, typename OtherCancellationSlot>+  cancellation_slot_binder(+      const cancellation_slot_binder<U, OtherCancellationSlot>& other)+    : slot_(other.get_cancellation_slot()),+      target_(other.get())+  {+  }++  /// Construct a copy of a different cancellation slot wrapper type, but+  /// specify a different cancellation slot.+  /**+   * This constructor is only valid if the type @c T is constructible from type+   * @c U.+   */+  template <typename U, typename OtherCancellationSlot>+  cancellation_slot_binder(const cancellation_slot_type& s,+      const cancellation_slot_binder<U, OtherCancellationSlot>& other)+    : slot_(s),+      target_(other.get())+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Move constructor.+  cancellation_slot_binder(cancellation_slot_binder&& other)+    : slot_(ASIO_MOVE_CAST(cancellation_slot_type)(+          other.get_cancellation_slot())),+      target_(ASIO_MOVE_CAST(T)(other.get()))+  {+  }++  /// Move construct the target object, but specify a different cancellation+  /// slot.+  cancellation_slot_binder(const cancellation_slot_type& s,+      cancellation_slot_binder&& other)+    : slot_(s),+      target_(ASIO_MOVE_CAST(T)(other.get()))+  {+  }++  /// Move construct from a different cancellation slot wrapper type.+  template <typename U, typename OtherCancellationSlot>+  cancellation_slot_binder(+      cancellation_slot_binder<U, OtherCancellationSlot>&& other)+    : slot_(ASIO_MOVE_CAST(OtherCancellationSlot)(+          other.get_cancellation_slot())),+      target_(ASIO_MOVE_CAST(U)(other.get()))+  {+  }++  /// Move construct from a different cancellation slot wrapper type, but+  /// specify a different cancellation slot.+  template <typename U, typename OtherCancellationSlot>+  cancellation_slot_binder(const cancellation_slot_type& s,+      cancellation_slot_binder<U, OtherCancellationSlot>&& other)+    : slot_(s),+      target_(ASIO_MOVE_CAST(U)(other.get()))+  {+  }++#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  ~cancellation_slot_binder()+  {+  }++  /// Obtain a reference to the target object.+  target_type& get() ASIO_NOEXCEPT+  {+    return target_;+  }++  /// Obtain a reference to the target object.+  const target_type& get() const ASIO_NOEXCEPT+  {+    return target_;+  }++  /// Obtain the associated cancellation slot.+  cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+  {+    return slot_;+  }++#if defined(GENERATING_DOCUMENTATION)++  template <typename... Args> auto operator()(Args&& ...);+  template <typename... Args> auto operator()(Args&& ...) const;++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++  /// Forwarding function call operator.+  template <typename... Args>+  typename result_of<T(Args...)>::type operator()(+      ASIO_MOVE_ARG(Args)... args)+  {+    return target_(ASIO_MOVE_CAST(Args)(args)...);+  }++  /// Forwarding function call operator.+  template <typename... Args>+  typename result_of<T(Args...)>::type operator()(+      ASIO_MOVE_ARG(Args)... args) const+  {+    return target_(ASIO_MOVE_CAST(Args)(args)...);+  }++#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++  typename detail::cancellation_slot_binder_result_of0<T>::type operator()()+  {+    return target_();+  }++  typename detail::cancellation_slot_binder_result_of0<T>::type+  operator()() const+  {+    return target_();+  }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) const \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++  typedef typename detail::cancellation_slot_binder_result_type<+    T>::result_type_or_void result_type_or_void;++  result_type_or_void operator()()+  {+    return target_();+  }++  result_type_or_void operator()() const+  {+    return target_();+  }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  result_type_or_void operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  result_type_or_void operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) const \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++private:+  CancellationSlot slot_;+  T target_;+};++/// Associate an object of type @c T with a cancellation slot of type+/// @c CancellationSlot.+template <typename CancellationSlot, typename T>+ASIO_NODISCARD inline+cancellation_slot_binder<typename decay<T>::type, CancellationSlot>+bind_cancellation_slot(const CancellationSlot& s, ASIO_MOVE_ARG(T) t)+{+  return cancellation_slot_binder<+    typename decay<T>::type, CancellationSlot>(+      s, ASIO_MOVE_CAST(T)(t));+}++#if !defined(GENERATING_DOCUMENTATION)++namespace detail {++template <typename TargetAsyncResult,+  typename CancellationSlot, typename = void>+struct cancellation_slot_binder_async_result_completion_handler_type+{+};++template <typename TargetAsyncResult, typename CancellationSlot>+struct cancellation_slot_binder_async_result_completion_handler_type<+  TargetAsyncResult, CancellationSlot,+  typename void_type<+    typename TargetAsyncResult::completion_handler_type+  >::type>+{+  typedef cancellation_slot_binder<+    typename TargetAsyncResult::completion_handler_type, CancellationSlot>+      completion_handler_type;+};++template <typename TargetAsyncResult, typename = void>+struct cancellation_slot_binder_async_result_return_type+{+};++template <typename TargetAsyncResult>+struct cancellation_slot_binder_async_result_return_type<+  TargetAsyncResult,+  typename void_type<+    typename TargetAsyncResult::return_type+  >::type>+{+  typedef typename TargetAsyncResult::return_type return_type;+};++} // namespace detail++template <typename T, typename CancellationSlot, typename Signature>+class async_result<cancellation_slot_binder<T, CancellationSlot>, Signature> :+  public detail::cancellation_slot_binder_async_result_completion_handler_type<+    async_result<T, Signature>, CancellationSlot>,+  public detail::cancellation_slot_binder_async_result_return_type<+    async_result<T, Signature> >+{+public:+  explicit async_result(cancellation_slot_binder<T, CancellationSlot>& b)+    : target_(b.get())+  {+  }++  typename async_result<T, Signature>::return_type get()+  {+    return target_.get();+  }++  template <typename Initiation>+  struct init_wrapper+  {+    template <typename Init>+    init_wrapper(const CancellationSlot& slot, ASIO_MOVE_ARG(Init) init)+      : slot_(slot),+        initiation_(ASIO_MOVE_CAST(Init)(init))+    {+    }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          cancellation_slot_binder<+            typename decay<Handler>::type, CancellationSlot>(+              slot_, ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args) const+    {+      initiation_(+          cancellation_slot_binder<+            typename decay<Handler>::type, CancellationSlot>(+              slot_, ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++    template <typename Handler>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          cancellation_slot_binder<+            typename decay<Handler>::type, CancellationSlot>(+              slot_, ASIO_MOVE_CAST(Handler)(handler)));+    }++    template <typename Handler>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler) const+    {+      initiation_(+          cancellation_slot_binder<+            typename decay<Handler>::type, CancellationSlot>(+              slot_, ASIO_MOVE_CAST(Handler)(handler)));+    }++#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \+    template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+    void operator()( \+        ASIO_MOVE_ARG(Handler) handler, \+        ASIO_VARIADIC_MOVE_PARAMS(n)) \+    { \+      ASIO_MOVE_CAST(Initiation)(initiation_)( \+          cancellation_slot_binder< \+            typename decay<Handler>::type, CancellationSlot>( \+              slot_, ASIO_MOVE_CAST(Handler)(handler)), \+          ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    \+    template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+    void operator()( \+        ASIO_MOVE_ARG(Handler) handler, \+        ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    { \+      initiation_( \+          cancellation_slot_binder< \+            typename decay<Handler>::type, CancellationSlot>( \+              slot_, ASIO_MOVE_CAST(Handler)(handler)), \+          ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    /**/+    ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)+#undef ASIO_PRIVATE_INIT_WRAPPER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++    CancellationSlot slot_;+    Initiation initiation_;+  };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+    (async_initiate<T, Signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<RawCompletionToken>().get(),+        declval<ASIO_MOVE_ARG(Args)>()...)))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+  {+    return async_initiate<T, Signature>(+        init_wrapper<typename decay<Initiation>::type>(+          token.get_cancellation_slot(),+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.get(), ASIO_MOVE_CAST(Args)(args)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+    (async_initiate<T, Signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<RawCompletionToken>().get())))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token)+  {+    return async_initiate<T, Signature>(+        init_wrapper<typename decay<Initiation>::type>(+          token.get_cancellation_slot(),+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.get());+  }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, typename RawCompletionToken, \+      ASIO_VARIADIC_TPARAMS(n)> \+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \+    (async_initiate<T, Signature>( \+        declval<init_wrapper<typename decay<Initiation>::type> >(), \+        declval<RawCompletionToken>().get(), \+        ASIO_VARIADIC_MOVE_DECLVAL(n)))) \+  initiate( \+      ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_MOVE_ARG(RawCompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return async_initiate<T, Signature>( \+        init_wrapper<typename decay<Initiation>::type>( \+          token.get_cancellation_slot(), \+          ASIO_MOVE_CAST(Initiation)(initiation)), \+        token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++private:+  async_result(const async_result&) ASIO_DELETED;+  async_result& operator=(const async_result&) ASIO_DELETED;++  async_result<T, Signature> target_;+};++template <template <typename, typename> class Associator,+    typename T, typename CancellationSlot, typename DefaultCandidate>+struct associator<Associator,+    cancellation_slot_binder<T, CancellationSlot>,+    DefaultCandidate>+  : Associator<T, DefaultCandidate>+{+  static typename Associator<T, DefaultCandidate>::type+  get(const cancellation_slot_binder<T, CancellationSlot>& b)+    ASIO_NOEXCEPT+  {+    return Associator<T, DefaultCandidate>::get(b.get());+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<T, DefaultCandidate>::type)+  get(const cancellation_slot_binder<T, CancellationSlot>& b,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<T, DefaultCandidate>::get(b.get(), c)))+  {+    return Associator<T, DefaultCandidate>::get(b.get(), c);+  }+};++template <typename T, typename CancellationSlot, typename CancellationSlot1>+struct associated_cancellation_slot<+    cancellation_slot_binder<T, CancellationSlot>,+    CancellationSlot1>+{+  typedef CancellationSlot type;++  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const cancellation_slot_binder<T, CancellationSlot>& b,+      const CancellationSlot1& = CancellationSlot1()) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((b.get_cancellation_slot()))+  {+    return b.get_cancellation_slot();+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BIND_CANCELLATION_SLOT_HPP
link/modules/asio-standalone/asio/include/asio/bind_executor.hpp view
@@ -2,7 +2,7 @@ // bind_executor.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,7 +19,7 @@ #include "asio/detail/type_traits.hpp" #include "asio/detail/variadic_templates.hpp" #include "asio/associated_executor.hpp"-#include "asio/associated_allocator.hpp"+#include "asio/associator.hpp" #include "asio/async_result.hpp" #include "asio/execution/executor.hpp" #include "asio/execution_context.hpp"@@ -486,11 +486,11 @@  /// 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>+ASIO_NODISCARD inline executor_binder<typename decay<T>::type, Executor> bind_executor(const Executor& ex, ASIO_MOVE_ARG(T) t,-    typename enable_if<+    typename constraint<       is_executor<Executor>::value || execution::is_executor<Executor>::value-    >::type* = 0)+    >::type = 0) {   return executor_binder<typename decay<T>::type, Executor>(       executor_arg_t(), ex, ASIO_MOVE_CAST(T)(t));@@ -498,11 +498,11 @@  /// 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,+ASIO_NODISCARD 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)+    typename constraint<is_convertible<+      ExecutionContext&, execution_context&>::value>::type = 0) {   return executor_binder<typename decay<T>::type,     typename ExecutionContext::executor_type>(@@ -515,42 +515,246 @@ 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>+namespace detail {++template <typename TargetAsyncResult, typename Executor, typename = void>+class executor_binder_completion_handler_async_result { public:+  template <typename T>+  explicit executor_binder_completion_handler_async_result(T&)+  {+  }+};++template <typename TargetAsyncResult, typename Executor>+class executor_binder_completion_handler_async_result<+  TargetAsyncResult, Executor,+  typename void_type<+    typename TargetAsyncResult::completion_handler_type+  >::type>+{+public:   typedef executor_binder<-    typename async_result<T, Signature>::completion_handler_type, Executor>+    typename TargetAsyncResult::completion_handler_type, Executor>       completion_handler_type; -  typedef typename async_result<T, Signature>::return_type return_type;+  explicit executor_binder_completion_handler_async_result(+      typename TargetAsyncResult::completion_handler_type& handler)+    : target_(handler)+  {+  } +  typename TargetAsyncResult::return_type get()+  {+    return target_.get();+  }++private:+  TargetAsyncResult target_;+};++template <typename TargetAsyncResult, typename = void>+struct executor_binder_async_result_return_type+{+};++template <typename TargetAsyncResult>+struct executor_binder_async_result_return_type<+  TargetAsyncResult,+  typename void_type<+    typename TargetAsyncResult::return_type+  >::type>+{+  typedef typename TargetAsyncResult::return_type return_type;+};++} // namespace detail++template <typename T, typename Executor, typename Signature>+class async_result<executor_binder<T, Executor>, Signature> :+  public detail::executor_binder_completion_handler_async_result<+    async_result<T, Signature>, Executor>,+  public detail::executor_binder_async_result_return_type<+    async_result<T, Signature> >+{+public:   explicit async_result(executor_binder<T, Executor>& b)-    : target_(b.get())+    : detail::executor_binder_completion_handler_async_result<+        async_result<T, Signature>, Executor>(b.get())   {   } -  return_type get()+  template <typename Initiation>+  struct init_wrapper   {-    return target_.get();+    template <typename Init>+    init_wrapper(const Executor& ex, ASIO_MOVE_ARG(Init) init)+      : ex_(ex),+        initiation_(ASIO_MOVE_CAST(Init)(init))+    {+    }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          executor_binder<typename decay<Handler>::type, Executor>(+            executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args) const+    {+      initiation_(+          executor_binder<typename decay<Handler>::type, Executor>(+            executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++    template <typename Handler>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          executor_binder<typename decay<Handler>::type, Executor>(+            executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)));+    }++    template <typename Handler>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler) const+    {+      initiation_(+          executor_binder<typename decay<Handler>::type, Executor>(+            executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)));+    }++#define ASIO_PRIVATE_INIT_WRAPPER_DEF(n) \+    template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+    void operator()( \+        ASIO_MOVE_ARG(Handler) handler, \+        ASIO_VARIADIC_MOVE_PARAMS(n)) \+    { \+      ASIO_MOVE_CAST(Initiation)(initiation_)( \+          executor_binder<typename decay<Handler>::type, Executor>( \+            executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \+          ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    \+    template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+    void operator()( \+        ASIO_MOVE_ARG(Handler) handler, \+        ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    { \+      initiation_( \+          executor_binder<typename decay<Handler>::type, Executor>( \+            executor_arg_t(), ex_, ASIO_MOVE_CAST(Handler)(handler)), \+          ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    /**/+    ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)+#undef ASIO_PRIVATE_INIT_WRAPPER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++    Executor ex_;+    Initiation initiation_;+  };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+    (async_initiate<T, Signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<RawCompletionToken>().get(),+        declval<ASIO_MOVE_ARG(Args)>()...)))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+  {+    return async_initiate<T, Signature>(+        init_wrapper<typename decay<Initiation>::type>(+          token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)),+        token.get(), ASIO_MOVE_CAST(Args)(args)...);   } +#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+    (async_initiate<T, Signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<RawCompletionToken>().get())))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token)+  {+    return async_initiate<T, Signature>(+        init_wrapper<typename decay<Initiation>::type>(+          token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)),+        token.get());+  }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, typename RawCompletionToken, \+      ASIO_VARIADIC_TPARAMS(n)> \+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \+    (async_initiate<T, Signature>( \+        declval<init_wrapper<typename decay<Initiation>::type> >(), \+        declval<RawCompletionToken>().get(), \+        ASIO_VARIADIC_MOVE_DECLVAL(n)))) \+  initiate( \+      ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_MOVE_ARG(RawCompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return async_initiate<T, Signature>( \+        init_wrapper<typename decay<Initiation>::type>( \+          token.get_executor(), ASIO_MOVE_CAST(Initiation)(initiation)), \+        token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+ private:   async_result(const async_result&) ASIO_DELETED;   async_result& operator=(const async_result&) ASIO_DELETED;--  async_result<T, Signature> target_; }; -template <typename T, typename Executor, typename Allocator>-struct associated_allocator<executor_binder<T, Executor>, Allocator>+template <template <typename, typename> class Associator,+    typename T, typename Executor, typename DefaultCandidate>+struct associator<Associator, executor_binder<T, Executor>, DefaultCandidate>+  : Associator<T, DefaultCandidate> {-  typedef typename associated_allocator<T, Allocator>::type type;+  static typename Associator<T, DefaultCandidate>::type+  get(const executor_binder<T, Executor>& b) ASIO_NOEXCEPT+  {+    return Associator<T, DefaultCandidate>::get(b.get());+  } -  static type get(const executor_binder<T, Executor>& b,-      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<T, DefaultCandidate>::type)+  get(const executor_binder<T, Executor>& b,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<T, DefaultCandidate>::get(b.get(), c)))   {-    return associated_allocator<T, Allocator>::get(b.get(), a);+    return Associator<T, DefaultCandidate>::get(b.get(), c);   } }; @@ -559,8 +763,10 @@ {   typedef Executor type; -  static type get(const executor_binder<T, Executor>& b,+  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const executor_binder<T, Executor>& b,       const Executor1& = Executor1()) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((b.get_executor()))   {     return b.get_executor();   }
+ link/modules/asio-standalone/asio/include/asio/bind_immediate_executor.hpp view
@@ -0,0 +1,736 @@+//+// bind_immediate_executor.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_IMMEDIATE_EXECUTOR_HPP+#define ASIO_BIND_IMMEDIATE_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_immediate_executor.hpp"+#include "asio/associator.hpp"+#include "asio/async_result.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Helper to automatically define nested typedef result_type.++template <typename T, typename = void>+struct immediate_executor_binder_result_type+{+protected:+  typedef void result_type_or_void;+};++template <typename T>+struct immediate_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 immediate_executor_binder_result_type<R(*)()>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R>+struct immediate_executor_binder_result_type<R(&)()>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct immediate_executor_binder_result_type<R(*)(A1)>+{+  typedef R result_type;+protected:+  typedef result_type result_type_or_void;+};++template <typename R, typename A1>+struct immediate_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 immediate_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 immediate_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 immediate_executor_binder_argument_type {};++template <typename T>+struct immediate_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 immediate_executor_binder_argument_type<R(*)(A1)>+{+  typedef A1 argument_type;+};++template <typename R, typename A1>+struct immediate_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 immediate_executor_binder_argument_types {};++template <typename T>+struct immediate_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 immediate_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 immediate_executor_binder_argument_type<R(&)(A1, A2)>+{+  typedef A1 first_argument_type;+  typedef A2 second_argument_type;+};++// Helper to enable SFINAE on zero-argument operator() below.++template <typename T, typename = void>+struct immediate_executor_binder_result_of0+{+  typedef void type;+};++template <typename T>+struct immediate_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 a immediate executor of type @c Executor+/// to an object of type @c T.+template <typename T, typename Executor>+class immediate_executor_binder+#if !defined(GENERATING_DOCUMENTATION)+  : public detail::immediate_executor_binder_result_type<T>,+    public detail::immediate_executor_binder_argument_type<T>,+    public detail::immediate_executor_binder_argument_types<T>+#endif // !defined(GENERATING_DOCUMENTATION)+{+public:+  /// The type of the target object.+  typedef T target_type;++  /// The type of the associated immediate executor.+  typedef Executor immediate_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 a immediate 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>+  immediate_executor_binder(const immediate_executor_type& e,+      ASIO_MOVE_ARG(U) u)+    : executor_(e),+      target_(ASIO_MOVE_CAST(U)(u))+  {+  }++  /// Copy constructor.+  immediate_executor_binder(const immediate_executor_binder& other)+    : executor_(other.get_immediate_executor()),+      target_(other.get())+  {+  }++  /// Construct a copy, but specify a different immediate executor.+  immediate_executor_binder(const immediate_executor_type& e,+      const immediate_executor_binder& other)+    : executor_(e),+      target_(other.get())+  {+  }++  /// Construct a copy of a different immediate 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>+  immediate_executor_binder(+      const immediate_executor_binder<U, OtherExecutor>& other)+    : executor_(other.get_immediate_executor()),+      target_(other.get())+  {+  }++  /// Construct a copy of a different immediate executor wrapper type, but+  /// specify a different immediate executor.+  /**+   * This constructor is only valid if the type @c T is constructible from type+   * @c U.+   */+  template <typename U, typename OtherExecutor>+  immediate_executor_binder(const immediate_executor_type& e,+      const immediate_executor_binder<U, OtherExecutor>& other)+    : executor_(e),+      target_(other.get())+  {+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Move constructor.+  immediate_executor_binder(immediate_executor_binder&& other)+    : executor_(ASIO_MOVE_CAST(immediate_executor_type)(+          other.get_immediate_executor())),+      target_(ASIO_MOVE_CAST(T)(other.get()))+  {+  }++  /// Move construct the target object, but specify a different immediate+  /// executor.+  immediate_executor_binder(const immediate_executor_type& e,+      immediate_executor_binder&& other)+    : executor_(e),+      target_(ASIO_MOVE_CAST(T)(other.get()))+  {+  }++  /// Move construct from a different immediate executor wrapper type.+  template <typename U, typename OtherExecutor>+  immediate_executor_binder(+      immediate_executor_binder<U, OtherExecutor>&& other)+    : executor_(ASIO_MOVE_CAST(OtherExecutor)(+          other.get_immediate_executor())),+      target_(ASIO_MOVE_CAST(U)(other.get()))+  {+  }++  /// Move construct from a different immediate executor wrapper type, but+  /// specify a different immediate executor.+  template <typename U, typename OtherExecutor>+  immediate_executor_binder(const immediate_executor_type& e,+      immediate_executor_binder<U, OtherExecutor>&& other)+    : executor_(e),+      target_(ASIO_MOVE_CAST(U)(other.get()))+  {+  }++#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  ~immediate_executor_binder()+  {+  }++  /// Obtain a reference to the target object.+  target_type& get() ASIO_NOEXCEPT+  {+    return target_;+  }++  /// Obtain a reference to the target object.+  const target_type& get() const ASIO_NOEXCEPT+  {+    return target_;+  }++  /// Obtain the associated immediate executor.+  immediate_executor_type get_immediate_executor() const ASIO_NOEXCEPT+  {+    return 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 target_(ASIO_MOVE_CAST(Args)(args)...);+  }++  /// Forwarding function call operator.+  template <typename... Args>+  typename result_of<T(Args...)>::type operator()(+      ASIO_MOVE_ARG(Args)... args) const+  {+    return target_(ASIO_MOVE_CAST(Args)(args)...);+  }++#elif defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++  typename detail::immediate_executor_binder_result_of0<T>::type operator()()+  {+    return target_();+  }++  typename detail::immediate_executor_binder_result_of0<T>::type+  operator()() const+  {+    return target_();+  }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  typename result_of<T(ASIO_VARIADIC_TARGS(n))>::type operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) const \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#else // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++  typedef typename detail::immediate_executor_binder_result_type<+    T>::result_type_or_void result_type_or_void;++  result_type_or_void operator()()+  {+    return target_();+  }++  result_type_or_void operator()() const+  {+    return target_();+  }++#define ASIO_PRIVATE_BINDER_CALL_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  result_type_or_void operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  result_type_or_void operator()( \+      ASIO_VARIADIC_MOVE_PARAMS(n)) const \+  { \+    return target_(ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_BINDER_CALL_DEF)+#undef ASIO_PRIVATE_BINDER_CALL_DEF++#endif // defined(ASIO_HAS_STD_TYPE_TRAITS) && !defined(_MSC_VER)++private:+  Executor executor_;+  T target_;+};++/// Associate an object of type @c T with a immediate executor of type+/// @c Executor.+template <typename Executor, typename T>+ASIO_NODISCARD inline+immediate_executor_binder<typename decay<T>::type, Executor>+bind_immediate_executor(const Executor& e, ASIO_MOVE_ARG(T) t)+{+  return immediate_executor_binder<+    typename decay<T>::type, Executor>(+      e, ASIO_MOVE_CAST(T)(t));+}++#if !defined(GENERATING_DOCUMENTATION)++namespace detail {++template <typename TargetAsyncResult,+  typename Executor, typename = void>+struct immediate_executor_binder_async_result_completion_handler_type+{+};++template <typename TargetAsyncResult, typename Executor>+struct immediate_executor_binder_async_result_completion_handler_type<+  TargetAsyncResult, Executor,+  typename void_type<+    typename TargetAsyncResult::completion_handler_type+  >::type>+{+  typedef immediate_executor_binder<+    typename TargetAsyncResult::completion_handler_type, Executor>+      completion_handler_type;+};++template <typename TargetAsyncResult, typename = void>+struct immediate_executor_binder_async_result_return_type+{+};++template <typename TargetAsyncResult>+struct immediate_executor_binder_async_result_return_type<+  TargetAsyncResult,+  typename void_type<+    typename TargetAsyncResult::return_type+  >::type>+{+  typedef typename TargetAsyncResult::return_type return_type;+};++} // namespace detail++template <typename T, typename Executor, typename Signature>+class async_result<immediate_executor_binder<T, Executor>, Signature> :+  public detail::immediate_executor_binder_async_result_completion_handler_type<+    async_result<T, Signature>, Executor>,+  public detail::immediate_executor_binder_async_result_return_type<+    async_result<T, Signature> >+{+public:+  explicit async_result(immediate_executor_binder<T, Executor>& b)+    : target_(b.get())+  {+  }++  typename async_result<T, Signature>::return_type get()+  {+    return target_.get();+  }++  template <typename Initiation>+  struct init_wrapper+  {+    template <typename Init>+    init_wrapper(const Executor& e, ASIO_MOVE_ARG(Init) init)+      : executor_(e),+        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_)(+          immediate_executor_binder<+            typename decay<Handler>::type, Executor>(+              executor_, ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args) const+    {+      initiation_(+          immediate_executor_binder<+            typename decay<Handler>::type, Executor>(+              executor_, 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_)(+          immediate_executor_binder<+            typename decay<Handler>::type, Executor>(+              executor_, ASIO_MOVE_CAST(Handler)(handler)));+    }++    template <typename Handler>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler) const+    {+      initiation_(+          immediate_executor_binder<+            typename decay<Handler>::type, Executor>(+              executor_, 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_)( \+          immediate_executor_binder< \+            typename decay<Handler>::type, Executor>( \+              executor_, ASIO_MOVE_CAST(Handler)(handler)), \+          ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    \+    template <typename Handler, ASIO_VARIADIC_TPARAMS(n)> \+    void operator()( \+        ASIO_MOVE_ARG(Handler) handler, \+        ASIO_VARIADIC_MOVE_PARAMS(n)) const \+    { \+      initiation_( \+          immediate_executor_binder< \+            typename decay<Handler>::type, Executor>( \+              executor_, ASIO_MOVE_CAST(Handler)(handler)), \+          ASIO_VARIADIC_MOVE_ARGS(n)); \+    } \+    /**/+    ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INIT_WRAPPER_DEF)+#undef ASIO_PRIVATE_INIT_WRAPPER_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++    Executor executor_;+    Initiation initiation_;+  };++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+    (async_initiate<T, Signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<RawCompletionToken>().get(),+        declval<ASIO_MOVE_ARG(Args)>()...)))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+  {+    return async_initiate<T, Signature>(+        init_wrapper<typename decay<Initiation>::type>(+          token.get_immediate_executor(),+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.get(), ASIO_MOVE_CAST(Args)(args)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation, typename RawCompletionToken>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature,+    (async_initiate<T, Signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<RawCompletionToken>().get())))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token)+  {+    return async_initiate<T, Signature>(+        init_wrapper<typename decay<Initiation>::type>(+          token.get_immediate_executor(),+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.get());+  }++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, typename RawCompletionToken, \+      ASIO_VARIADIC_TPARAMS(n)> \+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(T, Signature, \+    (async_initiate<T, Signature>( \+        declval<init_wrapper<typename decay<Initiation>::type> >(), \+        declval<RawCompletionToken>().get(), \+        ASIO_VARIADIC_MOVE_DECLVAL(n)))) \+  initiate( \+      ASIO_MOVE_ARG(Initiation) initiation, \+      ASIO_MOVE_ARG(RawCompletionToken) token, \+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    return async_initiate<T, Signature>( \+        init_wrapper<typename decay<Initiation>::type>( \+          token.get_immediate_executor(), \+          ASIO_MOVE_CAST(Initiation)(initiation)), \+        token.get(), ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++private:+  async_result(const async_result&) ASIO_DELETED;+  async_result& operator=(const async_result&) ASIO_DELETED;++  async_result<T, Signature> target_;+};++template <template <typename, typename> class Associator,+    typename T, typename Executor, typename DefaultCandidate>+struct associator<Associator,+    immediate_executor_binder<T, Executor>,+    DefaultCandidate>+  : Associator<T, DefaultCandidate>+{+  static typename Associator<T, DefaultCandidate>::type+  get(const immediate_executor_binder<T, Executor>& b)+    ASIO_NOEXCEPT+  {+    return Associator<T, DefaultCandidate>::get(b.get());+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<T, DefaultCandidate>::type)+  get(const immediate_executor_binder<T, Executor>& b,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<T, DefaultCandidate>::get(b.get(), c)))+  {+    return Associator<T, DefaultCandidate>::get(b.get(), c);+  }+};++template <typename T, typename Executor, typename Executor1>+struct associated_immediate_executor<+    immediate_executor_binder<T, Executor>,+    Executor1>+{+  typedef Executor type;++  static ASIO_AUTO_RETURN_TYPE_PREFIX(type) get(+      const immediate_executor_binder<T, Executor>& b,+      const Executor1& = Executor1()) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((b.get_immediate_executor()))+  {+    return b.get_immediate_executor();+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BIND_IMMEDIATE_EXECUTOR_HPP
link/modules/asio-standalone/asio/include/asio/buffer.hpp view
@@ -2,7 +2,7 @@ // buffer.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -27,6 +27,7 @@ #include "asio/detail/string_view.hpp" #include "asio/detail/throw_exception.hpp" #include "asio/detail/type_traits.hpp"+#include "asio/is_contiguous_iterator.hpp"  #if defined(ASIO_MSVC) && (ASIO_MSVC >= 1700) # if defined(_HAS_ITERATOR_DEBUGGING) && (_HAS_ITERATOR_DEBUGGING != 0)@@ -386,9 +387,9 @@ /// 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<+    typename constraint<       is_convertible<const MutableBuffer*, const mutable_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT+    >::type = 0) ASIO_NOEXCEPT {   return static_cast<const mutable_buffer*>(detail::addressof(b)); }@@ -396,9 +397,9 @@ /// 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<+    typename constraint<       is_convertible<const ConstBuffer*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT+    >::type = 0) ASIO_NOEXCEPT {   return static_cast<const const_buffer*>(detail::addressof(b)); }@@ -408,10 +409,10 @@ /// Get an iterator to the first element in a buffer sequence. template <typename C> inline auto buffer_sequence_begin(C& c,-    typename enable_if<+    typename constraint<       !is_convertible<const C*, const mutable_buffer*>::value         && !is_convertible<const C*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())+    >::type = 0) ASIO_NOEXCEPT -> decltype(c.begin()) {   return c.begin(); }@@ -419,10 +420,10 @@ /// 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<+    typename constraint<       !is_convertible<const C*, const mutable_buffer*>::value         && !is_convertible<const C*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT -> decltype(c.begin())+    >::type = 0) ASIO_NOEXCEPT -> decltype(c.begin()) {   return c.begin(); }@@ -431,20 +432,20 @@  template <typename C> inline typename C::iterator buffer_sequence_begin(C& c,-    typename enable_if<+    typename constraint<       !is_convertible<const C*, const mutable_buffer*>::value         && !is_convertible<const C*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT+    >::type = 0) ASIO_NOEXCEPT {   return c.begin(); }  template <typename C> inline typename C::const_iterator buffer_sequence_begin(const C& c,-    typename enable_if<+    typename constraint<       !is_convertible<const C*, const mutable_buffer*>::value         && !is_convertible<const C*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT+    >::type = 0) ASIO_NOEXCEPT {   return c.begin(); }@@ -463,9 +464,9 @@ /// 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<+    typename constraint<       is_convertible<const MutableBuffer*, const mutable_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT+    >::type = 0) ASIO_NOEXCEPT {   return static_cast<const mutable_buffer*>(detail::addressof(b)) + 1; }@@ -473,9 +474,9 @@ /// 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<+    typename constraint<       is_convertible<const ConstBuffer*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT+    >::type = 0) ASIO_NOEXCEPT {   return static_cast<const const_buffer*>(detail::addressof(b)) + 1; }@@ -485,10 +486,10 @@ /// 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<+    typename constraint<       !is_convertible<const C*, const mutable_buffer*>::value         && !is_convertible<const C*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())+    >::type = 0) ASIO_NOEXCEPT -> decltype(c.end()) {   return c.end(); }@@ -496,10 +497,10 @@ /// 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<+    typename constraint<       !is_convertible<const C*, const mutable_buffer*>::value         && !is_convertible<const C*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT -> decltype(c.end())+    >::type = 0) ASIO_NOEXCEPT -> decltype(c.end()) {   return c.end(); }@@ -508,20 +509,20 @@  template <typename C> inline typename C::iterator buffer_sequence_end(C& c,-    typename enable_if<+    typename constraint<       !is_convertible<const C*, const mutable_buffer*>::value         && !is_convertible<const C*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT+    >::type = 0) ASIO_NOEXCEPT {   return c.end(); }  template <typename C> inline typename C::const_iterator buffer_sequence_end(const C& c,-    typename enable_if<+    typename constraint<       !is_convertible<const C*, const mutable_buffer*>::value         && !is_convertible<const C*, const const_buffer*>::value-    >::type* = 0) ASIO_NOEXCEPT+    >::type = 0) ASIO_NOEXCEPT {   return c.end(); }@@ -891,6 +892,25 @@  * bufs2.push_back(asio::buffer(d2));  * bufs2.push_back(asio::buffer(d3));  * bytes_transferred = sock.send(bufs2); @endcode+ *+ * @par Buffer Literals+ *+ * The `_buf` literal suffix, defined in namespace+ * <tt>asio::buffer_literals</tt>, may be used to create @c const_buffer+ * objects from string, binary integer, and hexadecimal integer literals.+ * For example:+ *+ * @code+ * using namespace asio::buffer_literals;+ *+ * asio::const_buffer b1 = "hello"_buf;+ * asio::const_buffer b2 = 0xdeadbeef_buf;+ * asio::const_buffer b3 = 0x0123456789abcdef0123456789abcdef_buf;+ * asio::const_buffer b4 = 0b1010101011001100_buf; @endcode+ *+ * Note that the memory associated with a buffer literal is valid for the+ * lifetime of the program. This means that the buffer can be safely used with+ * asynchronous operations.  */ /*@{*/ @@ -906,7 +926,7 @@ /**  * @returns <tt>mutable_buffer(b)</tt>.  */-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(     const mutable_buffer& b) ASIO_NOEXCEPT {   return ASIO_MUTABLE_BUFFER(b);@@ -919,7 +939,8 @@  *     b.data(),  *     min(b.size(), max_size_in_bytes)); @endcode  */-inline ASIO_MUTABLE_BUFFER buffer(const mutable_buffer& b,+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+    const mutable_buffer& b,     std::size_t max_size_in_bytes) ASIO_NOEXCEPT {   return ASIO_MUTABLE_BUFFER(@@ -936,7 +957,7 @@ /**  * @returns <tt>const_buffer(b)</tt>.  */-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     const const_buffer& b) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(b);@@ -949,7 +970,8 @@  *     b.data(),  *     min(b.size(), max_size_in_bytes)); @endcode  */-inline ASIO_CONST_BUFFER buffer(const const_buffer& b,+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+    const const_buffer& b,     std::size_t max_size_in_bytes) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(b.data(),@@ -965,8 +987,8 @@ /**  * @returns <tt>mutable_buffer(data, size_in_bytes)</tt>.  */-inline ASIO_MUTABLE_BUFFER buffer(void* data,-    std::size_t size_in_bytes) ASIO_NOEXCEPT+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+    void* data, std::size_t size_in_bytes) ASIO_NOEXCEPT {   return ASIO_MUTABLE_BUFFER(data, size_in_bytes); }@@ -975,8 +997,8 @@ /**  * @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+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+    const void* data, std::size_t size_in_bytes) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(data, size_in_bytes); }@@ -989,7 +1011,8 @@  *     N * sizeof(PodType)); @endcode  */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N]) ASIO_NOEXCEPT+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+    PodType (&data)[N]) ASIO_NOEXCEPT {   return ASIO_MUTABLE_BUFFER(data, N * sizeof(PodType)); }@@ -1002,7 +1025,8 @@  *     min(N * sizeof(PodType), max_size_in_bytes)); @endcode  */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(PodType (&data)[N],+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+    PodType (&data)[N],     std::size_t max_size_in_bytes) ASIO_NOEXCEPT {   return ASIO_MUTABLE_BUFFER(data,@@ -1018,7 +1042,7 @@  *     N * sizeof(PodType)); @endcode  */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     const PodType (&data)[N]) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(data, N * sizeof(PodType));@@ -1032,7 +1056,8 @@  *     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],+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+    const PodType (&data)[N],     std::size_t max_size_in_bytes) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(data,@@ -1082,7 +1107,8 @@ } // namespace detail  template <typename PodType, std::size_t N>-inline typename detail::buffer_types<PodType>::container_type+ASIO_NODISCARD 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@@ -1094,7 +1120,8 @@ }  template <typename PodType, std::size_t N>-inline typename detail::buffer_types<PodType>::container_type+ASIO_NODISCARD inline+typename detail::buffer_types<PodType>::container_type buffer(boost::array<PodType, N>& data,     std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1118,7 +1145,7 @@  *     data.size() * sizeof(PodType)); @endcode  */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(     boost::array<PodType, N>& data) ASIO_NOEXCEPT {   return ASIO_MUTABLE_BUFFER(@@ -1133,7 +1160,8 @@  *     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,+ASIO_NODISCARD 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(),@@ -1149,7 +1177,7 @@  *     data.size() * sizeof(PodType)); @endcode  */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     boost::array<const PodType, N>& data) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1163,7 +1191,8 @@  *     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,+ASIO_NODISCARD 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(),@@ -1181,7 +1210,7 @@  *     data.size() * sizeof(PodType)); @endcode  */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     const boost::array<PodType, N>& data) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1195,7 +1224,8 @@  *     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,+ASIO_NODISCARD 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(),@@ -1213,7 +1243,7 @@  *     data.size() * sizeof(PodType)); @endcode  */ template <typename PodType, std::size_t N>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(     std::array<PodType, N>& data) ASIO_NOEXCEPT {   return ASIO_MUTABLE_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1227,7 +1257,8 @@  *     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,+ASIO_NODISCARD 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(),@@ -1243,7 +1274,7 @@  *     data.size() * sizeof(PodType)); @endcode  */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     std::array<const PodType, N>& data) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1257,7 +1288,8 @@  *     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,+ASIO_NODISCARD 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(),@@ -1273,7 +1305,7 @@  *     data.size() * sizeof(PodType)); @endcode  */ template <typename PodType, std::size_t N>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     const std::array<PodType, N>& data) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(data.data(), data.size() * sizeof(PodType));@@ -1287,7 +1319,8 @@  *     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,+ASIO_NODISCARD 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(),@@ -1308,7 +1341,7 @@  * invalidate iterators.  */ template <typename PodType, typename Allocator>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(     std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT {   return ASIO_MUTABLE_BUFFER(@@ -1332,7 +1365,8 @@  * invalidate iterators.  */ template <typename PodType, typename Allocator>-inline ASIO_MUTABLE_BUFFER buffer(std::vector<PodType, Allocator>& data,+ASIO_NODISCARD 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,@@ -1357,7 +1391,7 @@  * invalidate iterators.  */ template <typename PodType, typename Allocator>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     const std::vector<PodType, Allocator>& data) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(@@ -1381,7 +1415,7 @@  * invalidate iterators.  */ template <typename PodType, typename Allocator>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     const std::vector<PodType, Allocator>& data,     std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1405,7 +1439,7 @@  * given string object.  */ template <typename Elem, typename Traits, typename Allocator>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(     std::basic_string<Elem, Traits, Allocator>& data) ASIO_NOEXCEPT {   return ASIO_MUTABLE_BUFFER(data.size() ? &data[0] : 0,@@ -1429,7 +1463,7 @@  * given string object.  */ template <typename Elem, typename Traits, typename Allocator>-inline ASIO_MUTABLE_BUFFER buffer(+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(     std::basic_string<Elem, Traits, Allocator>& data,     std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1452,7 +1486,7 @@  * given string object.  */ template <typename Elem, typename Traits, typename Allocator>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD 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)@@ -1475,7 +1509,7 @@  * given string object.  */ template <typename Elem, typename Traits, typename Allocator>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     const std::basic_string<Elem, Traits, Allocator>& data,     std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1493,13 +1527,13 @@ #if defined(ASIO_HAS_STRING_VIEW) \   || defined(GENERATING_DOCUMENTATION) -/// Create a new modifiable buffer that represents the given string_view.+/// Create a new non-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(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     basic_string_view<Elem, Traits> data) ASIO_NOEXCEPT {   return ASIO_CONST_BUFFER(data.size() ? &data[0] : 0,@@ -1520,7 +1554,7 @@  *     min(data.size() * sizeof(Elem), max_size_in_bytes)); @endcode  */ template <typename Elem, typename Traits>-inline ASIO_CONST_BUFFER buffer(+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(     basic_string_view<Elem, Traits> data,     std::size_t max_size_in_bytes) ASIO_NOEXCEPT {@@ -1538,6 +1572,215 @@ #endif // defined(ASIO_HAS_STRING_VIEW)        //  || defined(GENERATING_DOCUMENTATION) +/// Create a new modifiable buffer from a contiguous container.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.size() ? &data[0] : 0,+ *     data.size() * sizeof(typename T::value_type)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+    T& data,+    typename constraint<+      is_contiguous_iterator<typename T::iterator>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, const_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, mutable_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_const<+        typename remove_reference<+          typename std::iterator_traits<typename T::iterator>::reference+        >::type+      >::value,+      defaulted_constraint+    >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(+      data.size() ? detail::to_address(data.begin()) : 0,+      data.size() * sizeof(typename T::value_type));+}++/// Create a new modifiable buffer from a contiguous container.+/**+ * @returns A mutable_buffer value equivalent to:+ * @code mutable_buffer(+ *     data.size() ? &data[0] : 0,+ *     min(+ *       data.size() * sizeof(typename T::value_type),+ *       max_size_in_bytes)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_MUTABLE_BUFFER buffer(+    T& data, std::size_t max_size_in_bytes,+    typename constraint<+      is_contiguous_iterator<typename T::iterator>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, const_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, mutable_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_const<+        typename remove_reference<+          typename std::iterator_traits<typename T::iterator>::reference+        >::type+      >::value,+      defaulted_constraint+    >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+  return ASIO_MUTABLE_BUFFER(+      data.size() ? detail::to_address(data.begin()) : 0,+      data.size() * sizeof(typename T::value_type) < max_size_in_bytes+      ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes);+}++/// Create a new non-modifiable buffer from a contiguous container.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.size() ? &data[0] : 0,+ *     data.size() * sizeof(typename T::value_type)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+    T& data,+    typename constraint<+      is_contiguous_iterator<typename T::iterator>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, const_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, mutable_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      is_const<+        typename remove_reference<+          typename std::iterator_traits<typename T::iterator>::reference+        >::type+      >::value,+      defaulted_constraint+    >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(+      data.size() ? detail::to_address(data.begin()) : 0,+      data.size() * sizeof(typename T::value_type));+}++/// Create a new non-modifiable buffer from a contiguous container.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.size() ? &data[0] : 0,+ *     min(+ *       data.size() * sizeof(typename T::value_type),+ *       max_size_in_bytes)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+    T& data, std::size_t max_size_in_bytes,+    typename constraint<+      is_contiguous_iterator<typename T::iterator>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, const_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, mutable_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      is_const<+        typename remove_reference<+          typename std::iterator_traits<typename T::iterator>::reference+        >::type+      >::value,+      defaulted_constraint+    >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(+      data.size() ? detail::to_address(data.begin()) : 0,+      data.size() * sizeof(typename T::value_type) < max_size_in_bytes+      ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes);+}++/// Create a new non-modifiable buffer from a contiguous container.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.size() ? &data[0] : 0,+ *     data.size() * sizeof(typename T::value_type)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+    const T& data,+    typename constraint<+      is_contiguous_iterator<typename T::const_iterator>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, const_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, mutable_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(+      data.size() ? detail::to_address(data.begin()) : 0,+      data.size() * sizeof(typename T::value_type));+}++/// Create a new non-modifiable buffer from a contiguous container.+/**+ * @returns A const_buffer value equivalent to:+ * @code const_buffer(+ *     data.size() ? &data[0] : 0,+ *     min(+ *       data.size() * sizeof(typename T::value_type),+ *       max_size_in_bytes)); @endcode+ */+template <typename T>+ASIO_NODISCARD inline ASIO_CONST_BUFFER buffer(+    const T& data, std::size_t max_size_in_bytes,+    typename constraint<+      is_contiguous_iterator<typename T::const_iterator>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, const_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint(),+    typename constraint<+      !is_convertible<T, mutable_buffer>::value,+      defaulted_constraint+    >::type = defaulted_constraint()) ASIO_NOEXCEPT+{+  return ASIO_CONST_BUFFER(+      data.size() ? detail::to_address(data.begin()) : 0,+      data.size() * sizeof(typename T::value_type) < max_size_in_bytes+      ? data.size() * sizeof(typename T::value_type) : max_size_in_bytes);+}+ /*@}*/  /// Adapt a basic_string to the DynamicBuffer requirements.@@ -2096,7 +2339,8 @@  * @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(+ASIO_NODISCARD 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);@@ -2108,7 +2352,8 @@  * max_size)</tt>.  */ template <typename Elem, typename Traits, typename Allocator>-inline dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(+ASIO_NODISCARD inline+dynamic_string_buffer<Elem, Traits, Allocator> dynamic_buffer(     std::basic_string<Elem, Traits, Allocator>& data,     std::size_t max_size) ASIO_NOEXCEPT {@@ -2120,7 +2365,8 @@  * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data)</tt>.  */ template <typename Elem, typename Allocator>-inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(+ASIO_NODISCARD inline+dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(     std::vector<Elem, Allocator>& data) ASIO_NOEXCEPT {   return dynamic_vector_buffer<Elem, Allocator>(data);@@ -2131,7 +2377,8 @@  * @returns <tt>dynamic_vector_buffer<Elem, Allocator>(data, max_size)</tt>.  */ template <typename Elem, typename Allocator>-inline dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(+ASIO_NODISCARD inline+dynamic_vector_buffer<Elem, Allocator> dynamic_buffer(     std::vector<Elem, Allocator>& data,     std::size_t max_size) ASIO_NOEXCEPT {@@ -2488,6 +2735,172 @@ #endif // defined(ASIO_NO_DYNAMIC_BUFFER_V1) { };++#if (defined(ASIO_HAS_USER_DEFINED_LITERALS) \+    && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+  || defined(GENERATING_DOCUMENTATION)++namespace buffer_literals {+namespace detail {++template <char... Chars>+struct chars {};++template <unsigned char... Bytes>+struct bytes {};++// Literal processor that converts binary literals to an array of bytes.++template <typename Bytes, char... Chars>+struct bin_literal;++template <unsigned char... Bytes>+struct bin_literal<bytes<Bytes...> >+{+  static const std::size_t size = sizeof...(Bytes);+  static const unsigned char data[sizeof...(Bytes)];+};++template <unsigned char... Bytes>+const unsigned char bin_literal<bytes<Bytes...> >::data[sizeof...(Bytes)]+  = { Bytes... };++template <unsigned char... Bytes, char Bit7, char Bit6, char Bit5,+    char Bit4, char Bit3, char Bit2, char Bit1, char Bit0, char... Chars>+struct bin_literal<bytes<Bytes...>, Bit7, Bit6,+    Bit5, Bit4, Bit3, Bit2, Bit1, Bit0, Chars...> :+  bin_literal<+    bytes<Bytes...,+      static_cast<unsigned char>(+      (Bit7 == '1' ? 0x80 : 0) |+        (Bit6 == '1' ? 0x40 : 0) |+        (Bit5 == '1' ? 0x20 : 0) |+        (Bit4 == '1' ? 0x10 : 0) |+        (Bit3 == '1' ? 0x08 : 0) |+        (Bit2 == '1' ? 0x04 : 0) |+        (Bit1 == '1' ? 0x02 : 0) |+        (Bit0 == '1' ? 0x01 : 0))+    >, Chars...> {};++template <unsigned char... Bytes, char... Chars>+struct bin_literal<bytes<Bytes...>, Chars...>+{+  static_assert(sizeof...(Chars) == 0,+      "number of digits in a binary buffer literal must be a multiple of 8");++  static const std::size_t size = 0;+  static const unsigned char data[1];+};++template <unsigned char... Bytes, char... Chars>+const unsigned char bin_literal<bytes<Bytes...>, Chars...>::data[1] = {};++// Literal processor that converts hexadecimal literals to an array of bytes.++template <typename Bytes, char... Chars>+struct hex_literal;++template <unsigned char... Bytes>+struct hex_literal<bytes<Bytes...> >+{+  static const std::size_t size = sizeof...(Bytes);+  static const unsigned char data[sizeof...(Bytes)];+};++template <unsigned char... Bytes>+const unsigned char hex_literal<bytes<Bytes...> >::data[sizeof...(Bytes)]+  = { Bytes... };++template <unsigned char... Bytes, char Hi, char Lo, char... Chars>+struct hex_literal<bytes<Bytes...>, Hi, Lo, Chars...> :+  hex_literal<+    bytes<Bytes...,+      static_cast<unsigned char>(+        Lo >= 'A' && Lo <= 'F' ? Lo - 'A' + 10 :+          (Lo >= 'a' && Lo <= 'f' ? Lo - 'a' + 10 : Lo - '0')) |+      ((static_cast<unsigned char>(+        Hi >= 'A' && Hi <= 'F' ? Hi - 'A' + 10 :+          (Hi >= 'a' && Hi <= 'f' ? Hi - 'a' + 10 : Hi - '0'))) << 4)+    >, Chars...> {};++template <unsigned char... Bytes, char Char>+struct hex_literal<bytes<Bytes...>, Char>+{+  static_assert(!Char,+      "a hexadecimal buffer literal must have an even number of digits");++  static const std::size_t size = 0;+  static const unsigned char data[1];+};++template <unsigned char... Bytes, char Char>+const unsigned char hex_literal<bytes<Bytes...>, Char>::data[1] = {};++// Helper template that removes digit separators and then passes the cleaned+// variadic pack of characters to the literal processor.++template <template <typename, char...> class Literal,+    typename Clean, char... Raw>+struct remove_separators;++template <template <typename, char...> class Literal,+    char... Clean, char... Raw>+struct remove_separators<Literal, chars<Clean...>, '\'', Raw...> :+  remove_separators<Literal, chars<Clean...>, Raw...> {};++template <template <typename, char...> class Literal,+    char... Clean, char C, char... Raw>+struct remove_separators<Literal, chars<Clean...>, C, Raw...> :+  remove_separators<Literal, chars<Clean..., C>, Raw...> {};++template <template <typename, char...> class Literal, char... Clean>+struct remove_separators<Literal, chars<Clean...> > :+  Literal<bytes<>, Clean...> {};++// Helper template to determine the literal type based on the prefix.++template <char... Chars>+struct literal;++template <char... Chars>+struct literal<'0', 'b', Chars...> :+  remove_separators<bin_literal, chars<>, Chars...>{};++template <char... Chars>+struct literal<'0', 'B', Chars...> :+  remove_separators<bin_literal, chars<>, Chars...>{};++template <char... Chars>+struct literal<'0', 'x', Chars...> :+  remove_separators<hex_literal, chars<>, Chars...>{};++template <char... Chars>+struct literal<'0', 'X', Chars...> :+  remove_separators<hex_literal, chars<>, Chars...>{};++} // namespace detail++/// Literal operator for creating const_buffer objects from string literals.+inline ASIO_CONST_BUFFER operator"" _buf(const char* data, std::size_t n)+{+  return ASIO_CONST_BUFFER(data, n);+}++/// Literal operator for creating const_buffer objects from unbounded binary or+/// hexadecimal integer literals.+template <char... Chars>+inline ASIO_CONST_BUFFER operator"" _buf()+{+  return ASIO_CONST_BUFFER(+      +detail::literal<Chars...>::data,+      detail::literal<Chars...>::size);+}++} // namespace buffer_literals++#endif // (defined(ASIO_HAS_USER_DEFINED_LITERALS)+       //     && defined(ASIO_HAS_VARIADIC_TEMPLATES))+       //   || defined(GENERATING_DOCUMENTATION)  } // namespace asio 
+ link/modules/asio-standalone/asio/include/asio/buffer_registration.hpp view
@@ -0,0 +1,328 @@+//+// buffer_registration.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_BUFFER_REGISTRATION_HPP+#define ASIO_BUFFER_REGISTRATION_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <iterator>+#include <vector>+#include "asio/detail/memory.hpp"+#include "asio/execution/context.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution_context.hpp"+#include "asio/is_executor.hpp"+#include "asio/query.hpp"+#include "asio/registered_buffer.hpp"++#if defined(ASIO_HAS_IO_URING)+# include "asio/detail/scheduler.hpp"+# include "asio/detail/io_uring_service.hpp"+#endif // defined(ASIO_HAS_IO_URING)++#if defined(ASIO_HAS_MOVE)+# include <utility>+#endif // defined(ASIO_HAS_MOVE)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class buffer_registration_base+{+protected:+  static mutable_registered_buffer make_buffer(const mutable_buffer& b,+      const void* scope, int index) ASIO_NOEXCEPT+  {+    return mutable_registered_buffer(b, registered_buffer_id(scope, index));+  }+};++} // namespace detail++/// Automatically registers and unregistered buffers with an execution context.+/**+ * For portability, applications should assume that only one registration is+ * permitted per execution context.+ */+template <typename MutableBufferSequence,+    typename Allocator = std::allocator<void> >+class buffer_registration+  : detail::buffer_registration_base+{+public:+  /// The allocator type used for allocating storage for the buffers container.+  typedef Allocator allocator_type;++#if defined(GENERATING_DOCUMENTATION)+  /// The type of an iterator over the registered buffers.+  typedef unspecified iterator;++  /// The type of a const iterator over the registered buffers.+  typedef unspecified const_iterator;+#else // defined(GENERATING_DOCUMENTATION)+  typedef std::vector<mutable_registered_buffer>::const_iterator iterator;+  typedef std::vector<mutable_registered_buffer>::const_iterator const_iterator;+#endif // defined(GENERATING_DOCUMENTATION)++  /// Register buffers with an executor's execution context.+  template <typename Executor>+  buffer_registration(const Executor& ex,+      const MutableBufferSequence& buffer_sequence,+      const allocator_type& alloc = allocator_type(),+      typename constraint<+        is_executor<Executor>::value || execution::is_executor<Executor>::value+      >::type = 0)+    : buffer_sequence_(buffer_sequence),+      buffers_(+          ASIO_REBIND_ALLOC(allocator_type,+            mutable_registered_buffer)(alloc))+  {+    init_buffers(buffer_registration::get_context(ex),+        asio::buffer_sequence_begin(buffer_sequence_),+        asio::buffer_sequence_end(buffer_sequence_));+  }++  /// Register buffers with an execution context.+  template <typename ExecutionContext>+  buffer_registration(ExecutionContext& ctx,+      const MutableBufferSequence& buffer_sequence,+      const allocator_type& alloc = allocator_type(),+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value+      >::type = 0)+    : buffer_sequence_(buffer_sequence),+      buffers_(+          ASIO_REBIND_ALLOC(allocator_type,+            mutable_registered_buffer)(alloc))+  {+    init_buffers(ctx,+        asio::buffer_sequence_begin(buffer_sequence_),+        asio::buffer_sequence_end(buffer_sequence_));+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move constructor.+  buffer_registration(buffer_registration&& other) ASIO_NOEXCEPT+    : buffer_sequence_(std::move(other.buffer_sequence_)),+      buffers_(std::move(other.buffers_))+  {+#if defined(ASIO_HAS_IO_URING)+    service_ = other.service_;+    other.service_ = 0;+#endif // defined(ASIO_HAS_IO_URING)+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Unregisters the buffers.+  ~buffer_registration()+  {+#if defined(ASIO_HAS_IO_URING)+    if (service_)+      service_->unregister_buffers();+#endif // defined(ASIO_HAS_IO_URING)+  }+  +#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move assignment.+  buffer_registration& operator=(+      buffer_registration&& other) ASIO_NOEXCEPT+  {+    if (this != &other)+    {+      buffer_sequence_ = std::move(other.buffer_sequence_);+      buffers_ = std::move(other.buffers_);+#if defined(ASIO_HAS_IO_URING)+      if (service_)+        service_->unregister_buffers();+      service_ = other.service_;+      other.service_ = 0;+#endif // defined(ASIO_HAS_IO_URING)+    }+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Get the number of registered buffers.+  std::size_t size() const ASIO_NOEXCEPT+  {+    return buffers_.size();+  }++  /// Get the begin iterator for the sequence of registered buffers.+  const_iterator begin() const ASIO_NOEXCEPT+  {+    return buffers_.begin();+  }++  /// Get the begin iterator for the sequence of registered buffers.+  const_iterator cbegin() const ASIO_NOEXCEPT+  {+    return buffers_.cbegin();+  }++  /// Get the end iterator for the sequence of registered buffers.+  const_iterator end() const ASIO_NOEXCEPT+  {+    return buffers_.end();+  }++  /// Get the end iterator for the sequence of registered buffers.+  const_iterator cend() const ASIO_NOEXCEPT+  {+    return buffers_.cend();+  }++  /// Get the buffer at the specified index.+  const mutable_registered_buffer& operator[](std::size_t i) ASIO_NOEXCEPT+  {+    return buffers_[i];+  }++  /// Get the buffer at the specified index.+  const mutable_registered_buffer& at(std::size_t i) ASIO_NOEXCEPT+  {+    return buffers_.at(i);+  }++private:+  // Disallow copying and assignment.+  buffer_registration(const buffer_registration&) ASIO_DELETED;+  buffer_registration& operator=(const buffer_registration&) ASIO_DELETED;++  // Helper function to get an executor's context.+  template <typename T>+  static execution_context& get_context(const T& t,+      typename enable_if<execution::is_executor<T>::value>::type* = 0)+  {+    return asio::query(t, execution::context);+  }++  // Helper function to get an executor's context.+  template <typename T>+  static execution_context& get_context(const T& t,+      typename enable_if<!execution::is_executor<T>::value>::type* = 0)+  {+    return t.context();+  }++  // Helper function to initialise the container of buffers.+  template <typename Iterator>+  void init_buffers(execution_context& ctx, Iterator begin, Iterator end)+  {+    std::size_t n = std::distance(begin, end);+    buffers_.resize(n);++#if defined(ASIO_HAS_IO_URING)+    service_ = &use_service<detail::io_uring_service>(ctx);+    std::vector<iovec,+      ASIO_REBIND_ALLOC(allocator_type, iovec)> iovecs(n,+          ASIO_REBIND_ALLOC(allocator_type, iovec)(+            buffers_.get_allocator()));+#endif // defined(ASIO_HAS_IO_URING)++    Iterator iter = begin;+    for (int index = 0; iter != end; ++index, ++iter)+    {+      mutable_buffer b(*iter);+      std::size_t i = static_cast<std::size_t>(index);+      buffers_[i] = this->make_buffer(b, &ctx, index);++#if defined(ASIO_HAS_IO_URING)+      iovecs[i].iov_base = buffers_[i].data();+      iovecs[i].iov_len = buffers_[i].size();+#endif // defined(ASIO_HAS_IO_URING)+    }++#if defined(ASIO_HAS_IO_URING)+    if (n > 0)+    {+      service_->register_buffers(&iovecs[0],+          static_cast<unsigned>(iovecs.size()));+    }+#endif // defined(ASIO_HAS_IO_URING)+  }++  MutableBufferSequence buffer_sequence_;+  std::vector<mutable_registered_buffer,+    ASIO_REBIND_ALLOC(allocator_type,+      mutable_registered_buffer)> buffers_;+#if defined(ASIO_HAS_IO_URING)+  detail::io_uring_service* service_;+#endif // defined(ASIO_HAS_IO_URING)+};++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+/// Register buffers with an execution context.+template <typename Executor, typename MutableBufferSequence>+ASIO_NODISCARD inline+buffer_registration<MutableBufferSequence>+register_buffers(const Executor& ex,+    const MutableBufferSequence& buffer_sequence,+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type = 0)+{+  return buffer_registration<MutableBufferSequence>(ex, buffer_sequence);+}++/// Register buffers with an execution context.+template <typename Executor, typename MutableBufferSequence, typename Allocator>+ASIO_NODISCARD inline+buffer_registration<MutableBufferSequence, Allocator>+register_buffers(const Executor& ex,+    const MutableBufferSequence& buffer_sequence, const Allocator& alloc,+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type = 0)+{+  return buffer_registration<MutableBufferSequence, Allocator>(+      ex, buffer_sequence, alloc);+}++/// Register buffers with an execution context.+template <typename ExecutionContext, typename MutableBufferSequence>+ASIO_NODISCARD inline+buffer_registration<MutableBufferSequence>+register_buffers(ExecutionContext& ctx,+    const MutableBufferSequence& buffer_sequence,+    typename constraint<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type = 0)+{+  return buffer_registration<MutableBufferSequence>(ctx, buffer_sequence);+}++/// Register buffers with an execution context.+template <typename ExecutionContext,+    typename MutableBufferSequence, typename Allocator>+ASIO_NODISCARD inline+buffer_registration<MutableBufferSequence, Allocator>+register_buffers(ExecutionContext& ctx,+    const MutableBufferSequence& buffer_sequence, const Allocator& alloc,+    typename constraint<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type = 0)+{+  return buffer_registration<MutableBufferSequence, Allocator>(+      ctx, buffer_sequence, alloc);+}+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_BUFFER_REGISTRATION_HPP
link/modules/asio-standalone/asio/include/asio/buffered_read_stream.hpp view
@@ -2,7 +2,7 @@ // buffered_read_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,7 +30,13 @@ #include "asio/detail/push_options.hpp"  namespace asio {+namespace detail { +template <typename> class initiate_async_buffered_fill;+template <typename> class initiate_async_buffered_read_some;++} // namespace detail+ /// Adds buffering to the read-related operations of a stream. /**  * The buffered_read_stream class template can be used to add buffering to the@@ -66,16 +72,17 @@    /// Construct, passing the specified argument to initialise the next layer.   template <typename Arg>-  explicit buffered_read_stream(Arg& a)-    : next_layer_(a),+  explicit buffered_read_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a)+    : next_layer_(ASIO_MOVE_OR_LVALUE(Arg)(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),+  buffered_read_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a,+      std::size_t buffer_size)+    : next_layer_(ASIO_MOVE_OR_LVALUE(Arg)(a)),       storage_(buffer_size)   {   }@@ -136,15 +143,23 @@    /// Start an asynchronous write. The data being written must be valid for the   /// lifetime of the asynchronous operation.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) WriteHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(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))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      declval<typename conditional<true, Stream&, WriteHandler>::type>()+        .async_write_some(buffers,+          ASIO_MOVE_CAST(WriteHandler)(handler))))   {     return next_layer_.async_write_some(buffers,         ASIO_MOVE_CAST(WriteHandler)(handler));@@ -159,15 +174,24 @@   std::size_t fill(asio::error_code& ec);    /// Start an asynchronous fill.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) ReadHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler,       void (asio::error_code, std::size_t))   async_fill(       ASIO_MOVE_ARG(ReadHandler) handler-        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadHandler,+        void (asio::error_code, std::size_t)>(+          declval<detail::initiate_async_buffered_fill<Stream> >(),+          handler, declval<detail::buffered_stream_storage*>())));    /// Read some data from the stream. Returns the number of bytes read. Throws   /// an exception on failure.@@ -182,15 +206,24 @@    /// Start an asynchronous read. The buffer into which the data will be read   /// must be valid for the lifetime of the asynchronous operation.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) ReadHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(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));+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadHandler,+        void (asio::error_code, std::size_t)>(+          declval<detail::initiate_async_buffered_read_some<Stream> >(),+          handler, declval<detail::buffered_stream_storage*>(), buffers)));    /// Peek at the incoming data on the stream. Returns the number of bytes read.   /// Throws an exception on failure.
link/modules/asio-standalone/asio/include/asio/buffered_read_stream_fwd.hpp view
@@ -2,7 +2,7 @@ // buffered_read_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/buffered_stream.hpp view
@@ -2,7 +2,7 @@ // buffered_stream.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -56,17 +56,17 @@    /// Construct, passing the specified argument to initialise the next layer.   template <typename Arg>-  explicit buffered_stream(Arg& a)-    : inner_stream_impl_(a),+  explicit buffered_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a)+    : inner_stream_impl_(ASIO_MOVE_OR_LVALUE(Arg)(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),+  explicit buffered_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a,+      std::size_t read_buffer_size, std::size_t write_buffer_size)+    : inner_stream_impl_(ASIO_MOVE_OR_LVALUE(Arg)(a), write_buffer_size),       stream_impl_(inner_stream_impl_, read_buffer_size)   {   }@@ -125,15 +125,22 @@   }    /// Start an asynchronous flush.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) WriteHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler,       void (asio::error_code, std::size_t))   async_flush(       ASIO_MOVE_ARG(WriteHandler) handler         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      declval<buffered_write_stream<Stream>&>().async_flush(+          ASIO_MOVE_CAST(WriteHandler)(handler))))   {     return stream_impl_.next_layer().async_flush(         ASIO_MOVE_CAST(WriteHandler)(handler));@@ -158,15 +165,22 @@    /// Start an asynchronous write. The data being written must be valid for the   /// lifetime of the asynchronous operation.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) WriteHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(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))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      declval<Stream&>().async_write_some(buffers,+          ASIO_MOVE_CAST(WriteHandler)(handler))))   {     return stream_impl_.async_write_some(buffers,         ASIO_MOVE_CAST(WriteHandler)(handler));@@ -187,15 +201,23 @@   }    /// Start an asynchronous fill.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) ReadHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler,       void (asio::error_code, std::size_t))   async_fill(       ASIO_MOVE_ARG(ReadHandler) handler         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      declval<buffered_read_stream<+        buffered_write_stream<Stream> >&>().async_fill(+          ASIO_MOVE_CAST(ReadHandler)(handler))))   {     return stream_impl_.async_fill(ASIO_MOVE_CAST(ReadHandler)(handler));   }@@ -219,15 +241,22 @@    /// Start an asynchronous read. The buffer into which the data will be read   /// must be valid for the lifetime of the asynchronous operation.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) ReadHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(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))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      declval<Stream&>().async_read_some(buffers,+          ASIO_MOVE_CAST(ReadHandler)(handler))))   {     return stream_impl_.async_read_some(buffers,         ASIO_MOVE_CAST(ReadHandler)(handler));
link/modules/asio-standalone/asio/include/asio/buffered_stream_fwd.hpp view
@@ -2,7 +2,7 @@ // buffered_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/buffered_write_stream.hpp view
@@ -2,7 +2,7 @@ // buffered_write_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,7 +30,13 @@ #include "asio/detail/push_options.hpp"  namespace asio {+namespace detail { +template <typename> class initiate_async_buffered_flush;+template <typename> class initiate_async_buffered_write_some;++} // namespace detail+ /// Adds buffering to the write-related operations of a stream. /**  * The buffered_write_stream class template can be used to add buffering to the@@ -66,16 +72,17 @@    /// Construct, passing the specified argument to initialise the next layer.   template <typename Arg>-  explicit buffered_write_stream(Arg& a)-    : next_layer_(a),+  explicit buffered_write_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a)+    : next_layer_(ASIO_MOVE_OR_LVALUE(Arg)(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),+  buffered_write_stream(ASIO_MOVE_OR_LVALUE_ARG(Arg) a,+      std::size_t buffer_size)+    : next_layer_(ASIO_MOVE_OR_LVALUE(Arg)(a)),       storage_(buffer_size)   {   }@@ -128,15 +135,24 @@   std::size_t flush(asio::error_code& ec);    /// Start an asynchronous flush.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) WriteHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler,       void (asio::error_code, std::size_t))   async_flush(       ASIO_MOVE_ARG(WriteHandler) handler-        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type));+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteHandler,+        void (asio::error_code, std::size_t)>(+          declval<detail::initiate_async_buffered_flush<Stream> >(),+          handler, declval<detail::buffered_stream_storage*>())));    /// Write the given data to the stream. Returns the number of bytes written.   /// Throws an exception on failure.@@ -151,15 +167,24 @@    /// Start an asynchronous write. The data being written must be valid for the   /// lifetime of the asynchronous operation.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) WriteHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(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));+        ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteHandler,+        void (asio::error_code, std::size_t)>(+          declval<detail::initiate_async_buffered_write_some<Stream> >(),+          handler, declval<detail::buffered_stream_storage*>(), buffers)));    /// Read some data from the stream. Returns the number of bytes read. Throws   /// an exception on failure.@@ -180,15 +205,23 @@    /// Start an asynchronous read. The buffer into which the data will be read   /// must be valid for the lifetime of the asynchronous operation.+  /**+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,         std::size_t)) ReadHandler           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(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))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      declval<typename conditional<true, Stream&, ReadHandler>::type>()+        .async_read_some(buffers,+          ASIO_MOVE_CAST(ReadHandler)(handler))))   {     return next_layer_.async_read_some(buffers,         ASIO_MOVE_CAST(ReadHandler)(handler));
link/modules/asio-standalone/asio/include/asio/buffered_write_stream_fwd.hpp view
@@ -2,7 +2,7 @@ // buffered_write_stream_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/buffers_iterator.hpp view
@@ -2,7 +2,7 @@ // buffers_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/cancellation_signal.hpp view
@@ -0,0 +1,305 @@+//+// cancellation_signal.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CANCELLATION_SIGNAL_HPP+#define ASIO_CANCELLATION_SIGNAL_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <cassert>+#include <new>+#include <utility>+#include "asio/cancellation_type.hpp"+#include "asio/detail/cstddef.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class cancellation_handler_base+{+public:+  virtual void call(cancellation_type_t) = 0;+  virtual std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT = 0;++protected:+  ~cancellation_handler_base() {}+};++template <typename Handler>+class cancellation_handler+  : public cancellation_handler_base+{+public:+#if defined(ASIO_HAS_VARIADIC_TEMPLATES)+  template <typename... Args>+  cancellation_handler(std::size_t size, ASIO_MOVE_ARG(Args)... args)+    : handler_(ASIO_MOVE_CAST(Args)(args)...),+      size_(size)+  {+  }+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+  cancellation_handler(std::size_t size)+    : handler_(),+      size_(size)+  {+  }++#define ASIO_PRIVATE_HANDLER_CTOR_DEF(n) \+  template <ASIO_VARIADIC_TPARAMS(n)> \+  cancellation_handler(std::size_t size, ASIO_VARIADIC_MOVE_PARAMS(n)) \+    : handler_(ASIO_VARIADIC_MOVE_ARGS(n)), \+      size_(size) \+  { \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_CTOR_DEF)+#undef ASIO_PRIVATE_HANDLER_CTOR_DEF+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  void call(cancellation_type_t type)+  {+    handler_(type);+  }++  std::pair<void*, std::size_t> destroy() ASIO_NOEXCEPT+  {+    std::pair<void*, std::size_t> mem(this, size_);+    this->cancellation_handler::~cancellation_handler();+    return mem;+  }++  Handler& handler() ASIO_NOEXCEPT+  {+    return handler_;+  }++private:+  ~cancellation_handler()+  {+  }++  Handler handler_;+  std::size_t size_;+};++} // namespace detail++class cancellation_slot;++/// A cancellation signal with a single slot.+class cancellation_signal+{+public:+  ASIO_CONSTEXPR cancellation_signal()+    : handler_(0)+  {+  }++  ASIO_DECL ~cancellation_signal();++  /// Emits the signal and causes invocation of the slot's handler, if any.+  void emit(cancellation_type_t type)+  {+    if (handler_)+      handler_->call(type);+  }++  /// Returns the single slot associated with the signal.+  /**+   * The signal object must remain valid for as long the slot may be used.+   * Destruction of the signal invalidates the slot.+   */+  cancellation_slot slot() ASIO_NOEXCEPT;++private:+  cancellation_signal(const cancellation_signal&) ASIO_DELETED;+  cancellation_signal& operator=(const cancellation_signal&) ASIO_DELETED;++  detail::cancellation_handler_base* handler_;+};++/// A slot associated with a cancellation signal.+class cancellation_slot+{+public:+  /// Creates a slot that is not connected to any cancellation signal.+  ASIO_CONSTEXPR cancellation_slot()+    : handler_(0)+  {+  }++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  || defined(GENERATING_DOCUMENTATION)+  /// Installs a handler into the slot, constructing the new object directly.+  /**+   * Destroys any existing handler in the slot, then installs the new handler,+   * constructing it with the supplied @c args.+   *+   * The handler is a function object to be called when the signal is emitted.+   * The signature of the handler must be+   * @code void handler(asio::cancellation_type_t); @endcode+   *+   * @param args Arguments to be passed to the @c CancellationHandler object's+   * constructor.+   *+   * @returns A reference to the newly installed handler.+   *+   * @note Handlers installed into the slot via @c emplace are not required to+   * be copy constructible or move constructible.+   */+  template <typename CancellationHandler, typename... Args>+  CancellationHandler& emplace(ASIO_MOVE_ARG(Args)... args)+  {+    typedef detail::cancellation_handler<CancellationHandler>+      cancellation_handler_type;+    auto_delete_helper del = { prepare_memory(+        sizeof(cancellation_handler_type),+        ASIO_ALIGNOF(CancellationHandler)) };+    cancellation_handler_type* handler_obj =+      new (del.mem.first) cancellation_handler_type(+        del.mem.second, ASIO_MOVE_CAST(Args)(args)...);+    del.mem.first = 0;+    *handler_ = handler_obj;+    return handler_obj->handler();+  }+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)+      //   || defined(GENERATING_DOCUMENTATION)+  template <typename CancellationHandler>+  CancellationHandler& emplace()+  {+    typedef detail::cancellation_handler<CancellationHandler>+      cancellation_handler_type;+    auto_delete_helper del = { prepare_memory(+        sizeof(cancellation_handler_type),+        ASIO_ALIGNOF(CancellationHandler)) };+    cancellation_handler_type* handler_obj =+      new (del.mem.first) cancellation_handler_type(del.mem.second);+    del.mem.first = 0;+    *handler_ = handler_obj;+    return handler_obj->handler();+  }++#define ASIO_PRIVATE_HANDLER_EMPLACE_DEF(n) \+  template <typename CancellationHandler, ASIO_VARIADIC_TPARAMS(n)> \+  CancellationHandler& emplace(ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    typedef detail::cancellation_handler<CancellationHandler> \+      cancellation_handler_type; \+    auto_delete_helper del = { prepare_memory( \+        sizeof(cancellation_handler_type), \+        ASIO_ALIGNOF(CancellationHandler)) }; \+    cancellation_handler_type* handler_obj = \+      new (del.mem.first) cancellation_handler_type( \+        del.mem.second, ASIO_VARIADIC_MOVE_ARGS(n)); \+    del.mem.first = 0; \+    *handler_ = handler_obj; \+    return handler_obj->handler(); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_HANDLER_EMPLACE_DEF)+#undef ASIO_PRIVATE_HANDLER_EMPLACE_DEF+#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  /// Installs a handler into the slot.+  /**+   * Destroys any existing handler in the slot, then installs the new handler,+   * constructing it as a decay-copy of the supplied handler.+   *+   * The handler is a function object to be called when the signal is emitted.+   * The signature of the handler must be+   * @code void handler(asio::cancellation_type_t); @endcode+   *+   * @param handler The handler to be installed.+   *+   * @returns A reference to the newly installed handler.+   */+  template <typename CancellationHandler>+  typename decay<CancellationHandler>::type& assign(+      ASIO_MOVE_ARG(CancellationHandler) handler)+  {+    return this->emplace<typename decay<CancellationHandler>::type>(+        ASIO_MOVE_CAST(CancellationHandler)(handler));+  }++  /// Clears the slot.+  /**+   * Destroys any existing handler in the slot.+   */+  ASIO_DECL void clear();++  /// Returns whether the slot is connected to a signal.+  ASIO_CONSTEXPR bool is_connected() const ASIO_NOEXCEPT+  {+    return handler_ != 0;+  }++  /// Returns whether the slot is connected and has an installed handler.+  ASIO_CONSTEXPR bool has_handler() const ASIO_NOEXCEPT+  {+    return handler_ != 0 && *handler_ != 0;+  }++  /// Compare two slots for equality.+  friend ASIO_CONSTEXPR bool operator==(const cancellation_slot& lhs,+      const cancellation_slot& rhs) ASIO_NOEXCEPT+  {+    return lhs.handler_ == rhs.handler_;+  }++  /// Compare two slots for inequality.+  friend ASIO_CONSTEXPR bool operator!=(const cancellation_slot& lhs,+      const cancellation_slot& rhs) ASIO_NOEXCEPT+  {+    return lhs.handler_ != rhs.handler_;+  }++private:+  friend class cancellation_signal;++  ASIO_CONSTEXPR cancellation_slot(int,+      detail::cancellation_handler_base** handler)+    : handler_(handler)+  {+  }++  ASIO_DECL std::pair<void*, std::size_t> prepare_memory(+      std::size_t size, std::size_t align);++  struct auto_delete_helper+  {+    std::pair<void*, std::size_t> mem;++    ASIO_DECL ~auto_delete_helper();+  };++  detail::cancellation_handler_base** handler_;+};++inline cancellation_slot cancellation_signal::slot() ASIO_NOEXCEPT+{+  return cancellation_slot(0, &handler_);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/cancellation_signal.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_CANCELLATION_SIGNAL_HPP
+ link/modules/asio-standalone/asio/include/asio/cancellation_state.hpp view
@@ -0,0 +1,235 @@+//+// cancellation_state.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CANCELLATION_STATE_HPP+#define ASIO_CANCELLATION_STATE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <cassert>+#include <new>+#include <utility>+#include "asio/cancellation_signal.hpp"+#include "asio/detail/cstddef.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// A simple cancellation signal propagation filter.+template <cancellation_type_t Mask>+struct cancellation_filter+{+  /// Returns <tt>type & Mask</tt>.+  cancellation_type_t operator()(+      cancellation_type_t type) const ASIO_NOEXCEPT+  {+    return type & Mask;+  }+};++/// A cancellation filter that disables cancellation.+typedef cancellation_filter<cancellation_type::none>+  disable_cancellation;++/// A cancellation filter that enables terminal cancellation only.+typedef cancellation_filter<cancellation_type::terminal>+  enable_terminal_cancellation;++#if defined(GENERATING_DOCUMENTATION)++/// A cancellation filter that enables terminal and partial cancellation.+typedef cancellation_filter<+    cancellation_type::terminal | cancellation_type::partial>+  enable_partial_cancellation;++/// A cancellation filter that enables terminal, partial and total cancellation.+typedef cancellation_filter<cancellation_type::terminal+    | cancellation_type::partial | cancellation_type::total>+  enable_total_cancellation;++#else // defined(GENERATING_DOCUMENTATION)++typedef cancellation_filter<+    static_cast<cancellation_type_t>(+      static_cast<unsigned int>(cancellation_type::terminal)+        | static_cast<unsigned int>(cancellation_type::partial))>+  enable_partial_cancellation;++typedef cancellation_filter<+    static_cast<cancellation_type_t>(+      static_cast<unsigned int>(cancellation_type::terminal)+        | static_cast<unsigned int>(cancellation_type::partial)+        | static_cast<unsigned int>(cancellation_type::total))>+  enable_total_cancellation;++#endif // defined(GENERATING_DOCUMENTATION)++/// A cancellation state is used for chaining signals and slots in compositions.+class cancellation_state+{+public:+  /// Construct a disconnected cancellation state.+  ASIO_CONSTEXPR cancellation_state() ASIO_NOEXCEPT+    : impl_(0)+  {+  }++  /// Construct and attach to a parent slot to create a new child slot.+  /**+   * Initialises the cancellation state so that it allows terminal cancellation+   * only. Equivalent to <tt>cancellation_state(slot,+   * enable_terminal_cancellation())</tt>.+   *+   * @param slot The parent cancellation slot to which the state will be+   * attached.+   */+  template <typename CancellationSlot>+  ASIO_CONSTEXPR explicit cancellation_state(CancellationSlot slot)+    : impl_(slot.is_connected() ? &slot.template emplace<impl<> >() : 0)+  {+  }++  /// Construct and attach to a parent slot to create a new child slot.+  /**+   * @param slot The parent cancellation slot to which the state will be+   * attached.+   *+   * @param filter A function object that is used to transform incoming+   * cancellation signals as they are received from the parent slot. This+   * function object must have the signature:+   * @code asio::cancellation_type_t filter(+   *     asio::cancellation_type_t); @endcode+   *+   * The library provides the following pre-defined cancellation filters:+   *+   * @li asio::disable_cancellation+   * @li asio::enable_terminal_cancellation+   * @li asio::enable_partial_cancellation+   * @li asio::enable_total_cancellation+   */+  template <typename CancellationSlot, typename Filter>+  ASIO_CONSTEXPR cancellation_state(CancellationSlot slot, Filter filter)+    : impl_(slot.is_connected()+        ? &slot.template emplace<impl<Filter, Filter> >(filter, filter)+        : 0)+  {+  }++  /// Construct and attach to a parent slot to create a new child slot.+  /**+   * @param slot The parent cancellation slot to which the state will be+   * attached.+   *+   * @param in_filter A function object that is used to transform incoming+   * cancellation signals as they are received from the parent slot. This+   * function object must have the signature:+   * @code asio::cancellation_type_t in_filter(+   *     asio::cancellation_type_t); @endcode+   *+   * @param out_filter A function object that is used to transform outcoming+   * cancellation signals as they are relayed to the child slot. This function+   * object must have the signature:+   * @code asio::cancellation_type_t out_filter(+   *     asio::cancellation_type_t); @endcode+   *+   * The library provides the following pre-defined cancellation filters:+   *+   * @li asio::disable_cancellation+   * @li asio::enable_terminal_cancellation+   * @li asio::enable_partial_cancellation+   * @li asio::enable_total_cancellation+   */+  template <typename CancellationSlot, typename InFilter, typename OutFilter>+  ASIO_CONSTEXPR cancellation_state(CancellationSlot slot,+      InFilter in_filter, OutFilter out_filter)+    : impl_(slot.is_connected()+        ? &slot.template emplace<impl<InFilter, OutFilter> >(+            ASIO_MOVE_CAST(InFilter)(in_filter),+            ASIO_MOVE_CAST(OutFilter)(out_filter))+        : 0)+  {+  }++  /// Returns the single child slot associated with the state.+  /**+   * This sub-slot is used with the operations that are being composed.+   */+  ASIO_CONSTEXPR cancellation_slot slot() const ASIO_NOEXCEPT+  {+    return impl_ ? impl_->signal_.slot() : cancellation_slot();+  }++  /// Returns the cancellation types that have been triggered.+  cancellation_type_t cancelled() const ASIO_NOEXCEPT+  {+    return impl_ ? impl_->cancelled_ : cancellation_type_t();+  }++  /// Clears the specified cancellation types, if they have been triggered.+  void clear(cancellation_type_t mask = cancellation_type::all)+    ASIO_NOEXCEPT+  {+    if (impl_)+      impl_->cancelled_ &= ~mask;+  }++private:+  struct impl_base+  {+    impl_base()+      : cancelled_()+    {+    }++    cancellation_signal signal_;+    cancellation_type_t cancelled_;+  };++  template <+      typename InFilter = enable_terminal_cancellation,+      typename OutFilter = InFilter>+  struct impl : impl_base+  {+    impl()+      : in_filter_(),+        out_filter_()+    {+    }++    impl(InFilter in_filter, OutFilter out_filter)+      : in_filter_(ASIO_MOVE_CAST(InFilter)(in_filter)),+        out_filter_(ASIO_MOVE_CAST(OutFilter)(out_filter))+    {+    }++    void operator()(cancellation_type_t in)+    {+      this->cancelled_ = in_filter_(in);+      cancellation_type_t out = out_filter_(this->cancelled_);+      if (out != cancellation_type::none)+        this->signal_.emit(out);+    }++    InFilter in_filter_;+    OutFilter out_filter_;+  };++  impl_base* impl_;+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_CANCELLATION_STATE_HPP
+ link/modules/asio-standalone/asio/include/asio/cancellation_type.hpp view
@@ -0,0 +1,174 @@+//+// cancellation_type.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CANCELLATION_TYPE_HPP+#define ASIO_CANCELLATION_TYPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++# if defined(GENERATING_DOCUMENTATION)++/// Enumeration representing the different types of cancellation that may+/// be requested from or implemented by an asynchronous operation.+enum cancellation_type+{+  /// Bitmask representing no types of cancellation.+  none = 0,++  /// Requests cancellation where, following a successful cancellation, the only+  /// safe operations on the I/O object are closure or destruction.+  terminal = 1,++  /// Requests cancellation where a successful cancellation may result in+  /// partial side effects or no side effects. Following cancellation, the I/O+  /// object is in a well-known state, and may be used for further operations.+  partial = 2,++  /// Requests cancellation where a successful cancellation results in no+  /// apparent side effects. Following cancellation, the I/O object is in the+  /// same observable state as it was prior to the operation.+  total = 4,++  /// Bitmask representing all types of cancellation.+  all = 0xFFFFFFFF+};++/// Portability typedef.+typedef cancellation_type cancellation_type_t;++#elif defined(ASIO_HAS_ENUM_CLASS)++enum class cancellation_type : unsigned int+{+  none = 0,+  terminal = 1,+  partial = 2,+  total = 4,+  all = 0xFFFFFFFF+};++typedef cancellation_type cancellation_type_t;++#else // defined(ASIO_HAS_ENUM_CLASS)++namespace cancellation_type {++enum cancellation_type_t+{+  none = 0,+  terminal = 1,+  partial = 2,+  total = 4,+  all = 0xFFFFFFFF+};++} // namespace cancellation_type++typedef cancellation_type::cancellation_type_t cancellation_type_t;++#endif // defined(ASIO_HAS_ENUM_CLASS)++/// Negation operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR bool operator!(cancellation_type_t x)+{+  return static_cast<unsigned int>(x) == 0;+}++/// Bitwise and operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR cancellation_type_t operator&(+    cancellation_type_t x, cancellation_type_t y)+{+  return static_cast<cancellation_type_t>(+      static_cast<unsigned int>(x) & static_cast<unsigned int>(y));+}++/// Bitwise or operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR cancellation_type_t operator|(+    cancellation_type_t x, cancellation_type_t y)+{+  return static_cast<cancellation_type_t>(+      static_cast<unsigned int>(x) | static_cast<unsigned int>(y));+}++/// Bitwise xor operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR cancellation_type_t operator^(+    cancellation_type_t x, cancellation_type_t y)+{+  return static_cast<cancellation_type_t>(+      static_cast<unsigned int>(x) ^ static_cast<unsigned int>(y));+}++/// Bitwise negation operator.+/**+ * @relates cancellation_type+ */+inline ASIO_CONSTEXPR cancellation_type_t operator~(cancellation_type_t x)+{+  return static_cast<cancellation_type_t>(~static_cast<unsigned int>(x));+}++/// Bitwise and-assignment operator.+/**+ * @relates cancellation_type+ */+inline cancellation_type_t& operator&=(+    cancellation_type_t& x, cancellation_type_t y)+{+  x = x & y;+  return x;+}++/// Bitwise or-assignment operator.+/**+ * @relates cancellation_type+ */+inline cancellation_type_t& operator|=(+    cancellation_type_t& x, cancellation_type_t y)+{+  x = x | y;+  return x;+}++/// Bitwise xor-assignment operator.+/**+ * @relates cancellation_type+ */+inline cancellation_type_t& operator^=(+    cancellation_type_t& x, cancellation_type_t y)+{+  x = x ^ y;+  return x;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_CANCELLATION_TYPE_HPP
link/modules/asio-standalone/asio/include/asio/co_spawn.hpp view
@@ -2,7 +2,7 @@ // co_spawn.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -54,11 +54,14 @@  * @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+ * @param token The @ref completion_token that will handle the notification that  * the thread of execution has completed. The function signature of the  * completion handler must be:  * @code void handler(std::exception_ptr, T); @endcode  *+ * @par Completion Signature+ * @code void(std::exception_ptr, T) @endcode+ *  * @par Example  * @code  * asio::awaitable<std::size_t> echo(tcp::socket socket)@@ -95,6 +98,11 @@  *     std::cout << "transferred " << n << "\n";  *   });  * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state.  */ template <typename Executor, typename T, typename AwaitableExecutor,     ASIO_COMPLETION_TOKEN_FOR(@@ -105,10 +113,10 @@ co_spawn(const Executor& ex, awaitable<T, AwaitableExecutor> a,     CompletionToken&& token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<+    typename constraint<       (is_executor<Executor>::value || execution::is_executor<Executor>::value)         && is_convertible<Executor, AwaitableExecutor>::value-    >::type* = 0);+    >::type = 0);  /// Spawn a new coroutined-based thread of execution. /**@@ -118,11 +126,14 @@  * @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+ * @param token The @ref completion_token that will handle the notification that  * the thread of execution has completed. The function signature of the  * completion handler must be:  * @code void handler(std::exception_ptr); @endcode  *+ * @par Completion Signature+ * @code void(std::exception_ptr) @endcode+ *  * @par Example  * @code  * asio::awaitable<void> echo(tcp::socket socket)@@ -151,6 +162,11 @@  *   echo(std::move(my_tcp_socket)),  *   asio::detached);  * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state.  */ template <typename Executor, typename AwaitableExecutor,     ASIO_COMPLETION_TOKEN_FOR(@@ -161,10 +177,10 @@ co_spawn(const Executor& ex, awaitable<void, AwaitableExecutor> a,     CompletionToken&& token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<+    typename constraint<       (is_executor<Executor>::value || execution::is_executor<Executor>::value)         && is_convertible<Executor, AwaitableExecutor>::value-    >::type* = 0);+    >::type = 0);  /// Spawn a new coroutined-based thread of execution. /**@@ -174,11 +190,14 @@  * @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+ * @param token The @ref completion_token that will handle the notification that  * the thread of execution has completed. The function signature of the  * completion handler must be:  * @code void handler(std::exception_ptr); @endcode  *+ * @par Completion Signature+ * @code void(std::exception_ptr, T) @endcode+ *  * @par Example  * @code  * asio::awaitable<std::size_t> echo(tcp::socket socket)@@ -215,6 +234,11 @@  *     std::cout << "transferred " << n << "\n";  *   });  * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state.  */ template <typename ExecutionContext, typename T, typename AwaitableExecutor,     ASIO_COMPLETION_TOKEN_FOR(@@ -227,11 +251,11 @@     CompletionToken&& token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename ExecutionContext::executor_type),-    typename enable_if<+    typename constraint<       is_convertible<ExecutionContext&, execution_context&>::value         && is_convertible<typename ExecutionContext::executor_type,           AwaitableExecutor>::value-    >::type* = 0);+    >::type = 0);  /// Spawn a new coroutined-based thread of execution. /**@@ -241,11 +265,14 @@  * @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+ * @param token The @ref completion_token that will handle the notification that  * the thread of execution has completed. The function signature of the  * completion handler must be:  * @code void handler(std::exception_ptr); @endcode  *+ * @par Completion Signature+ * @code void(std::exception_ptr) @endcode+ *  * @par Example  * @code  * asio::awaitable<void> echo(tcp::socket socket)@@ -274,6 +301,11 @@  *   echo(std::move(my_tcp_socket)),  *   asio::detached);  * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state.  */ template <typename ExecutionContext, typename AwaitableExecutor,     ASIO_COMPLETION_TOKEN_FOR(@@ -286,11 +318,11 @@     CompletionToken&& token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename ExecutionContext::executor_type),-    typename enable_if<+    typename constraint<       is_convertible<ExecutionContext&, execution_context&>::value         && is_convertible<typename ExecutionContext::executor_type,           AwaitableExecutor>::value-    >::type* = 0);+    >::type = 0);  /// Spawn a new coroutined-based thread of execution. /**@@ -301,14 +333,19 @@  * @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+ * @param token The @ref completion_token that will handle the notification+ * that the thread of execution has completed. If @c R is @c void, the function  * signature of the completion handler must be:  *  * @code void handler(std::exception_ptr); @endcode  * Otherwise, the function signature of the completion handler must be:  * @code void handler(std::exception_ptr, R); @endcode  *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the first template argument to the @c awaitable returned by the+ * supplied function object @c F:+ * @code asio::awaitable<R, AwaitableExecutor> F() @endcode  *  * @par Example  * @code@@ -361,6 +398,11 @@  *     }  *   }, asio::detached);  * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state.  */ template <typename Executor, typename F,     ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<@@ -371,9 +413,9 @@ co_spawn(const Executor& ex, F&& f,     CompletionToken&& token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<+    typename constraint<       is_executor<Executor>::value || execution::is_executor<Executor>::value-    >::type* = 0);+    >::type = 0);  /// Spawn a new coroutined-based thread of execution. /**@@ -384,14 +426,19 @@  * @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+ * @param token The @ref completion_token that will handle the notification+ * that the thread of execution has completed. If @c R is @c void, the function  * signature of the completion handler must be:  *  * @code void handler(std::exception_ptr); @endcode  * Otherwise, the function signature of the completion handler must be:  * @code void handler(std::exception_ptr, R); @endcode  *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the first template argument to the @c awaitable returned by the+ * supplied function object @c F:+ * @code asio::awaitable<R, AwaitableExecutor> F() @endcode  *  * @par Example  * @code@@ -444,6 +491,11 @@  *     }  *   }, asio::detached);  * @endcode+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call asio::this_coro::reset_cancellation_state.  */ template <typename ExecutionContext, typename F,     ASIO_COMPLETION_TOKEN_FOR(typename detail::awaitable_signature<@@ -456,9 +508,9 @@     CompletionToken&& token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename ExecutionContext::executor_type),-    typename enable_if<+    typename constraint<       is_convertible<ExecutionContext&, execution_context&>::value-    >::type* = 0);+    >::type = 0);  } // namespace asio 
link/modules/asio-standalone/asio/include/asio/completion_condition.hpp view
@@ -2,7 +2,7 @@ // completion_condition.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/compose.hpp view
@@ -2,7 +2,7 @@ // compose.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,12 +16,308 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"+#include "asio/associated_executor.hpp" #include "asio/async_result.hpp"+#include "asio/detail/base_from_cancellation_state.hpp"+#include "asio/detail/composed_work.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/detail/push_options.hpp"  namespace asio {+namespace detail { +#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 base_from_cancellation_state<Handler>+{+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)+    : base_from_cancellation_state<Handler>(+        handler, enable_terminal_cancellation()),+      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)+    : base_from_cancellation_state<Handler>(+        ASIO_MOVE_CAST(base_from_cancellation_state<+          Handler>)(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 composed_work_guard<+    typename Work::head_type>::executor_type io_executor_type;++  io_executor_type get_io_executor() const ASIO_NOEXCEPT+  {+    return work_.head_.get_executor();+  }++  typedef typename associated_executor<Handler, io_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_;+    this->get_cancellation_state().slot().clear();+    impl_(*this, ASIO_MOVE_CAST(T)(t)...);+  }++  void complete(Args... args)+  {+    this->work_.reset();+    ASIO_MOVE_OR_LVALUE(Handler)(this->handler_)(+        ASIO_MOVE_CAST(Args)(args)...);+  }++#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  void operator()()+  {+    if (invocations_ < ~0u)+      ++invocations_;+    this->get_cancellation_state().slot().clear();+    impl_(*this);+  }++  void complete()+  {+    this->work_.reset();+    ASIO_MOVE_OR_LVALUE(Handler)(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_; \+    this->get_cancellation_state().slot().clear(); \+    impl_(*this, ASIO_VARIADIC_MOVE_ARGS(n)); \+  } \+  \+  template<ASIO_VARIADIC_TPARAMS(n)> \+  void complete(ASIO_VARIADIC_MOVE_PARAMS(n)) \+  { \+    this->work_.reset(); \+    ASIO_MOVE_OR_LVALUE(Handler)(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)++  void reset_cancellation_state()+  {+    base_from_cancellation_state<Handler>::reset_cancellation_state(handler_);+  }++  template <typename Filter>+  void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter)+  {+    base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,+        ASIO_MOVE_CAST(Filter)(filter));+  }++  template <typename InFilter, typename OutFilter>+  void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter,+      ASIO_MOVE_ARG(OutFilter) out_filter)+  {+    base_from_cancellation_state<Handler>::reset_cancellation_state(handler_,+        ASIO_MOVE_CAST(InFilter)(in_filter),+        ASIO_MOVE_CAST(OutFilter)(out_filter));+  }++  cancellation_type_t cancelled() const ASIO_NOEXCEPT+  {+    return base_from_cancellation_state<Handler>::cancelled();+  }++//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));+}++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <template <typename, typename> class Associator,+    typename Impl, typename Work, typename Handler,+    typename Signature, typename DefaultCandidate>+struct associator<Associator,+    detail::composed_op<Impl, Work, Handler, Signature>,+    DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::composed_op<Impl, Work, Handler, Signature>& h)+    ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::composed_op<Impl, Work, Handler, Signature>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)+ #if defined(ASIO_HAS_VARIADIC_TEMPLATES) \   || defined(GENERATING_DOCUMENTATION) @@ -37,7 +333,7 @@  * 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@@ -87,9 +383,11 @@  * 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+ *   decltype(+ *     asio::async_compose<CompletionToken,+ *       void(asio::error_code, std::size_t)>(+ *         std::declval<async_echo_implementation>(),+ *         token, socket))  * {  *   return asio::async_compose<CompletionToken,  *     void(asio::error_code, std::size_t)>(@@ -100,37 +398,134 @@  */ template <typename CompletionToken, typename Signature,     typename Implementation, typename... IoObjectsOrExecutors>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, Signature) async_compose(ASIO_MOVE_ARG(Implementation) implementation,     ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token,-    ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors);+    ASIO_MOVE_ARG(IoObjectsOrExecutors)... io_objects_or_executors)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    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))))+{+  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)       //   || defined(GENERATING_DOCUMENTATION)  template <typename CompletionToken, typename Signature, typename Implementation>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, Signature)+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, Signature) async_compose(ASIO_MOVE_ARG(Implementation) implementation,-    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token);+    ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken, Signature>(+        detail::make_initiate_composed_op<Signature>(+          detail::make_composed_io_executors()),+        token, ASIO_MOVE_CAST(Implementation)(implementation))))+{+  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) \+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, Signature) \   async_compose(ASIO_MOVE_ARG(Implementation) implementation, \       ASIO_NONDEDUCED_MOVE_ARG(CompletionToken) token, \-      ASIO_VARIADIC_MOVE_PARAMS(n));+      ASIO_VARIADIC_MOVE_PARAMS(n)) \+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX(( \+      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)))) \+  { \+    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)        //   || 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
@@ -2,7 +2,7 @@ // connect.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -27,6 +27,10 @@  namespace detail {+  struct default_connect_condition;+  template <typename, typename> class initiate_async_range_connect;+  template <typename, typename> class initiate_async_iterator_connect;+   char (&has_iterator_helper(...))[2];    template <typename T>@@ -90,8 +94,8 @@ 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);+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type = 0);  /// Establishes a socket connection by trying each endpoint in a sequence. /**@@ -126,8 +130,8 @@ 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);+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type = 0);  #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Establishes a socket connection by trying@@ -156,7 +160,7 @@  */ 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);+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0);  /// (Deprecated: Use range overload.) Establishes a socket connection by trying /// each endpoint in a sequence.@@ -185,7 +189,7 @@ 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);+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); #endif // !defined(ASIO_NO_DEPRECATED)  /// Establishes a socket connection by trying each endpoint in a sequence.@@ -311,8 +315,8 @@     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);+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type = 0);  /// Establishes a socket connection by trying each endpoint in a sequence. /**@@ -379,8 +383,8 @@ 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);+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type = 0);  #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Establishes a socket connection by trying@@ -422,7 +426,7 @@     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);+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0);  /// (Deprecated: Use range overload.) Establishes a socket connection by trying /// each endpoint in a sequence.@@ -463,7 +467,7 @@     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);+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0); #endif // !defined(ASIO_NO_DEPRECATED)  /// Establishes a socket connection by trying each endpoint in a sequence.@@ -610,16 +614,19 @@  * 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.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately.  *  * @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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation. if the sequence is empty, set to  *   // asio::error::not_found. Otherwise, contains the@@ -631,10 +638,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, typename Protocol::endpoint) @endcode+ *  * @par Example  * @code tcp::resolver r(my_context);  * tcp::resolver::query q("host", "service");@@ -664,19 +674,34 @@  * {  *   // ...  * } @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation.  */ template <typename Protocol, typename Executor, typename EndpointSequence,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      typename Protocol::endpoint)) RangeConnectHandler+      typename Protocol::endpoint)) RangeConnectToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken,     void (asio::error_code, typename Protocol::endpoint)) async_connect(basic_socket<Protocol, Executor>& s,     const EndpointSequence& endpoints,-    ASIO_MOVE_ARG(RangeConnectHandler) handler+    ASIO_MOVE_ARG(RangeConnectToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<is_endpoint_sequence<-        EndpointSequence>::value>::type* = 0);+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<RangeConnectToken,+      void (asio::error_code, typename Protocol::endpoint)>(+        declval<detail::initiate_async_range_connect<Protocol, Executor> >(),+        token, endpoints, declval<detail::default_connect_condition>())));  #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Asynchronously establishes a socket@@ -685,16 +710,19 @@  * 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.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately.  *  * @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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation. if the sequence is empty, set to  *   // asio::error::not_found. Otherwise, contains the@@ -706,24 +734,43 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, Iterator) @endcode+ *  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation.  */ template <typename Protocol, typename Executor, typename Iterator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      Iterator)) IteratorConnectHandler+      Iterator)) IteratorConnectToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,     void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,-    ASIO_MOVE_ARG(IteratorConnectHandler) handler+    ASIO_MOVE_ARG(IteratorConnectToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<IteratorConnectToken,+      void (asio::error_code, Iterator)>(+        declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+        token, begin, Iterator(),+        declval<detail::default_connect_condition>()))); #endif // !defined(ASIO_NO_DEPRECATED)  /// Asynchronously establishes a socket connection by trying each endpoint in a@@ -732,7 +779,8 @@  * 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.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately.  *  * @param s The socket to be connected. If the socket is already open, it will  * be closed.@@ -741,9 +789,11 @@  *  * @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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation. if the sequence is empty, set to  *   // asio::error::not_found. Otherwise, contains the@@ -755,10 +805,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, Iterator) @endcode+ *  * @par Example  * @code std::vector<tcp::endpoint> endpoints = ...;  * tcp::socket s(my_context);@@ -774,16 +827,31 @@  * {  *   // ...  * } @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation.  */ template <typename Protocol, typename Executor, typename Iterator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      Iterator)) IteratorConnectHandler+      Iterator)) IteratorConnectToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,     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));+    ASIO_MOVE_ARG(IteratorConnectToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<IteratorConnectToken,+      void (asio::error_code, Iterator)>(+        declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+        token, begin, end, declval<detail::default_connect_condition>())));  /// Asynchronously establishes a socket connection by trying each endpoint in a /// sequence.@@ -791,7 +859,8 @@  * 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.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately.  *  * @param s The socket to be connected. If the socket is already open, it will  * be closed.@@ -809,9 +878,11 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation. if the sequence is empty, set to  *   // asio::error::not_found. Otherwise, contains the@@ -823,10 +894,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, typename Protocol::endpoint) @endcode+ *  * @par Example  * The following connect condition function object can be used to output  * information about the individual connection attempts:@@ -879,20 +953,35 @@  *     std::cout << "Connected to: " << endpoint << std::endl;  *   }  * } @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation.  */ template <typename Protocol, typename Executor,     typename EndpointSequence, typename ConnectCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      typename Protocol::endpoint)) RangeConnectHandler+      typename Protocol::endpoint)) RangeConnectToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(RangeConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken,     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_MOVE_ARG(RangeConnectToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<is_endpoint_sequence<-        EndpointSequence>::value>::type* = 0);+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<RangeConnectToken,+      void (asio::error_code, typename Protocol::endpoint)>(+        declval<detail::initiate_async_range_connect<Protocol, Executor> >(),+        token, endpoints, connect_condition)));  #if !defined(ASIO_NO_DEPRECATED) /// (Deprecated: Use range overload.) Asynchronously establishes a socket@@ -901,7 +990,8 @@  * 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.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately.  *  * @param s The socket to be connected. If the socket is already open, it will  * be closed.@@ -919,9 +1009,11 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation. if the sequence is empty, set to  *   // asio::error::not_found. Otherwise, contains the@@ -933,26 +1025,44 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, Iterator) @endcode+ *  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation.  */ template <typename Protocol, typename Executor,     typename Iterator, typename ConnectCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      Iterator)) IteratorConnectHandler+      Iterator)) IteratorConnectToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,     void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin,     ConnectCondition connect_condition,-    ASIO_MOVE_ARG(IteratorConnectHandler) handler+    ASIO_MOVE_ARG(IteratorConnectToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<!is_endpoint_sequence<Iterator>::value>::type* = 0);+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<IteratorConnectToken,+      void (asio::error_code, Iterator)>(+        declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+        token, begin, Iterator(), connect_condition))); #endif // !defined(ASIO_NO_DEPRECATED)  /// Asynchronously establishes a socket connection by trying each endpoint in a@@ -961,7 +1071,8 @@  * 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.+ * is successfully established. It is an initiating function for an @ref+ * asynchronous_operation, and always returns immediately.  *  * @param s The socket to be connected. If the socket is already open, it will  * be closed.@@ -981,9 +1092,11 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the connect completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation. if the sequence is empty, set to  *   // asio::error::not_found. Otherwise, contains the@@ -995,10 +1108,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, Iterator) @endcode+ *  * @par Example  * The following connect condition function object can be used to output  * information about the individual connection attempts:@@ -1052,18 +1168,33 @@  *     std::cout << "Connected to: " << i->endpoint() << std::endl;  *   }  * } @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the socket's @c async_connect operation.  */ template <typename Protocol, typename Executor,     typename Iterator, typename ConnectCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      Iterator)) IteratorConnectHandler+      Iterator)) IteratorConnectToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(IteratorConnectHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,     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));+    ASIO_MOVE_ARG(IteratorConnectToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<IteratorConnectToken,+      void (asio::error_code, Iterator)>(+        declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+        token, begin, end, connect_condition)));  /*@}*/ 
+ link/modules/asio-standalone/asio/include/asio/connect_pipe.hpp view
@@ -0,0 +1,83 @@+//+// connect_pipe.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CONNECT_PIPE_HPP+#define ASIO_CONNECT_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_readable_pipe.hpp"+#include "asio/basic_writable_pipe.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if defined(ASIO_HAS_IOCP)+typedef HANDLE native_pipe_handle;+#else // defined(ASIO_HAS_IOCP)+typedef int native_pipe_handle;+#endif // defined(ASIO_HAS_IOCP)++ASIO_DECL void create_pipe(native_pipe_handle p[2],+    asio::error_code& ec);++ASIO_DECL void close_pipe(native_pipe_handle p);++} // namespace detail++/// Connect two pipe ends using an anonymous pipe.+/**+ * @param read_end The read end of the pipe.+ *+ * @param write_end The write end of the pipe.+ *+ * @throws asio::system_error Thrown on failure.+ */+template <typename Executor1, typename Executor2>+void connect_pipe(basic_readable_pipe<Executor1>& read_end,+    basic_writable_pipe<Executor2>& write_end);++/// Connect two pipe ends using an anonymous pipe.+/**+ * @param read_end The read end of the pipe.+ *+ * @param write_end The write end of the pipe.+ *+ * @throws asio::system_error Thrown on failure.+ *+ * @param ec Set to indicate what error occurred, if any.+ */+template <typename Executor1, typename Executor2>+ASIO_SYNC_OP_VOID connect_pipe(basic_readable_pipe<Executor1>& read_end,+    basic_writable_pipe<Executor2>& write_end, asio::error_code& ec);++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/connect_pipe.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/impl/connect_pipe.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_PIPE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_CONNECT_PIPE_HPP
+ link/modules/asio-standalone/asio/include/asio/consign.hpp view
@@ -0,0 +1,88 @@+//+// consign.hpp+// ~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_CONSIGN_HPP+#define ASIO_CONSIGN_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_TUPLE) \+    && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+  || defined(GENERATING_DOCUMENTATION)++#include <tuple>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Completion token type used to specify that the completion handler should+/// carry additional values along with it.+/**+ * This completion token adapter is typically used to keep at least one copy of+ * an object, such as a smart pointer, alive until the completion handler is+ * called.+ */+template <typename CompletionToken, typename... Values>+class consign_t+{+public:+  /// Constructor.+  template <typename T, typename... V>+  ASIO_CONSTEXPR explicit consign_t(+      ASIO_MOVE_ARG(T) completion_token,+      ASIO_MOVE_ARG(V)... values)+    : token_(ASIO_MOVE_CAST(T)(completion_token)),+      values_(ASIO_MOVE_CAST(V)(values)...)+  {+  }++#if defined(GENERATING_DOCUMENTATION)+private:+#endif // defined(GENERATING_DOCUMENTATION)+  CompletionToken token_;+  std::tuple<Values...> values_;+};++/// Completion token adapter used to specify that the completion handler should+/// carry additional values along with it.+/**+ * This completion token adapter is typically used to keep at least one copy of+ * an object, such as a smart pointer, alive until the completion handler is+ * called.+ */+template <typename CompletionToken, typename... Values>+ASIO_NODISCARD inline ASIO_CONSTEXPR consign_t<+  typename decay<CompletionToken>::type, typename decay<Values>::type...>+consign(ASIO_MOVE_ARG(CompletionToken) completion_token,+    ASIO_MOVE_ARG(Values)... values)+{+  return consign_t<+    typename decay<CompletionToken>::type, typename decay<Values>::type...>(+      ASIO_MOVE_CAST(CompletionToken)(completion_token),+      ASIO_MOVE_CAST(Values)(values)...);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/consign.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+       //     && defined(ASIO_HAS_VARIADIC_TEMPLATES))+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_CONSIGN_HPP
link/modules/asio-standalone/asio/include/asio/coroutine.hpp view
@@ -2,7 +2,7 @@ // coroutine.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/deadline_timer.hpp view
@@ -2,7 +2,7 @@ // deadline_timer.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/defer.hpp view
@@ -2,7 +2,7 @@ // defer.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,10 +17,13 @@  #include "asio/detail/config.hpp" #include "asio/async_result.hpp"+#include "asio/detail/initiate_defer.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp"+#include "asio/execution/blocking.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp"+#include "asio/require.hpp"  #include "asio/detail/push_options.hpp" @@ -37,27 +40,54 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode  *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{}, token)</tt>, where @c Init is a function object type defined+ * as:  *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @code class Init+ * {+ * public:+ *   template <typename CompletionHandler>+ *     void operator()(CompletionHandler&& completion_handler) const;+ * }; @endcode  *- * @li Obtains the handler's associated executor object @c ex by performing- * <tt>get_associated_executor(handler)</tt>.+ * The function call operator of @c Init:  *+ * @li Obtains the handler's associated executor object @c ex of type @c Ex by+ * performing @code auto ex = get_associated_executor(handler); @endcode+ *  * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode  *- * @li Performs <tt>ex.defer(std::move(handler), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(+ *     require(ex, execution::blocking.never),+ *     execution::relationship.continuation,+ *     execution::allocator(alloc)+ *   ).execute(std::forward<CompletionHandler>(completion_handler)); @endcode  *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.defer(+ *     std::forward<CompletionHandler>(completion_handler),+ *     alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode  */-template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(-    ASIO_MOVE_ARG(CompletionToken) token);+template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) defer(+    ASIO_MOVE_ARG(NullaryToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<NullaryToken, void()>(+        declval<detail::initiate_defer>(), token)))+{+  return async_initiate<NullaryToken, void()>(+      detail::initiate_defer(), token);+}  /// Submits a completion token or function object for execution. /**@@ -70,61 +100,123 @@  * 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:+ * @param ex The target executor.  *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode  *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{ex}, token)</tt>, where @c Init is a function object type+ * defined as:  *- * @li Obtains the handler's associated executor object @c ex1 by performing- * <tt>get_associated_executor(handler)</tt>.+ * @code class Init+ * {+ * public:+ *   using executor_type = Executor;+ *   explicit Init(const Executor& ex) : ex_(ex) {}+ *   executor_type get_executor() const noexcept { return ex_; }+ *   template <typename CompletionHandler>+ *     void operator()(CompletionHandler&& completion_handler) const;+ * private:+ *   Executor ex_; // exposition only+ * }; @endcode  *- * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.+ * The function call operator of @c Init:  *+ * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by+ * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode+ *  * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode  *- * @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 If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a+ * function object @c f with a member @c executor_ that is initialised with+ * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c+ * handler_ that is a decay-copy of @c completion_handler, and a function call+ * operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * prefer(executor_, execution::allocator(a)).execute(std::move(handler_));+ * @endcode  *- * @li Performs <tt>Executor(ex).defer(std::move(f), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a+ * function object @c f with a member @c work_ that is initialised with+ * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of+ * @c completion_handler, and a function call operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * work_.get_executor().dispatch(std::move(handler_), a);+ * work_.reset(); @endcode  *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(+ *     require(ex, execution::blocking.never),+ *     execution::relationship.continuation,+ *     execution::allocator(alloc)+ *   ).execute(std::move(f)); @endcode+ *+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.defer(std::move(f), alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode  */ template <typename Executor,-    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+    ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken       ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) defer(     const Executor& ex,-    ASIO_MOVE_ARG(CompletionToken) token+    ASIO_MOVE_ARG(NullaryToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<-      execution::is_executor<Executor>::value || is_executor<Executor>::value-    >::type* = 0);+    typename constraint<+      (execution::is_executor<Executor>::value+          && can_require<Executor, execution::blocking_t::never_t>::value)+        || is_executor<Executor>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<NullaryToken, void()>(+        declval<detail::initiate_defer_with_executor<Executor> >(), token)))+{+  return async_initiate<NullaryToken, void()>(+      detail::initiate_defer_with_executor<Executor>(ex), token);+}  /// Submits a completion token or function object for execution. /**- * @returns <tt>defer(ctx.get_executor(), forward<CompletionToken>(token))</tt>.+ * @param ctx An execution context, from which the target executor is obtained.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode+ *+ * @returns <tt>defer(ctx.get_executor(), forward<NullaryToken>(token))</tt>.+ *+ * @par Completion Signature+ * @code void() @endcode  */ template <typename ExecutionContext,-    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+    ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken       ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(         typename ExecutionContext::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) defer(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) defer(     ExecutionContext& ctx,-    ASIO_MOVE_ARG(CompletionToken) token+    ASIO_MOVE_ARG(NullaryToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename ExecutionContext::executor_type),-    typename enable_if<is_convertible<-      ExecutionContext&, execution_context&>::value>::type* = 0);+    typename constraint<is_convertible<+      ExecutionContext&, execution_context&>::value>::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<NullaryToken, void()>(+        declval<detail::initiate_defer_with_executor<+          typename ExecutionContext::executor_type> >(), token)))+{+  return async_initiate<NullaryToken, void()>(+      detail::initiate_defer_with_executor<+        typename ExecutionContext::executor_type>(+          ctx.get_executor()), token);+}  } // namespace asio  #include "asio/detail/pop_options.hpp"--#include "asio/impl/defer.hpp"  #endif // ASIO_DEFER_HPP
+ link/modules/asio-standalone/asio/include/asio/deferred.hpp view
@@ -0,0 +1,802 @@+//+// deferred.hpp+// ~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_DEFERRED_HPP+#define ASIO_DEFERRED_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_TUPLE) \+    && defined(ASIO_HAS_DECLTYPE) \+    && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+  || defined(GENERATING_DOCUMENTATION)++#include <tuple>+#include "asio/associator.hpp"+#include "asio/async_result.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/utility.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Trait for detecting objects that are usable as deferred operations.+template <typename T>+struct is_deferred : false_type+{+};++/// Helper type to wrap multiple completion signatures.+template <typename... Signatures>+struct deferred_signatures+{+};++namespace detail {++// Helper trait for getting the completion signatures of the tail in a sequence+// when invoked with the specified arguments.++template <typename Tail, typename... Signatures>+struct deferred_sequence_signatures;++template <typename Tail, typename R, typename... Args, typename... Signatures>+struct deferred_sequence_signatures<Tail, R(Args...), Signatures...>+  : completion_signature_of<decltype(declval<Tail>()(declval<Args>()...))>+{+  static_assert(+      !is_same<decltype(declval<Tail>()(declval<Args>()...)), void>::value,+      "deferred functions must produce a deferred return type");+};++// Completion handler for the head component of a deferred sequence.+template <typename Handler, typename Tail>+class deferred_sequence_handler+{+public:+  template <typename H, typename T>+  explicit deferred_sequence_handler(+      ASIO_MOVE_ARG(H) handler, ASIO_MOVE_ARG(T) tail)+    : handler_(ASIO_MOVE_CAST(H)(handler)),+      tail_(ASIO_MOVE_CAST(T)(tail))+  {+  }++  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)... args)+  {+    ASIO_MOVE_OR_LVALUE(Tail)(tail_)(+        ASIO_MOVE_CAST(Args)(args)...)(+          ASIO_MOVE_OR_LVALUE(Handler)(handler_));+  }++//private:+  Handler handler_;+  Tail tail_;+};++template <typename Head, typename Tail, typename... Signatures>+class deferred_sequence_base+{+private:+  struct initiate+  {+    template <typename Handler>+    void operator()(ASIO_MOVE_ARG(Handler) handler,+        Head head, ASIO_MOVE_ARG(Tail) tail)+    {+      ASIO_MOVE_OR_LVALUE(Head)(head)(+          deferred_sequence_handler<+            typename decay<Handler>::type,+            typename decay<Tail>::type>(+              ASIO_MOVE_CAST(Handler)(handler),+              ASIO_MOVE_CAST(Tail)(tail)));+    }+  };++  Head head_;+  Tail tail_;++public:+  template <typename H, typename T>+  ASIO_CONSTEXPR explicit deferred_sequence_base(+      ASIO_MOVE_ARG(H) head, ASIO_MOVE_ARG(T) tail)+    : head_(ASIO_MOVE_CAST(H)(head)),+      tail_(ASIO_MOVE_CAST(T)(tail))+  {+  }++  template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>+  auto operator()(+      ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL+    -> decltype(+        asio::async_initiate<CompletionToken, Signatures...>(+          declval<initiate>(), token,+          ASIO_MOVE_OR_LVALUE(Head)(this->head_),+          ASIO_MOVE_OR_LVALUE(Tail)(this->tail_)))+  {+    return asio::async_initiate<CompletionToken, Signatures...>(+        initiate(), token,+        ASIO_MOVE_OR_LVALUE(Head)(head_),+        ASIO_MOVE_OR_LVALUE(Tail)(tail_));+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>+  auto operator()(+      ASIO_MOVE_ARG(CompletionToken) token) const &+    -> decltype(+        asio::async_initiate<CompletionToken, Signatures...>(+          initiate(), token, this->head_, this->tail_))+  {+    return asio::async_initiate<CompletionToken, Signatures...>(+        initiate(), token, head_, tail_);+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++// Two-step application of variadic Signatures to determine correct base type.++template <typename Head, typename Tail>+struct deferred_sequence_types+{+  template <typename... Signatures>+  struct op1+  {+    typedef deferred_sequence_base<Head, Tail, Signatures...> type;+  };++  template <typename... Signatures>+  struct op2+  {+    typedef typename deferred_sequence_signatures<Tail, Signatures...>::template+      apply<op1>::type::type type;+  };++  typedef typename completion_signature_of<Head>::template+    apply<op2>::type::type base;+};++} // namespace detail++/// Used to represent an empty deferred action.+struct deferred_noop+{+  /// No effect.+  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)...) ASIO_RVALUE_REF_QUAL+  {+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  /// No effect.+  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)...) const &+  {+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <>+struct is_deferred<deferred_noop> : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Tag type to disambiguate deferred constructors.+struct deferred_init_tag {};++/// Wraps a function object so that it may be used as an element in a deferred+/// composition.+template <typename Function>+class deferred_function+{+public:+  /// Constructor. +  template <typename F>+  ASIO_CONSTEXPR explicit deferred_function(+      deferred_init_tag, ASIO_MOVE_ARG(F) function)+    : function_(ASIO_MOVE_CAST(F)(function))+  {+  }++//private:+  Function function_;++public:+  template <typename... Args>+  auto operator()(+      ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL+    -> decltype(+        ASIO_MOVE_CAST(Function)(this->function_)(+          ASIO_MOVE_CAST(Args)(args)...))+  {+    return ASIO_MOVE_CAST(Function)(function_)(+        ASIO_MOVE_CAST(Args)(args)...);+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  template <typename... Args>+  auto operator()(+      ASIO_MOVE_ARG(Args)... args) const &+    -> decltype(Function(function_)(ASIO_MOVE_CAST(Args)(args)...))+  {+    return Function(function_)(ASIO_MOVE_CAST(Args)(args)...);+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename Function>+struct is_deferred<deferred_function<Function> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Encapsulates deferred values.+template <typename... Values>+class ASIO_NODISCARD deferred_values+{+private:+  std::tuple<Values...> values_;++  struct initiate+  {+    template <typename Handler, typename... V>+    void operator()(Handler handler, ASIO_MOVE_ARG(V)... values)+    {+      ASIO_MOVE_OR_LVALUE(Handler)(handler)(+          ASIO_MOVE_CAST(V)(values)...);+    }+  };++  template <typename CompletionToken, std::size_t... I>+  auto invoke_helper(+      ASIO_MOVE_ARG(CompletionToken) token,+      detail::index_sequence<I...>)+    -> decltype(+        asio::async_initiate<CompletionToken, void(Values...)>(+          initiate(), token,+          std::get<I>(+            ASIO_MOVE_CAST(std::tuple<Values...>)(this->values_))...))+  {+    return asio::async_initiate<CompletionToken, void(Values...)>(+        initiate(), token,+        std::get<I>(ASIO_MOVE_CAST(std::tuple<Values...>)(values_))...);+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  template <typename CompletionToken, std::size_t... I>+  auto const_invoke_helper(+      ASIO_MOVE_ARG(CompletionToken) token,+      detail::index_sequence<I...>)+    -> decltype(+        asio::async_initiate<CompletionToken, void(Values...)>(+          initiate(), token, std::get<I>(values_)...))+  {+    return asio::async_initiate<CompletionToken, void(Values...)>(+        initiate(), token, std::get<I>(values_)...);+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++public:+  /// Construct a deferred asynchronous operation from the arguments to an+  /// initiation function object.+  template <typename... V>+  ASIO_CONSTEXPR explicit deferred_values(+      deferred_init_tag, ASIO_MOVE_ARG(V)... values)+    : values_(ASIO_MOVE_CAST(V)(values)...)+  {+  }++  /// Initiate the deferred operation using the supplied completion token.+  template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>+  auto operator()(+      ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL+    -> decltype(+        this->invoke_helper(+          ASIO_MOVE_CAST(CompletionToken)(token),+          detail::index_sequence_for<Values...>()))+  {+    return this->invoke_helper(+        ASIO_MOVE_CAST(CompletionToken)(token),+        detail::index_sequence_for<Values...>());+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  template <ASIO_COMPLETION_TOKEN_FOR(void(Values...)) CompletionToken>+  auto operator()(+      ASIO_MOVE_ARG(CompletionToken) token) const &+    -> decltype(+        this->const_invoke_helper(+          ASIO_MOVE_CAST(CompletionToken)(token),+          detail::index_sequence_for<Values...>()))+  {+    return this->const_invoke_helper(+        ASIO_MOVE_CAST(CompletionToken)(token),+        detail::index_sequence_for<Values...>());+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename... Values>+struct is_deferred<deferred_values<Values...> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Encapsulates a deferred asynchronous operation.+template <typename Signature, typename Initiation, typename... InitArgs>+class ASIO_NODISCARD deferred_async_operation+{+private:+  typedef typename decay<Initiation>::type initiation_t;+  initiation_t initiation_;+  typedef std::tuple<typename decay<InitArgs>::type...> init_args_t;+  init_args_t init_args_;++  template <typename CompletionToken, std::size_t... I>+  auto invoke_helper(+      ASIO_MOVE_ARG(CompletionToken) token,+      detail::index_sequence<I...>)+    -> decltype(+        asio::async_initiate<CompletionToken, Signature>(+          ASIO_MOVE_CAST(initiation_t)(initiation_), token,+          std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...))+  {+    return asio::async_initiate<CompletionToken, Signature>(+        ASIO_MOVE_CAST(initiation_t)(initiation_), token,+        std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...);+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  template <typename CompletionToken, std::size_t... I>+  auto const_invoke_helper(+      ASIO_MOVE_ARG(CompletionToken) token,+      detail::index_sequence<I...>) const &+    -> decltype(+        asio::async_initiate<CompletionToken, Signature>(+          initiation_t(initiation_), token, std::get<I>(init_args_)...))+    {+    return asio::async_initiate<CompletionToken, Signature>(+        initiation_t(initiation_), token, std::get<I>(init_args_)...);+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++public:+  /// Construct a deferred asynchronous operation from the arguments to an+  /// initiation function object.+  template <typename I, typename... A>+  ASIO_CONSTEXPR explicit deferred_async_operation(+      deferred_init_tag, ASIO_MOVE_ARG(I) initiation,+      ASIO_MOVE_ARG(A)... init_args)+    : initiation_(ASIO_MOVE_CAST(I)(initiation)),+      init_args_(ASIO_MOVE_CAST(A)(init_args)...)+  {+  }++  /// Initiate the asynchronous operation using the supplied completion token.+  template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>+  auto operator()(+      ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL+    -> decltype(+        this->invoke_helper(+          ASIO_MOVE_CAST(CompletionToken)(token),+          detail::index_sequence_for<InitArgs...>()))+  {+    return this->invoke_helper(+        ASIO_MOVE_CAST(CompletionToken)(token),+        detail::index_sequence_for<InitArgs...>());+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  template <ASIO_COMPLETION_TOKEN_FOR(Signature) CompletionToken>+  auto operator()(+      ASIO_MOVE_ARG(CompletionToken) token) const &+    -> decltype(+        this->const_invoke_helper(+          ASIO_MOVE_CAST(CompletionToken)(token),+          detail::index_sequence_for<InitArgs...>()))+  {+    return this->const_invoke_helper(+        ASIO_MOVE_CAST(CompletionToken)(token),+        detail::index_sequence_for<InitArgs...>());+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++/// Encapsulates a deferred asynchronous operation thas has multiple completion+/// signatures.+template <typename... Signatures, typename Initiation, typename... InitArgs>+class ASIO_NODISCARD deferred_async_operation<+    deferred_signatures<Signatures...>, Initiation, InitArgs...>+{+private:+  typedef typename decay<Initiation>::type initiation_t;+  initiation_t initiation_;+  typedef std::tuple<typename decay<InitArgs>::type...> init_args_t;+  init_args_t init_args_;++  template <typename CompletionToken, std::size_t... I>+  auto invoke_helper(+      ASIO_MOVE_ARG(CompletionToken) token,+      detail::index_sequence<I...>)+    -> decltype(+        asio::async_initiate<CompletionToken, Signatures...>(+          ASIO_MOVE_CAST(initiation_t)(initiation_), token,+          std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...))+  {+    return asio::async_initiate<CompletionToken, Signatures...>(+        ASIO_MOVE_CAST(initiation_t)(initiation_), token,+        std::get<I>(ASIO_MOVE_CAST(init_args_t)(init_args_))...);+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  template <typename CompletionToken, std::size_t... I>+  auto const_invoke_helper(+      ASIO_MOVE_ARG(CompletionToken) token,+      detail::index_sequence<I...>) const &+    -> decltype(+        asio::async_initiate<CompletionToken, Signatures...>(+          initiation_t(initiation_), token, std::get<I>(init_args_)...))+    {+    return asio::async_initiate<CompletionToken, Signatures...>(+        initiation_t(initiation_), token, std::get<I>(init_args_)...);+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++public:+  /// Construct a deferred asynchronous operation from the arguments to an+  /// initiation function object.+  template <typename I, typename... A>+  ASIO_CONSTEXPR explicit deferred_async_operation(+      deferred_init_tag, ASIO_MOVE_ARG(I) initiation,+      ASIO_MOVE_ARG(A)... init_args)+    : initiation_(ASIO_MOVE_CAST(I)(initiation)),+      init_args_(ASIO_MOVE_CAST(A)(init_args)...)+  {+  }++  /// Initiate the asynchronous operation using the supplied completion token.+  template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>+  auto operator()(+      ASIO_MOVE_ARG(CompletionToken) token) ASIO_RVALUE_REF_QUAL+    -> decltype(+        this->invoke_helper(+          ASIO_MOVE_CAST(CompletionToken)(token),+          detail::index_sequence_for<InitArgs...>()))+  {+    return this->invoke_helper(+        ASIO_MOVE_CAST(CompletionToken)(token),+        detail::index_sequence_for<InitArgs...>());+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  template <ASIO_COMPLETION_TOKEN_FOR(Signatures...) CompletionToken>+  auto operator()(+      ASIO_MOVE_ARG(CompletionToken) token) const &+    -> decltype(+        this->const_invoke_helper(+          ASIO_MOVE_CAST(CompletionToken)(token),+          detail::index_sequence_for<InitArgs...>()))+  {+    return this->const_invoke_helper(+        ASIO_MOVE_CAST(CompletionToken)(token),+        detail::index_sequence_for<InitArgs...>());+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename Signature, typename Initiation, typename... InitArgs>+struct is_deferred<+    deferred_async_operation<Signature, Initiation, InitArgs...> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Defines a link between two consecutive operations in a sequence.+template <typename Head, typename Tail>+class ASIO_NODISCARD deferred_sequence :+  public detail::deferred_sequence_types<Head, Tail>::base+{+public:+  template <typename H, typename T>+  ASIO_CONSTEXPR explicit deferred_sequence(deferred_init_tag,+      ASIO_MOVE_ARG(H) head, ASIO_MOVE_ARG(T) tail)+    : detail::deferred_sequence_types<Head, Tail>::base(+        ASIO_MOVE_CAST(H)(head), ASIO_MOVE_CAST(T)(tail))+  {+  }++#if defined(GENERATING_DOCUMENTATION)+  template <typename CompletionToken>+  auto operator()(ASIO_MOVE_ARG(CompletionToken) token)+    ASIO_RVALUE_REF_QUAL;++  template <typename CompletionToken>+  auto operator()(ASIO_MOVE_ARG(CompletionToken) token) const &;+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename Head, typename Tail>+struct is_deferred<deferred_sequence<Head, Tail> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Used to represent a deferred conditional branch.+template <typename OnTrue = deferred_noop,+    typename OnFalse = deferred_noop>+class ASIO_NODISCARD deferred_conditional+{+private:+  template <typename T, typename F> friend class deferred_conditional;++  // Helper constructor.+  template <typename T, typename F>+  explicit deferred_conditional(bool b, ASIO_MOVE_ARG(T) on_true,+      ASIO_MOVE_ARG(F) on_false)+    : on_true_(ASIO_MOVE_CAST(T)(on_true)),+      on_false_(ASIO_MOVE_CAST(F)(on_false)),+      bool_(b)+  {+  }++  OnTrue on_true_;+  OnFalse on_false_;+  bool bool_;++public:+  /// Construct a deferred conditional with the value to determine which branch+  /// will be executed.+  ASIO_CONSTEXPR explicit deferred_conditional(bool b)+    : on_true_(),+      on_false_(),+      bool_(b)+  {+  }++  /// Invoke the conditional branch bsaed on the stored alue.+  template <typename... Args>+  auto operator()(ASIO_MOVE_ARG(Args)... args) ASIO_RVALUE_REF_QUAL+    -> decltype(+        ASIO_MOVE_OR_LVALUE(OnTrue)(on_true_)(+          ASIO_MOVE_CAST(Args)(args)...))+  {+    if (bool_)+    {+      return ASIO_MOVE_OR_LVALUE(OnTrue)(on_true_)(+          ASIO_MOVE_CAST(Args)(args)...);+    }+    else+    {+      return ASIO_MOVE_OR_LVALUE(OnFalse)(on_false_)(+          ASIO_MOVE_CAST(Args)(args)...);+    }+  }++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)+  template <typename... Args>+  auto operator()(ASIO_MOVE_ARG(Args)... args) const &+    -> decltype(on_true_(ASIO_MOVE_CAST(Args)(args)...))+  {+    if (bool_)+    {+      return on_true_(ASIO_MOVE_CAST(Args)(args)...);+    }+    else+    {+      return on_false_(ASIO_MOVE_CAST(Args)(args)...);+    }+  }+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++  /// Set the true branch of the conditional.+  template <typename T>+  deferred_conditional<T, OnFalse> then(T on_true,+      typename constraint<+        is_deferred<T>::value+      >::type* = 0,+      typename constraint<+        is_same<+          typename conditional<true, OnTrue, T>::type,+          deferred_noop+        >::value+      >::type* = 0) ASIO_RVALUE_REF_QUAL+  {+    return deferred_conditional<T, OnFalse>(+        bool_, ASIO_MOVE_CAST(T)(on_true),+        ASIO_MOVE_CAST(OnFalse)(on_false_));+  }++  /// Set the false branch of the conditional.+  template <typename T>+  deferred_conditional<OnTrue, T> otherwise(T on_false,+      typename constraint<+        is_deferred<T>::value+      >::type* = 0,+      typename constraint<+        !is_same<+          typename conditional<true, OnTrue, T>::type,+          deferred_noop+        >::value+      >::type* = 0,+      typename constraint<+        is_same<+          typename conditional<true, OnFalse, T>::type,+          deferred_noop+        >::value+      >::type* = 0) ASIO_RVALUE_REF_QUAL+  {+    return deferred_conditional<OnTrue, T>(+        bool_, ASIO_MOVE_CAST(OnTrue)(on_true_),+        ASIO_MOVE_CAST(T)(on_false));+  }+};++#if !defined(GENERATING_DOCUMENTATION)+template <typename OnTrue, typename OnFalse>+struct is_deferred<deferred_conditional<OnTrue, OnFalse> > : true_type+{+};+#endif // !defined(GENERATING_DOCUMENTATION)++/// Class used to specify that an asynchronous operation should return a+/// function object to lazily launch the operation.+/**+ * The deferred_t class is used to indicate that an asynchronous operation+ * should return a function object which is itself an initiation function. A+ * deferred_t object may be passed as a completion token to an asynchronous+ * operation, typically using the special value @c asio::deferred. For+ * example:+ *+ * @code auto my_deferred_op+ *   = my_socket.async_read_some(my_buffer,+ *       asio::deferred); @endcode+ *+ * The initiating function (async_read_some in the above example) returns a+ * function object that will lazily initiate the operation.+ */+class deferred_t+{+public:+  /// Default constructor.+  ASIO_CONSTEXPR deferred_t()+  {+  }++  /// Adapts an executor to add the @c deferred_t completion token as the+  /// default.+  template <typename InnerExecutor>+  struct executor_with_default : InnerExecutor+  {+    /// Specify @c deferred_t as the default completion token type.+    typedef deferred_t default_completion_token_type;++    /// Construct the adapted executor from the inner executor type.+    template <typename InnerExecutor1>+    executor_with_default(const InnerExecutor1& ex,+        typename constraint<+          conditional<+            !is_same<InnerExecutor1, executor_with_default>::value,+            is_convertible<InnerExecutor1, InnerExecutor>,+            false_type+          >::type::value+        >::type = 0) ASIO_NOEXCEPT+      : InnerExecutor(ex)+    {+    }+  };++  /// Type alias to adapt an I/O object to use @c deferred_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 deferred_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));+  }++  /// Creates a new deferred from a function.+  template <typename Function>+  typename constraint<+    !is_deferred<typename decay<Function>::type>::value,+    deferred_function<typename decay<Function>::type>+  >::type operator()(ASIO_MOVE_ARG(Function) function) const+  {+    return deferred_function<typename decay<Function>::type>(+        deferred_init_tag{}, ASIO_MOVE_CAST(Function)(function));+  }++  /// Passes through anything that is already deferred.+  template <typename T>+  typename constraint<+    is_deferred<typename decay<T>::type>::value,+    typename decay<T>::type+  >::type operator()(ASIO_MOVE_ARG(T) t) const+  {+    return ASIO_MOVE_CAST(T)(t);+  }++  /// Returns a deferred operation that returns the provided values.+  template <typename... Args>+  static ASIO_CONSTEXPR deferred_values<typename decay<Args>::type...>+  values(ASIO_MOVE_ARG(Args)... args)+  {+    return deferred_values<typename decay<Args>::type...>(+        deferred_init_tag{}, ASIO_MOVE_CAST(Args)(args)...);+  }++  /// Creates a conditional object for branching deferred operations.+  static ASIO_CONSTEXPR deferred_conditional<> when(bool b)+  {+    return deferred_conditional<>(b);+  }+};++/// Pipe operator used to chain deferred operations.+template <typename Head, typename Tail>+inline auto operator|(Head head, ASIO_MOVE_ARG(Tail) tail)+  -> typename constraint<+      is_deferred<Head>::value,+      decltype(ASIO_MOVE_OR_LVALUE(Head)(head)(+            ASIO_MOVE_CAST(Tail)(tail)))+    >::type+{+  return ASIO_MOVE_OR_LVALUE(Head)(head)(+      ASIO_MOVE_CAST(Tail)(tail));+}++/// A @ref completion_token object used to specify that an asynchronous+/// operation should return a function object to lazily launch the operation.+/**+ * See the documentation for asio::deferred_t for a usage example.+ */+#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr deferred_t deferred;+#elif defined(ASIO_MSVC)+__declspec(selectany) deferred_t deferred;+#endif++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/deferred.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+       //     && defined(ASIO_HAS_DECLTYPE))+       //     && defined(ASIO_HAS_VARIADIC_TEMPLATES))+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_DEFERRED_HPP
link/modules/asio-standalone/asio/include/asio/detached.hpp view
@@ -2,7 +2,7 @@ // detached.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -23,15 +23,15 @@  namespace asio { -/// Class used to specify that an asynchronous operation is detached.+/// A @ref completion_token type 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  */@@ -61,9 +61,9 @@     /// that to construct the adapted executor.     template <typename OtherExecutor>     executor_with_default(const OtherExecutor& ex,-        typename enable_if<+        typename constraint<           is_convertible<OtherExecutor, InnerExecutor>::value-        >::type* = 0) ASIO_NOEXCEPT+        >::type = 0) ASIO_NOEXCEPT       : InnerExecutor(ex)     {     }@@ -93,7 +93,8 @@   } }; -/// A special value, similar to std::nothrow.+/// A @ref completion_token object used to specify that an asynchronous+/// operation is detached. /**  * See the documentation for asio::detached_t for a usage example.  */
link/modules/asio-standalone/asio/include/asio/detail/array.hpp view
@@ -2,7 +2,7 @@ // detail/array.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/array_fwd.hpp view
@@ -2,7 +2,7 @@ // detail/array_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/assert.hpp view
@@ -2,7 +2,7 @@ // detail/assert.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/atomic_count.hpp view
@@ -2,7 +2,7 @@ // detail/atomic_count.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -31,11 +31,13 @@ #if !defined(ASIO_HAS_THREADS) typedef long atomic_count; inline void increment(atomic_count& a, long b) { a += b; }+inline void decrement(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 decrement(atomic_count& a, long b) { a -= b; }  inline void ref_count_up(atomic_count& a) {@@ -54,6 +56,7 @@ #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 decrement(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)
+ link/modules/asio-standalone/asio/include/asio/detail/base_from_cancellation_state.hpp view
@@ -0,0 +1,163 @@+//+// detail/base_from_cancellation_state.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_CANCELLATION_STATE_HPP+#define ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename = void>+class base_from_cancellation_state+{+public:+  typedef cancellation_slot cancellation_slot_type;++  cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+  {+    return cancellation_state_.slot();+  }++  cancellation_state get_cancellation_state() const ASIO_NOEXCEPT+  {+    return cancellation_state_;+  }++protected:+  explicit base_from_cancellation_state(const Handler& handler)+    : cancellation_state_(+        asio::get_associated_cancellation_slot(handler))+  {+  }++  template <typename Filter>+  base_from_cancellation_state(const Handler& handler, Filter filter)+    : cancellation_state_(+        asio::get_associated_cancellation_slot(handler), filter, filter)+  {+  }++  template <typename InFilter, typename OutFilter>+  base_from_cancellation_state(const Handler& handler,+      ASIO_MOVE_ARG(InFilter) in_filter,+      ASIO_MOVE_ARG(OutFilter) out_filter)+    : cancellation_state_(+        asio::get_associated_cancellation_slot(handler),+        ASIO_MOVE_CAST(InFilter)(in_filter),+        ASIO_MOVE_CAST(OutFilter)(out_filter))+  {+  }++  void reset_cancellation_state(const Handler& handler)+  {+    cancellation_state_ = cancellation_state(+        asio::get_associated_cancellation_slot(handler));+  }++  template <typename Filter>+  void reset_cancellation_state(const Handler& handler, Filter filter)+  {+    cancellation_state_ = cancellation_state(+        asio::get_associated_cancellation_slot(handler), filter, filter);+  }++  template <typename InFilter, typename OutFilter>+  void reset_cancellation_state(const Handler& handler,+      ASIO_MOVE_ARG(InFilter) in_filter,+      ASIO_MOVE_ARG(OutFilter) out_filter)+  {+    cancellation_state_ = cancellation_state(+        asio::get_associated_cancellation_slot(handler),+        ASIO_MOVE_CAST(InFilter)(in_filter),+        ASIO_MOVE_CAST(OutFilter)(out_filter));+  }++  cancellation_type_t cancelled() const ASIO_NOEXCEPT+  {+    return cancellation_state_.cancelled();+  }++private:+  cancellation_state cancellation_state_;+};++template <typename Handler>+class base_from_cancellation_state<Handler,+    typename enable_if<+      is_same<+        typename associated_cancellation_slot<+          Handler, cancellation_slot+        >::asio_associated_cancellation_slot_is_unspecialised,+        void+      >::value+    >::type>+{+public:+  cancellation_state get_cancellation_state() const ASIO_NOEXCEPT+  {+    return cancellation_state();+  }++protected:+  explicit base_from_cancellation_state(const Handler&)+  {+  }++  template <typename Filter>+  base_from_cancellation_state(const Handler&, Filter)+  {+  }++  template <typename InFilter, typename OutFilter>+  base_from_cancellation_state(const Handler&,+      ASIO_MOVE_ARG(InFilter),+      ASIO_MOVE_ARG(OutFilter))+  {+  }++  void reset_cancellation_state(const Handler&)+  {+  }++  template <typename Filter>+  void reset_cancellation_state(const Handler&, Filter)+  {+  }++  template <typename InFilter, typename OutFilter>+  void reset_cancellation_state(const Handler&,+      ASIO_MOVE_ARG(InFilter),+      ASIO_MOVE_ARG(OutFilter))+  {+  }++  ASIO_CONSTEXPR cancellation_type_t cancelled() const ASIO_NOEXCEPT+  {+    return cancellation_type::none;+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_BASE_FROM_CANCELLATION_STATE_HPP
link/modules/asio-standalone/asio/include/asio/detail/base_from_completion_cond.hpp view
@@ -2,7 +2,7 @@ // detail/base_from_completion_cond.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/bind_handler.hpp view
@@ -2,7 +2,7 @@ // detail/bind_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,8 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp"@@ -28,6 +27,113 @@ namespace asio { namespace detail { +template <typename Handler>+class binder0+{+public:+  template <typename T>+  binder0(int, ASIO_MOVE_ARG(T) handler)+    : handler_(ASIO_MOVE_CAST(T)(handler))+  {+  }++  binder0(Handler& handler)+    : handler_(ASIO_MOVE_CAST(Handler)(handler))+  {+  }++#if defined(ASIO_HAS_MOVE)+  binder0(const binder0& other)+    : handler_(other.handler_)+  {+  }++  binder0(binder0&& other)+    : handler_(ASIO_MOVE_CAST(Handler)(other.handler_))+  {+  }+#endif // defined(ASIO_HAS_MOVE)++  void operator()()+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)();+  }++  void operator()() const+  {+    handler_();+  }++//private:+  Handler handler_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    binder0<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,+    binder0<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(+    binder0<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,+    binder0<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,+    binder0<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 Handler>+inline binder0<typename decay<Handler>::type> bind_handler(+    ASIO_MOVE_ARG(Handler) handler)+{+  return binder0<typename decay<Handler>::type>(+      0, ASIO_MOVE_CAST(Handler)(handler));+}+ template <typename Handler, typename Arg1> class binder1 {@@ -61,7 +167,8 @@    void operator()()   {-    handler_(static_cast<const Arg1&>(arg1_));+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        static_cast<const Arg1&>(arg1_));   }    void operator()() const@@ -178,7 +285,8 @@    void operator()()   {-    handler_(static_cast<const Arg1&>(arg1_),+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        static_cast<const Arg1&>(arg1_),         static_cast<const Arg2&>(arg2_));   } @@ -302,8 +410,10 @@    void operator()()   {-    handler_(static_cast<const Arg1&>(arg1_),-        static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_));+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        static_cast<const Arg1&>(arg1_),+        static_cast<const Arg2&>(arg2_),+        static_cast<const Arg3&>(arg3_));   }    void operator()() const@@ -435,8 +545,10 @@    void operator()()   {-    handler_(static_cast<const Arg1&>(arg1_),-        static_cast<const Arg2&>(arg2_), static_cast<const Arg3&>(arg3_),+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        static_cast<const Arg1&>(arg1_),+        static_cast<const Arg2&>(arg2_),+        static_cast<const Arg3&>(arg3_),         static_cast<const Arg4&>(arg4_));   } @@ -578,9 +690,12 @@    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_));+    ASIO_MOVE_OR_LVALUE(Handler)(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@@ -691,7 +806,8 @@    void operator()()   {-    handler_(ASIO_MOVE_CAST(Arg1)(arg1_));+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        ASIO_MOVE_CAST(Arg1)(arg1_));   }  //private:@@ -766,7 +882,8 @@    void operator()()   {-    handler_(static_cast<const Arg1&>(arg1_),+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        static_cast<const Arg1&>(arg1_),         ASIO_MOVE_CAST(Arg2)(arg2_));   } @@ -826,102 +943,196 @@  } // namespace detail -template <typename Handler, typename Arg1, typename Allocator>-struct associated_allocator<detail::binder1<Handler, Arg1>, Allocator>+template <template <typename, typename> class Associator,+    typename Handler, typename DefaultCandidate>+struct associator<Associator,+    detail::binder0<Handler>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  typedef typename associated_allocator<Handler, Allocator>::type type;+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::binder0<Handler>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  } -  static type get(const detail::binder1<Handler, Arg1>& h,-      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::binder0<Handler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; -template <typename Handler, typename Arg1, typename Arg2, typename Allocator>-struct associated_allocator<detail::binder2<Handler, Arg1, Arg2>, Allocator>+template <template <typename, typename> class Associator,+    typename Handler, typename Arg1, typename DefaultCandidate>+struct associator<Associator,+    detail::binder1<Handler, Arg1>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  typedef typename associated_allocator<Handler, Allocator>::type type;+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::binder1<Handler, Arg1>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  } -  static type get(const detail::binder2<Handler, Arg1, Arg2>& h,-      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::binder1<Handler, Arg1>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; -template <typename Handler, typename Arg1, typename Executor>-struct associated_executor<detail::binder1<Handler, Arg1>, Executor>+template <template <typename, typename> class Associator,+    typename Handler, typename Arg1, typename Arg2,+    typename DefaultCandidate>+struct associator<Associator,+    detail::binder2<Handler, Arg1, Arg2>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  typedef typename associated_executor<Handler, Executor>::type type;+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::binder2<Handler, Arg1, Arg2>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  } -  static type get(const detail::binder1<Handler, Arg1>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::binder2<Handler, Arg1, Arg2>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<Handler, Executor>::get(h.handler_, ex);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; -template <typename Handler, typename Arg1, typename Arg2, typename Executor>-struct associated_executor<detail::binder2<Handler, Arg1, Arg2>, Executor>+template <template <typename, typename> class Associator,+    typename Handler, typename Arg1, typename Arg2, typename Arg3,+    typename DefaultCandidate>+struct associator<Associator,+    detail::binder3<Handler, Arg1, Arg2, Arg3>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  typedef typename associated_executor<Handler, Executor>::type type;+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::binder3<Handler, Arg1, Arg2, Arg3>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  } -  static type get(const detail::binder2<Handler, Arg1, Arg2>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::binder3<Handler, Arg1, Arg2, Arg3>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<Handler, Executor>::get(h.handler_, ex);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; -#if defined(ASIO_HAS_MOVE)--template <typename Handler, typename Arg1, typename Allocator>-struct associated_allocator<detail::move_binder1<Handler, Arg1>, Allocator>+template <template <typename, typename> class Associator,+    typename Handler, typename Arg1, typename Arg2, typename Arg3,+    typename Arg4, typename DefaultCandidate>+struct associator<Associator,+    detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  typedef typename associated_allocator<Handler, Allocator>::type type;+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>& h)+    ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  } -  static type get(const detail::move_binder1<Handler, Arg1>& h,-      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::binder4<Handler, Arg1, Arg2, Arg3, Arg4>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; -template <typename Handler, typename Arg1, typename Arg2, typename Allocator>-struct associated_allocator<-    detail::move_binder2<Handler, Arg1, Arg2>, Allocator>+template <template <typename, typename> class Associator,+    typename Handler, typename Arg1, typename Arg2, typename Arg3,+    typename Arg4, typename Arg5, typename DefaultCandidate>+struct associator<Associator,+    detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  typedef typename associated_allocator<Handler, Allocator>::type type;+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>& h)+    ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  } -  static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,-      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::binder5<Handler, Arg1, Arg2, Arg3, Arg4, Arg5>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; -template <typename Handler, typename Arg1, typename Executor>-struct associated_executor<detail::move_binder1<Handler, Arg1>, Executor>+#if defined(ASIO_HAS_MOVE)++template <template <typename, typename> class Associator,+    typename Handler, typename Arg1, typename DefaultCandidate>+struct associator<Associator,+    detail::move_binder1<Handler, Arg1>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  typedef typename associated_executor<Handler, Executor>::type type;+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::move_binder1<Handler, Arg1>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  } -  static type get(const detail::move_binder1<Handler, Arg1>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::move_binder1<Handler, Arg1>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<Handler, Executor>::get(h.handler_, ex);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; -template <typename Handler, typename Arg1, typename Arg2, typename Executor>-struct associated_executor<detail::move_binder2<Handler, Arg1, Arg2>, Executor>+template <template <typename, typename> class Associator,+    typename Handler, typename Arg1, typename Arg2,+    typename DefaultCandidate>+struct associator<Associator,+    detail::move_binder2<Handler, Arg1, Arg2>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  typedef typename associated_executor<Handler, Executor>::type type;+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::move_binder2<Handler, Arg1, Arg2>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  } -  static type get(const detail::move_binder2<Handler, Arg1, Arg2>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::move_binder2<Handler, Arg1, Arg2>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<Handler, Executor>::get(h.handler_, ex);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; 
link/modules/asio-standalone/asio/include/asio/detail/blocking_executor_op.hpp view
@@ -2,7 +2,7 @@ // detail/blocking_executor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -77,6 +77,7 @@       const asio::error_code& /*ec*/,       std::size_t /*bytes_transferred*/)   {+    ASIO_ASSUME(base != 0);     blocking_executor_op* o(static_cast<blocking_executor_op*>(base));      typename blocking_executor_op_base<Operation>::do_complete_cleanup
link/modules/asio-standalone/asio/include/asio/detail/buffer_resize_guard.hpp view
@@ -2,7 +2,7 @@ // detail/buffer_resize_guard.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/buffer_sequence_adapter.hpp view
@@ -2,7 +2,7 @@ // detail/buffer_sequence_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@ #include "asio/buffer.hpp" #include "asio/detail/array_fwd.hpp" #include "asio/detail/socket_types.hpp"+#include "asio/registered_buffer.hpp"  #include "asio/detail/push_options.hpp" @@ -105,6 +106,7 @@ { public:   enum { is_single_buffer = false };+  enum { is_registered_buffer = false };    explicit buffer_sequence_adapter(const Buffers& buffer_sequence)     : count_(0), total_buffer_size_(0)@@ -129,6 +131,11 @@     return total_buffer_size_;   } +  registered_buffer_id registered_id() const+  {+    return registered_buffer_id();+  }+   bool all_empty() const   {     return total_buffer_size_ == 0;@@ -248,6 +255,7 @@ { public:   enum { is_single_buffer = true };+  enum { is_registered_buffer = false };    explicit buffer_sequence_adapter(       const asio::mutable_buffer& buffer_sequence)@@ -271,6 +279,11 @@     return total_buffer_size_;   } +  registered_buffer_id registered_id() const+  {+    return registered_buffer_id();+  }+   bool all_empty() const   {     return total_buffer_size_ == 0;@@ -310,6 +323,7 @@ { public:   enum { is_single_buffer = true };+  enum { is_registered_buffer = false };    explicit buffer_sequence_adapter(       const asio::const_buffer& buffer_sequence)@@ -333,6 +347,11 @@     return total_buffer_size_;   } +  registered_buffer_id registered_id() const+  {+    return registered_buffer_id();+  }+   bool all_empty() const   {     return total_buffer_size_ == 0;@@ -374,6 +393,7 @@ { public:   enum { is_single_buffer = true };+  enum { is_registered_buffer = false };    explicit buffer_sequence_adapter(       const asio::mutable_buffers_1& buffer_sequence)@@ -397,6 +417,11 @@     return total_buffer_size_;   } +  registered_buffer_id registered_id() const+  {+    return registered_buffer_id();+  }+   bool all_empty() const   {     return total_buffer_size_ == 0;@@ -436,6 +461,7 @@ { public:   enum { is_single_buffer = true };+  enum { is_registered_buffer = false };    explicit buffer_sequence_adapter(       const asio::const_buffers_1& buffer_sequence)@@ -459,6 +485,11 @@     return total_buffer_size_;   } +  registered_buffer_id registered_id() const+  {+    return registered_buffer_id();+  }+   bool all_empty() const   {     return total_buffer_size_ == 0;@@ -494,12 +525,161 @@  #endif // !defined(ASIO_NO_DEPRECATED) +template <typename Buffer>+class buffer_sequence_adapter<Buffer, asio::mutable_registered_buffer>+  : buffer_sequence_adapter_base+{+public:+  enum { is_single_buffer = true };+  enum { is_registered_buffer = true };++  explicit buffer_sequence_adapter(+      const asio::mutable_registered_buffer& buffer_sequence)+  {+    init_native_buffer(buffer_, buffer_sequence.buffer());+    total_buffer_size_ = buffer_sequence.size();+    registered_id_ = buffer_sequence.id();+  }++  native_buffer_type* buffers()+  {+    return &buffer_;+  }++  std::size_t count() const+  {+    return 1;+  }++  std::size_t total_size() const+  {+    return total_buffer_size_;+  }++  registered_buffer_id registered_id() const+  {+    return registered_id_;+  }++  bool all_empty() const+  {+    return total_buffer_size_ == 0;+  }++  static bool all_empty(+      const asio::mutable_registered_buffer& buffer_sequence)+  {+    return buffer_sequence.size() == 0;+  }++  static void validate(+      const asio::mutable_registered_buffer& buffer_sequence)+  {+    buffer_sequence.data();+  }++  static Buffer first(+      const asio::mutable_registered_buffer& buffer_sequence)+  {+    return Buffer(buffer_sequence.buffer());+  }++  enum { linearisation_storage_size = 1 };++  static Buffer linearise(+      const asio::mutable_registered_buffer& buffer_sequence,+      const Buffer&)+  {+    return Buffer(buffer_sequence.buffer());+  }++private:+  native_buffer_type buffer_;+  std::size_t total_buffer_size_;+  registered_buffer_id registered_id_;+};++template <typename Buffer>+class buffer_sequence_adapter<Buffer, asio::const_registered_buffer>+  : buffer_sequence_adapter_base+{+public:+  enum { is_single_buffer = true };+  enum { is_registered_buffer = true };++  explicit buffer_sequence_adapter(+      const asio::const_registered_buffer& buffer_sequence)+  {+    init_native_buffer(buffer_, buffer_sequence.buffer());+    total_buffer_size_ = buffer_sequence.size();+    registered_id_ = buffer_sequence.id();+  }++  native_buffer_type* buffers()+  {+    return &buffer_;+  }++  std::size_t count() const+  {+    return 1;+  }++  std::size_t total_size() const+  {+    return total_buffer_size_;+  }++  registered_buffer_id registered_id() const+  {+    return registered_id_;+  }++  bool all_empty() const+  {+    return total_buffer_size_ == 0;+  }++  static bool all_empty(+      const asio::const_registered_buffer& buffer_sequence)+  {+    return buffer_sequence.size() == 0;+  }++  static void validate(+      const asio::const_registered_buffer& buffer_sequence)+  {+    buffer_sequence.data();+  }++  static Buffer first(+      const asio::const_registered_buffer& buffer_sequence)+  {+    return Buffer(buffer_sequence.buffer());+  }++  enum { linearisation_storage_size = 1 };++  static Buffer linearise(+      const asio::const_registered_buffer& buffer_sequence,+      const Buffer&)+  {+    return Buffer(buffer_sequence.buffer());+  }++private:+  native_buffer_type buffer_;+  std::size_t total_buffer_size_;+  registered_buffer_id registered_id_;+};+ template <typename Buffer, typename Elem> class buffer_sequence_adapter<Buffer, boost::array<Elem, 2> >   : buffer_sequence_adapter_base { public:   enum { is_single_buffer = false };+  enum { is_registered_buffer = false };    explicit buffer_sequence_adapter(       const boost::array<Elem, 2>& buffer_sequence)@@ -524,6 +704,11 @@     return total_buffer_size_;   } +  registered_buffer_id registered_id() const+  {+    return registered_buffer_id();+  }+   bool all_empty() const   {     return total_buffer_size_ == 0;@@ -572,6 +757,7 @@ { public:   enum { is_single_buffer = false };+  enum { is_registered_buffer = false };    explicit buffer_sequence_adapter(       const std::array<Elem, 2>& buffer_sequence)@@ -594,6 +780,11 @@   std::size_t total_size() const   {     return total_buffer_size_;+  }++  registered_buffer_id registered_id() const+  {+    return registered_buffer_id();   }    bool all_empty() const
link/modules/asio-standalone/asio/include/asio/detail/buffered_stream_storage.hpp view
@@ -2,7 +2,7 @@ // detail/buffered_stream_storage.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/bulk_executor_op.hpp view
@@ -2,7 +2,7 @@ // detail/bulk_executor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -49,6 +49,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     bulk_executor_op* o(static_cast<bulk_executor_op*>(base));     Alloc allocator(o->allocator_);     ptr p = { detail::addressof(allocator), o, o };
link/modules/asio-standalone/asio/include/asio/detail/call_stack.hpp view
@@ -2,7 +2,7 @@ // detail/call_stack.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/chrono.hpp view
@@ -2,7 +2,7 @@ // detail/chrono.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/chrono_time_traits.hpp view
@@ -2,7 +2,7 @@ // detail/chrono_time_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/completion_handler.hpp view
@@ -2,7 +2,7 @@ // detail/completion_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/composed_work.hpp view
@@ -0,0 +1,328 @@+//+// detail/composed_work.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_COMPOSED_WORK_HPP+#define ASIO_DETAIL_COMPOSED_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/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_;+};++template <>+struct composed_work_guard<system_executor>+{+public:+  typedef system_executor executor_type;++  composed_work_guard(const system_executor&)+  {+  }++  void reset()+  {+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return system_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)++template <typename IoObject>+inline typename IoObject::executor_type+get_composed_io_executor(IoObject& io_object,+    typename enable_if<+      !is_executor<IoObject>::value+    >::type* = 0,+    typename enable_if<+      !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+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_COMPOSED_WORK_HPP
link/modules/asio-standalone/asio/include/asio/detail/concurrency_hint.hpp view
@@ -2,7 +2,7 @@ // detail/concurrency_hint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_event.hpp view
@@ -2,7 +2,7 @@ // detail/conditionally_enabled_event.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/conditionally_enabled_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/config.hpp view
@@ -2,7 +2,7 @@ // detail/config.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,8 +24,20 @@ # endif // !defined(ASIO_ENABLE_BOOST) #endif // !defined(ASIO_STANDALONE) +// Make standard library feature macros available.+#if defined(__has_include)+# if __has_include(<version>)+#  include <version>+# else // __has_include(<version>)+#  include <cstddef>+# endif // __has_include(<version>)+#else // defined(__has_include)+# include <cstddef>+#endif // defined(__has_include)+ // boostify: non-boost code ends here #if defined(ASIO_STANDALONE)+# define ASIO_DISABLE_BOOST_ALIGN 1 # define ASIO_DISABLE_BOOST_ARRAY 1 # define ASIO_DISABLE_BOOST_ASSERT 1 # define ASIO_DISABLE_BOOST_BIND 1@@ -37,6 +49,7 @@ # define ASIO_DISABLE_BOOST_THROW_EXCEPTION 1 # define ASIO_DISABLE_BOOST_WORKAROUND 1 #else // defined(ASIO_STANDALONE)+// Boost.Config library is available. # include <boost/config.hpp> # include <boost/version.hpp> # define ASIO_HAS_BOOST_CONFIG 1@@ -112,8 +125,7 @@ #   if __has_feature(__cxx_rvalue_references__) #    define ASIO_HAS_MOVE 1 #   endif // __has_feature(__cxx_rvalue_references__)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_MOVE 1@@ -148,6 +160,7 @@ # 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_ARG(type) type&& # define ASIO_MOVE_OR_LVALUE_TYPE(type) type #endif // defined(ASIO_HAS_MOVE) && !defined(ASIO_MOVE_CAST) @@ -176,6 +189,7 @@ # 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_ARG(type) type& # define ASIO_MOVE_OR_LVALUE_TYPE(type) type& #endif // !defined(ASIO_MOVE_CAST) @@ -186,8 +200,7 @@ #   if __has_feature(__cxx_variadic_templates__) #    define ASIO_HAS_VARIADIC_TEMPLATES 1 #   endif // __has_feature(__cxx_variadic_templates__)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_VARIADIC_TEMPLATES 1@@ -211,18 +224,17 @@  // Support deleted functions on compilers known to allow it. #if !defined(ASIO_DELETED)-# if defined(__GNUC__)+# if defined(__clang__)+#  if __has_feature(__cxx_deleted_functions__)+#   define ASIO_DELETED = delete+#  endif // __has_feature(__cxx_deleted_functions__)+# elif 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@@ -240,8 +252,7 @@ #   if __has_feature(__cxx_constexpr__) #    define ASIO_HAS_CONSTEXPR 1 #   endif // __has_feature(__cxx_constexpr__)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_CONSTEXPR 1@@ -347,6 +358,25 @@ # endif // defined(ASIO_HAS_NOEXCEPT) #endif // !defined(ASIO_NOEXCEPT_IF) +// Support noexcept on function types on compilers known to allow it.+#if !defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+# if !defined(ASIO_DISABLE_NOEXCEPT_FUNCTION_TYPE)+#  if defined(__clang__)+#   if (__cplusplus >= 202002)+#    define ASIO_HAS_NOEXCEPT_FUNCTION_TYPE 1+#   endif // (__cplusplus >= 202002)+#  elif defined(__GNUC__)+#   if (__cplusplus >= 202002)+#    define ASIO_HAS_NOEXCEPT_FUNCTION_TYPE 1+#   endif // (__cplusplus >= 202002)+#  elif defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900 && _MSVC_LANG >= 202002)+#    define ASIO_HAS_NOEXCEPT_FUNCTION_TYPE 1+#   endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 202002)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_NOEXCEPT_FUNCTION_TYPE)+#endif // !defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+ // Support automatic type deduction on compilers known to support it. #if !defined(ASIO_HAS_DECLTYPE) # if !defined(ASIO_DISABLE_DECLTYPE)@@ -354,8 +384,7 @@ #   if __has_feature(__cxx_decltype__) #    define ASIO_HAS_DECLTYPE 1 #   endif // __has_feature(__cxx_decltype__)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_DECLTYPE 1@@ -369,6 +398,17 @@ #  endif // defined(ASIO_MSVC) # endif // !defined(ASIO_DISABLE_DECLTYPE) #endif // !defined(ASIO_HAS_DECLTYPE)+#if defined(ASIO_HAS_DECLTYPE)+# define ASIO_AUTO_RETURN_TYPE_PREFIX(t) auto+# define ASIO_AUTO_RETURN_TYPE_PREFIX2(t0, t1) auto+# define ASIO_AUTO_RETURN_TYPE_PREFIX3(t0, t1, t2) auto+# define ASIO_AUTO_RETURN_TYPE_SUFFIX(expr) -> decltype expr+#else // defined(ASIO_HAS_DECLTYPE)+# define ASIO_AUTO_RETURN_TYPE_PREFIX(t) t+# define ASIO_AUTO_RETURN_TYPE_PREFIX2(t0, t1) t0, t1+# define ASIO_AUTO_RETURN_TYPE_PREFIX3(t0, t1, t2) t0, t1, t2+# define ASIO_AUTO_RETURN_TYPE_SUFFIX(expr)+#endif // defined(ASIO_HAS_DECLTYPE)  // Support alias templates on compilers known to allow it. #if !defined(ASIO_HAS_ALIAS_TEMPLATES)@@ -377,8 +417,7 @@ #   if __has_feature(__cxx_alias_templates__) #    define ASIO_HAS_ALIAS_TEMPLATES 1 #   endif // __has_feature(__cxx_alias_templates__)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_ALIAS_TEMPLATES 1@@ -406,7 +445,11 @@ #   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)+#  elif defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900 && _MSVC_LANG >= 201402)+#    define ASIO_HAS_RETURN_TYPE_DEDUCTION 1+#   endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201402)+#  endif // defined(ASIO_MSVC) # endif // !defined(ASIO_DISABLE_RETURN_TYPE_DEDUCTION) #endif // !defined(ASIO_HAS_RETURN_TYPE_DEDUCTION) @@ -415,10 +458,27 @@ # if !defined(ASIO_DISABLE_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) #  if (__cplusplus >= 201103) #   define ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS 1-#  endif // (__cplusplus >= 201103)+#  elif defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+#    define ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS 1+#   endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+#  endif // defined(ASIO_MSVC) # endif // !defined(ASIO_DISABLE_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) #endif // !defined(ASIO_HAS_DEFAULT_FUNCTION_TEMPLATE_ARGUMENTS) +// Support enum classes on compilers known to allow them.+#if !defined(ASIO_HAS_ENUM_CLASS)+# if !defined(ASIO_DISABLE_ENUM_CLASS)+#  if (__cplusplus >= 201103)+#   define ASIO_HAS_ENUM_CLASS 1+#  elif defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+#    define ASIO_HAS_ENUM_CLASS 1+#   endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_ENUM_CLASS)+#endif // !defined(ASIO_HAS_ENUM_CLASS)+ // Support concepts on compilers known to allow them. #if !defined(ASIO_HAS_CONCEPTS) # if !defined(ASIO_DISABLE_CONCEPTS)@@ -433,6 +493,17 @@ # endif // !defined(ASIO_DISABLE_CONCEPTS) #endif // !defined(ASIO_HAS_CONCEPTS) +// Support concepts on compilers known to allow them.+#if !defined(ASIO_HAS_STD_CONCEPTS)+# if !defined(ASIO_DISABLE_STD_CONCEPTS)+#  if defined(ASIO_HAS_CONCEPTS)+#   if (__cpp_lib_concepts >= 202002L)+#    define ASIO_HAS_STD_CONCEPTS 1+#   endif // (__cpp_concepts >= 202002L)+#  endif // defined(ASIO_HAS_CONCEPTS)+# endif // !defined(ASIO_DISABLE_STD_CONCEPTS)+#endif // !defined(ASIO_HAS_STD_CONCEPTS)+ // Support template variables on compilers known to allow it. #if !defined(ASIO_HAS_VARIABLE_TEMPLATES) # if !defined(ASIO_DISABLE_VARIABLE_TEMPLATES)@@ -442,14 +513,13 @@ #     define ASIO_HAS_VARIABLE_TEMPLATES 1 #    endif // __has_feature(__cxx_variable_templates__) #   endif // (__cplusplus >= 201402)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) && !defined(__INTEL_COMPILER) #   if (__GNUC__ >= 6) #    if (__cplusplus >= 201402) #     define ASIO_HAS_VARIABLE_TEMPLATES 1 #    endif // (__cplusplus >= 201402) #   endif // (__GNUC__ >= 6)-#  endif // defined(__GNUC__)+#  endif // defined(__GNUC__) && !defined(__INTEL_COMPILER) #  if defined(ASIO_MSVC) #   if (_MSC_VER >= 1901) #    define ASIO_HAS_VARIABLE_TEMPLATES 1@@ -467,8 +537,7 @@ #     define ASIO_HAS_SFINAE_VARIABLE_TEMPLATES 1 #    endif // __has_feature(__cxx_variable_templates__) #   endif // (__cplusplus >= 201703)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 8) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 8) #    if (__cplusplus >= 201402) #     define ASIO_HAS_SFINAE_VARIABLE_TEMPLATES 1@@ -490,14 +559,13 @@ #   if (__cplusplus >= 201402) #    define ASIO_HAS_CONSTANT_EXPRESSION_SFINAE 1 #   endif // (__cplusplus >= 201402)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) && !defined(__INTEL_COMPILER) #   if (__GNUC__ >= 7) #    if (__cplusplus >= 201402) #     define ASIO_HAS_CONSTANT_EXPRESSION_SFINAE 1 #    endif // (__cplusplus >= 201402) #   endif // (__GNUC__ >= 7)-#  endif // defined(__GNUC__)+#  endif // defined(__GNUC__) && !defined(__INTEL_COMPILER) #  if defined(ASIO_MSVC) #   if (_MSC_VER >= 1901) #    define ASIO_HAS_CONSTANT_EXPRESSION_SFINAE 1@@ -509,11 +577,15 @@ // 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 !defined(ASIO_MSVC) && !defined(__INTEL_COMPILER) #   if (__cplusplus >= 201103) #    define ASIO_HAS_WORKING_EXPRESSION_SFINAE 1 #   endif // (__cplusplus >= 201103)-#  endif // !defined(ASIO_MSVC)+#  elif defined(ASIO_MSVC) && (_MSC_VER >= 1929)+#   if (_MSVC_LANG >= 202000)+#    define ASIO_HAS_WORKING_EXPRESSION_SFINAE 1+#   endif // (_MSVC_LANG >= 202000)+#  endif // defined(ASIO_MSVC) && (_MSC_VER >= 1929) # endif // !defined(ASIO_DISABLE_WORKING_EXPRESSION_SFINAE) #endif // !defined(ASIO_HAS_WORKING_EXPRESSION_SFINAE) @@ -524,8 +596,7 @@ #   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__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_REF_QUALIFIED_FUNCTIONS 1@@ -555,6 +626,134 @@ # endif // !defined(ASIO_RVALUE_REF_QUAL) #endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) +// Support for capturing parameter packs in lambdas.+#if !defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)+# if !defined(ASIO_DISABLE_VARIADIC_LAMBDA_CAPTURES)+#  if defined(__GNUC__)+#   if (__GNUC__ >= 6)+#    define ASIO_HAS_VARIADIC_LAMBDA_CAPTURES 1+#   endif // (__GNUC__ >= 6)+#  elif defined(ASIO_MSVC)+#   if (_MSVC_LANG >= 201103)+#    define ASIO_HAS_VARIADIC_LAMBDA_CAPTURES 1+#   endif // (_MSC_LANG >= 201103)+#  else // defined(ASIO_MSVC)+#   if (__cplusplus >= 201103)+#    define ASIO_HAS_VARIADIC_LAMBDA_CAPTURES 1+#   endif // (__cplusplus >= 201103)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_VARIADIC_LAMBDA_CAPTURES)+#endif // !defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)++// Support for the alignof operator.+#if !defined(ASIO_HAS_ALIGNOF)+# if !defined(ASIO_DISABLE_ALIGNOF)+#  if (__cplusplus >= 201103)+#   define ASIO_HAS_ALIGNOF 1+#  endif // (__cplusplus >= 201103)+# endif // !defined(ASIO_DISABLE_ALIGNOF)+#endif // !defined(ASIO_HAS_ALIGNOF)++#if defined(ASIO_HAS_ALIGNOF)+# define ASIO_ALIGNOF(T) alignof(T)+# if defined(__STDCPP_DEFAULT_NEW_ALIGNMENT__)+#  define ASIO_DEFAULT_ALIGN __STDCPP_DEFAULT_NEW_ALIGNMENT__+# elif defined(__GNUC__)+#  if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+#   define ASIO_DEFAULT_ALIGN alignof(std::max_align_t)+#  else // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+#   define ASIO_DEFAULT_ALIGN alignof(max_align_t)+#  endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)+# else // defined(__GNUC__)+#  define ASIO_DEFAULT_ALIGN alignof(std::max_align_t)+# endif // defined(__GNUC__)+#else // defined(ASIO_HAS_ALIGNOF)+# define ASIO_ALIGNOF(T) 1+# define ASIO_DEFAULT_ALIGN 1+#endif // defined(ASIO_HAS_ALIGNOF)++// Support for user-defined literals.+#if !defined(ASIO_HAS_USER_DEFINED_LITERALS)+# if !defined(ASIO_DISABLE_USER_DEFINED_LITERALS)+#  if (__cplusplus >= 201103)+#   define ASIO_HAS_USER_DEFINED_LITERALS 1+#  elif defined(ASIO_MSVC)+#   if (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+#    define ASIO_HAS_USER_DEFINED_LITERALS 1+#   endif // (_MSC_VER >= 1900 && _MSVC_LANG >= 201103)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_USER_DEFINED_LITERALS)+#endif // !defined(ASIO_HAS_USER_DEFINED_LITERALS)++// Standard library support for aligned allocation.+#if !defined(ASIO_HAS_STD_ALIGNED_ALLOC)+# if !defined(ASIO_DISABLE_STD_ALIGNED_ALLOC)+#  if (__cplusplus >= 201703)+#   if defined(__clang__)+#    if defined(ASIO_HAS_CLANG_LIBCXX)+#     if (_LIBCPP_STD_VER > 14) && defined(_LIBCPP_HAS_ALIGNED_ALLOC) \+        && !defined(_LIBCPP_MSVCRT) && !defined(__MINGW32__)+#      if defined(__APPLE__)+#       if defined(__MAC_OS_X_VERSION_MIN_REQUIRED)+#        if (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)+#         define ASIO_HAS_STD_ALIGNED_ALLOC 1+#        endif // (__MAC_OS_X_VERSION_MIN_REQUIRED >= 101500)+#       elif defined(__IPHONE_OS_VERSION_MIN_REQUIRED)+#        if (__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)+#         define ASIO_HAS_STD_ALIGNED_ALLOC 1+#        endif // (__IPHONE_OS_VERSION_MIN_REQUIRED >= 130000)+#       elif defined(__TV_OS_VERSION_MIN_REQUIRED)+#        if (__TV_OS_VERSION_MIN_REQUIRED >= 130000)+#         define ASIO_HAS_STD_ALIGNED_ALLOC 1+#        endif // (__TV_OS_VERSION_MIN_REQUIRED >= 130000)+#       elif defined(__WATCH_OS_VERSION_MIN_REQUIRED)+#        if (__WATCH_OS_VERSION_MIN_REQUIRED >= 60000)+#         define ASIO_HAS_STD_ALIGNED_ALLOC 1+#        endif // (__WATCH_OS_VERSION_MIN_REQUIRED >= 60000)+#       endif // defined(__WATCH_OS_X_VERSION_MIN_REQUIRED)+#      else // defined(__APPLE__)+#       define ASIO_HAS_STD_ALIGNED_ALLOC 1+#      endif // defined(__APPLE__)+#     endif // (_LIBCPP_STD_VER > 14) && defined(_LIBCPP_HAS_ALIGNED_ALLOC)+            //   && !defined(_LIBCPP_MSVCRT) && !defined(__MINGW32__)+#    elif defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)+#     define ASIO_HAS_STD_ALIGNED_ALLOC 1+#    endif // defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)+#   elif defined(__GNUC__)+#    if ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 7)+#     if defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)+#      define ASIO_HAS_STD_ALIGNED_ALLOC 1+#     endif // defined(_GLIBCXX_HAVE_ALIGNED_ALLOC)+#    endif // ((__GNUC__ == 7) && (__GNUC_MINOR__ >= 4)) || (__GNUC__ > 7)+#   endif // defined(__GNUC__)+#  endif // (__cplusplus >= 201703)+# endif // !defined(ASIO_DISABLE_STD_ALIGNED_ALLOC)+#endif // !defined(ASIO_HAS_STD_ALIGNED_ALLOC)++// Standard library support for std::align.+#if !defined(ASIO_HAS_STD_ALIGN)+# if !defined(ASIO_DISABLE_STD_ALIGN)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_ALIGN 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_STD_ALIGN 1+#   endif // (__cplusplus >= 201103)+#  elif defined(__GNUC__)+#   if (__GNUC__ >= 6)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_ALIGN 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // (__GNUC__ >= 6)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1700)+#    define ASIO_HAS_STD_ALIGN 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_ALIGN)+#endif // !defined(ASIO_HAS_STD_ALIGN)+ // Standard library support for system errors. #if !defined(ASIO_HAS_STD_SYSTEM_ERROR) # if !defined(ASIO_DISABLE_STD_SYSTEM_ERROR)@@ -566,8 +765,7 @@ #     define ASIO_HAS_STD_SYSTEM_ERROR 1 #    endif // __has_include(<system_error>) #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_SYSTEM_ERROR 1@@ -617,8 +815,7 @@ #     define ASIO_HAS_STD_ARRAY 1 #    endif // __has_include(<array>) #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_ARRAY 1@@ -642,8 +839,7 @@ #   elif (__cplusplus >= 201103) #    define ASIO_HAS_STD_SHARED_PTR 1 #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 3)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_SHARED_PTR 1@@ -667,8 +863,7 @@ #   elif (__cplusplus >= 201103) #    define ASIO_HAS_STD_ALLOCATOR_ARG 1 #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_ALLOCATOR_ARG 1@@ -700,8 +895,7 @@ #     endif // __has_include(<atomic>) #    endif // (__clang_major__ >= 10) #   endif // defined(__apple_build_version__) && defined(_LIBCPP_VERSION)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_ATOMIC 1@@ -729,8 +923,7 @@ #     define ASIO_HAS_STD_CHRONO 1 #    endif // __has_include(<chrono>) #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_CHRONO 1@@ -773,6 +966,35 @@ # endif // !defined(ASIO_DISABLE_BOOST_DATE_TIME) #endif // !defined(ASIO_HAS_BOOST_DATE_TIME) +// Boost support for the Coroutine library.+#if !defined(ASIO_HAS_BOOST_COROUTINE)+# if !defined(ASIO_DISABLE_BOOST_COROUTINE)+#  define ASIO_HAS_BOOST_COROUTINE 1+# endif // !defined(ASIO_DISABLE_BOOST_COROUTINE)+#endif // !defined(ASIO_HAS_BOOST_COROUTINE)++// Boost support for the Context library's fibers.+#if !defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+# if !defined(ASIO_DISABLE_BOOST_CONTEXT_FIBER)+#  if defined(__clang__)+#   if (__cplusplus >= 201103)+#    define ASIO_HAS_BOOST_CONTEXT_FIBER 1+#   endif // (__cplusplus >= 201103)+#  elif defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_BOOST_CONTEXT_FIBER 1+#    endif // (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#   endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSVC_LANG >= 201103)+#    define ASIO_HAS_BOOST_CONTEXT_FIBER 1+#   endif // (_MSC_LANG >= 201103)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_BOOST_CONTEXT_FIBER)+#endif // !defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+ // Standard library support for addressof. #if !defined(ASIO_HAS_STD_ADDRESSOF) # if !defined(ASIO_DISABLE_STD_ADDRESSOF)@@ -782,8 +1004,7 @@ #   elif (__cplusplus >= 201103) #    define ASIO_HAS_STD_ADDRESSOF 1 #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 6)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_ADDRESSOF 1@@ -807,8 +1028,7 @@ #   elif (__cplusplus >= 201103) #    define ASIO_HAS_STD_FUNCTION 1 #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_FUNCTION 1@@ -823,6 +1043,30 @@ # endif // !defined(ASIO_DISABLE_STD_FUNCTION) #endif // !defined(ASIO_HAS_STD_FUNCTION) +// Standard library support for the reference_wrapper class.+#if !defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+# if !defined(ASIO_DISABLE_STD_REFERENCE_WRAPPER)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_REFERENCE_WRAPPER 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_STD_REFERENCE_WRAPPER 1+#   endif // (__cplusplus >= 201103)+#  elif defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_REFERENCE_WRAPPER 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_REFERENCE_WRAPPER 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_REFERENCE_WRAPPER)+#endif // !defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+ // Standard library support for type traits. #if !defined(ASIO_HAS_STD_TYPE_TRAITS) # if !defined(ASIO_DISABLE_STD_TYPE_TRAITS)@@ -834,8 +1078,7 @@ #     define ASIO_HAS_STD_TYPE_TRAITS 1 #    endif // __has_include(<type_traits>) #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_TYPE_TRAITS 1@@ -905,8 +1148,7 @@ #   elif (__cplusplus >= 201103) #    define ASIO_HAS_CSTDINT 1 #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_CSTDINT 1@@ -932,8 +1174,7 @@ #     define ASIO_HAS_STD_THREAD 1 #    endif // __has_include(<thread>) #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_THREAD 1@@ -959,8 +1200,7 @@ #     define ASIO_HAS_STD_MUTEX_AND_CONDVAR 1 #    endif // __has_include(<mutex>) #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif 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@@ -986,8 +1226,7 @@ #     define ASIO_HAS_STD_CALL_ONCE 1 #    endif // __has_include(<mutex>) #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_CALL_ONCE 1@@ -1013,8 +1252,7 @@ #     define ASIO_HAS_STD_FUTURE 1 #    endif // __has_include(<future>) #   endif // (__cplusplus >= 201103)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 7)) || (__GNUC__ > 4) #    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__) #     define ASIO_HAS_STD_FUTURE 1@@ -1029,6 +1267,32 @@ # endif // !defined(ASIO_DISABLE_STD_FUTURE) #endif // !defined(ASIO_HAS_STD_FUTURE) +// Standard library support for std::tuple.+#if !defined(ASIO_HAS_STD_TUPLE)+# if !defined(ASIO_DISABLE_STD_TUPLE)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_TUPLE 1+#   elif (__cplusplus >= 201103)+#    if __has_include(<tuple>)+#     define ASIO_HAS_STD_TUPLE 1+#    endif // __has_include(<tuple>)+#   endif // (__cplusplus >= 201103)+#  elif defined(__GNUC__)+#   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 8)) || (__GNUC__ > 4)+#    if (__cplusplus >= 201103) || defined(__GXX_EXPERIMENTAL_CXX0X__)+#     define ASIO_HAS_STD_TUPLE 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_TUPLE 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_TUPLE)+#endif // !defined(ASIO_HAS_STD_TUPLE)+ // Standard library support for std::string_view. #if !defined(ASIO_HAS_STD_STRING_VIEW) # if !defined(ASIO_DISABLE_STD_STRING_VIEW)@@ -1079,8 +1343,7 @@ #     endif // __has_include(<experimental/string_view>) #    endif // (__cplusplus >= 201402) #   endif // // defined(ASIO_HAS_CLANG_LIBCXX)-#  endif // defined(__clang__)-#  if defined(__GNUC__)+#  elif defined(__GNUC__) #   if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4) #    if (__cplusplus >= 201402) #     define ASIO_HAS_STD_EXPERIMENTAL_STRING_VIEW 1@@ -1104,14 +1367,17 @@ // 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 defined(__clang__)+#   if (__cplusplus >= 201103)+#    define ASIO_HAS_STD_IOSTREAM_MOVE 1+#   endif // (__cplusplus >= 201103)+#  elif 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)+#  elif defined(ASIO_MSVC) #   if (_MSC_VER >= 1700) #    define ASIO_HAS_STD_IOSTREAM_MOVE 1 #   endif // (_MSC_VER >= 1700)@@ -1126,6 +1392,10 @@ #   if (_MSC_VER >= 1911 && _MSVC_LANG >= 201703) #    define ASIO_HAS_STD_INVOKE_RESULT 1 #   endif // (_MSC_VER >= 1911 && _MSVC_LANG >= 201703)+#  else // defined(ASIO_MSVC)+#   if (__cplusplus >= 201703)+#    define ASIO_HAS_STD_INVOKE_RESULT 1+#   endif // (__cplusplus >= 201703) #  endif // defined(ASIO_MSVC) # endif // !defined(ASIO_DISABLE_STD_INVOKE_RESULT) #endif // !defined(ASIO_HAS_STD_INVOKE_RESULT)@@ -1202,6 +1472,30 @@ # endif // !defined(ASIO_DISABLE_STD_ANY) #endif // !defined(ASIO_HAS_STD_ANY) +// Standard library support for std::variant.+#if !defined(ASIO_HAS_STD_VARIANT)+# if !defined(ASIO_DISABLE_STD_VARIANT)+#  if defined(__clang__)+#   if (__cplusplus >= 201703)+#    if __has_include(<variant>)+#     define ASIO_HAS_STD_VARIANT 1+#    endif // __has_include(<variant>)+#   endif // (__cplusplus >= 201703)+#  elif defined(__GNUC__)+#   if (__GNUC__ >= 7)+#    if (__cplusplus >= 201703)+#     define ASIO_HAS_STD_VARIANT 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_VARIANT 1+#   endif // (_MSC_VER >= 1910) && (_MSVC_LANG >= 201703)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_VARIANT)+#endif // !defined(ASIO_HAS_STD_VARIANT)+ // Standard library support for std::source_location. #if !defined(ASIO_HAS_STD_SOURCE_LOCATION) # if !defined(ASIO_DISABLE_STD_SOURCE_LOCATION)@@ -1233,6 +1527,50 @@ # endif // !defined(ASIO_DISABLE_SOURCE_LOCATION) #endif // !defined(ASIO_HAS_SOURCE_LOCATION) +// Boost support for source_location and system errors.+#if !defined(ASIO_HAS_BOOST_SOURCE_LOCATION)+# if !defined(ASIO_DISABLE_BOOST_SOURCE_LOCATION)+#  if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 107900)+#   define ASIO_HAS_BOOST_SOURCE_LOCATION 1+#  endif // defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 107900)+# endif // !defined(ASIO_DISABLE_BOOST_SOURCE_LOCATION)+#endif // !defined(ASIO_HAS_BOOST_SOURCE_LOCATION)++// Helper macros for working with Boost source locations.+#if defined(ASIO_HAS_BOOST_SOURCE_LOCATION)+# define ASIO_SOURCE_LOCATION_PARAM \+  , const boost::source_location& loc+# define ASIO_SOURCE_LOCATION_DEFAULTED_PARAM \+  , const boost::source_location& loc = BOOST_CURRENT_LOCATION+# define ASIO_SOURCE_LOCATION_ARG , loc+#else // if defined(ASIO_HAS_BOOST_SOURCE_LOCATION)+# define ASIO_SOURCE_LOCATION_PARAM+# define ASIO_SOURCE_LOCATION_DEFAULTED_PARAM+# define ASIO_SOURCE_LOCATION_ARG+#endif // if defined(ASIO_HAS_BOOST_SOURCE_LOCATION)++// Standard library support for std::index_sequence.+#if !defined(ASIO_HAS_STD_INDEX_SEQUENCE)+# if !defined(ASIO_DISABLE_STD_INDEX_SEQUENCE)+#  if defined(__clang__)+#   if (__cplusplus >= 201402)+#    define ASIO_HAS_STD_INDEX_SEQUENCE 1+#   endif // (__cplusplus >= 201402)+#  elif defined(__GNUC__)+#   if (__GNUC__ >= 7)+#    if (__cplusplus >= 201402)+#     define ASIO_HAS_STD_INDEX_SEQUENCE 1+#    endif // (__cplusplus >= 201402)+#   endif // (__GNUC__ >= 7)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1910) && (_MSVC_LANG >= 201402)+#    define ASIO_HAS_STD_INDEX_SEQUENCE 1+#   endif // (_MSC_VER >= 1910) && (_MSVC_LANG >= 201402)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_INDEX_SEQUENCE)+#endif // !defined(ASIO_HAS_STD_INDEX_SEQUENCE)+ // Windows App target. Windows but with a limited API. #if !defined(ASIO_WINDOWS_APP) # if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0603)@@ -1394,6 +1732,13 @@ # endif // !defined(ASIO_HAS_TIMERFD) #endif // defined(__linux__) +// Linux: io_uring is used instead of epoll.+#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# if !defined(ASIO_HAS_EPOLL) && defined(ASIO_HAS_IO_URING)+#  define ASIO_HAS_IO_URING_AS_DEFAULT 1+# endif // !defined(ASIO_HAS_EPOLL) && defined(ASIO_HAS_IO_URING)+#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ // Mac OS X, FreeBSD, NetBSD, OpenBSD: kqueue. #if (defined(__MACH__) && defined(__APPLE__)) \   || defined(__FreeBSD__) \@@ -1489,16 +1834,40 @@ // 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__)+#  if !defined(ASIO_WINDOWS_RUNTIME) #   define ASIO_HAS_LOCAL_SOCKETS 1-#  endif // !defined(ASIO_WINDOWS)-         //   && !defined(ASIO_WINDOWS_RUNTIME)-         //   && !defined(__CYGWIN__)+#  endif // !defined(ASIO_WINDOWS_RUNTIME) # endif // !defined(ASIO_DISABLE_LOCAL_SOCKETS) #endif // !defined(ASIO_HAS_LOCAL_SOCKETS) +// Files.+#if !defined(ASIO_HAS_FILE)+# if !defined(ASIO_DISABLE_FILE)+#  if defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)+#   define ASIO_HAS_FILE 1+#  elif defined(ASIO_HAS_IO_URING)+#   define ASIO_HAS_FILE 1+#  endif // defined(ASIO_HAS_IO_URING)+# endif // !defined(ASIO_DISABLE_FILE)+#endif // !defined(ASIO_HAS_FILE)++// Pipes.+#if !defined(ASIO_HAS_PIPE)+# if defined(ASIO_HAS_IOCP) \+  || !defined(ASIO_WINDOWS) \+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(__CYGWIN__)+#  if !defined(__SYMBIAN32__)+#   if !defined(ASIO_DISABLE_PIPE)+#    define ASIO_HAS_PIPE 1+#   endif // !defined(ASIO_DISABLE_PIPE)+#  endif // !defined(__SYMBIAN32__)+# endif // defined(ASIO_HAS_IOCP)+        //   || !defined(ASIO_WINDOWS)+        //   && !defined(ASIO_WINDOWS_RUNTIME)+        //   && !defined(__CYGWIN__)+#endif // !defined(ASIO_HAS_PIPE)+ // Can use sigaction() instead of signal(). #if !defined(ASIO_HAS_SIGACTION) # if !defined(ASIO_DISABLE_SIGACTION)@@ -1616,6 +1985,15 @@ # endif // !defined(ASIO_DISABLE_BOOST_STATIC_CONSTANT) #endif // !defined(ASIO_STATIC_CONSTANT) +// Boost align library.+#if !defined(ASIO_HAS_BOOST_ALIGN)+# if !defined(ASIO_DISABLE_BOOST_ALIGN)+#  if defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105600)+#   define ASIO_HAS_BOOST_ALIGN 1+#  endif // defined(ASIO_HAS_BOOST_CONFIG) && (BOOST_VERSION >= 105600)+# endif // !defined(ASIO_DISABLE_BOOST_ALIGN)+#endif // !defined(ASIO_HAS_BOOST_ALIGN)+ // Boost array library. #if !defined(ASIO_HAS_BOOST_ARRAY) # if !defined(ASIO_DISABLE_BOOST_ARRAY)@@ -1766,22 +2144,51 @@ # define ASIO_UNUSED_VARIABLE #endif // !defined(ASIO_UNUSED_VARIABLE) +// Helper macro to tell the optimiser what may be assumed to be true.+#if defined(ASIO_MSVC)+# define ASIO_ASSUME(expr) __assume(expr)+#elif defined(__clang__)+# if __has_builtin(__builtin_assume)+#  define ASIO_ASSUME(expr) __builtin_assume(expr)+# endif // __has_builtin(__builtin_assume)+#elif defined(__GNUC__)+# if ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+#  define ASIO_ASSUME(expr) if (expr) {} else { __builtin_unreachable(); }+# endif // ((__GNUC__ == 4) && (__GNUC_MINOR__ >= 5)) || (__GNUC__ > 4)+#endif // defined(__GNUC__)+#if !defined(ASIO_ASSUME)+# define ASIO_ASSUME(expr) (void)0+#endif // !defined(ASIO_ASSUME)+ // 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 (_MSC_VER >= 1928) && (_MSVC_LANG >= 201705) && !defined(__clang__)+#    define ASIO_HAS_CO_AWAIT 1+#   elif (_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(__clang__)+#   if (__clang_major__ >= 14)+#    if (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902)+#     if __has_include(<coroutine>)+#      define ASIO_HAS_CO_AWAIT 1+#     endif // __has_include(<coroutine>)+#    elif (__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)+#   else // (__clang_major__ >= 14)+#    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)+#   endif // (__clang_major__ >= 14) #  elif defined(__GNUC__) #   if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902) #    if __has_include(<coroutine>)@@ -1795,7 +2202,19 @@ // Standard library support for coroutines. #if !defined(ASIO_HAS_STD_COROUTINE) # if !defined(ASIO_DISABLE_STD_COROUTINE)-#  if defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1928) && (_MSVC_LANG >= 201705)+#    define ASIO_HAS_STD_COROUTINE 1+#   endif // (_MSC_VER >= 1928) && (_MSVC_LANG >= 201705)+#  elif defined(__clang__)+#   if (__clang_major__ >= 14)+#    if (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902)+#     if __has_include(<coroutine>)+#      define ASIO_HAS_STD_COROUTINE 1+#     endif // __has_include(<coroutine>)+#    endif // (__cplusplus >= 202002) && (__cpp_impl_coroutine >= 201902)+#   endif // (__clang_major__ >= 14)+#  elif defined(__GNUC__) #   if (__cplusplus >= 201709) && (__cpp_impl_coroutine >= 201902) #    if __has_include(<coroutine>) #     define ASIO_HAS_STD_COROUTINE 1@@ -1818,5 +2237,73 @@ #if !defined(ASIO_NODISCARD) # define ASIO_NODISCARD #endif // !defined(ASIO_NODISCARD)++// Kernel support for MSG_NOSIGNAL.+#if !defined(ASIO_HAS_MSG_NOSIGNAL)+# if defined(__linux__)+#  define ASIO_HAS_MSG_NOSIGNAL 1+# elif defined(_POSIX_VERSION)+#  if (_POSIX_VERSION >= 200809L)+#   define ASIO_HAS_MSG_NOSIGNAL 1+#  endif // _POSIX_VERSION >= 200809L+# endif // defined(_POSIX_VERSION)+#endif // !defined(ASIO_HAS_MSG_NOSIGNAL)++// Standard library support for std::hash.+#if !defined(ASIO_HAS_STD_HASH)+# if !defined(ASIO_DISABLE_STD_HASH)+#  if defined(__clang__)+#   if defined(ASIO_HAS_CLANG_LIBCXX)+#    define ASIO_HAS_STD_HASH 1+#   elif (__cplusplus >= 201103)+#    define ASIO_HAS_STD_HASH 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_HASH 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_HASH 1+#   endif // (_MSC_VER >= 1700)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_HASH)+#endif // !defined(ASIO_HAS_STD_HASH)++// Standard library support for std::to_address.+#if !defined(ASIO_HAS_STD_TO_ADDRESS)+# if !defined(ASIO_DISABLE_STD_TO_ADDRESS)+#  if defined(__clang__)+#   if (__cplusplus >= 202002)+#    define ASIO_HAS_STD_TO_ADDRESS 1+#   endif // (__cplusplus >= 202002)+#  elif defined(__GNUC__)+#   if (__GNUC__ >= 8)+#    if (__cplusplus >= 202002)+#     define ASIO_HAS_STD_TO_ADDRESS 1+#    endif // (__cplusplus >= 202002)+#   endif // (__GNUC__ >= 8)+#  endif // defined(__GNUC__)+#  if defined(ASIO_MSVC)+#   if (_MSC_VER >= 1922) && (_MSVC_LANG >= 202002)+#    define ASIO_HAS_STD_TO_ADDRESS 1+#   endif // (_MSC_VER >= 1922) && (_MSVC_LANG >= 202002)+#  endif // defined(ASIO_MSVC)+# endif // !defined(ASIO_DISABLE_STD_TO_ADDRESS)+#endif // !defined(ASIO_HAS_STD_TO_ADDRESS)++// Standard library support for snprintf.+#if !defined(ASIO_HAS_SNPRINTF)+# if !defined(ASIO_DISABLE_SNPRINTF)+#  if defined(__apple_build_version__)+#    if (__clang_major__ >= 14)+#     define ASIO_HAS_SNPRINTF 1+#    endif // (__clang_major__ >= 14)+#  endif // defined(__apple_build_version__)+# endif // !defined(ASIO_DISABLE_SNPRINTF)+#endif // !defined(ASIO_HAS_SNPRINTF)  #endif // ASIO_DETAIL_CONFIG_HPP
link/modules/asio-standalone/asio/include/asio/detail/consuming_buffers.hpp view
@@ -2,7 +2,7 @@ // detail/consuming_buffers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,6 +20,7 @@ #include "asio/buffer.hpp" #include "asio/detail/buffer_sequence_adapter.hpp" #include "asio/detail/limits.hpp"+#include "asio/registered_buffer.hpp"  #include "asio/detail/push_options.hpp" @@ -268,6 +269,42 @@ };  #endif // !defined(ASIO_NO_DEPRECATED)++template <>+class consuming_buffers<mutable_buffer,+    mutable_registered_buffer, const mutable_buffer*>+  : public consuming_single_buffer<mutable_registered_buffer>+{+public:+  explicit consuming_buffers(const mutable_registered_buffer& buffer)+    : consuming_single_buffer<mutable_registered_buffer>(buffer)+  {+  }+};++template <>+class consuming_buffers<const_buffer,+    mutable_registered_buffer, const mutable_buffer*>+  : public consuming_single_buffer<mutable_registered_buffer>+{+public:+  explicit consuming_buffers(const mutable_registered_buffer& buffer)+    : consuming_single_buffer<mutable_registered_buffer>(buffer)+  {+  }+};++template <>+class consuming_buffers<const_buffer,+    const_registered_buffer, const const_buffer*>+  : public consuming_single_buffer<const_registered_buffer>+{+public:+  explicit consuming_buffers(const const_registered_buffer& buffer)+    : consuming_single_buffer<const_registered_buffer>(buffer)+  {+  }+};  template <typename Buffer, typename Elem> class consuming_buffers<Buffer, boost::array<Elem, 2>,
link/modules/asio-standalone/asio/include/asio/detail/cstddef.hpp view
@@ -2,7 +2,7 @@ // detail/cstddef.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/cstdint.hpp view
@@ -2,7 +2,7 @@ // detail/cstdint.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -38,6 +38,7 @@ using std::int_least64_t; using std::uint64_t; using std::uint_least64_t;+using std::uintptr_t; using std::uintmax_t; #else // defined(ASIO_HAS_CSTDINT) using boost::int16_t;@@ -52,6 +53,7 @@ using boost::int_least64_t; using boost::uint64_t; using boost::uint_least64_t;+using boost::uintptr_t; using boost::uintmax_t; #endif // defined(ASIO_HAS_CSTDINT) 
link/modules/asio-standalone/asio/include/asio/detail/date_time_fwd.hpp view
@@ -2,7 +2,7 @@ // detail/date_time_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/deadline_timer_service.hpp view
@@ -2,7 +2,7 @@ // detail/deadline_timer_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,8 @@  #include "asio/detail/config.hpp" #include <cstddef>+#include "asio/associated_cancellation_slot.hpp"+#include "asio/cancellation_type.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/detail/bind_handler.hpp"@@ -245,12 +247,22 @@   void async_wait(implementation_type& impl,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<op_cancellation>(this, &impl.timer_data);+    }+     impl.might_have_pending_waits = true;      ASIO_HANDLER_CREATION((scheduler_.context(),@@ -279,6 +291,34 @@     socket_ops::select(0, 0, 0, 0, &tv, ec); #endif // defined(ASIO_WINDOWS_RUNTIME)   }++  // Helper class used to implement per-operation cancellation.+  class op_cancellation+  {+  public:+    op_cancellation(deadline_timer_service* s,+        typename timer_queue<Time_Traits>::per_timer_data* p)+      : service_(s),+        timer_data_(p)+    {+    }++    void operator()(cancellation_type_t type)+    {+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        service_->scheduler_.cancel_timer_by_key(+            service_->timer_queue_, timer_data_, this);+      }+    }++  private:+    deadline_timer_service* service_;+    typename timer_queue<Time_Traits>::per_timer_data* timer_data_;+  };    // The queue of timers.   timer_queue<Time_Traits> timer_queue_;
link/modules/asio-standalone/asio/include/asio/detail/dependent_type.hpp view
@@ -2,7 +2,7 @@ // detail/dependent_type.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/descriptor_ops.hpp view
@@ -2,7 +2,7 @@ // detail/descriptor_ops.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,6 +24,7 @@ #include <cstddef> #include "asio/error.hpp" #include "asio/error_code.hpp"+#include "asio/detail/cstdint.hpp" #include "asio/detail/socket_types.hpp"  #include "asio/detail/push_options.hpp"@@ -55,7 +56,7 @@ {   if (!is_error_condition)   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);   }   else   {@@ -67,6 +68,9 @@ ASIO_DECL int open(const char* path, int flags,     asio::error_code& ec); +ASIO_DECL int open(const char* path, int flags, unsigned mode,+    asio::error_code& ec);+ ASIO_DECL int close(int d, state_type& state,     asio::error_code& ec); @@ -104,6 +108,42 @@ ASIO_DECL bool non_blocking_write1(int d,     const void* data, std::size_t size,     asio::error_code& ec, std::size_t& bytes_transferred);++#if defined(ASIO_HAS_FILE)++ASIO_DECL std::size_t sync_read_at(int d, state_type state,+    uint64_t offset, buf* bufs, std::size_t count, bool all_empty,+    asio::error_code& ec);++ASIO_DECL std::size_t sync_read_at1(int d, state_type state,+    uint64_t offset, void* data, std::size_t size,+    asio::error_code& ec);++ASIO_DECL bool non_blocking_read_at(int d, uint64_t offset,+    buf* bufs, std::size_t count, asio::error_code& ec,+    std::size_t& bytes_transferred);++ASIO_DECL bool non_blocking_read_at1(int d, uint64_t offset,+    void* data, std::size_t size, asio::error_code& ec,+    std::size_t& bytes_transferred);++ASIO_DECL std::size_t sync_write_at(int d, state_type state,+    uint64_t offset, const buf* bufs, std::size_t count, bool all_empty,+    asio::error_code& ec);++ASIO_DECL std::size_t sync_write_at1(int d, state_type state,+    uint64_t offset, const void* data, std::size_t size,+    asio::error_code& ec);++ASIO_DECL bool non_blocking_write_at(int d,+    uint64_t offset, const buf* bufs, std::size_t count,+    asio::error_code& ec, std::size_t& bytes_transferred);++ASIO_DECL bool non_blocking_write_at1(int d,+    uint64_t offset, const void* data, std::size_t size,+    asio::error_code& ec, std::size_t& bytes_transferred);++#endif // defined(ASIO_HAS_FILE)  ASIO_DECL int ioctl(int d, state_type& state, long cmd,     ioctl_arg_type* arg, asio::error_code& ec);
link/modules/asio-standalone/asio/include/asio/detail/descriptor_read_op.hpp view
@@ -2,7 +2,7 @@ // detail/descriptor_read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -26,6 +26,7 @@ #include "asio/detail/handler_work.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/reactor_op.hpp"+#include "asio/dispatch.hpp"  #include "asio/detail/push_options.hpp" @@ -48,6 +49,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     descriptor_read_op_base* o(static_cast<descriptor_read_op_base*>(base));      typedef buffer_sequence_adapter<asio::mutable_buffer,@@ -85,6 +87,9 @@   : public descriptor_read_op_base<MutableBufferSequence> { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(descriptor_read_op);    descriptor_read_op(const asio::error_code& success_ec,@@ -102,6 +107,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     descriptor_read_op* o(static_cast<descriptor_read_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -112,6 +118,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -131,6 +139,38 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/descriptor_write_op.hpp view
@@ -2,7 +2,7 @@ // detail/descriptor_write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -48,6 +48,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     descriptor_write_op_base* o(static_cast<descriptor_write_op_base*>(base));      typedef buffer_sequence_adapter<asio::const_buffer,@@ -85,6 +86,9 @@   : public descriptor_write_op_base<ConstBufferSequence> { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(descriptor_write_op);    descriptor_write_op(const asio::error_code& success_ec,@@ -102,6 +106,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     descriptor_write_op* o(static_cast<descriptor_write_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -112,6 +117,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -131,6 +138,38 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/dev_poll_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/dev_poll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -28,6 +28,7 @@ #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp" #include "asio/detail/reactor_op_queue.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp"@@ -41,7 +42,8 @@ namespace detail {  class dev_poll_reactor-  : public execution_context_service_base<dev_poll_reactor>+  : public execution_context_service_base<dev_poll_reactor>,+    public scheduler_task { public:   enum op_types { read_op = 0, write_op = 1,@@ -84,22 +86,44 @@       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);-  }+  void post_immediate_completion(operation* op, bool is_continuation) const; +  // Post a reactor operation for immediate completion.+  ASIO_DECL static void call_post_immediate_completion(+      operation* op, bool is_continuation, const void* self);+   // 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);+      bool is_continuation, bool allow_speculative,+      void (*on_immediate)(operation*, bool, const void*),+      const void* immediate_arg); +  // Start a new operation. The reactor operation will be performed when the+  // given descriptor is flagged as ready, or an error has occurred.+  void start_op(int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op,+      bool is_continuation, bool allow_speculative)+  {+    start_op(op_type, descriptor, descriptor_data,+        op, is_continuation, allow_speculative,+        &epoll_reactor::call_post_immediate_completion, this);+  }++   // 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 all operations associated with the given descriptor and key. The+  // handlers associated with the descriptor will be invoked with the+  // operation_aborted error.+  ASIO_DECL void cancel_ops_by_key(socket_type descriptor,+      per_descriptor_data& descriptor_data,+      int op_type, void* cancellation_key);+   // 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.@@ -137,6 +161,12 @@   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)());++  // Cancel the timer operations associated with the given key.+  template <typename Time_Traits>+  void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data* timer,+      void* cancellation_key);    // Move the timer operations associated with the given timer.   template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/epoll_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/epoll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,6 +25,7 @@ #include "asio/detail/object_pool.hpp" #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp"@@ -42,7 +43,8 @@ namespace detail {  class epoll_reactor-  : public execution_context_service_base<epoll_reactor>+  : public execution_context_service_base<epoll_reactor>,+    public scheduler_task { private:   // The mutex type used by this reactor.@@ -114,23 +116,44 @@       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);-  }+  void post_immediate_completion(operation* op, bool is_continuation) const; +  // Post a reactor operation for immediate completion.+  ASIO_DECL static void call_post_immediate_completion(+      operation* op, bool is_continuation, const void* self);+   // 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);+      bool is_continuation, bool allow_speculative,+      void (*on_immediate)(operation*, bool, const void*),+      const void* immediate_arg); +  // Start a new operation. The reactor operation will be performed when the+  // given descriptor is flagged as ready, or an error has occurred.+  void start_op(int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op,+      bool is_continuation, bool allow_speculative)+  {+    start_op(op_type, descriptor, descriptor_data,+        op, is_continuation, allow_speculative,+        &epoll_reactor::call_post_immediate_completion, this);+  }+   // 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 all operations associated with the given descriptor and key. The+  // handlers associated with the descriptor will be invoked with the+  // operation_aborted error.+  ASIO_DECL void cancel_ops_by_key(socket_type descriptor,+      per_descriptor_data& descriptor_data,+      int op_type, void* cancellation_key);+   // 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.@@ -169,6 +192,12 @@   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)());++  // Cancel the timer operations associated with the given key.+  template <typename Time_Traits>+  void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data* timer,+      void* cancellation_key);    // Move the timer operations associated with the given timer.   template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/event.hpp view
@@ -2,7 +2,7 @@ // detail/event.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/eventfd_select_interrupter.hpp view
@@ -2,7 +2,7 @@ // detail/eventfd_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
+ link/modules/asio-standalone/asio/include/asio/detail/exception.hpp view
@@ -0,0 +1,40 @@+//+// detail/exception.hpp+// ~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_EXCEPTION_HPP+#define ASIO_DETAIL_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_STD_EXCEPTION_PTR)+# include <exception>+#else // defined(ASIO_HAS_STD_EXCEPTION_PTR)+# include <boost/exception_ptr.hpp>+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)++namespace asio {++#if defined(ASIO_HAS_STD_EXCEPTION_PTR)+using std::exception_ptr;+using std::current_exception;+using std::rethrow_exception;+#else // defined(ASIO_HAS_STD_EXCEPTION_PTR)+using boost::exception_ptr;+using boost::current_exception;+using boost::rethrow_exception;+#endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)++} // namespace asio++#endif // ASIO_DETAIL_EXCEPTION_HPP
link/modules/asio-standalone/asio/include/asio/detail/executor_function.hpp view
@@ -2,7 +2,7 @@ // detail/executor_function.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,7 @@  #include "asio/detail/config.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"@@ -111,7 +112,7 @@     // Make the upcall if required.     if (call)     {-      function();+      asio_handler_invoke_helpers::invoke(function, function);     }   } 
link/modules/asio-standalone/asio/include/asio/detail/executor_op.hpp view
@@ -2,7 +2,7 @@ // detail/executor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -46,6 +46,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     executor_op* o(static_cast<executor_op*>(base));     Alloc allocator(o->allocator_);     ptr p = { detail::addressof(allocator), o, o };
link/modules/asio-standalone/asio/include/asio/detail/fd_set_adapter.hpp view
@@ -2,7 +2,7 @@ // detail/fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/functional.hpp view
@@ -2,7 +2,7 @@ // detail/functional.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -33,6 +33,12 @@ #endif // defined(ASIO_HAS_STD_FUNCTION)  } // namespace detail++#if defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+using std::ref;+using std::reference_wrapper;+#endif // defined(ASIO_HAS_STD_REFERENCE_WRAPPER)+ } // namespace asio  #endif // ASIO_DETAIL_FUNCTIONAL_HPP
link/modules/asio-standalone/asio/include/asio/detail/future.hpp view
@@ -2,7 +2,7 @@ // detail/future.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/gcc_arm_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/gcc_arm_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/gcc_hppa_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/gcc_hppa_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/gcc_sync_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/gcc_sync_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/gcc_x86_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/gcc_x86_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,7 +55,7 @@   {     int r = 0, m = 1;     __asm__ __volatile__ (-        "xchgl %0, %1" :+        "xchg{l} %0, %1" :         "=r"(r), "=m"(m) :         "0"(1), "m"(m) :         "memory", "cc");
link/modules/asio-standalone/asio/include/asio/detail/global.hpp view
@@ -2,7 +2,7 @@ // detail/global.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/handler_alloc_helpers.hpp view
@@ -2,7 +2,7 @@ // detail/handler_alloc_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,21 +51,24 @@ #endif // defined(ASIO_NO_DEPRECATED)  template <typename Handler>-inline void* allocate(std::size_t s, Handler& h)+inline void* allocate(std::size_t s, Handler& h,+    std::size_t align = ASIO_DEFAULT_ALIGN) { #if !defined(ASIO_HAS_HANDLER_HOOKS)-  return ::operator new(s);+  return asio::aligned_new(align, 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)+# 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)+      asio::detail::thread_context::top_of_thread_call_stack(),+      s, align);+# else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)+  return asio::aligned_new(align, s);+# endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) #else+  (void)align;   using asio::asio_handler_allocate;   return asio_handler_allocate(s, asio::detail::addressof(h)); #endif@@ -75,17 +78,17 @@ inline void deallocate(void* p, std::size_t s, Handler& h) { #if !defined(ASIO_HAS_HANDLER_HOOKS)-  ::operator delete(p);+  asio::aligned_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);+      asio::detail::thread_context::top_of_thread_call_stack(), p, s); #else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)   (void)s;-  ::operator delete(p);+  asio::aligned_delete(p); #endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) #else   using asio::asio_handler_deallocate;@@ -124,7 +127,8 @@   T* allocate(std::size_t n)   {     return static_cast<T*>(-        asio_handler_alloc_helpers::allocate(sizeof(T) * n, handler_));+        asio_handler_alloc_helpers::allocate(+          sizeof(T) * n, handler_, ASIO_ALIGNOF(T)));   }    void deallocate(T* p, std::size_t n)
link/modules/asio-standalone/asio/include/asio/detail/handler_cont_helpers.hpp view
@@ -2,7 +2,7 @@ // detail/handler_cont_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/handler_invoke_helpers.hpp view
@@ -2,7 +2,7 @@ // detail/handler_invoke_helpers.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/handler_tracking.hpp view
@@ -2,7 +2,7 @@ // detail/handler_tracking.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/handler_type_requirements.hpp view
@@ -2,7 +2,7 @@ // detail/handler_type_requirements.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -64,7 +64,7 @@ auto zero_arg_copyable_handler_test(Handler h, void*)   -> decltype(     sizeof(Handler(static_cast<const Handler&>(h))),-    ((h)()),+    (ASIO_MOVE_OR_LVALUE(Handler)(h)()),     char(0));  template <typename Handler>@@ -74,7 +74,7 @@ auto one_arg_handler_test(Handler h, Arg1* a1)   -> decltype(     sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),-    ((h)(*a1)),+    (ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1)),     char(0));  template <typename Handler>@@ -84,7 +84,7 @@ auto two_arg_handler_test(Handler h, Arg1* a1, Arg2* a2)   -> decltype(     sizeof(Handler(ASIO_MOVE_CAST(Handler)(h))),-    ((h)(*a1, *a2)),+    (ASIO_MOVE_OR_LVALUE(Handler)(h)(*a1, *a2)),     char(0));  template <typename Handler>@@ -94,7 +94,8 @@ 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))),+    (ASIO_MOVE_OR_LVALUE(Handler)(h)(+      *a1, ASIO_MOVE_CAST(Arg2)(*a2))),     char(0));  template <typename Handler>@@ -116,9 +117,11 @@ #if defined(ASIO_HAS_MOVE) template <typename T> T rvref(); template <typename T> T rvref(T);+template <typename T> T rorlvref(); #else // defined(ASIO_HAS_MOVE) template <typename T> const T& rvref(); template <typename T> const T& rvref(T);+template <typename T> T& rorlvref(); #endif // defined(ASIO_HAS_MOVE) template <typename T> char argbyv(T); @@ -145,7 +148,7 @@           asio::detail::clvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()(), \         char(0))> ASIO_UNUSED_TYPEDEF @@ -170,7 +173,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>(), \             asio::detail::lvref<const std::size_t>()), \@@ -197,7 +200,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>(), \             asio::detail::lvref<const std::size_t>()), \@@ -223,7 +226,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>()), \         char(0))> ASIO_UNUSED_TYPEDEF@@ -249,7 +252,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>(), \             asio::detail::rvref<socket_type>()), \@@ -275,7 +278,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>()), \         char(0))> ASIO_UNUSED_TYPEDEF@@ -301,7 +304,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>(), \             asio::detail::lvref<const endpoint_type>()), \@@ -328,7 +331,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>(), \             asio::detail::lvref<const iter_type>()), \@@ -355,7 +358,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>(), \             asio::detail::lvref<const range_type>()), \@@ -381,7 +384,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>()), \         char(0))> ASIO_UNUSED_TYPEDEF@@ -407,7 +410,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>(), \             asio::detail::lvref<const int>()), \@@ -433,7 +436,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>()), \         char(0))> ASIO_UNUSED_TYPEDEF@@ -459,7 +462,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \           asio::detail::lvref<const asio::error_code>(), \           asio::detail::lvref<const std::size_t>()), \@@ -485,7 +488,7 @@           asio::detail::rvref< \             asio_true_handler_type>())) + \       sizeof( \-        asio::detail::lvref< \+        asio::detail::rorlvref< \           asio_true_handler_type>()( \             asio::detail::lvref<const asio::error_code>()), \         char(0))> ASIO_UNUSED_TYPEDEF
link/modules/asio-standalone/asio/include/asio/detail/handler_work.hpp view
@@ -2,7 +2,7 @@ // detail/handler_work.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,9 +16,13 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"+#include "asio/associated_allocator.hpp" #include "asio/associated_executor.hpp"+#include "asio/associated_immediate_executor.hpp" #include "asio/detail/handler_invoke_helpers.hpp"+#include "asio/detail/initiate_dispatch.hpp" #include "asio/detail/type_traits.hpp"+#include "asio/detail/work_dispatcher.hpp" #include "asio/execution/allocator.hpp" #include "asio/execution/blocking.hpp" #include "asio/execution/execute.hpp"@@ -34,6 +38,13 @@ class executor; class io_context; +#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++class any_completion_executor;+class any_io_executor;++#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+ namespace execution {  #if defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -56,14 +67,14 @@ class handler_work_base { public:-  explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT+  explicit handler_work_base(int, int, 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+  handler_work_base(bool /*base1_owns_work*/, const Executor& ex,+      const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT     : executor_(asio::prefer(ex, execution::outstanding_work.tracked))   {   }@@ -88,11 +99,16 @@   template <typename Function, typename Handler>   void dispatch(Function& function, Handler& handler)   {+#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(executor_,+        execution::allocator((get_associated_allocator)(handler))+      ).execute(ASIO_MOVE_CAST(Function)(function));+#else // defined(ASIO_NO_DEPRECATED)     execution::execute(         asio::prefer(executor_,-          execution::blocking.possibly,           execution::allocator((get_associated_allocator)(handler))),         ASIO_MOVE_CAST(Function)(function));+#endif // defined(ASIO_NO_DEPRECATED)   }  private:@@ -116,14 +132,14 @@     >::type> { public:-  explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT+  explicit handler_work_base(int, int, const Executor& ex) ASIO_NOEXCEPT     : executor_(ex),       owns_work_(true)   {     executor_.on_work_started();   } -  handler_work_base(const Executor& ex,+  handler_work_base(bool /*base1_owns_work*/, const Executor& ex,       const Executor& candidate) ASIO_NOEXCEPT     : executor_(ex),       owns_work_(ex != candidate)@@ -133,8 +149,8 @@   }    template <typename OtherExecutor>-  handler_work_base(const Executor& ex,-      const OtherExecutor&) ASIO_NOEXCEPT+  handler_work_base(bool /*base1_owns_work*/, const Executor& ex,+      const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT     : executor_(ex),       owns_work_(true)   {@@ -191,7 +207,7 @@     >::type> { public:-  explicit handler_work_base(const Executor&)+  explicit handler_work_base(int, int, const Executor&)   {   } @@ -214,7 +230,7 @@ class handler_work_base<Executor, void, IoContext, Executor> { public:-  explicit handler_work_base(const Executor& ex) ASIO_NOEXCEPT+  explicit handler_work_base(int, int, const Executor& ex) ASIO_NOEXCEPT #if !defined(ASIO_NO_TYPEID)     : executor_(         ex.target_type() == typeid(typename IoContext::executor_type)@@ -227,7 +243,7 @@       executor_.on_work_started();   } -  handler_work_base(const Executor& ex,+  handler_work_base(bool /*base1_owns_work*/, const Executor& ex,       const Executor& candidate) ASIO_NOEXCEPT     : executor_(ex != candidate ? ex : Executor())   {@@ -286,14 +302,15 @@     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>+    typename CandidateExecutor, 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>+    CandidateExecutor, IoContext, PolymorphicExecutor> { public:   typedef@@ -304,7 +321,8 @@ #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)     executor_type; -  explicit handler_work_base(const executor_type& ex) ASIO_NOEXCEPT+  explicit handler_work_base(int, int,+      const executor_type& ex) ASIO_NOEXCEPT #if !defined(ASIO_NO_TYPEID)     : executor_(         ex.target_type() == typeid(typename IoContext::executor_type)@@ -316,15 +334,18 @@   {   } -  handler_work_base(const executor_type& ex,+  handler_work_base(bool base1_owns_work, const executor_type& ex,       const executor_type& candidate) ASIO_NOEXCEPT-    : executor_(ex != candidate ? ex : executor_type())+    : executor_(+        !base1_owns_work && ex == candidate+          ? executor_type()+          : asio::prefer(ex, execution::outstanding_work.tracked))   {   }    template <typename OtherExecutor>-  handler_work_base(const executor_type& ex,-      const OtherExecutor&) ASIO_NOEXCEPT+  handler_work_base(bool /*base1_owns_work*/, const executor_type& ex,+      const OtherExecutor& /*candidate*/) ASIO_NOEXCEPT     : executor_(asio::prefer(ex, execution::outstanding_work.tracked))   {   }@@ -347,19 +368,96 @@   }    template <typename Function, typename Handler>-  void dispatch(Function& function, Handler& handler)+  void dispatch(Function& function, Handler&)   {-    execution::execute(-        asio::prefer(executor_,-          execution::blocking.possibly,-          execution::allocator((get_associated_allocator)(handler))),-        ASIO_MOVE_CAST(Function)(function));+#if defined(ASIO_NO_DEPRECATED)+    executor_.execute(ASIO_MOVE_CAST(Function)(function));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(executor_, ASIO_MOVE_CAST(Function)(function));+#endif // defined(ASIO_NO_DEPRECATED)   }  private:   executor_type executor_; }; +#if !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++template <typename Executor, typename CandidateExecutor,+    typename IoContext, typename PolymorphicExecutor>+class handler_work_base<+    Executor, CandidateExecutor,+    IoContext, PolymorphicExecutor,+    typename enable_if<+      is_same<Executor, any_completion_executor>::value+        || is_same<Executor, any_io_executor>::value+    >::type>+{+public:+  typedef Executor executor_type;++  explicit handler_work_base(int, int,+      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(bool base1_owns_work, const executor_type& ex,+      const executor_type& candidate) ASIO_NOEXCEPT+    : executor_(+        !base1_owns_work && ex == candidate+          ? executor_type()+          : asio::prefer(ex, execution::outstanding_work.tracked))+  {+  }++  template <typename OtherExecutor>+  handler_work_base(bool /*base1_owns_work*/, const executor_type& ex,+      const OtherExecutor& /*candidate*/) 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&)+  {+#if defined(ASIO_NO_DEPRECATED)+    executor_.execute(ASIO_MOVE_CAST(Function)(function));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(executor_, ASIO_MOVE_CAST(Function)(function));+#endif // defined(ASIO_NO_DEPRECATED)+  }++private:+  executor_type executor_;+};++#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)+ template <typename Handler, typename IoExecutor, typename = void> class handler_work :   handler_work_base<IoExecutor>,@@ -372,8 +470,9 @@     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)+    : base1_type(0, 0, io_ex),+      base2_type(base1_type::owns_work(),+          asio::get_associated_executor(handler, io_ex), io_ex)   {   } @@ -409,7 +508,7 @@   typedef handler_work_base<IoExecutor> base1_type;    handler_work(Handler&, const IoExecutor& io_ex) ASIO_NOEXCEPT-    : base1_type(io_ex)+    : base1_type(0, 0, io_ex)   {   } @@ -428,6 +527,34 @@       base1_type::dispatch(function, handler);     }   }+};++template <typename Handler, typename IoExecutor>+class immediate_handler_work+{+public:+  typedef handler_work<Handler, IoExecutor> handler_work_type;++  explicit immediate_handler_work(ASIO_MOVE_ARG(handler_work_type) w)+    : handler_work_(ASIO_MOVE_CAST(handler_work_type)(w))+  {+  }++  template <typename Function>+  void complete(Function& function, Handler& handler, const void* io_ex)+  {+    typedef typename associated_immediate_executor<Handler, IoExecutor>::type+      immediate_ex_type;++    immediate_ex_type immediate_ex = (get_associated_immediate_executor)(+        handler, *static_cast<const IoExecutor*>(io_ex));++    (initiate_dispatch_with_executor<immediate_ex_type>(immediate_ex))(+        ASIO_MOVE_CAST(Function)(function));+  }++private:+  handler_work_type handler_work_; };  } // namespace detail
link/modules/asio-standalone/asio/include/asio/detail/hash_map.hpp view
@@ -2,7 +2,7 @@ // detail/hash_map.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp view
@@ -2,7 +2,7 @@ // detail/impl/buffer_sequence_adapter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/descriptor_ops.ipp view
@@ -2,7 +2,7 @@ // detail/impl/descriptor_ops.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -37,6 +37,14 @@   return result; } +int open(const char* path, int flags,+    unsigned mode, asio::error_code& ec)+{+  int result = ::open(path, flags, mode);+  get_last_error(ec, result < 0);+  return result;+}+ int close(int d, state_type& state, asio::error_code& ec) {   int result = 0;@@ -61,7 +69,18 @@         ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK); #else // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)       ioctl_arg_type arg = 0;+# if defined(ENOTTY)+      result = ::ioctl(d, FIONBIO, &arg);+      get_last_error(ec, result < 0);+      if (ec.value() == ENOTTY)+      {+        int flags = ::fcntl(d, F_GETFL, 0);+        if (flags >= 0)+          ::fcntl(d, F_SETFL, flags & ~O_NONBLOCK);+      }+# else // defined(ENOTTY)       ::ioctl(d, FIONBIO, &arg);+# endif // defined(ENOTTY) #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)       state &= ~non_blocking; @@ -95,6 +114,19 @@   ioctl_arg_type arg = (value ? 1 : 0);   int result = ::ioctl(d, FIONBIO, &arg);   get_last_error(ec, result < 0);+# if defined(ENOTTY)+  if (ec.value() == ENOTTY)+  {+    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);+    }+  }+# endif // defined(ENOTTY) #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)    if (result >= 0)@@ -145,6 +177,19 @@   ioctl_arg_type arg = (value ? 1 : 0);   int result = ::ioctl(d, FIONBIO, &arg);   get_last_error(ec, result < 0);+# if defined(ENOTTY)+  if (ec.value() == ENOTTY)+  {+    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);+    }+  }+# endif // defined(ENOTTY) #endif // defined(__SYMBIAN32__) || defined(__EMSCRIPTEN__)    if (result >= 0)@@ -171,7 +216,7 @@   // A request to read 0 bytes on a stream is a no-op.   if (all_empty)   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -217,7 +262,7 @@   // A request to read 0 bytes on a stream is a no-op.   if (size == 0)   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -339,7 +384,7 @@   // A request to write 0 bytes on a stream is a no-op.   if (all_empty)   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -378,7 +423,7 @@   // A request to write 0 bytes on a stream is a no-op.   if (size == 0)   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -466,6 +511,323 @@     return true;   } }++#if defined(ASIO_HAS_FILE)++std::size_t sync_read_at(int d, state_type state, uint64_t offset,+    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)+  {+    asio::error::clear(ec);+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset);+    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_read_at1(int d, state_type state, uint64_t offset,+    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)+  {+    asio::error::clear(ec);+    return 0;+  }++  // Read some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = ::pread(d, data, size, offset);+    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_at(int d, uint64_t offset, buf* bufs, std::size_t count,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  for (;;)+  {+    // Read some data.+    signed_size_type bytes = ::preadv(d, bufs, static_cast<int>(count), offset);+    get_last_error(ec, bytes < 0);++    // Check for EOF.+    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_read_at1(int d, uint64_t offset, void* data, std::size_t size,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  for (;;)+  {+    // Read some data.+    signed_size_type bytes = ::pread(d, data, size, offset);+    get_last_error(ec, bytes < 0);++    // Check for EOF.+    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_at(int d, state_type state, uint64_t offset,+    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)+  {+    asio::error::clear(ec);+    return 0;+  }++  // Write some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = ::pwritev(d,+        bufs, static_cast<int>(count), offset);+    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_write_at1(int d, state_type state, uint64_t offset,+    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)+  {+    asio::error::clear(ec);+    return 0;+  }++  // Write some data.+  for (;;)+  {+    // Try to complete the operation without blocking.+    signed_size_type bytes = ::pwrite(d, data, size, offset);+    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_at(int d, uint64_t offset,+    const buf* bufs, std::size_t count,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  for (;;)+  {+    // Write some data.+    signed_size_type bytes = ::pwritev(d,+        bufs, static_cast<int>(count), offset);+    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_write_at1(int d, uint64_t offset,+    const void* data, std::size_t size,+    asio::error_code& ec, std::size_t& bytes_transferred)+{+  for (;;)+  {+    // Write some data.+    signed_size_type bytes = ::pwrite(d, data, size, offset);+    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;+  }+}++#endif // defined(ASIO_HAS_FILE)  int ioctl(int d, state_type& state, long cmd,     ioctl_arg_type* arg, asio::error_code& ec)
link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/impl/dev_poll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,11 +19,19 @@  #if defined(ASIO_HAS_DEV_POLL) +#include "asio/detail/scheduler.hpp"+ #include "asio/detail/push_options.hpp"  namespace asio { namespace detail { +inline void dev_poll_reactor::post_immediate_completion(+    operation* op, bool is_continuation) const+{+  scheduler_.post_immediate_completion(op, is_continuation);+}+ template <typename Time_Traits> void dev_poll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) {@@ -66,6 +74,18 @@   lock.unlock();   scheduler_.post_deferred_completions(ops);   return n;+}++template <typename Time_Traits>+void dev_poll_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data* timer,+    void* cancellation_key)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer_by_key(timer, ops, cancellation_key);+  lock.unlock();+  scheduler_.post_deferred_completions(ops); }  template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.ipp view
@@ -2,7 +2,7 @@ // detail/impl/dev_poll_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -21,6 +21,7 @@  #include "asio/detail/dev_poll_reactor.hpp" #include "asio/detail/assert.hpp"+#include "asio/detail/scheduler.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" @@ -147,15 +148,24 @@ { } +void dev_poll_reactor::call_post_immediate_completion(+    operation* op, bool is_continuation, const void* self)+{+  static_cast<const dev_poll_reactor*>(self)->post_immediate_completion(+      op, is_continuation);+}+ 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)+    bool is_continuation, bool allow_speculative,+    void (*on_immediate)(operation*, bool, const void*),+    const void* immediate_arg) {   asio::detail::mutex::scoped_lock lock(mutex_);    if (shutdown_)   {-    post_immediate_completion(op, is_continuation);+    on_immediate(op, is_continuation, immediate_arg);     return;   } @@ -168,7 +178,7 @@         if (op->perform())         {           lock.unlock();-          scheduler_.post_immediate_completion(op, is_continuation);+          on_immediate(op, is_continuation, immediate_arg);           return;         }       }@@ -199,6 +209,19 @@ {   asio::detail::mutex::scoped_lock lock(mutex_);   cancel_ops_unlocked(descriptor, asio::error::operation_aborted);+}++void dev_poll_reactor::cancel_ops_by_key(socket_type descriptor,+    dev_poll_reactor::per_descriptor_data&,+    int op_type, void* cancellation_key)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  bool need_interrupt = op_queue_[op_type].cancel_operations_by_key(+      descriptor, ops, cancellation_key, asio::error::operation_aborted);+  scheduler_.post_deferred_completions(ops);+  if (need_interrupt)+    interrupter_.interrupt(); }  void dev_poll_reactor::deregister_descriptor(socket_type descriptor,
link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/impl/epoll_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,11 +17,19 @@  #if defined(ASIO_HAS_EPOLL) +#include "asio/detail/scheduler.hpp"+ #include "asio/detail/push_options.hpp"  namespace asio { namespace detail { +inline void epoll_reactor::post_immediate_completion(+    operation* op, bool is_continuation) const+{+  scheduler_.post_immediate_completion(op, is_continuation);+}+ template <typename Time_Traits> void epoll_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) {@@ -64,6 +72,18 @@   lock.unlock();   scheduler_.post_deferred_completions(ops);   return n;+}++template <typename Time_Traits>+void epoll_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data* timer,+    void* cancellation_key)+{+  mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer_by_key(timer, ops, cancellation_key);+  lock.unlock();+  scheduler_.post_deferred_completions(ops); }  template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.ipp view
@@ -2,7 +2,7 @@ // detail/impl/epoll_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -22,6 +22,7 @@ #include <cstddef> #include <sys/epoll.h> #include "asio/detail/epoll_reactor.hpp"+#include "asio/detail/scheduler.hpp" #include "asio/detail/throw_error.hpp" #include "asio/error.hpp" @@ -228,14 +229,23 @@   source_descriptor_data = 0; } +void epoll_reactor::call_post_immediate_completion(+    operation* op, bool is_continuation, const void* self)+{+  static_cast<const epoll_reactor*>(self)->post_immediate_completion(+      op, is_continuation);+}+ 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)+    bool is_continuation, bool allow_speculative,+    void (*on_immediate)(operation*, bool, const void*),+    const void* immediate_arg) {   if (!descriptor_data)   {     op->ec_ = asio::error::bad_descriptor;-    post_immediate_completion(op, is_continuation);+    on_immediate(op, is_continuation, immediate_arg);     return;   } @@ -243,7 +253,7 @@    if (descriptor_data->shutdown_)   {-    post_immediate_completion(op, is_continuation);+    on_immediate(op, is_continuation, immediate_arg);     return;   } @@ -261,7 +271,7 @@             if (descriptor_data->registered_events_ != 0)               descriptor_data->try_speculative_[op_type] = false;           descriptor_lock.unlock();-          scheduler_.post_immediate_completion(op, is_continuation);+          on_immediate(op, is_continuation, immediate_arg);           return;         }       }@@ -269,7 +279,7 @@       if (descriptor_data->registered_events_ == 0)       {         op->ec_ = asio::error::operation_not_supported;-        scheduler_.post_immediate_completion(op, is_continuation);+        on_immediate(op, is_continuation, immediate_arg);         return;       } @@ -288,7 +298,7 @@           {             op->ec_ = asio::error_code(errno,                 asio::error::get_system_category());-            scheduler_.post_immediate_completion(op, is_continuation);+            on_immediate(op, is_continuation, immediate_arg);             return;           }         }@@ -297,7 +307,7 @@     else if (descriptor_data->registered_events_ == 0)     {       op->ec_ = asio::error::operation_not_supported;-      scheduler_.post_immediate_completion(op, is_continuation);+      on_immediate(op, is_continuation, immediate_arg);       return;     }     else@@ -336,6 +346,35 @@       ops.push(op);     }   }++  descriptor_lock.unlock();++  scheduler_.post_deferred_completions(ops);+}++void epoll_reactor::cancel_ops_by_key(socket_type,+    epoll_reactor::per_descriptor_data& descriptor_data,+    int op_type, void* cancellation_key)+{+  if (!descriptor_data)+    return;++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  op_queue<operation> ops;+  op_queue<reactor_op> other_ops;+  while (reactor_op* op = descriptor_data->op_queue_[op_type].front())+  {+    descriptor_data->op_queue_[op_type].pop();+    if (op->cancellation_key_ == cancellation_key)+    {+      op->ec_ = asio::error::operation_aborted;+      ops.push(op);+    }+    else+      other_ops.push(op);+  }+  descriptor_data->op_queue_[op_type].push(other_ops);    descriptor_lock.unlock(); 
link/modules/asio-standalone/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp view
@@ -2,7 +2,7 @@ // detail/impl/eventfd_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -23,11 +23,11 @@ #include <sys/stat.h> #include <sys/types.h> #include <fcntl.h>-#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) # include <asm/unistd.h>-#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) # include <sys/eventfd.h>-#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) #include "asio/detail/cstdint.hpp" #include "asio/detail/eventfd_select_interrupter.hpp" #include "asio/detail/throw_error.hpp"@@ -45,14 +45,14 @@  void eventfd_select_interrupter::open_descriptors() {-#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)   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+#else // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__) # if defined(EFD_CLOEXEC) && defined(EFD_NONBLOCK)   write_descriptor_ = read_descriptor_ =     ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);@@ -69,7 +69,7 @@       ::fcntl(read_descriptor_, F_SETFD, FD_CLOEXEC);     }   }-#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8+#endif // __GLIBC__ == 2 && __GLIBC_MINOR__ < 8 && !defined(__UCLIBC__)    if (read_descriptor_ == -1)   {@@ -152,7 +152,9 @@         return false;       if (errno == EINTR)         continue;-      if (errno == EWOULDBLOCK || errno == EAGAIN)+      if (errno == EWOULDBLOCK)+        return true;+      if (errno == EAGAIN)         return true;       return false;     }
link/modules/asio-standalone/asio/include/asio/detail/impl/handler_tracking.ipp view
@@ -2,7 +2,7 @@ // detail/impl/handler_tracking.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -365,7 +365,9 @@   va_start(args, format);    char line[256] = "";-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+  int length = vsnprintf(line, sizeof(line), format, args);+#elif 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);
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_descriptor_service.ipp view
@@ -0,0 +1,205 @@+//+// detail/impl/io_uring_descriptor_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_IO_URING_DESCRIPTOR_SERVICE_IPP+#define ASIO_DETAIL_IMPL_IO_URING_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_HAS_IO_URING)++#include "asio/error.hpp"+#include "asio/detail/io_uring_descriptor_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++io_uring_descriptor_service::io_uring_descriptor_service(+    execution_context& context)+  : execution_context_service_base<io_uring_descriptor_service>(context),+    io_uring_service_(asio::use_service<io_uring_service>(context))+{+  io_uring_service_.init_task();+}++void io_uring_descriptor_service::shutdown()+{+}++void io_uring_descriptor_service::construct(+    io_uring_descriptor_service::implementation_type& impl)+{+  impl.descriptor_ = -1;+  impl.state_ = 0;+  impl.io_object_data_ = 0;+}++void io_uring_descriptor_service::move_construct(+    io_uring_descriptor_service::implementation_type& impl,+    io_uring_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;++  impl.io_object_data_ = other_impl.io_object_data_;+  other_impl.io_object_data_ = 0;+}++void io_uring_descriptor_service::move_assign(+    io_uring_descriptor_service::implementation_type& impl,+    io_uring_descriptor_service& /*other_service*/,+    io_uring_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;++  impl.io_object_data_ = other_impl.io_object_data_;+  other_impl.io_object_data_ = 0;+}++void io_uring_descriptor_service::destroy(+    io_uring_descriptor_service::implementation_type& impl)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((io_uring_service_.context(),+          "descriptor", &impl, impl.descriptor_, "close"));++    io_uring_service_.deregister_io_object(impl.io_object_data_);+    asio::error_code ignored_ec;+    descriptor_ops::close(impl.descriptor_, impl.state_, ignored_ec);+    io_uring_service_.cleanup_io_object(impl.io_object_data_);+  }+}++asio::error_code io_uring_descriptor_service::assign(+    io_uring_descriptor_service::implementation_type& impl,+    const native_handle_type& native_descriptor, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }++  io_uring_service_.register_io_object(impl.io_object_data_);++  impl.descriptor_ = native_descriptor;+  impl.state_ = descriptor_ops::possible_dup;+  ec = success_ec_;+  return ec;+}++asio::error_code io_uring_descriptor_service::close(+    io_uring_descriptor_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((io_uring_service_.context(),+          "descriptor", &impl, impl.descriptor_, "close"));++    io_uring_service_.deregister_io_object(impl.io_object_data_);+    descriptor_ops::close(impl.descriptor_, impl.state_, ec);+    io_uring_service_.cleanup_io_object(impl.io_object_data_);+  }+  else+  {+    ec = success_ec_;+  }++  // 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+  construct(impl);++  ASIO_ERROR_LOCATION(ec);+  return ec;+}++io_uring_descriptor_service::native_handle_type+io_uring_descriptor_service::release(+    io_uring_descriptor_service::implementation_type& impl)+{+  native_handle_type descriptor = impl.descriptor_;++  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((io_uring_service_.context(),+          "descriptor", &impl, impl.descriptor_, "release"));++    io_uring_service_.deregister_io_object(impl.io_object_data_);+    io_uring_service_.cleanup_io_object(impl.io_object_data_);+    construct(impl);+  }++  return descriptor;+}++asio::error_code io_uring_descriptor_service::cancel(+    io_uring_descriptor_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (!is_open(impl))+  {+    ec = asio::error::bad_descriptor;+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }++  ASIO_HANDLER_OPERATION((io_uring_service_.context(),+        "descriptor", &impl, impl.descriptor_, "cancel"));++  io_uring_service_.cancel_ops(impl.io_object_data_);+  ec = success_ec_;+  return ec;+}++void io_uring_descriptor_service::start_op(+    io_uring_descriptor_service::implementation_type& impl,+    int op_type, io_uring_operation* op, bool is_continuation, bool noop)+{+  if (!noop)+  {+    io_uring_service_.start_op(op_type,+        impl.io_object_data_, op, is_continuation);+  }+  else+  {+    io_uring_service_.post_immediate_completion(op, is_continuation);+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_DESCRIPTOR_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_file_service.ipp view
@@ -0,0 +1,140 @@+//+// detail/impl/io_uring_file_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_IO_URING_FILE_SERVICE_IPP+#define ASIO_DETAIL_IMPL_IO_URING_FILE_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_FILE) \+  && defined(ASIO_HAS_IO_URING)++#include <cstring>+#include <sys/stat.h>+#include "asio/detail/io_uring_file_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++io_uring_file_service::io_uring_file_service(+    execution_context& context)+  : execution_context_service_base<io_uring_file_service>(context),+    descriptor_service_(context)+{+}++void io_uring_file_service::shutdown()+{+  descriptor_service_.shutdown();+}++asio::error_code io_uring_file_service::open(+    io_uring_file_service::implementation_type& impl,+    const char* path, file_base::flags open_flags,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }++  descriptor_ops::state_type state = 0;+  int fd = descriptor_ops::open(path, static_cast<int>(open_flags), 0777, ec);+  if (fd < 0)+  {+    ASIO_ERROR_LOCATION(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);+  }++  (void)::posix_fadvise(native_handle(impl), 0, 0,+      impl.is_stream_ ? POSIX_FADV_SEQUENTIAL : POSIX_FADV_RANDOM);++  ASIO_ERROR_LOCATION(ec);+  return ec;+}++uint64_t io_uring_file_service::size(+    const io_uring_file_service::implementation_type& impl,+    asio::error_code& ec) const+{+  struct stat s;+  int result = ::fstat(native_handle(impl), &s);+  descriptor_ops::get_last_error(ec, result != 0);+  ASIO_ERROR_LOCATION(ec);+  return !ec ? s.st_size : 0;+}++asio::error_code io_uring_file_service::resize(+    io_uring_file_service::implementation_type& impl,+    uint64_t n, asio::error_code& ec)+{+  int result = ::ftruncate(native_handle(impl), n);+  descriptor_ops::get_last_error(ec, result != 0);+  ASIO_ERROR_LOCATION(ec);+  return ec;+}++asio::error_code io_uring_file_service::sync_all(+    io_uring_file_service::implementation_type& impl,+    asio::error_code& ec)+{+  int result = ::fsync(native_handle(impl));+  descriptor_ops::get_last_error(ec, result != 0);+  return ec;+}++asio::error_code io_uring_file_service::sync_data(+    io_uring_file_service::implementation_type& impl,+    asio::error_code& ec)+{+#if defined(_POSIX_SYNCHRONIZED_IO)+  int result = ::fdatasync(native_handle(impl));+#else // defined(_POSIX_SYNCHRONIZED_IO)+  int result = ::fsync(native_handle(impl));+#endif // defined(_POSIX_SYNCHRONIZED_IO)+  descriptor_ops::get_last_error(ec, result != 0);+  ASIO_ERROR_LOCATION(ec);+  return ec;+}++uint64_t io_uring_file_service::seek(+    io_uring_file_service::implementation_type& impl, int64_t offset,+    file_base::seek_basis whence, asio::error_code& ec)+{+  int64_t result = ::lseek(native_handle(impl), offset, whence);+  descriptor_ops::get_last_error(ec, result < 0);+  ASIO_ERROR_LOCATION(ec);+  return !ec ? static_cast<uint64_t>(result) : 0;+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+       //   && defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_FILE_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.hpp view
@@ -0,0 +1,112 @@+//+// detail/impl/io_uring_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_IO_URING_SERVICE_HPP+#define ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/scheduler.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++inline void io_uring_service::post_immediate_completion(+    operation* op, bool is_continuation)+{+  scheduler_.post_immediate_completion(op, is_continuation);+}++template <typename Time_Traits>+void io_uring_service::add_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_add_timer_queue(queue);+}++template <typename Time_Traits>+void io_uring_service::remove_timer_queue(timer_queue<Time_Traits>& queue)+{+  do_remove_timer_queue(queue);+}++template <typename Time_Traits>+void io_uring_service::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();+    post_submit_sqes_op(lock);+  }+}++template <typename Time_Traits>+std::size_t io_uring_service::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 io_uring_service::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data* timer,+    void* cancellation_key)+{+  mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer_by_key(timer, ops, cancellation_key);+  lock.unlock();+  scheduler_.post_deferred_completions(ops);+}++template <typename Time_Traits>+void io_uring_service::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_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.ipp view
@@ -0,0 +1,909 @@+//+// detail/impl/io_uring_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_IO_URING_SERVICE_IPP+#define ASIO_DETAIL_IMPL_IO_URING_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_IO_URING)++#include <cstddef>+#include <sys/eventfd.h>+#include "asio/detail/io_uring_service.hpp"+#include "asio/detail/reactor_op.hpp"+#include "asio/detail/scheduler.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++io_uring_service::io_uring_service(asio::execution_context& ctx)+  : execution_context_service_base<io_uring_service>(ctx),+    scheduler_(use_service<scheduler>(ctx)),+    mutex_(ASIO_CONCURRENCY_HINT_IS_LOCKING(+          REACTOR_REGISTRATION, scheduler_.concurrency_hint())),+    outstanding_work_(0),+    submit_sqes_op_(this),+    pending_sqes_(0),+    pending_submit_sqes_op_(false),+    shutdown_(false),+    timeout_(),+    registration_mutex_(mutex_.enabled()),+    reactor_(use_service<reactor>(ctx)),+    reactor_data_(),+    event_fd_(-1)+{+  reactor_.init_task();+  init_ring();+  register_with_reactor();+}++io_uring_service::~io_uring_service()+{+  if (ring_.ring_fd != -1)+    ::io_uring_queue_exit(&ring_);+  if (event_fd_ != -1)+    ::close(event_fd_);+}++void io_uring_service::shutdown()+{+  mutex::scoped_lock lock(mutex_);+  shutdown_ = true;+  lock.unlock();++  op_queue<operation> ops;++  // Cancel all outstanding operations.+  while (io_object* io_obj = registered_io_objects_.first())+  {+    for (int i = 0; i < max_ops; ++i)+    {+      if (!io_obj->queues_[i].op_queue_.empty())+      {+        ops.push(io_obj->queues_[i].op_queue_);+        if (::io_uring_sqe* sqe = get_sqe())+          ::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0);+      }+    }+    io_obj->shutdown_ = true;+    registered_io_objects_.free(io_obj);+  }++  // Cancel the timeout operation.+  if (::io_uring_sqe* sqe = get_sqe())+    ::io_uring_prep_cancel(sqe, &timeout_, IOSQE_IO_DRAIN);+  submit_sqes();++  // Wait for all completions to come back.+  for (; outstanding_work_ > 0; --outstanding_work_)+  {+    ::io_uring_cqe* cqe = 0;+    if (::io_uring_wait_cqe(&ring_, &cqe) != 0)+      break;+  }++  timer_queues_.get_all_timers(ops);++  scheduler_.abandon_operations(ops);+}++void io_uring_service::notify_fork(+    asio::execution_context::fork_event fork_ev)+{+  switch (fork_ev)+  {+  case asio::execution_context::fork_prepare:+    {+      // Cancel all outstanding operations. They will be restarted+      // after the fork completes.+      mutex::scoped_lock registration_lock(registration_mutex_);+      for (io_object* io_obj = registered_io_objects_.first();+          io_obj != 0; io_obj = io_obj->next_)+      {+        mutex::scoped_lock io_object_lock(io_obj->mutex_);+        for (int i = 0; i < max_ops; ++i)+        {+          if (!io_obj->queues_[i].op_queue_.empty()+              && !io_obj->queues_[i].cancel_requested_)+          {+            mutex::scoped_lock lock(mutex_);+            if (::io_uring_sqe* sqe = get_sqe())+              ::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0);+          }+        }+      }++      // Cancel the timeout operation.+      {+        mutex::scoped_lock lock(mutex_);+        if (::io_uring_sqe* sqe = get_sqe())+          ::io_uring_prep_cancel(sqe, &timeout_, IOSQE_IO_DRAIN);+        submit_sqes();+      }++      // Wait for all completions to come back, and post all completed I/O+      // queues to the scheduler. Note that some operations may have already+      // completed, or were explicitly cancelled. All others will be+      // automatically restarted.+      op_queue<operation> ops;+      for (; outstanding_work_ > 0; --outstanding_work_)+      {+        ::io_uring_cqe* cqe = 0;+        if (::io_uring_wait_cqe(&ring_, &cqe) != 0)+          break;+        if (void* ptr = ::io_uring_cqe_get_data(cqe))+        {+          if (ptr != this && ptr != &timer_queues_ && ptr != &timeout_)+          {+            io_queue* io_q = static_cast<io_queue*>(ptr);+            io_q->set_result(cqe->res);+            ops.push(io_q);+          }+        }+      }+      scheduler_.post_deferred_completions(ops);++      // Restart and eventfd operation.+      register_with_reactor();+    }+    break;++  case asio::execution_context::fork_parent:+    // Restart the timeout and eventfd operations.+    update_timeout();+    register_with_reactor();+    break;++  case asio::execution_context::fork_child:+    {+      // The child process gets a new io_uring instance.+      ::io_uring_queue_exit(&ring_);+      init_ring();+      register_with_reactor();+    }+    break;+  default:+    break;+  }+}++void io_uring_service::init_task()+{+  scheduler_.init_task();+}++void io_uring_service::register_io_object(+    io_uring_service::per_io_object_data& io_obj)+{+  io_obj = allocate_io_object();++  mutex::scoped_lock io_object_lock(io_obj->mutex_);++  io_obj->service_ = this;+  io_obj->shutdown_ = false;+  for (int i = 0; i < max_ops; ++i)+  {+    io_obj->queues_[i].io_object_ = io_obj;+    io_obj->queues_[i].cancel_requested_ = false;+  }+}++void io_uring_service::register_internal_io_object(+    io_uring_service::per_io_object_data& io_obj,+    int op_type, io_uring_operation* op)+{+  io_obj = allocate_io_object();++  mutex::scoped_lock io_object_lock(io_obj->mutex_);++  io_obj->service_ = this;+  io_obj->shutdown_ = false;+  for (int i = 0; i < max_ops; ++i)+  {+    io_obj->queues_[i].io_object_ = io_obj;+    io_obj->queues_[i].cancel_requested_ = false;+  }++  io_obj->queues_[op_type].op_queue_.push(op);+  io_object_lock.unlock();+  mutex::scoped_lock lock(mutex_);+  if (::io_uring_sqe* sqe = get_sqe())+  {+    op->prepare(sqe);+    ::io_uring_sqe_set_data(sqe, &io_obj->queues_[op_type]);+    post_submit_sqes_op(lock);+  }+  else+  {+    asio::error_code ec(ENOBUFS,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "io_uring_get_sqe");+  }+}++void io_uring_service::register_buffers(const ::iovec* v, unsigned n)+{+  int result = ::io_uring_register_buffers(&ring_, v, n);+  if (result < 0)+  {+    asio::error_code ec(-result,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "io_uring_register_buffers");+  }+}++void io_uring_service::unregister_buffers()+{+  (void)::io_uring_unregister_buffers(&ring_);+}++void io_uring_service::start_op(int op_type,+    io_uring_service::per_io_object_data& io_obj,+    io_uring_operation* op, bool is_continuation)+{+  if (!io_obj)+  {+    op->ec_ = asio::error::bad_descriptor;+    post_immediate_completion(op, is_continuation);+    return;+  }++  mutex::scoped_lock io_object_lock(io_obj->mutex_);++  if (io_obj->shutdown_)+  {+    io_object_lock.unlock();+    post_immediate_completion(op, is_continuation);+    return;+  }++  if (io_obj->queues_[op_type].op_queue_.empty())+  {+    if (op->perform(false))+    {+      io_object_lock.unlock();+      scheduler_.post_immediate_completion(op, is_continuation);+    }+    else+    {+      io_obj->queues_[op_type].op_queue_.push(op);+      io_object_lock.unlock();+      mutex::scoped_lock lock(mutex_);+      if (::io_uring_sqe* sqe = get_sqe())+      {+        op->prepare(sqe);+        ::io_uring_sqe_set_data(sqe, &io_obj->queues_[op_type]);+        scheduler_.work_started();+        post_submit_sqes_op(lock);+      }+      else+      {+        lock.unlock();+        io_obj->queues_[op_type].set_result(-ENOBUFS);+        post_immediate_completion(&io_obj->queues_[op_type], is_continuation);+      }+    }+  }+  else+  {+    io_obj->queues_[op_type].op_queue_.push(op);+    scheduler_.work_started();+  }+}++void io_uring_service::cancel_ops(io_uring_service::per_io_object_data& io_obj)+{+  if (!io_obj)+    return;++  mutex::scoped_lock io_object_lock(io_obj->mutex_);+  op_queue<operation> ops;+  do_cancel_ops(io_obj, ops);+  io_object_lock.unlock();+  scheduler_.post_deferred_completions(ops);+}++void io_uring_service::cancel_ops_by_key(+    io_uring_service::per_io_object_data& io_obj,+    int op_type, void* cancellation_key)+{+  if (!io_obj)+    return;++  mutex::scoped_lock io_object_lock(io_obj->mutex_);++  bool first = true;+  op_queue<operation> ops;+  op_queue<io_uring_operation> other_ops;+  while (io_uring_operation* op = io_obj->queues_[op_type].op_queue_.front())+  {+    io_obj->queues_[op_type].op_queue_.pop();+    if (op->cancellation_key_ == cancellation_key)+    {+      if (first)+      {+        other_ops.push(op);+        if (!io_obj->queues_[op_type].cancel_requested_)+        {+          io_obj->queues_[op_type].cancel_requested_ = true;+          mutex::scoped_lock lock(mutex_);+          if (::io_uring_sqe* sqe = get_sqe())+          {+            ::io_uring_prep_cancel(sqe, &io_obj->queues_[op_type], 0);+            submit_sqes();+          }+        }+      }+      else+      {+        op->ec_ = asio::error::operation_aborted;+        ops.push(op);+      }+    }+    else+      other_ops.push(op);+    first = false;+  }+  io_obj->queues_[op_type].op_queue_.push(other_ops);++  io_object_lock.unlock();++  scheduler_.post_deferred_completions(ops);+}++void io_uring_service::deregister_io_object(+    io_uring_service::per_io_object_data& io_obj)+{+  if (!io_obj)+    return;++  mutex::scoped_lock io_object_lock(io_obj->mutex_);+  if (!io_obj->shutdown_)+  {+    op_queue<operation> ops;+    bool pending_cancelled_ops = do_cancel_ops(io_obj, ops);+    io_obj->shutdown_ = true;+    io_object_lock.unlock();+    scheduler_.post_deferred_completions(ops);+    if (pending_cancelled_ops)+    {+      // There are still pending operations. Prevent cleanup_io_object from+      // freeing the I/O object and let the last operation to complete free it.+      io_obj = 0;+    }+    else+    {+      // Leave io_obj set so that it will be freed by the subsequent call to+      // cleanup_io_object.+    }+  }+  else+  {+    // We are shutting down, so prevent cleanup_io_object from freeing+    // the I/O object and let the destructor free it instead.+    io_obj = 0;+  }+}++void io_uring_service::cleanup_io_object(+    io_uring_service::per_io_object_data& io_obj)+{+  if (io_obj)+  {+    free_io_object(io_obj);+    io_obj = 0;+  }+}++void io_uring_service::run(long usec, op_queue<operation>& ops)+{+  __kernel_timespec ts;+  int local_ops = 0;++  if (usec > 0)+  {+    ts.tv_sec = usec / 1000000;+    ts.tv_nsec = (usec % 1000000) * 1000;+    mutex::scoped_lock lock(mutex_);+    if (::io_uring_sqe* sqe = get_sqe())+    {+      ++local_ops;+      ::io_uring_prep_timeout(sqe, &ts, 0, 0);+      ::io_uring_sqe_set_data(sqe, &ts);+      submit_sqes();+    }+  }++  ::io_uring_cqe* cqe = 0;+  int result = (usec == 0)+    ? ::io_uring_peek_cqe(&ring_, &cqe)+    : ::io_uring_wait_cqe(&ring_, &cqe);++  if (result == 0 && usec > 0)+  {+    if (::io_uring_cqe_get_data(cqe) != &ts)+    {+      mutex::scoped_lock lock(mutex_);+      if (::io_uring_sqe* sqe = get_sqe())+      {+        ++local_ops;+        ::io_uring_prep_timeout_remove(sqe, reinterpret_cast<__u64>(&ts), 0);+        submit_sqes();+      }+    }+  }++  bool check_timers = false;+  int count = 0;+  while (result == 0)+  {+    if (void* ptr = ::io_uring_cqe_get_data(cqe))+    {+      if (ptr == this)+      {+        // The io_uring service was interrupted.+      }+      else if (ptr == &timer_queues_)+      {+        check_timers = true;+      }+      else if (ptr == &timeout_)+      {+        check_timers = true;+        timeout_.tv_sec = 0;+        timeout_.tv_nsec = 0;+      }+      else if (ptr == &ts)+      {+        --local_ops;+      }+      else+      {+        io_queue* io_q = static_cast<io_queue*>(ptr);+        io_q->set_result(cqe->res);+        ops.push(io_q);+      }+    }+    ::io_uring_cqe_seen(&ring_, cqe);+    result = (++count < complete_batch_size || local_ops > 0)+      ? ::io_uring_peek_cqe(&ring_, &cqe) : -EAGAIN;+  }++  decrement(outstanding_work_, count);++  if (check_timers)+  {+    mutex::scoped_lock lock(mutex_);+    timer_queues_.get_ready_timers(ops);+    if (timeout_.tv_sec == 0 && timeout_.tv_nsec == 0)+    {+      timeout_ = get_timeout();+      if (::io_uring_sqe* sqe = get_sqe())+      {+        ::io_uring_prep_timeout(sqe, &timeout_, 0, 0);+        ::io_uring_sqe_set_data(sqe, &timeout_);+        push_submit_sqes_op(ops);+      }+    }+  }+}++void io_uring_service::interrupt()+{+  mutex::scoped_lock lock(mutex_);+  if (::io_uring_sqe* sqe = get_sqe())+  {+    ::io_uring_prep_nop(sqe);+    ::io_uring_sqe_set_data(sqe, this);+  }+  submit_sqes();+}++void io_uring_service::init_ring()+{+  int result = ::io_uring_queue_init(ring_size, &ring_, 0);+  if (result < 0)+  {+    ring_.ring_fd = -1;+    asio::error_code ec(-result,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "io_uring_queue_init");+  }++#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  event_fd_ = ::eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);+  if (event_fd_ < 0)+  {+    asio::error_code ec(-result,+        asio::error::get_system_category());+    ::io_uring_queue_exit(&ring_);+    asio::detail::throw_error(ec, "eventfd");+  }++  result = ::io_uring_register_eventfd(&ring_, event_fd_);+  if (result < 0)+  {+    ::close(event_fd_);+    ::io_uring_queue_exit(&ring_);+    asio::error_code ec(-result,+        asio::error::get_system_category());+    asio::detail::throw_error(ec, "io_uring_queue_init");+  }+#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+}++#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+class io_uring_service::event_fd_read_op :+  public reactor_op+{+public:+  event_fd_read_op(io_uring_service* s)+    : reactor_op(asio::error_code(),+        &event_fd_read_op::do_perform, event_fd_read_op::do_complete),+      service_(s)+  {+  }++  static status do_perform(reactor_op* base)+  {+    event_fd_read_op* o(static_cast<event_fd_read_op*>(base));++    for (;;)+    {+      // Only perform one read. The kernel maintains an atomic counter.+      uint64_t counter(0);+      errno = 0;+      int bytes_read = ::read(o->service_->event_fd_,+          &counter, sizeof(uint64_t));+      if (bytes_read < 0 && errno == EINTR)+        continue;+      break;+    }++    op_queue<operation> ops;+    o->service_->run(0, ops);+    o->service_->scheduler_.post_deferred_completions(ops);++    return not_done;+  }++  static void do_complete(void* /*owner*/, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    event_fd_read_op* o(static_cast<event_fd_read_op*>(base));+    delete o;+  }++private:+  io_uring_service* service_;+};+#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT)++void io_uring_service::register_with_reactor()+{+#if !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  reactor_.register_internal_descriptor(reactor::read_op,+      event_fd_, reactor_data_, new event_fd_read_op(this));+#endif // !defined(ASIO_HAS_IO_URING_AS_DEFAULT)+}++io_uring_service::io_object* io_uring_service::allocate_io_object()+{+  mutex::scoped_lock registration_lock(registration_mutex_);+  return registered_io_objects_.alloc(+      ASIO_CONCURRENCY_HINT_IS_LOCKING(+        REACTOR_IO, scheduler_.concurrency_hint()));+}++void io_uring_service::free_io_object(io_uring_service::io_object* io_obj)+{+  mutex::scoped_lock registration_lock(registration_mutex_);+  registered_io_objects_.free(io_obj);+}++bool io_uring_service::do_cancel_ops(+    per_io_object_data& io_obj, op_queue<operation>& ops)+{+  bool cancel_op = false;++  for (int i = 0; i < max_ops; ++i)+  {+    if (io_uring_operation* first_op = io_obj->queues_[i].op_queue_.front())+    {+      cancel_op = true;+      io_obj->queues_[i].op_queue_.pop();+      while (io_uring_operation* op = io_obj->queues_[i].op_queue_.front())+      {+        op->ec_ = asio::error::operation_aborted;+        io_obj->queues_[i].op_queue_.pop();+        ops.push(op);+      }+      io_obj->queues_[i].op_queue_.push(first_op);+    }+  }++  if (cancel_op)+  {+    mutex::scoped_lock lock(mutex_);+    for (int i = 0; i < max_ops; ++i)+    {+      if (!io_obj->queues_[i].op_queue_.empty()+          && !io_obj->queues_[i].cancel_requested_)+      {+        io_obj->queues_[i].cancel_requested_ = true;+        if (::io_uring_sqe* sqe = get_sqe())+          ::io_uring_prep_cancel(sqe, &io_obj->queues_[i], 0);+      }+    }+    submit_sqes();+  }++  return cancel_op;+}++void io_uring_service::do_add_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.insert(&queue);+}++void io_uring_service::do_remove_timer_queue(timer_queue_base& queue)+{+  mutex::scoped_lock lock(mutex_);+  timer_queues_.erase(&queue);+}++void io_uring_service::update_timeout()+{+  if (::io_uring_sqe* sqe = get_sqe())+  {+    ::io_uring_prep_timeout_remove(sqe, reinterpret_cast<__u64>(&timeout_), 0);+    ::io_uring_sqe_set_data(sqe, &timer_queues_);+  }+}++__kernel_timespec io_uring_service::get_timeout() const+{+  __kernel_timespec ts;+  long usec = timer_queues_.wait_duration_usec(5 * 60 * 1000 * 1000);+  ts.tv_sec = usec / 1000000;+  ts.tv_nsec = usec ? (usec % 1000000) * 1000 : 1;+  return ts;+}++::io_uring_sqe* io_uring_service::get_sqe()+{+  ::io_uring_sqe* sqe = ::io_uring_get_sqe(&ring_);+  if (!sqe)+  {+    submit_sqes();+    sqe = ::io_uring_get_sqe(&ring_);+  }+  if (sqe)+  {+    ::io_uring_sqe_set_data(sqe, 0);+    ++pending_sqes_;+  }+  return sqe;+}++void io_uring_service::submit_sqes()+{+  if (pending_sqes_ != 0)+  {+    int result = ::io_uring_submit(&ring_);+    if (result > 0)+    {+      pending_sqes_ -= result;+      increment(outstanding_work_, result);+    }+  }+}++void io_uring_service::post_submit_sqes_op(mutex::scoped_lock& lock)+{+  if (pending_sqes_ >= submit_batch_size)+  {+    submit_sqes();+  }+  else if (pending_sqes_ != 0 && !pending_submit_sqes_op_)+  {+    pending_submit_sqes_op_ = true;+    lock.unlock();+    scheduler_.post_immediate_completion(&submit_sqes_op_, false);+  }+}++void io_uring_service::push_submit_sqes_op(op_queue<operation>& ops)+{+  if (pending_sqes_ != 0 && !pending_submit_sqes_op_)+  {+    pending_submit_sqes_op_ = true;+    ops.push(&submit_sqes_op_);+    scheduler_.compensating_work_started();+  }+}++io_uring_service::submit_sqes_op::submit_sqes_op(io_uring_service* s)+  : operation(&io_uring_service::submit_sqes_op::do_complete),+    service_(s)+{+}++void io_uring_service::submit_sqes_op::do_complete(void* owner, operation* base,+    const asio::error_code& /*ec*/, std::size_t /*bytes_transferred*/)+{+  if (owner)+  {+    submit_sqes_op* o = static_cast<submit_sqes_op*>(base);+    mutex::scoped_lock lock(o->service_->mutex_);+    o->service_->submit_sqes();+    if (o->service_->pending_sqes_ != 0)+      o->service_->scheduler_.post_immediate_completion(o, true);+    else+      o->service_->pending_submit_sqes_op_ = false;+  }+}++io_uring_service::io_queue::io_queue()+  : operation(&io_uring_service::io_queue::do_complete)+{+}++struct io_uring_service::perform_io_cleanup_on_block_exit+{+  explicit perform_io_cleanup_on_block_exit(io_uring_service* s)+    : service_(s), io_object_to_free_(0), first_op_(0)+  {+  }++  ~perform_io_cleanup_on_block_exit()+  {+    if (io_object_to_free_)+    {+      mutex::scoped_lock lock(service_->mutex_);+      service_->free_io_object(io_object_to_free_);+    }++    if (first_op_)+    {+      // Post the remaining completed operations for invocation.+      if (!ops_.empty())+        service_->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.+      service_->scheduler_.compensating_work_started();+    }+  }++  io_uring_service* service_;+  io_object* io_object_to_free_;+  op_queue<operation> ops_;+  operation* first_op_;+};++operation* io_uring_service::io_queue::perform_io(int result)+{+  perform_io_cleanup_on_block_exit io_cleanup(io_object_->service_);+  mutex::scoped_lock io_object_lock(io_object_->mutex_);++  if (result != -ECANCELED || cancel_requested_)+  {+    if (io_uring_operation* op = op_queue_.front())+    {+      if (result < 0)+      {+        op->ec_.assign(-result, asio::error::get_system_category());+        op->bytes_transferred_ = 0;+      }+      else+      {+        op->ec_.assign(0, op->ec_.category());+        op->bytes_transferred_ = static_cast<std::size_t>(result);+      }+    }++    while (io_uring_operation* op = op_queue_.front())+    {+      if (op->perform(io_cleanup.ops_.empty()))+      {+        op_queue_.pop();+        io_cleanup.ops_.push(op);+      }+      else+        break;+    }+  }++  cancel_requested_ = false;++  if (!op_queue_.empty())+  {+    io_uring_service* service = io_object_->service_;+    mutex::scoped_lock lock(service->mutex_);+    if (::io_uring_sqe* sqe = service->get_sqe())+    {+      op_queue_.front()->prepare(sqe);+      ::io_uring_sqe_set_data(sqe, this);+      service->post_submit_sqes_op(lock);+    }+    else+    {+      lock.unlock();+      while (io_uring_operation* op = op_queue_.front())+      {+        op->ec_ = asio::error::no_buffer_space;+        op_queue_.pop();+        io_cleanup.ops_.push(op);+      }+    }+  }++  // The last operation to complete on a shut down object must free it.+  if (io_object_->shutdown_)+  {+    io_cleanup.io_object_to_free_ = io_object_;+    for (int i = 0; i < max_ops; ++i)+      if (!io_object_->queues_[i].op_queue_.empty())+        io_cleanup.io_object_to_free_ = 0;+  }++  // 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 io_uring_service::io_queue::do_complete(void* owner, operation* base,+    const asio::error_code& ec, std::size_t bytes_transferred)+{+  if (owner)+  {+    io_queue* io_q = static_cast<io_queue*>(base);+    int result = static_cast<int>(bytes_transferred);+    if (operation* op = io_q->perform_io(result))+    {+      op->complete(owner, ec, 0);+    }+  }+}++io_uring_service::io_object::io_object(bool locking)+  : mutex_(locking)+{+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_SERVICE_IPP
+ link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_socket_service_base.ipp view
@@ -0,0 +1,249 @@+//+// detail/io_uring_socket_service_base.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_IO_URING_SOCKET_SERVICE_BASE_IPP+#define ASIO_DETAIL_IMPL_IO_URING_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_IO_URING)++#include "asio/detail/io_uring_socket_service_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++io_uring_socket_service_base::io_uring_socket_service_base(+    execution_context& context)+  : io_uring_service_(asio::use_service<io_uring_service>(context))+{+  io_uring_service_.init_task();+}++void io_uring_socket_service_base::base_shutdown()+{+}++void io_uring_socket_service_base::construct(+    io_uring_socket_service_base::base_implementation_type& impl)+{+  impl.socket_ = invalid_socket;+  impl.state_ = 0;+  impl.io_object_data_ = 0;+}++void io_uring_socket_service_base::base_move_construct(+    io_uring_socket_service_base::base_implementation_type& impl,+    io_uring_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.io_object_data_ = other_impl.io_object_data_;+  other_impl.io_object_data_ = 0;+}++void io_uring_socket_service_base::base_move_assign(+    io_uring_socket_service_base::base_implementation_type& impl,+    io_uring_socket_service_base& /*other_service*/,+    io_uring_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;++  impl.io_object_data_ = other_impl.io_object_data_;+  other_impl.io_object_data_ = 0;+}++void io_uring_socket_service_base::destroy(+    io_uring_socket_service_base::base_implementation_type& impl)+{+  if (impl.socket_ != invalid_socket)+  {+    ASIO_HANDLER_OPERATION((io_uring_service_.context(),+          "socket", &impl, impl.socket_, "close"));++    io_uring_service_.deregister_io_object(impl.io_object_data_);+    asio::error_code ignored_ec;+    socket_ops::close(impl.socket_, impl.state_, true, ignored_ec);+    io_uring_service_.cleanup_io_object(impl.io_object_data_);+  }+}++asio::error_code io_uring_socket_service_base::close(+    io_uring_socket_service_base::base_implementation_type& impl,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ASIO_HANDLER_OPERATION((io_uring_service_.context(),+          "socket", &impl, impl.socket_, "close"));++    io_uring_service_.deregister_io_object(impl.io_object_data_);+    socket_ops::close(impl.socket_, impl.state_, false, ec);+    io_uring_service_.cleanup_io_object(impl.io_object_data_);+  }+  else+  {+    ec = success_ec_;+  }++  // 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+  construct(impl);++  return ec;+}++socket_type io_uring_socket_service_base::release(+    io_uring_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((io_uring_service_.context(),+        "socket", &impl, impl.socket_, "release"));++  io_uring_service_.deregister_io_object(impl.io_object_data_);+  io_uring_service_.cleanup_io_object(impl.io_object_data_);+  socket_type sock = impl.socket_;+  construct(impl);+  ec = success_ec_;+  return sock;+}++asio::error_code io_uring_socket_service_base::cancel(+    io_uring_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((io_uring_service_.context(),+        "socket", &impl, impl.socket_, "cancel"));++  io_uring_service_.cancel_ops(impl.io_object_data_);+  ec = success_ec_;+  return ec;+}++asio::error_code io_uring_socket_service_base::do_open(+    io_uring_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;++  io_uring_service_.register_io_object(impl.io_object_data_);++  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 = success_ec_;+  return ec;+}++asio::error_code io_uring_socket_service_base::do_assign(+    io_uring_socket_service_base::base_implementation_type& impl, int type,+    const io_uring_socket_service_base::native_handle_type& native_socket,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    return ec;+  }++  io_uring_service_.register_io_object(impl.io_object_data_);++  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 = success_ec_;+  return ec;+}++void io_uring_socket_service_base::start_op(+    io_uring_socket_service_base::base_implementation_type& impl,+    int op_type, io_uring_operation* op, bool is_continuation, bool noop)+{+  if (!noop)+  {+    io_uring_service_.start_op(op_type,+        impl.io_object_data_, op, is_continuation);+  }+  else+  {+    io_uring_service_.post_immediate_completion(op, is_continuation);+  }+}++void io_uring_socket_service_base::start_accept_op(+    io_uring_socket_service_base::base_implementation_type& impl,+    io_uring_operation* op, bool is_continuation, bool peer_is_open)+{+  if (!peer_is_open)+    start_op(impl, io_uring_service::read_op, op, is_continuation, false);+  else+  {+    op->ec_ = asio::error::already_open;+    io_uring_service_.post_immediate_completion(op, is_continuation);+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IMPL_IO_URING_SOCKET_SERVICE_BASE_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/impl/kqueue_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -20,11 +20,19 @@  #if defined(ASIO_HAS_KQUEUE) +#include "asio/detail/scheduler.hpp"+ #include "asio/detail/push_options.hpp"  namespace asio { namespace detail { +inline void kqueue_reactor::post_immediate_completion(+    operation* op, bool is_continuation) const+{+  scheduler_.post_immediate_completion(op, is_continuation);+}+ template <typename Time_Traits> void kqueue_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) {@@ -68,6 +76,18 @@   lock.unlock();   scheduler_.post_deferred_completions(ops);   return n;+}++template <typename Time_Traits>+void kqueue_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data* timer,+    void* cancellation_key)+{+  mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer_by_key(timer, ops, cancellation_key);+  lock.unlock();+  scheduler_.post_deferred_completions(ops); }  template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.ipp view
@@ -2,7 +2,7 @@ // detail/impl/kqueue_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -190,14 +190,23 @@   source_descriptor_data = 0; } +void kqueue_reactor::call_post_immediate_completion(+    operation* op, bool is_continuation, const void* self)+{+  static_cast<const kqueue_reactor*>(self)->post_immediate_completion(+      op, is_continuation);+}+ 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)+    bool is_continuation, bool allow_speculative,+    void (*on_immediate)(operation*, bool, const void*),+    const void* immediate_arg) {   if (!descriptor_data)   {     op->ec_ = asio::error::bad_descriptor;-    post_immediate_completion(op, is_continuation);+    on_immediate(op, is_continuation, immediate_arg);     return;   } @@ -205,7 +214,7 @@    if (descriptor_data->shutdown_)   {-    post_immediate_completion(op, is_continuation);+    on_immediate(op, is_continuation, immediate_arg);     return;   } @@ -220,7 +229,7 @@       if (op->perform())       {         descriptor_lock.unlock();-        scheduler_.post_immediate_completion(op, is_continuation);+        on_immediate(op, is_continuation, immediate_arg);         return;       } @@ -239,7 +248,7 @@         {           op->ec_ = asio::error_code(errno,               asio::error::get_system_category());-          scheduler_.post_immediate_completion(op, is_continuation);+          on_immediate(op, is_continuation, immediate_arg);           return;         }       }@@ -280,6 +289,35 @@       ops.push(op);     }   }++  descriptor_lock.unlock();++  scheduler_.post_deferred_completions(ops);+}++void kqueue_reactor::cancel_ops_by_key(socket_type,+    kqueue_reactor::per_descriptor_data& descriptor_data,+    int op_type, void* cancellation_key)+{+  if (!descriptor_data)+    return;++  mutex::scoped_lock descriptor_lock(descriptor_data->mutex_);++  op_queue<operation> ops;+  op_queue<reactor_op> other_ops;+  while (reactor_op* op = descriptor_data->op_queue_[op_type].front())+  {+    descriptor_data->op_queue_[op_type].pop();+    if (op->cancellation_key_ == cancellation_key)+    {+      op->ec_ = asio::error::operation_aborted;+      ops.push(op);+    }+    else+      other_ops.push(op);+  }+  descriptor_data->op_queue_[op_type].push(other_ops);    descriptor_lock.unlock(); 
link/modules/asio-standalone/asio/include/asio/detail/impl/null_event.ipp view
@@ -2,7 +2,7 @@ // detail/impl/null_event.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/pipe_select_interrupter.ipp view
@@ -2,7 +2,7 @@ // detail/impl/pipe_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/posix_event.ipp view
@@ -2,7 +2,7 @@ // detail/impl/posix_event.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -37,10 +37,14 @@ #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);+  int error = ::pthread_condattr_init(&attr);   if (error == 0)-    error = ::pthread_cond_init(&cond_, &attr);+  {+    error = ::pthread_condattr_setclock(&attr, CLOCK_MONOTONIC);+    if (error == 0)+      error = ::pthread_cond_init(&cond_, &attr);+    ::pthread_condattr_destroy(&attr);+  } #endif // (defined(__MACH__) && defined(__APPLE__))        // || (defined(__ANDROID__) && (__ANDROID_API__ < 21)) 
link/modules/asio-standalone/asio/include/asio/detail/impl/posix_mutex.ipp view
@@ -2,7 +2,7 @@ // detail/impl/posix_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/impl/posix_serial_port_service.ipp view
@@ -0,0 +1,168 @@+//+// detail/impl/posix_serial_port_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 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_POSIX_SERIAL_PORT_SERVICE_IPP+#define ASIO_DETAIL_IMPL_POSIX_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/posix_serial_port_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++posix_serial_port_service::posix_serial_port_service(+    execution_context& context)+  : execution_context_service_base<posix_serial_port_service>(context),+    descriptor_service_(context)+{+}++void posix_serial_port_service::shutdown()+{+  descriptor_service_.shutdown();+}++asio::error_code posix_serial_port_service::open(+    posix_serial_port_service::implementation_type& impl,+    const std::string& device, asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    ASIO_ERROR_LOCATION(ec);+    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)+  {+    ASIO_ERROR_LOCATION(ec);+    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);+    ASIO_ERROR_LOCATION(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);+    ASIO_ERROR_LOCATION(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);+  }++  ASIO_ERROR_LOCATION(ec);+  return ec;+}++asio::error_code posix_serial_port_service::do_set_option(+    posix_serial_port_service::implementation_type& impl,+    posix_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)+  {+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }++  if (store(option, ios, ec))+  {+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }++  s = ::tcsetattr(descriptor_service_.native_handle(impl), TCSANOW, &ios);+  descriptor_ops::get_last_error(ec, s < 0);+  ASIO_ERROR_LOCATION(ec);+  return ec;+}++asio::error_code posix_serial_port_service::do_get_option(+    const posix_serial_port_service::implementation_type& impl,+    posix_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)+  {+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }++  load(option, ios, ec);+  ASIO_ERROR_LOCATION(ec);+  return 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_POSIX_SERIAL_PORT_SERVICE_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/posix_thread.ipp view
@@ -2,7 +2,7 @@ // detail/impl/posix_thread.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/posix_tss_ptr.ipp view
@@ -2,7 +2,7 @@ // detail/impl/posix_tss_ptr.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_descriptor_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/reactive_descriptor_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,7 +19,8 @@  #if !defined(ASIO_WINDOWS) \   && !defined(ASIO_WINDOWS_RUNTIME) \-  && !defined(__CYGWIN__)+  && !defined(__CYGWIN__) \+  && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #include "asio/error.hpp" #include "asio/detail/reactive_descriptor_service.hpp"@@ -46,6 +47,7 @@ {   impl.descriptor_ = -1;   impl.state_ = 0;+  impl.reactor_data_ = reactor::per_descriptor_data(); }  void reactive_descriptor_service::move_construct(@@ -105,6 +107,7 @@   if (is_open(impl))   {     ec = asio::error::already_open;+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -113,6 +116,7 @@   {     ec = asio::error_code(err,         asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -151,6 +155,7 @@   // We'll just have to assume that other OSes follow the same behaviour.)   construct(impl); +  ASIO_ERROR_LOCATION(ec);   return ec; } @@ -180,6 +185,7 @@   if (!is_open(impl))   {     ec = asio::error::bad_descriptor;+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -191,10 +197,10 @@   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)+void reactive_descriptor_service::do_start_op(implementation_type& impl,+    int op_type, reactor_op* op, bool is_continuation, bool is_non_blocking,+    bool noop, void (*on_immediate)(operation* op, bool, const void*),+    const void* immediate_arg) {   if (!noop)   {@@ -202,13 +208,13 @@         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);+      reactor_.start_op(op_type, impl.descriptor_, impl.reactor_data_, op,+          is_continuation, is_non_blocking, on_immediate, immediate_arg);       return;     }   } -  reactor_.post_immediate_completion(op, is_continuation);+  on_immediate(op, is_continuation, immediate_arg); }  } // namespace detail@@ -219,5 +225,6 @@ #endif // !defined(ASIO_WINDOWS)        //   && !defined(ASIO_WINDOWS_RUNTIME)        //   && !defined(__CYGWIN__)+       //   && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #endif // ASIO_DETAIL_IMPL_REACTIVE_DESCRIPTOR_SERVICE_IPP
− link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_serial_port_service.ipp
@@ -1,149 +0,0 @@-//-// 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
@@ -2,7 +2,7 @@ // detail/reactive_socket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,7 +18,8 @@ #include "asio/detail/config.hpp"  #if !defined(ASIO_HAS_IOCP) \-  && !defined(ASIO_WINDOWS_RUNTIME)+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #include "asio/detail/reactive_socket_service_base.hpp" @@ -43,6 +44,7 @@ {   impl.socket_ = invalid_socket;   impl.state_ = 0;+  impl.reactor_data_ = reactor::per_descriptor_data(); }  void reactive_socket_service_base::base_move_construct(@@ -231,10 +233,11 @@   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)+void reactive_socket_service_base::do_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,+    void (*on_immediate)(operation* op, bool, const void*),+    const void* immediate_arg) {   if (!noop)   {@@ -242,32 +245,38 @@         || 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);+      reactor_.start_op(op_type, impl.socket_, impl.reactor_data_, op,+          is_continuation, is_non_blocking, on_immediate, immediate_arg);       return;     }   } -  reactor_.post_immediate_completion(op, is_continuation);+  on_immediate(op, is_continuation, immediate_arg); } -void reactive_socket_service_base::start_accept_op(+void reactive_socket_service_base::do_start_accept_op(     reactive_socket_service_base::base_implementation_type& impl,-    reactor_op* op, bool is_continuation, bool peer_is_open)+    reactor_op* op, bool is_continuation, bool peer_is_open,+    void (*on_immediate)(operation* op, bool, const void*),+    const void* immediate_arg) {   if (!peer_is_open)-    start_op(impl, reactor::read_op, op, is_continuation, true, false);+  {+    do_start_op(impl, reactor::read_op, op, is_continuation,+        true, false, on_immediate, immediate_arg);+  }   else   {     op->ec_ = asio::error::already_open;-    reactor_.post_immediate_completion(op, is_continuation);+    on_immediate(op, is_continuation, immediate_arg);   } } -void reactive_socket_service_base::start_connect_op(+void reactive_socket_service_base::do_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)+    reactor_op* op, bool is_continuation, const void* addr, size_t addrlen,+    void (*on_immediate)(operation* op, bool, const void*),+    const void* immediate_arg) {   if ((impl.state_ & socket_ops::non_blocking)       || socket_ops::set_internal_non_blocking(@@ -279,14 +288,14 @@           || 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);+        reactor_.start_op(reactor::connect_op, impl.socket_, impl.reactor_data_,+            op, is_continuation, false, on_immediate, immediate_arg);         return;       }     }   } -  reactor_.post_immediate_completion(op, is_continuation);+  on_immediate(op, is_continuation, immediate_arg); }  } // namespace detail@@ -296,5 +305,6 @@  #endif // !defined(ASIO_HAS_IOCP)        //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #endif // ASIO_DETAIL_IMPL_REACTIVE_SOCKET_SERVICE_BASE_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/resolver_service_base.ipp view
@@ -2,7 +2,7 @@ // detail/impl/resolver_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/scheduler.ipp view
@@ -2,7 +2,7 @@ // detail/impl/scheduler.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,11 +20,16 @@ #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" +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_service.hpp"+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/reactor.hpp"+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ #include "asio/detail/push_options.hpp"  namespace asio {@@ -104,7 +109,7 @@ };  scheduler::scheduler(asio::execution_context& ctx,-    int concurrency_hint, bool own_thread)+    int concurrency_hint, bool own_thread, get_task_func_type get_task)   : asio::detail::execution_context_service_base<scheduler>(ctx),     one_thread_(concurrency_hint == 1         || !ASIO_CONCURRENCY_HINT_IS_LOCKING(@@ -114,6 +119,7 @@     mutex_(ASIO_CONCURRENCY_HINT_IS_LOCKING(           SCHEDULER, concurrency_hint)),     task_(0),+    get_task_(get_task),     task_interrupted_(true),     outstanding_work_(0),     stopped_(false),@@ -178,7 +184,7 @@   mutex::scoped_lock lock(mutex_);   if (!shutdown_ && !task_)   {-    task_ = &use_service<reactor>(this->context());+    task_ = get_task_(this->context());     op_queue_.push(&task_operation_);     wake_one_thread_and_unlock(lock);   }@@ -321,9 +327,15 @@ void scheduler::compensating_work_started() {   thread_info_base* this_thread = thread_call_stack::contains(this);+  ASIO_ASSUME(this_thread != 0); // Only called from inside scheduler.   ++static_cast<thread_info*>(this_thread)->private_outstanding_work; } +bool scheduler::can_dispatch()+{+  return thread_call_stack::contains(this) != 0;+}+ void scheduler::capture_current_exception() {   if (thread_info_base* this_thread = thread_call_stack::contains(this))@@ -644,6 +656,15 @@     }     lock.unlock();   }+}++scheduler_task* scheduler::get_default_task(asio::execution_context& ctx)+{+#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  return &use_service<io_uring_service>(ctx);+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  return &use_service<reactor>(ctx);+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) }  } // namespace detail
link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/impl/select_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -23,11 +23,23 @@       && !defined(ASIO_HAS_KQUEUE) \       && !defined(ASIO_WINDOWS_RUNTIME)) +#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 { +inline void select_reactor::post_immediate_completion(+    operation* op, bool is_continuation) const+{+  scheduler_.post_immediate_completion(op, is_continuation);+}+ template <typename Time_Traits> void select_reactor::add_timer_queue(timer_queue<Time_Traits>& queue) {@@ -71,6 +83,18 @@   lock.unlock();   scheduler_.post_deferred_completions(ops);   return n;+}++template <typename Time_Traits>+void select_reactor::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data* timer,+    void* cancellation_key)+{+  mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  queue.cancel_timer_by_key(timer, ops, cancellation_key);+  lock.unlock();+  scheduler_.post_deferred_completions(ops); }  template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.ipp view
@@ -2,7 +2,7 @@ // detail/impl/select_reactor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -28,6 +28,12 @@ #include "asio/detail/signal_blocker.hpp" #include "asio/detail/socket_ops.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 {@@ -60,6 +66,7 @@ #if defined(ASIO_HAS_IOCP)     stop_thread_(false),     thread_(0),+    restart_reactor_(this), #endif // defined(ASIO_HAS_IOCP)     shutdown_(false) {@@ -107,8 +114,12 @@ void select_reactor::notify_fork(     asio::execution_context::fork_event fork_ev) {+#if defined(ASIO_HAS_IOCP)+  (void)fork_ev;+#else // defined(ASIO_HAS_IOCP)   if (fork_ev == asio::execution_context::fork_child)     interrupter_.recreate();+#endif // defined(ASIO_HAS_IOCP) }  void select_reactor::init_task()@@ -140,15 +151,23 @@ { } +void select_reactor::call_post_immediate_completion(+    operation* op, bool is_continuation, const void* self)+{+  static_cast<const select_reactor*>(self)->post_immediate_completion(+      op, is_continuation);+}+ void select_reactor::start_op(int op_type, socket_type descriptor,-    select_reactor::per_descriptor_data&, reactor_op* op,-    bool is_continuation, bool)+    select_reactor::per_descriptor_data&, reactor_op* op, bool is_continuation,+    bool, void (*on_immediate)(operation*, bool, const void*),+    const void* immediate_arg) {   asio::detail::mutex::scoped_lock lock(mutex_);    if (shutdown_)   {-    post_immediate_completion(op, is_continuation);+    on_immediate(op, is_continuation, immediate_arg);     return;   } @@ -165,6 +184,19 @@   cancel_ops_unlocked(descriptor, asio::error::operation_aborted); } +void select_reactor::cancel_ops_by_key(socket_type descriptor,+    select_reactor::per_descriptor_data&,+    int op_type, void* cancellation_key)+{+  asio::detail::mutex::scoped_lock lock(mutex_);+  op_queue<operation> ops;+  bool need_interrupt = op_queue_[op_type].cancel_operations_by_key(+      descriptor, ops, cancellation_key, asio::error::operation_aborted);+  scheduler_.post_deferred_completions(ops);+  if (need_interrupt)+    interrupter_.interrupt();+}+ void select_reactor::deregister_descriptor(socket_type descriptor,     select_reactor::per_descriptor_data&, bool) {@@ -243,7 +275,12 @@     if (!interrupter_.reset())     {       lock.lock();+#if defined(ASIO_HAS_IOCP)+      stop_thread_ = true;+      scheduler_.post_immediate_completion(&restart_reactor_, false);+#else // defined(ASIO_HAS_IOCP)       interrupter_.recreate();+#endif // defined(ASIO_HAS_IOCP)     }     --retval;   }@@ -280,9 +317,34 @@   {     lock.unlock();     op_queue<operation> ops;-    run(true, ops);+    run(-1, ops);     scheduler_.post_deferred_completions(ops);     lock.lock();+  }+}++void select_reactor::restart_reactor::do_complete(void* owner, operation* base,+    const asio::error_code& /*ec*/, std::size_t /*bytes_transferred*/)+{+  if (owner)+  {+    select_reactor* reactor = static_cast<restart_reactor*>(base)->reactor_;++    if (reactor->thread_)+    {+      reactor->thread_->join();+      delete reactor->thread_;+      reactor->thread_ = 0;+    }++    asio::detail::mutex::scoped_lock lock(reactor->mutex_);+    reactor->interrupter_.recreate();+    reactor->stop_thread_ = false;+    lock.unlock();++    asio::detail::signal_blocker sb;+    reactor->thread_ =+      new asio::detail::thread(thread_function(reactor));   } } #endif // defined(ASIO_HAS_IOCP)
link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.hpp view
@@ -2,7 +2,7 @@ // detail/impl/service_registry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.ipp view
@@ -2,7 +2,7 @@ // detail/impl/service_registry.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/signal_set_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/signal_set_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,12 +19,17 @@  #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" +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_service.hpp"+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/reactor.hpp"+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ #include "asio/detail/push_options.hpp"  namespace asio {@@ -49,12 +54,16 @@    // A count of the number of objects that are registered for each signal.   std::size_t registration_count_[max_signal_number];++  // The flags used for each registered signal.+  signal_set_base::flags_t flags_[max_signal_number]; };  signal_state* get_signal_state() {   static signal_state state = {-    ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0, { 0 } };+    ASIO_STATIC_MUTEX_INIT, -1, -1, false, 0,+    { 0 }, { signal_set_base::flags_t() } };   return &state; } @@ -85,10 +94,43 @@ #if !defined(ASIO_WINDOWS) \   && !defined(ASIO_WINDOWS_RUNTIME) \   && !defined(__CYGWIN__)-class signal_set_service::pipe_read_op : public reactor_op+class signal_set_service::pipe_read_op :+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  public io_uring_operation+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  public reactor_op+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) { public:+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)   pipe_read_op()+    : io_uring_operation(asio::error_code(), &pipe_read_op::do_prepare,+        &pipe_read_op::do_perform, pipe_read_op::do_complete)+  {+  }++  static void do_prepare(io_uring_operation*, ::io_uring_sqe* sqe)+  {+    signal_state* state = get_signal_state();++    int fd = state->read_descriptor_;+    ::io_uring_prep_poll_add(sqe, fd, POLLIN);+  }++  static bool do_perform(io_uring_operation*, bool)+  {+    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 false;+  }+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  pipe_read_op()     : reactor_op(asio::error_code(),         &pipe_read_op::do_perform, pipe_read_op::do_complete)   {@@ -106,6 +148,7 @@      return not_done;   }+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)    static void do_complete(void* /*owner*/, operation* base,       const asio::error_code& /*ec*/,@@ -125,7 +168,11 @@ #if !defined(ASIO_WINDOWS) \   && !defined(ASIO_WINDOWS_RUNTIME) \   && !defined(__CYGWIN__)+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+    io_uring_service_(asio::use_service<io_uring_service>(context)),+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)     reactor_(asio::use_service<reactor>(context)),+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS)        //   && !defined(ASIO_WINDOWS_RUNTIME)        //   && !defined(__CYGWIN__)@@ -137,7 +184,11 @@ #if !defined(ASIO_WINDOWS) \   && !defined(ASIO_WINDOWS_RUNTIME) \   && !defined(__CYGWIN__)+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  io_uring_service_.init_task();+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)   reactor_.init_task();+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS)        //   && !defined(ASIO_WINDOWS_RUNTIME)        //   && !defined(__CYGWIN__)@@ -187,8 +238,14 @@       int read_descriptor = state->read_descriptor_;       state->fork_prepared_ = true;       lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+      (void)read_descriptor;+      io_uring_service_.deregister_io_object(io_object_data_);+      io_uring_service_.cleanup_io_object(io_object_data_);+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)       reactor_.deregister_internal_descriptor(read_descriptor, reactor_data_);       reactor_.cleanup_descriptor_data(reactor_data_);+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)     }     break;   case execution_context::fork_parent:@@ -197,8 +254,14 @@       int read_descriptor = state->read_descriptor_;       state->fork_prepared_ = false;       lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+      (void)read_descriptor;+      io_uring_service_.register_internal_io_object(io_object_data_,+          io_uring_service::read_op, new pipe_read_op);+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)       reactor_.register_internal_descriptor(reactor::read_op,           read_descriptor, reactor_data_, new pipe_read_op);+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)     }     break;   case execution_context::fork_child:@@ -210,8 +273,14 @@       int read_descriptor = state->read_descriptor_;       state->fork_prepared_ = false;       lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+      (void)read_descriptor;+      io_uring_service_.register_internal_io_object(io_object_data_,+          io_uring_service::read_op, new pipe_read_op);+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)       reactor_.register_internal_descriptor(reactor::read_op,           read_descriptor, reactor_data_, new pipe_read_op);+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)     }     break;   default:@@ -241,8 +310,8 @@ }  asio::error_code signal_set_service::add(-    signal_set_service::implementation_type& impl,-    int signal_number, asio::error_code& ec)+    signal_set_service::implementation_type& impl, int signal_number,+    signal_set_base::flags_t f, asio::error_code& ec) {   // Check that the signal number is valid.   if (signal_number < 0 || signal_number >= max_signal_number)@@ -251,6 +320,15 @@     return ec;   } +  // Check that the specified flags are supported.+#if !defined(ASIO_HAS_SIGACTION)+  if (f != signal_set_base::flags::dont_care)+  {+    ec = asio::error::operation_not_supported;+    return ec;+  }+#endif // !defined(ASIO_HAS_SIGACTION)+   signal_state* state = get_signal_state();   static_mutex::scoped_lock lock(state->mutex_); @@ -278,6 +356,8 @@       memset(&sa, 0, sizeof(sa));       sa.sa_handler = asio_signal_handler;       sigfillset(&sa.sa_mask);+      if (f != signal_set_base::flags::dont_care)+        sa.sa_flags = static_cast<int>(f);       if (::sigaction(signal_number, &sa, 0) == -1) # else // defined(ASIO_HAS_SIGACTION)       if (::signal(signal_number, asio_signal_handler) == SIG_ERR)@@ -292,7 +372,37 @@         delete new_registration;         return ec;       }+# if defined(ASIO_HAS_SIGACTION)+      state->flags_[signal_number] = f;+# endif // defined(ASIO_HAS_SIGACTION)     }+# if defined(ASIO_HAS_SIGACTION)+    // Otherwise check to see if the flags have changed.+    else if (f != signal_set_base::flags::dont_care)+    {+      if (f != state->flags_[signal_number])+      {+        using namespace std; // For memset.+        if (state->flags_[signal_number] != signal_set_base::flags::dont_care)+        {+          ec = asio::error::invalid_argument;+          return ec;+        }+        struct sigaction sa;+        memset(&sa, 0, sizeof(sa));+        sa.sa_handler = asio_signal_handler;+        sigfillset(&sa.sa_mask);+        sa.sa_flags = static_cast<int>(f);+        if (::sigaction(signal_number, &sa, 0) == -1)+        {+          ec = asio::error_code(errno,+              asio::error::get_system_category());+          return ec;+        }+        state->flags_[signal_number] = f;+      }+    }+# endif // defined(ASIO_HAS_SIGACTION) #endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION)      // Record the new registration in the set.@@ -361,6 +471,9 @@ # endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)         return ec;       }+# if defined(ASIO_HAS_SIGACTION)+      state->flags_[signal_number] = signal_set_base::flags_t();+# endif // defined(ASIO_HAS_SIGACTION)     } #endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION) @@ -415,6 +528,9 @@ # endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__)         return ec;       }+# if defined(ASIO_HAS_SIGACTION)+      state->flags_[reg->signal_number_] = signal_set_base::flags_t();+# endif // defined(ASIO_HAS_SIGACTION)     } #endif // defined(ASIO_HAS_SIGNAL) || defined(ASIO_HAS_SIGACTION) @@ -462,6 +578,33 @@   return ec; } +void signal_set_service::cancel_ops_by_key(+    signal_set_service::implementation_type& impl, void* cancellation_key)+{+  op_queue<operation> ops;+  {+    op_queue<signal_op> other_ops;+    signal_state* state = get_signal_state();+    static_mutex::scoped_lock lock(state->mutex_);++    while (signal_op* op = impl.queue_.front())+    {+      impl.queue_.pop();+      if (op->cancellation_key_ == cancellation_key)+      {+        op->ec_ = asio::error::operation_aborted;+        ops.push(op);+      }+      else+        other_ops.push(op);+    }++    impl.queue_.push(other_ops);+  }++  scheduler_.post_deferred_completions(ops);+}+ void signal_set_service::deliver_signal(int signal_number) {   signal_state* state = get_signal_state();@@ -538,8 +681,14 @@   // Register for pipe readiness notifications.   int read_descriptor = state->read_descriptor_;   lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  (void)read_descriptor;+  service->io_uring_service_.register_internal_io_object(+      service->io_object_data_, io_uring_service::read_op, new pipe_read_op);+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)   service->reactor_.register_internal_descriptor(reactor::read_op,       read_descriptor, service->reactor_data_, new pipe_read_op);+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS)        //   && !defined(ASIO_WINDOWS_RUNTIME)        //   && !defined(__CYGWIN__)@@ -558,10 +707,17 @@     // Disable the pipe readiness notifications.     int read_descriptor = state->read_descriptor_;     lock.unlock();+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+    (void)read_descriptor;+    service->io_uring_service_.deregister_io_object(service->io_object_data_);+    service->io_uring_service_.cleanup_io_object(service->io_object_data_);+    lock.lock();+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)     service->reactor_.deregister_internal_descriptor(         read_descriptor, service->reactor_data_);     service->reactor_.cleanup_descriptor_data(service->reactor_data_);     lock.lock();+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS)        //   && !defined(ASIO_WINDOWS_RUNTIME)        //   && !defined(__CYGWIN__)
link/modules/asio-standalone/asio/include/asio/detail/impl/socket_ops.ipp view
@@ -2,7 +2,7 @@ // detail/impl/socket_ops.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -78,7 +78,7 @@ {   if (!is_error_condition)   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);   }   else   {@@ -94,16 +94,18 @@  template <typename SockLenType> inline socket_type call_accept(SockLenType msghdr::*,-    socket_type s, socket_addr_type* addr, std::size_t* addrlen)+    socket_type s, void* addr, std::size_t* addrlen) {   SockLenType tmp_addrlen = addrlen ? (SockLenType)*addrlen : 0;-  socket_type result = ::accept(s, addr, addrlen ? &tmp_addrlen : 0);+  socket_type result = ::accept(s,+      static_cast<socket_addr_type*>(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,+socket_type accept(socket_type s, void* addr,     std::size_t* addrlen, asio::error_code& ec) {   if (s == invalid_socket)@@ -129,12 +131,12 @@   } #endif -  ec.assign(0, ec.category());+  asio::error::clear(ec);   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)+    void* addr, std::size_t* addrlen, asio::error_code& ec) {   // Accept a socket.   for (;;)@@ -179,9 +181,8 @@  #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,+void complete_iocp_accept(socket_type s, void* output_buffer,+    DWORD address_length, void* addr, std::size_t* addrlen,     socket_type new_socket, asio::error_code& ec) {   // Map non-portable errors to their portable counterparts.@@ -225,7 +226,7 @@ #else // defined(ASIO_HAS_IOCP)  bool non_blocking_accept(socket_type s,-    state_type state, socket_addr_type* addr, std::size_t* addrlen,+    state_type state, void* addr, std::size_t* addrlen,     asio::error_code& ec, socket_type& new_socket) {   for (;;)@@ -272,12 +273,13 @@  template <typename SockLenType> inline int call_bind(SockLenType msghdr::*,-    socket_type s, const socket_addr_type* addr, std::size_t addrlen)+    socket_type s, const void* addr, std::size_t addrlen) {-  return ::bind(s, addr, (SockLenType)addrlen);+  return ::bind(s, static_cast<const socket_addr_type*>(addr),+      (SockLenType)addrlen); } -int bind(socket_type s, const socket_addr_type* addr,+int bind(socket_type s, const void* addr,     std::size_t addrlen, asio::error_code& ec) {   if (s == invalid_socket)@@ -463,12 +465,13 @@  template <typename SockLenType> inline int call_connect(SockLenType msghdr::*,-    socket_type s, const socket_addr_type* addr, std::size_t addrlen)+    socket_type s, const void* addr, std::size_t addrlen) {-  return ::connect(s, addr, (SockLenType)addrlen);+  return ::connect(s, static_cast<const socket_addr_type*>(addr),+      (SockLenType)addrlen); } -int connect(socket_type s, const socket_addr_type* addr,+int connect(socket_type s, const void* addr,     std::size_t addrlen, asio::error_code& ec) {   if (s == invalid_socket)@@ -481,12 +484,17 @@   get_last_error(ec, result != 0); #if defined(__linux__)   if (result != 0 && ec == asio::error::try_again)-    ec = asio::error::no_buffer_space;+  {+    if (static_cast<const socket_addr_type*>(addr)->sa_family == AF_UNIX)+      ec = asio::error::in_progress;+    else+      ec = asio::error::no_buffer_space;+  } #endif // defined(__linux__)   return result; } -void sync_connect(socket_type s, const socket_addr_type* addr,+void sync_connect(socket_type s, const void* addr,     std::size_t addrlen, asio::error_code& ec) {   // Perform the connect operation.@@ -596,7 +604,7 @@           asio::error::get_system_category());     }     else-      ec.assign(0, ec.category());+      asio::error::clear(ec);   }    return true;@@ -641,7 +649,7 @@ # endif // defined(ENOTTY) #else // defined(SIOCATMARK)   int value = ::sockatmark(s);-  get_last_error(ec, result < 0);+  get_last_error(ec, value < 0); #endif // defined(SIOCATMARK)    return ec ? false : value != 0;@@ -722,9 +730,9 @@ #endif // defined(ASIO_WINDOWS) || defined(__CYGWIN__) } -inline void init_msghdr_msg_name(void*& name, socket_addr_type* addr)+inline void init_msghdr_msg_name(void*& name, void* addr) {-  name = addr;+  name = static_cast<socket_addr_type*>(addr); }  inline void init_msghdr_msg_name(void*& name, const socket_addr_type* addr)@@ -733,15 +741,15 @@ }  template <typename T>-inline void init_msghdr_msg_name(T& name, socket_addr_type* addr)+inline void init_msghdr_msg_name(T& name, void* addr) {-  name = reinterpret_cast<T>(addr);+  name = static_cast<T>(addr); }  template <typename T>-inline void init_msghdr_msg_name(T& name, const socket_addr_type* addr)+inline void init_msghdr_msg_name(T& name, const void* addr) {-  name = reinterpret_cast<T>(const_cast<socket_addr_type*>(addr));+  name = static_cast<T>(const_cast<void*>(addr)); }  signed_size_type recv(socket_type s, buf* bufs, size_t count,@@ -763,7 +771,7 @@     result = 0;   if (result != 0)     return socket_error_retval;-  ec.assign(0, ec.category());+  asio::error::clear(ec);   return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)   msghdr msg = msghdr();@@ -796,7 +804,7 @@     result = 0;   if (result != 0)     return socket_error_retval;-  ec.assign(0, ec.category());+  asio::error::clear(ec);   return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)   signed_size_type result = ::recv(s, static_cast<char*>(data), size, flags);@@ -817,7 +825,7 @@   // A request to read 0 bytes on a stream is a no-op.   if (all_empty && (state & stream_oriented))   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -862,7 +870,7 @@   // A request to read 0 bytes on a stream is a no-op.   if (size == 0 && (state & stream_oriented))   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -915,7 +923,7 @@   }   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);   }    // Check for connection closed.@@ -1008,8 +1016,7 @@ #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)+    int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__)   // Receive some data.@@ -1017,8 +1024,8 @@   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);+  int result = ::WSARecvFrom(s, bufs, recv_buf_count, &bytes_transferred,+      &recv_flags, static_cast<socket_addr_type*>(addr), &tmp_addrlen, 0, 0);   get_last_error(ec, true);   *addrlen = (std::size_t)tmp_addrlen;   if (ec.value() == ERROR_NETNAME_DELETED)@@ -1029,7 +1036,7 @@     result = 0;   if (result != 0)     return socket_error_retval;-  ec.assign(0, ec.category());+  asio::error::clear(ec);   return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)   msghdr msg = msghdr();@@ -1045,21 +1052,19 @@ }  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)+inline signed_size_type call_recvfrom(SockLenType msghdr::*, socket_type s,+    void* data, size_t size, int flags, void* 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);+  signed_size_type result = ::recvfrom(s, static_cast<char*>(data), size,+      flags, static_cast<socket_addr_type*>(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)+    int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__)   // Receive some data.@@ -1069,8 +1074,8 @@   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);+  int result = ::WSARecvFrom(s, &buf, 1, &bytes_transferred, &recv_flags,+      static_cast<socket_addr_type*>(addr), &tmp_addrlen, 0, 0);   get_last_error(ec, true);   *addrlen = (std::size_t)tmp_addrlen;   if (ec.value() == ERROR_NETNAME_DELETED)@@ -1081,7 +1086,7 @@     result = 0;   if (result != 0)     return socket_error_retval;-  ec.assign(0, ec.category());+  asio::error::clear(ec);   return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)   signed_size_type result = call_recvfrom(&msghdr::msg_namelen,@@ -1091,9 +1096,8 @@ #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)+size_t sync_recvfrom(socket_type s, state_type state, buf* bufs, size_t count,+    int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) {   if (s == invalid_socket)   {@@ -1124,9 +1128,8 @@   } } -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)+size_t sync_recvfrom1(socket_type s, state_type state, void* data, size_t size,+    int flags, void* addr, std::size_t* addrlen, asio::error_code& ec) {   if (s == invalid_socket)   {@@ -1177,15 +1180,14 @@   }   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);   } }  #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,+bool non_blocking_recvfrom(socket_type s, buf* bufs,+    size_t count, int flags, void* addr, std::size_t* addrlen,     asio::error_code& ec, size_t& bytes_transferred) {   for (;;)@@ -1216,9 +1218,8 @@   } } -bool non_blocking_recvfrom1(socket_type s,-    void* data, size_t size, int flags,-    socket_addr_type* addr, std::size_t* addrlen,+bool non_blocking_recvfrom1(socket_type s, void* data,+    size_t size, int flags, void* addr, std::size_t* addrlen,     asio::error_code& ec, size_t& bytes_transferred) {   for (;;)@@ -1324,7 +1325,7 @@   }   else if (ec.value() == WSAEMSGSIZE || ec.value() == ERROR_MORE_DATA)   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);   } } @@ -1381,15 +1382,15 @@     ec = asio::error::connection_refused;   if (result != 0)     return socket_error_retval;-  ec.assign(0, ec.category());+  asio::error::clear(ec);   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__)+#if defined(ASIO_HAS_MSG_NOSIGNAL)   flags |= MSG_NOSIGNAL;-#endif // defined(__linux__)+#endif // defined(ASIO_HAS_MSG_NOSIGNAL)   signed_size_type result = ::sendmsg(s, &msg, flags);   get_last_error(ec, result < 0);   return result;@@ -1415,12 +1416,12 @@     ec = asio::error::connection_refused;   if (result != 0)     return socket_error_retval;-  ec.assign(0, ec.category());+  asio::error::clear(ec);   return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)-#if defined(__linux__)+#if defined(ASIO_HAS_MSG_NOSIGNAL)   flags |= MSG_NOSIGNAL;-#endif // defined(__linux__)+#endif // defined(ASIO_HAS_MSG_NOSIGNAL)   signed_size_type result = ::send(s,       static_cast<const char*>(data), size, flags);   get_last_error(ec, result < 0);@@ -1440,7 +1441,7 @@   // A request to write 0 bytes to a stream is a no-op.   if (all_empty && (state & stream_oriented))   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -1478,7 +1479,7 @@   // A request to write 0 bytes to a stream is a no-op.   if (size == 0 && (state & stream_oriented))   {-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -1590,16 +1591,17 @@  #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)+signed_size_type sendto(socket_type s, const buf* bufs,+    size_t count, int flags, const void* 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,+        send_buf_count, &bytes_transferred, flags,+        static_cast<const socket_addr_type*>(addr),         static_cast<int>(addrlen), 0, 0);   get_last_error(ec, true);   if (ec.value() == ERROR_NETNAME_DELETED)@@ -1608,7 +1610,7 @@     ec = asio::error::connection_refused;   if (result != 0)     return socket_error_retval;-  ec.assign(0, ec.category());+  asio::error::clear(ec);   return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)   msghdr msg = msghdr();@@ -1616,9 +1618,9 @@   msg.msg_namelen = static_cast<int>(addrlen);   msg.msg_iov = const_cast<buf*>(bufs);   msg.msg_iovlen = static_cast<int>(count);-#if defined(__linux__)+#if defined(ASIO_HAS_MSG_NOSIGNAL)   flags |= MSG_NOSIGNAL;-#endif // defined(__linux__)+#endif // defined(ASIO_HAS_MSG_NOSIGNAL)   signed_size_type result = ::sendmsg(s, &msg, flags);   get_last_error(ec, result < 0);   return result;@@ -1628,15 +1630,15 @@ 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)+    const void* addr, std::size_t addrlen) {-  return ::sendto(s, static_cast<char*>(const_cast<void*>(data)),-      size, flags, addr, (SockLenType)addrlen);+  return ::sendto(s, static_cast<char*>(const_cast<void*>(data)), size, flags,+      static_cast<const socket_addr_type*>(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)+signed_size_type sendto1(socket_type s, const void* data,+    size_t size, int flags, const void* addr,+    std::size_t addrlen, asio::error_code& ec) { #if defined(ASIO_WINDOWS) || defined(__CYGWIN__)   // Send the data.@@ -1644,8 +1646,9 @@   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);+  int result = ::WSASendTo(s, &buf, 1, &bytes_transferred, flags,+      static_cast<const socket_addr_type*>(addr),+      static_cast<int>(addrlen), 0, 0);   get_last_error(ec, true);   if (ec.value() == ERROR_NETNAME_DELETED)     ec = asio::error::connection_reset;@@ -1653,12 +1656,12 @@     ec = asio::error::connection_refused;   if (result != 0)     return socket_error_retval;-  ec.assign(0, ec.category());+  asio::error::clear(ec);   return bytes_transferred; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)-#if defined(__linux__)+#if defined(ASIO_HAS_MSG_NOSIGNAL)   flags |= MSG_NOSIGNAL;-#endif // defined(__linux__)+#endif // defined(ASIO_HAS_MSG_NOSIGNAL)   signed_size_type result = call_sendto(&msghdr::msg_namelen,       s, data, size, flags, addr, addrlen);   get_last_error(ec, result < 0);@@ -1666,8 +1669,8 @@ #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,+size_t sync_sendto(socket_type s, state_type state,+    const buf* bufs, size_t count, int flags, const void* addr,     std::size_t addrlen, asio::error_code& ec) {   if (s == invalid_socket)@@ -1699,8 +1702,8 @@   } } -size_t sync_sendto1(socket_type s, state_type state, const void* data,-    size_t size, int flags, const socket_addr_type* addr,+size_t sync_sendto1(socket_type s, state_type state,+    const void* data, size_t size, int flags, const void* addr,     std::size_t addrlen, asio::error_code& ec) {   if (s == invalid_socket)@@ -1736,7 +1739,7 @@  bool non_blocking_sendto(socket_type s,     const buf* bufs, size_t count, int flags,-    const socket_addr_type* addr, std::size_t addrlen,+    const void* addr, std::size_t addrlen,     asio::error_code& ec, size_t& bytes_transferred) {   for (;;)@@ -1769,7 +1772,7 @@  bool non_blocking_sendto1(socket_type s,     const void* data, size_t size, int flags,-    const socket_addr_type* addr, std::size_t addrlen,+    const void* addr, std::size_t addrlen,     asio::error_code& ec, size_t& bytes_transferred) {   for (;;)@@ -1824,7 +1827,9 @@   return s; #elif defined(__MACH__) && defined(__APPLE__) || defined(__FreeBSD__)   socket_type s = ::socket(af, type, protocol);-  get_last_error(ec, s < 0);+  get_last_error(ec, s == invalid_socket);+  if (s == invalid_socket)+    return s;    int optval = 1;   int result = ::setsockopt(s, SOL_SOCKET,@@ -1881,7 +1886,7 @@       state |= enable_connection_aborted;     else       state &= ~enable_connection_aborted;-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -1966,7 +1971,7 @@     }      *static_cast<int*>(optval) = (state & enable_connection_aborted) ? 1 : 0;-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -1993,7 +1998,7 @@         // 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());+        asio::error::clear(ec);       }       return result;     }@@ -2013,7 +2018,7 @@     // 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());+    asio::error::clear(ec);   }   return result; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)@@ -2038,16 +2043,17 @@  template <typename SockLenType> inline int call_getpeername(SockLenType msghdr::*,-    socket_type s, socket_addr_type* addr, std::size_t* addrlen)+    socket_type s, void* addr, std::size_t* addrlen) {   SockLenType tmp_addrlen = (SockLenType)*addrlen;-  int result = ::getpeername(s, addr, &tmp_addrlen);+  int result = ::getpeername(s,+      static_cast<socket_addr_type*>(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)+int getpeername(socket_type s, void* addr, std::size_t* addrlen,+    bool cached, asio::error_code& ec) {   if (s == invalid_socket)   {@@ -2074,7 +2080,7 @@     }      // The cached value is still valid.-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } #else // defined(ASIO_WINDOWS) && !defined(ASIO_WINDOWS_APP)@@ -2090,15 +2096,16 @@  template <typename SockLenType> inline int call_getsockname(SockLenType msghdr::*,-    socket_type s, socket_addr_type* addr, std::size_t* addrlen)+    socket_type s, void* addr, std::size_t* addrlen) {   SockLenType tmp_addrlen = (SockLenType)*addrlen;-  int result = ::getsockname(s, addr, &tmp_addrlen);+  int result = ::getsockname(s,+      static_cast<socket_addr_type*>(addr), &tmp_addrlen);   *addrlen = (std::size_t)tmp_addrlen;   return result; } -int getsockname(socket_type s, socket_addr_type* addr,+int getsockname(socket_type s, void* addr,     std::size_t* addrlen, asio::error_code& ec) {   if (s == invalid_socket)@@ -2169,7 +2176,7 @@     if (milliseconds == 0)       milliseconds = 1; // Force context switch.     ::Sleep(milliseconds);-    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 0;   } @@ -2489,7 +2496,7 @@    // Windows may set error code on success.   if (result != socket_error_retval)-    ec.assign(0, ec.category());+    asio::error::clear(ec);    // Windows may not set an error code on failure.   else if (result == socket_error_retval && !ec)@@ -2512,7 +2519,11 @@         && ((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)+#if defined(ASIO_HAS_SNPRINTF)+      snprintf(if_name + 1, sizeof(if_name) - 1, "%lu", scope_id);+#else // defined(ASIO_HAS_SNPRINTF)       sprintf(if_name + 1, "%lu", scope_id);+#endif // defined(ASIO_HAS_SNPRINTF)     strcat(dest, if_name);   }   return result;@@ -2543,7 +2554,7 @@     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());+    asio::error::clear(ec);     return 1;   }   else if (af == ASIO_OS_DEF(AF_INET6))@@ -2659,7 +2670,7 @@     for (int i = 0; i < num_back_bytes; ++i)       bytes[16 - num_back_bytes + i] = back_bytes[i]; -    ec.assign(0, ec.category());+    asio::error::clear(ec);     return 1;   }   else@@ -2702,12 +2713,12 @@     if (result != socket_error_retval)     {       memcpy(dest, &address.v4.sin_addr, sizeof(in4_addr_type));-      ec.assign(0, ec.category());+      asio::error::clear(ec);     }     else if (strcmp(src, "255.255.255.255") == 0)     {       static_cast<in4_addr_type*>(dest)->s_addr = INADDR_NONE;-      ec.assign(0, ec.category());+      asio::error::clear(ec);     }   }   else // AF_INET6@@ -2717,7 +2728,7 @@       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());+      asio::error::clear(ec);     }   } @@ -2726,7 +2737,7 @@     ec = asio::error::invalid_argument;    if (result != socket_error_retval)-    ec.assign(0, ec.category());+    asio::error::clear(ec);    return result == socket_error_retval ? -1 : 1; #else // defined(ASIO_WINDOWS) || defined(__CYGWIN__)@@ -3620,7 +3631,9 @@       {         return ec = asio::error::no_buffer_space;       }-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+      snprintf(serv, servlen, "%u", ntohs(port));+#elif defined(ASIO_HAS_SECURE_RTL)       sprintf_s(serv, servlen, "%u", ntohs(port)); #else // defined(ASIO_HAS_SECURE_RTL)       sprintf(serv, "%u", ntohs(port));@@ -3643,7 +3656,9 @@         {           return ec = asio::error::no_buffer_space;         }-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+        snprintf(serv, servlen, "%u", ntohs(port));+#elif defined(ASIO_HAS_SECURE_RTL)         sprintf_s(serv, servlen, "%u", ntohs(port)); #else // defined(ASIO_HAS_SECURE_RTL)         sprintf(serv, "%u", ntohs(port));@@ -3655,7 +3670,7 @@     }   } -  ec.assign(0, ec.category());+  asio::error::clear(ec);   return ec; } @@ -3805,7 +3820,7 @@ #endif } -asio::error_code getnameinfo(const socket_addr_type* addr,+asio::error_code getnameinfo(const void* addr,     std::size_t addrlen, char* host, std::size_t hostlen,     char* serv, std::size_t servlen, int flags, asio::error_code& ec) {@@ -3813,8 +3828,8 @@ # 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),+  int error = ::getnameinfo(static_cast<const socket_addr_type*>(addr),+      static_cast<socklen_t>(addrlen), host, static_cast<DWORD>(hostlen),       serv, static_cast<DWORD>(servlen), flags);   return ec = translate_addrinfo_error(error); # else@@ -3826,34 +3841,34 @@     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),+      int error = gni(static_cast<const socket_addr_type*>(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);+  return getnameinfo_emulation(static_cast<const socket_addr_type*>(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);+  addr = &tmp_addr;   clear_last_error();-  return getnameinfo_emulation(addr, addrlen,-      host, hostlen, serv, servlen, flags, ec);+  return getnameinfo_emulation(static_cast<const socket_addr_type*>(addr),+      addrlen, host, hostlen, serv, servlen, flags, ec); #else   clear_last_error();-  int error = ::getnameinfo(addr, addrlen, host, hostlen, serv, servlen, flags);+  int error = ::getnameinfo(static_cast<const socket_addr_type*>(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,+asio::error_code sync_getnameinfo(const void* 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@@ -3872,7 +3887,7 @@  asio::error_code background_getnameinfo(     const weak_cancel_token_type& cancel_token,-    const socket_addr_type* addr, std::size_t addrlen,+    const void* addr, std::size_t addrlen,     char* host, std::size_t hostlen, char* serv,     std::size_t servlen, int sock_type, asio::error_code& ec) {
link/modules/asio-standalone/asio/include/asio/detail/impl/socket_select_interrupter.ipp view
@@ -2,7 +2,7 @@ // detail/impl/socket_select_interrupter.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -60,11 +60,11 @@   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,+  if (socket_ops::bind(acceptor.get(), &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,+  if (socket_ops::getsockname(acceptor.get(), &addr,         &addr_len, ec) == socket_error_retval)     asio::detail::throw_error(ec, "socket_select_interrupter"); @@ -83,7 +83,7 @@   if (client.get() == invalid_socket)     asio::detail::throw_error(ec, "socket_select_interrupter"); -  if (socket_ops::connect(client.get(), (const socket_addr_type*)&addr,+  if (socket_ops::connect(client.get(), &addr,         addr_len, ec) == socket_error_retval)     asio::detail::throw_error(ec, "socket_select_interrupter"); 
link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.hpp view
@@ -2,7 +2,7 @@ // detail/impl/strand_executor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,7 +15,6 @@ # 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"@@ -103,42 +102,37 @@      ~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)+      if (push_waiting_to_ready(this_->impl_))       {         recycling_allocator<void> allocator;+        executor_type ex = this_->executor_;+#if defined(ASIO_NO_DEPRECATED)+        asio::prefer(+            asio::require(+              ASIO_MOVE_CAST(executor_type)(ex),+              execution::blocking.never),+            execution::allocator(allocator)+          ).execute(ASIO_MOVE_CAST(invoker)(*this_));+#else // defined(ASIO_NO_DEPRECATED)         execution::execute(             asio::prefer(-              asio::require(this_->executor_,+              asio::require(+                ASIO_MOVE_CAST(executor_type)(ex),                 execution::blocking.never),-            execution::allocator(allocator)),+              execution::allocator(allocator)),             ASIO_MOVE_CAST(invoker)(*this_));+#endif // defined(ASIO_NO_DEPRECATED)       }     }   };    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);-    }+    run_ready_handlers(impl_);   }  private:@@ -188,13 +182,7 @@      ~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)+      if (push_waiting_to_ready(this_->impl_))       {         Executor ex(this_->work_.get_executor());         recycling_allocator<void> allocator;@@ -205,21 +193,11 @@    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);-    }+    run_ready_handlers(impl_);   }  private:@@ -262,7 +240,7 @@   // 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()))+      && running_in_this_thread(impl))   {     // Make a local, non-const copy of the function.     function_type tmp(ASIO_MOVE_CAST(Function)(function));@@ -285,7 +263,11 @@   p.v = p.p = 0;   if (first)   {+#if defined(ASIO_NO_DEPRECATED)+    ex.execute(invoker<Executor>(impl, ex));+#else // defined(ASIO_NO_DEPRECATED)     execution::execute(ex, invoker<Executor>(impl, ex));+#endif // defined(ASIO_NO_DEPRECATED)   } } @@ -296,7 +278,7 @@   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()))+  if (running_in_this_thread(impl))   {     // Make a local, non-const copy of the function.     function_type tmp(ASIO_MOVE_CAST(Function)(function));
link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/strand_executor_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -124,6 +124,30 @@     const implementation_type& impl) {   return !!call_stack<strand_impl>::contains(impl.get());+}++bool strand_executor_service::push_waiting_to_ready(implementation_type& impl)+{+  impl->mutex_->lock();+  impl->ready_queue_.push(impl->waiting_queue_);+  bool more_handlers = impl->locked_ = !impl->ready_queue_.empty();+  impl->mutex_->unlock();+  return more_handlers;+}++void strand_executor_service::run_ready_handlers(implementation_type& impl)+{+  // Indicate that this strand is executing on the current thread.+  call_stack<strand_impl>::context ctx(impl.get());++  // 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);+  } }  } // namespace detail
link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.hpp view
@@ -2,7 +2,7 @@ // detail/impl/strand_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,7 +15,6 @@ # 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"@@ -33,29 +32,12 @@ { } -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))+  if (running_in_this_thread(impl))   {     fenced_block b(fenced_block::full);     asio_handler_invoke_helpers::invoke(handler, handler);@@ -71,21 +53,9 @@   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);-  }+  do_dispatch(impl, o); }  // Request the io_context to invoke the given handler and return immediately.
link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/strand_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -91,8 +91,25 @@   return call_stack<strand_impl>::contains(impl) != 0; } -bool strand_service::do_dispatch(implementation_type& impl, operation* op)+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);+  }+};++void 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();@@ -102,7 +119,16 @@     // Immediate invocation is allowed.     impl->locked_ = true;     impl->mutex_.unlock();-    return true;++    // 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->complete(&io_context_impl_, asio::error_code(), 0);+    return;   }    if (impl->locked_)@@ -120,8 +146,6 @@     impl->ready_queue_.push(op);     io_context_impl_.post_immediate_completion(impl, false);   }--  return false; }  void strand_service::do_post(implementation_type& impl,
+ link/modules/asio-standalone/asio/include/asio/detail/impl/thread_context.ipp view
@@ -0,0 +1,35 @@+//+// detail/impl/thread_context.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_THREAD_CONTEXT_IPP+#define ASIO_DETAIL_IMPL_THREAD_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/detail/push_options.hpp"++namespace asio {+namespace detail {++thread_info_base* thread_context::top_of_thread_call_stack()+{+  return thread_call_stack::top();+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IMPL_THREAD_CONTEXT_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/throw_error.ipp view
@@ -2,7 +2,7 @@ // detail/impl/throw_error.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,7 +17,6 @@  #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"@@ -25,16 +24,23 @@ namespace asio { namespace detail { -void do_throw_error(const asio::error_code& err)+void do_throw_error(+    const asio::error_code& err+    ASIO_SOURCE_LOCATION_PARAM) {   asio::system_error e(err);-  asio::detail::throw_exception(e);+  asio::detail::throw_exception(e ASIO_SOURCE_LOCATION_ARG); } -void do_throw_error(const asio::error_code& err, const char* location)+void do_throw_error(+    const asio::error_code& err,+    const char* location+    ASIO_SOURCE_LOCATION_PARAM) {   // boostify: non-boost code starts here-#if defined(ASIO_MSVC) && defined(ASIO_HAS_STD_SYSTEM_ERROR)+#if defined(ASIO_MSVC) \+  && defined(ASIO_HAS_STD_SYSTEM_ERROR) \+  && (_MSC_VER < 1800)   // 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.@@ -42,13 +48,17 @@   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)+  asio::detail::throw_exception(e ASIO_SOURCE_LOCATION_ARG);+#else // defined(ASIO_MSVC)+      //   && defined(ASIO_HAS_STD_SYSTEM_ERROR)+      //   && (_MSC_VER < 1928)   // boostify: non-boost code ends here   asio::system_error e(err, location);-  asio::detail::throw_exception(e);+  asio::detail::throw_exception(e ASIO_SOURCE_LOCATION_ARG);   // boostify: non-boost code starts here-#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_STD_SYSTEM_ERROR)+#endif // defined(ASIO_MSVC)+       //   && defined(ASIO_HAS_STD_SYSTEM_ERROR)+       //   && (_MSC_VER < 1800)   // boostify: non-boost code ends here } 
link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_ptime.ipp view
@@ -2,7 +2,7 @@ // detail/impl/timer_queue_ptime.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -73,6 +73,12 @@     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> >::cancel_timer_by_key(+    per_timer_data* timer, op_queue<operation>& ops, void* cancellation_key)+{+  impl_.cancel_timer_by_key(timer, ops, cancellation_key); }  void timer_queue<time_traits<boost::posix_time::ptime> >::move_timer(
link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_set.ipp view
@@ -2,7 +2,7 @@ // detail/impl/timer_queue_set.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_event.ipp view
@@ -2,7 +2,7 @@ // detail/win_event.ipp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_file_service.ipp view
@@ -0,0 +1,265 @@+//+// detail/impl/win_iocp_file_service.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_FILE_SERVICE_IPP+#define ASIO_DETAIL_IMPL_WIN_IOCP_FILE_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_FILE) \+  && defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)++#include <cstring>+#include <sys/stat.h>+#include "asio/detail/win_iocp_file_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++win_iocp_file_service::win_iocp_file_service(+    execution_context& context)+  : execution_context_service_base<win_iocp_file_service>(context),+    handle_service_(context),+    nt_flush_buffers_file_ex_(0)+{+  if (FARPROC nt_flush_buffers_file_ex_ptr = ::GetProcAddress(+        ::GetModuleHandleA("NTDLL"), "NtFlushBuffersFileEx"))+  {+    nt_flush_buffers_file_ex_ = reinterpret_cast<nt_flush_buffers_file_ex_fn>(+        reinterpret_cast<void*>(nt_flush_buffers_file_ex_ptr));+  }+}++void win_iocp_file_service::shutdown()+{+  handle_service_.shutdown();+}++asio::error_code win_iocp_file_service::open(+    win_iocp_file_service::implementation_type& impl,+    const char* path, file_base::flags open_flags,+    asio::error_code& ec)+{+  if (is_open(impl))+  {+    ec = asio::error::already_open;+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }++  DWORD access = 0;+  if ((open_flags & file_base::read_only) != 0)+    access = GENERIC_READ;+  else if ((open_flags & file_base::write_only) != 0)+    access = GENERIC_WRITE;+  else if ((open_flags & file_base::read_write) != 0)+    access = GENERIC_READ | GENERIC_WRITE;++  DWORD share = FILE_SHARE_READ | FILE_SHARE_WRITE;++  DWORD disposition = 0;+  if ((open_flags & file_base::create) != 0)+  {+    if ((open_flags & file_base::exclusive) != 0)+      disposition = CREATE_NEW;+    else+      disposition = OPEN_ALWAYS;+  }+  else+  {+    if ((open_flags & file_base::truncate) != 0)+      disposition = TRUNCATE_EXISTING;+    else+      disposition = OPEN_EXISTING;+  }++  DWORD flags = FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED;+  if (impl.is_stream_)+    flags |= FILE_FLAG_SEQUENTIAL_SCAN;+  else+    flags |= FILE_FLAG_RANDOM_ACCESS;+  if ((open_flags & file_base::sync_all_on_write) != 0)+    flags |= FILE_FLAG_WRITE_THROUGH;++  HANDLE handle = ::CreateFileA(path, access, share, 0, disposition, flags, 0);+  if (handle != INVALID_HANDLE_VALUE)+  {+    if (disposition == OPEN_ALWAYS && (open_flags & file_base::truncate) != 0)+    {+      if (!::SetEndOfFile(handle))+      {+        DWORD last_error = ::GetLastError();+        ::CloseHandle(handle);+        ec.assign(last_error, asio::error::get_system_category());+        ASIO_ERROR_LOCATION(ec);+        return ec;+      }+    }++    handle_service_.assign(impl, handle, ec);+    if (ec)+      ::CloseHandle(handle);+    impl.offset_ = 0;+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }+  else+  {+    DWORD last_error = ::GetLastError();+    ec.assign(last_error, asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }+}++uint64_t win_iocp_file_service::size(+    const win_iocp_file_service::implementation_type& impl,+    asio::error_code& ec) const+{+  LARGE_INTEGER result;+  if (::GetFileSizeEx(native_handle(impl), &result))+  {+    asio::error::clear(ec);+    return static_cast<uint64_t>(result.QuadPart);+  }+  else+  {+    DWORD last_error = ::GetLastError();+    ec.assign(last_error, asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);+    return 0;+  }+}++asio::error_code win_iocp_file_service::resize(+    win_iocp_file_service::implementation_type& impl,+    uint64_t n, asio::error_code& ec)+{+  LARGE_INTEGER distance;+  distance.QuadPart = n;+  if (::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN))+  {+    BOOL result = ::SetEndOfFile(native_handle(impl));+    DWORD last_error = ::GetLastError();++    distance.QuadPart = static_cast<LONGLONG>(impl.offset_);+    if (!::SetFilePointerEx(native_handle(impl), distance, 0, FILE_BEGIN))+    {+      result = FALSE;+      last_error = ::GetLastError();+    }++    if (result)+      asio::error::clear(ec);+    else+      ec.assign(last_error, asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }+  else+  {+    DWORD last_error = ::GetLastError();+    ec.assign(last_error, asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }+}++asio::error_code win_iocp_file_service::sync_all(+    win_iocp_file_service::implementation_type& impl,+    asio::error_code& ec)+{+  BOOL result = ::FlushFileBuffers(native_handle(impl));+  if (result)+  {+    asio::error::clear(ec);+    return ec;+  }+  else+  {+    DWORD last_error = ::GetLastError();+    ec.assign(last_error, asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);+    return ec;+  }+}++asio::error_code win_iocp_file_service::sync_data(+    win_iocp_file_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (nt_flush_buffers_file_ex_)+  {+    io_status_block status = {};+    if (!nt_flush_buffers_file_ex_(native_handle(impl),+          flush_flags_file_data_sync_only, 0, 0, &status))+    {+      asio::error::clear(ec);+      return ec;+    }+  }+  return sync_all(impl, ec);+}++uint64_t win_iocp_file_service::seek(+    win_iocp_file_service::implementation_type& impl, int64_t offset,+    file_base::seek_basis whence, asio::error_code& ec)+{+  DWORD method;+  switch (whence)+  {+  case file_base::seek_set:+    method = FILE_BEGIN;+    break;+  case file_base::seek_cur:+    method = FILE_BEGIN;+    offset = static_cast<int64_t>(impl.offset_) + offset;+    break;+  case file_base::seek_end:+    method = FILE_END;+    break;+  default:+    ec = asio::error::invalid_argument;+    ASIO_ERROR_LOCATION(ec);+    return 0;+  }++  LARGE_INTEGER distance, new_offset;+  distance.QuadPart = offset;+  if (::SetFilePointerEx(native_handle(impl), distance, &new_offset, method))+  {+    impl.offset_ = new_offset.QuadPart;+    asio::error::clear(ec);+    return impl.offset_;+  }+  else+  {+    DWORD last_error = ::GetLastError();+    ec.assign(last_error, asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);+    return 0;+  }+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+       //   && defined(ASIO_HAS_WINDOWS_RANDOM_ACCESS_HANDLE)++#endif // ASIO_DETAIL_IMPL_WIN_IOCP_FILE_SERVICE_IPP
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_handle_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_handle_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -68,6 +68,7 @@ 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)),+    nt_set_info_(0),     mutex_(),     impl_list_(0) {@@ -182,11 +183,15 @@   if (is_open(impl))   {     ec = asio::error::already_open;+    ASIO_ERROR_LOCATION(ec);     return ec;   }    if (iocp_service_.register_handle(handle, ec))+  {+    ASIO_ERROR_LOCATION(ec);     return ec;+  }    impl.handle_ = handle;   ec = asio::error_code();@@ -221,9 +226,47 @@     ec = asio::error_code();   } +  ASIO_ERROR_LOCATION(ec);   return ec; } +win_iocp_handle_service::native_handle_type win_iocp_handle_service::release(+    win_iocp_handle_service::implementation_type& impl,+    asio::error_code& ec)+{+  if (!is_open(impl))+    return INVALID_HANDLE_VALUE;++  cancel(impl, ec);+  if (ec)+  {+    ASIO_ERROR_LOCATION(ec);+    return INVALID_HANDLE_VALUE;+  }++  nt_set_info_fn fn = get_nt_set_info();+  if (fn == 0)+  {+    ec = asio::error::operation_not_supported;+    ASIO_ERROR_LOCATION(ec);+    return INVALID_HANDLE_VALUE;+  }++  ULONG_PTR iosb[2] = { 0, 0 };+  void* info[2] = { 0, 0 };+  if (fn(impl.handle_, iosb, &info, sizeof(info),+        61 /* FileReplaceCompletionInformation */))+  {+    ec = asio::error::operation_not_supported;+    ASIO_ERROR_LOCATION(ec);+    return INVALID_HANDLE_VALUE;+  }++  native_handle_type tmp = impl.handle_;+  impl.handle_ = INVALID_HANDLE_VALUE;+  return tmp;+}+ asio::error_code win_iocp_handle_service::cancel(     win_iocp_handle_service::implementation_type& impl,     asio::error_code& ec)@@ -231,6 +274,7 @@   if (!is_open(impl))   {     ec = asio::error::bad_descriptor;+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -292,6 +336,7 @@     ec = asio::error::operation_not_supported;   } +  ASIO_ERROR_LOCATION(ec);   return ec; } @@ -302,6 +347,7 @@   if (!is_open(impl))   {     ec = asio::error::bad_descriptor;+    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -315,6 +361,7 @@   overlapped_wrapper overlapped(ec);   if (ec)   {+    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -330,6 +377,7 @@     {       ec = asio::error_code(last_error,           asio::error::get_system_category());+      ASIO_ERROR_LOCATION(ec);       return 0;     }   }@@ -343,6 +391,7 @@     DWORD last_error = ::GetLastError();     ec = asio::error_code(last_error,         asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -394,6 +443,7 @@   if (!is_open(impl))   {     ec = asio::error::bad_descriptor;+    ASIO_ERROR_LOCATION(ec);     return 0;   }   @@ -407,6 +457,7 @@   overlapped_wrapper overlapped(ec);   if (ec)   {+    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -429,6 +480,7 @@         ec = asio::error_code(last_error,             asio::error::get_system_category());       }+      ASIO_ERROR_LOCATION(ec);       return 0;     }   }@@ -449,6 +501,7 @@       ec = asio::error_code(last_error,           asio::error::get_system_category());     }+    ASIO_ERROR_LOCATION(ec);     return (last_error == ERROR_MORE_DATA) ? bytes_transferred : 0;   } @@ -513,6 +566,47 @@     impl.handle_ = INVALID_HANDLE_VALUE;     impl.safe_cancellation_thread_id_ = 0;   }+}++win_iocp_handle_service::nt_set_info_fn+win_iocp_handle_service::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_handle_service::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_handle_service::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
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.hpp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_io_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -76,8 +76,25 @@   mutex::scoped_lock lock(dispatch_mutex_);   op_queue<win_iocp_operation> ops;   std::size_t n = queue.cancel_timer(timer, ops, max_cancelled);+  lock.unlock();   post_deferred_completions(ops);   return n;+}++template <typename Time_Traits>+void win_iocp_io_context::cancel_timer_by_key(timer_queue<Time_Traits>& queue,+    typename timer_queue<Time_Traits>::per_timer_data* timer,+    void* cancellation_key)+{+  // If the service has been shut down we silently ignore the cancellation.+  if (::InterlockedExchangeAdd(&shutdown_, 0) != 0)+    return;++  mutex::scoped_lock lock(dispatch_mutex_);+  op_queue<win_iocp_operation> ops;+  queue.cancel_timer_by_key(timer, ops, cancellation_key);+  lock.unlock();+  post_deferred_completions(ops); }  template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_io_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,7 +51,7 @@  struct win_iocp_io_context::work_finished_on_block_exit {-  ~work_finished_on_block_exit()+  ~work_finished_on_block_exit() ASIO_NOEXCEPT_IF(false)   {     io_context_->work_finished();   }@@ -168,7 +168,10 @@   }    if (timer_thread_.get())+  {     timer_thread_->join();+    timer_thread_.reset();+  } }  asio::error_code win_iocp_io_context::register_handle(@@ -287,6 +290,11 @@   } } +bool win_iocp_io_context::can_dispatch()+{+  return thread_call_stack::contains(this) != 0;+}+ void win_iocp_io_context::capture_current_exception() {   if (thread_info_base* this_thread = thread_call_stack::contains(this))@@ -522,6 +530,7 @@  DWORD win_iocp_io_context::get_gqcs_timeout() {+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)   OSVERSIONINFOEX osvi;   ZeroMemory(&osvi, sizeof(osvi));   osvi.dwOSVersionInfoSize = sizeof(osvi);@@ -534,6 +543,9 @@     return INFINITE;    return default_gqcs_timeout;+#else // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)+  return INFINITE;+#endif // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) }  void win_iocp_io_context::do_add_timer_queue(timer_queue_base& queue)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_serial_port_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -46,6 +46,7 @@   if (is_open(impl))   {     ec = asio::error::already_open;+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -61,6 +62,7 @@     DWORD last_error = ::GetLastError();     ec = asio::error_code(last_error,         asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -75,6 +77,7 @@     ::CloseHandle(handle);     ec = asio::error_code(last_error,         asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -101,6 +104,7 @@     ::CloseHandle(handle);     ec = asio::error_code(last_error,         asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -119,6 +123,7 @@     ::CloseHandle(handle);     ec = asio::error_code(last_error,         asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -143,6 +148,7 @@     DWORD last_error = ::GetLastError();     ec = asio::error_code(last_error,         asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -154,6 +160,7 @@     DWORD last_error = ::GetLastError();     ec = asio::error_code(last_error,         asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -176,6 +183,7 @@     DWORD last_error = ::GetLastError();     ec = asio::error_code(last_error,         asio::error::get_system_category());+    ASIO_ERROR_LOCATION(ec);     return ec;   } 
link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_iocp_socket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -410,9 +410,8 @@  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)+    WSABUF* buffers, std::size_t buffer_count, const void* addr,+    int addrlen, socket_base::message_flags flags, operation* op) {   update_cancellation_thread_id(impl);   iocp_service_.work_started();@@ -423,8 +422,8 @@   {     DWORD bytes_transferred = 0;     int result = ::WSASendTo(impl.socket_, buffers,-        static_cast<DWORD>(buffer_count),-        &bytes_transferred, flags, addr, addrlen, op, 0);+        static_cast<DWORD>(buffer_count), &bytes_transferred, flags,+        static_cast<const socket_addr_type*>(addr), addrlen, op, 0);     DWORD last_error = ::WSAGetLastError();     if (last_error == ERROR_PORT_UNREACHABLE)       last_error = WSAECONNREFUSED;@@ -466,29 +465,30 @@   } } -void win_iocp_socket_service_base::start_null_buffers_receive_op(+int 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)+    socket_base::message_flags flags, reactor_op* op, operation* iocp_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);+    start_receive_op(impl, &buf, 1, flags, false, iocp_op);+    return -1;   }   else   {-    start_reactor_op(impl,-        (flags & socket_base::message_out_of_band)-          ? select_reactor::except_op : select_reactor::read_op,-        op);+    int op_type = (flags & socket_base::message_out_of_band)+      ? select_reactor::except_op : select_reactor::read_op;+    start_reactor_op(impl, op_type, op);+    return op_type;   } }  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,+    WSABUF* buffers, std::size_t buffer_count, void* addr,     socket_base::message_flags flags, int* addrlen, operation* op) {   update_cancellation_thread_id(impl);@@ -501,8 +501,8 @@     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);+        static_cast<DWORD>(buffer_count), &bytes_transferred, &recv_flags,+        static_cast<socket_addr_type*>(addr), addrlen, op, 0);     DWORD last_error = ::WSAGetLastError();     if (last_error == ERROR_PORT_UNREACHABLE)       last_error = WSAECONNREFUSED;@@ -547,11 +547,17 @@  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)+    int protocol, void* output_buffer, DWORD address_length,+    long* cancel_requested, operation* op) {   new_socket.reset();   iocp_service_.work_started(); +  // Check if we were cancelled after the first AcceptEx completed.+  if (cancel_requested)+    if (::InterlockedExchangeAdd(cancel_requested, 0) == 1)+      iocp_service_.on_completion(op, asio::error::operation_aborted);+   asio::error_code ec;   new_socket.reset(socket_ops::socket(family, type, protocol, ec));   if (new_socket.get() == invalid_socket)@@ -565,7 +571,19 @@     if (!result && last_error != WSA_IO_PENDING)       iocp_service_.on_completion(op, last_error);     else+    {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+      if (cancel_requested)+      {+        if (::InterlockedExchangeAdd(cancel_requested, 0) == 1)+        {+          HANDLE sock_as_handle = reinterpret_cast<HANDLE>(s);+          ::CancelIoEx(sock_as_handle, op);+        }+      }+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)       iocp_service_.on_pending(op);+    }   } } @@ -587,10 +605,10 @@   iocp_service_.post_immediate_completion(op, false); } -void win_iocp_socket_service_base::start_connect_op(+int 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)+    int family, int type, const void* addr, std::size_t addrlen,+    win_iocp_socket_connect_op_base* op, operation* iocp_op) {   // If ConnectEx is available, use that.   if (family == ASIO_OS_DEF(AF_INET)@@ -615,7 +633,7 @@       if (op->ec_ && op->ec_ != asio::error::invalid_argument)       {         iocp_service_.post_immediate_completion(op, false);-        return;+        return -1;       }        op->connect_ex_ = true;@@ -623,13 +641,14 @@       iocp_service_.work_started();        BOOL result = connect_ex(impl.socket_,-          addr, static_cast<int>(addrlen), 0, 0, 0, op);+          static_cast<const socket_addr_type*>(addr),+          static_cast<int>(addrlen), 0, 0, 0, iocp_op);       DWORD last_error = ::WSAGetLastError();       if (!result && last_error != WSA_IO_PENDING)-        iocp_service_.on_completion(op, last_error);+        iocp_service_.on_completion(iocp_op, last_error);       else-        iocp_service_.on_pending(op);-      return;+        iocp_service_.on_pending(iocp_op);+      return -1;     }   } @@ -649,12 +668,13 @@         op->ec_ = asio::error_code();         r.start_op(select_reactor::connect_op, impl.socket_,             impl.reactor_data_, op, false, false);-        return;+        return select_reactor::connect_op;       }     }   }    r.post_immediate_completion(op, false);+  return -1; }  void win_iocp_socket_service_base::close_for_destruction(
link/modules/asio-standalone/asio/include/asio/detail/impl/win_mutex.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_object_handle_service.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_object_handle_service.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -213,6 +213,7 @@   if (is_open(impl))   {     ec = asio::error::already_open;+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -270,6 +271,7 @@     ec = asio::error_code();   } +  ASIO_ERROR_LOCATION(ec);   return ec; } @@ -312,6 +314,7 @@     ec = asio::error::bad_descriptor;   } +  ASIO_ERROR_LOCATION(ec);   return ec; } @@ -326,6 +329,7 @@       DWORD last_error = ::GetLastError();       ec = asio::error_code(last_error,           asio::error::get_system_category());+      ASIO_ERROR_LOCATION(ec);       break;     }   case WAIT_OBJECT_0:
link/modules/asio-standalone/asio/include/asio/detail/impl/win_static_mutex.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_static_mutex.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_thread.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_thread.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/win_tss_ptr.ipp view
@@ -2,7 +2,7 @@ // detail/impl/win_tss_ptr.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp view
@@ -2,7 +2,7 @@ // detail/impl/winrt_ssocket_service_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -182,7 +182,7 @@         : impl.socket_->Information->RemotePort);     unsigned long scope = 0; -    switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family)+    switch (static_cast<const socket_addr_type*>(addr)->sa_family)     {     case ASIO_OS_DEF(AF_INET):       if (addr_len < sizeof(sockaddr_in4_type))@@ -351,7 +351,7 @@    char addr_string[max_addr_v6_str_len];   unsigned short port;-  switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family)+  switch (static_cast<const socket_addr_type*>(addr)->sa_family)   {   case ASIO_OS_DEF(AF_INET):     socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET),@@ -401,7 +401,7 @@    char addr_string[max_addr_v6_str_len];   unsigned short port = 0;-  switch (reinterpret_cast<const socket_addr_type*>(addr)->sa_family)+  switch (static_cast<const socket_addr_type*>(addr)->sa_family)   {   case ASIO_OS_DEF(AF_INET):     socket_ops::inet_ntop(ASIO_OS_DEF(AF_INET),
link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp view
@@ -2,7 +2,7 @@ // detail/impl/winrt_timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp view
@@ -2,7 +2,7 @@ // detail/impl/winrt_timer_scheduler.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/impl/winsock_init.ipp view
@@ -2,7 +2,7 @@ // detail/impl/winsock_init.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/initiate_defer.hpp view
@@ -0,0 +1,252 @@+//+// detail/initiate_defer.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_INITIATE_DEFER_HPP+#define ASIO_DETAIL_INITIATE_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));++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(+        asio::require(ex, execution::blocking.never),+        execution::relationship.continuation,+        execution::allocator(alloc)+      ).execute(+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(+        asio::prefer(+          asio::require(ex, execution::blocking.never),+          execution::relationship.continuation,+          execution::allocator(alloc)),+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+  }++  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::detail::bind_handler(+          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+      >::type* = 0,+      typename enable_if<+        !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));++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(+        asio::require(ex_, execution::blocking.never),+        execution::relationship.continuation,+        execution::allocator(alloc)+      ).execute(+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(+        asio::prefer(+          asio::require(ex_, execution::blocking.never),+          execution::relationship.continuation,+          execution::allocator(alloc)),+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+      >::type* = 0,+      typename enable_if<+        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));++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(+        asio::require(ex_, execution::blocking.never),+        execution::relationship.continuation,+        execution::allocator(alloc)+      ).execute(+        detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#else // defined(ASIO_NO_DEPRECATED)+    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));+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+      >::type* = 0,+      typename enable_if<+        !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::detail::bind_handler(+          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+      >::type* = 0,+      typename enable_if<+        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+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_INITIATE_DEFER_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/initiate_dispatch.hpp view
@@ -0,0 +1,229 @@+//+// detail/initiate_dispatch.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_INITIATE_DISPATCH_HPP+#define ASIO_DETAIL_INITIATE_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));++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(ex, execution::allocator(alloc)).execute(+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(+        asio::prefer(ex, execution::allocator(alloc)),+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+  }++  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::detail::bind_handler(+          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+      >::type* = 0,+      typename enable_if<+        !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));++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(ex_, execution::allocator(alloc)).execute(+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(+        asio::prefer(ex_, execution::allocator(alloc)),+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+      >::type* = 0,+      typename enable_if<+        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));++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(ex_, execution::allocator(alloc)).execute(+        detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(+        asio::prefer(ex_, execution::allocator(alloc)),+        detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+      >::type* = 0,+      typename enable_if<+        !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::detail::bind_handler(+          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+      >::type* = 0,+      typename enable_if<+        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+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_INITIATE_DISPATCH_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/initiate_post.hpp view
@@ -0,0 +1,252 @@+//+// detail/initiate_post.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_INITIATE_POST_HPP+#define ASIO_DETAIL_INITIATE_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));++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(+        asio::require(ex, execution::blocking.never),+        execution::relationship.fork,+        execution::allocator(alloc)+      ).execute(+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(+        asio::prefer(+          asio::require(ex, execution::blocking.never),+          execution::relationship.fork,+          execution::allocator(alloc)),+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+  }++  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::detail::bind_handler(+          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+      >::type* = 0,+      typename enable_if<+        !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));++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(+        asio::require(ex_, execution::blocking.never),+        execution::relationship.fork,+        execution::allocator(alloc)+      ).execute(+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(+        asio::prefer(+          asio::require(ex_, execution::blocking.never),+          execution::relationship.fork,+          execution::allocator(alloc)),+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(CompletionHandler)(handler)));+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+      >::type* = 0,+      typename enable_if<+        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));++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(+        asio::require(ex_, execution::blocking.never),+        execution::relationship.fork,+        execution::allocator(alloc)+      ).execute(+        detail::work_dispatcher<handler_t, handler_ex_t>(+          ASIO_MOVE_CAST(CompletionHandler)(handler), handler_ex));+#else // defined(ASIO_NO_DEPRECATED)+    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));+#endif // defined(ASIO_NO_DEPRECATED)+  }++  template <typename CompletionHandler>+  void operator()(ASIO_MOVE_ARG(CompletionHandler) handler,+      typename enable_if<+        !execution::is_executor<+          typename conditional<true, executor_type, CompletionHandler>::type+        >::value+      >::type* = 0,+      typename enable_if<+        !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::detail::bind_handler(+          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+      >::type* = 0,+      typename enable_if<+        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+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_INITIATE_POST_HPP
link/modules/asio-standalone/asio/include/asio/detail/io_control.hpp view
@@ -2,7 +2,7 @@ // detail/io_control.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/io_object_impl.hpp view
@@ -2,7 +2,7 @@ // io_object_impl.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -43,7 +43,7 @@   typedef Executor executor_type;    // Construct an I/O object using an executor.-  explicit io_object_impl(const executor_type& ex)+  explicit io_object_impl(int, const executor_type& ex)     : service_(&asio::use_service<IoObjectService>(           io_object_impl::get_context(ex))),       executor_(ex)@@ -53,9 +53,7 @@    // 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)+  explicit io_object_impl(int, int, ExecutionContext& context)     : service_(&asio::use_service<IoObjectService>(context)),       executor_(context.get_executor())   {@@ -71,7 +69,16 @@     service_->move_construct(implementation_, other.implementation_);   } -  // Perform a converting move-construction of an I/O object.+  // Perform converting move-construction of an I/O object on the same service.+  template <typename Executor1>+  io_object_impl(io_object_impl<IoObjectService, Executor1>&& other)+    : service_(&other.get_service()),+      executor_(other.get_executor())+  {+    service_->move_construct(implementation_, other.get_implementation());+  }++  // Perform converting move-construction of an I/O object on another service.   template <typename IoObjectService1, typename Executor1>   io_object_impl(io_object_impl<IoObjectService1, Executor1>&& other)     : service_(&asio::use_service<IoObjectService>(@@ -98,8 +105,7 @@       service_->move_assign(implementation_,           *other.service_, other.implementation_);       executor_.~executor_type();-      new (&executor_) executor_type(-          std::move(other.executor_));+      new (&executor_) executor_type(other.executor_);       service_ = other.service_;     }     return *this;
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_at_op.hpp view
@@ -0,0 +1,195 @@+//+// detail/io_uring_descriptor_read_at_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_DESCRIPTOR_READ_AT_OP_HPP+#define ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_AT_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_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/cstdint.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class io_uring_descriptor_read_at_op_base : public io_uring_operation+{+public:+  io_uring_descriptor_read_at_op_base(+      const asio::error_code& success_ec, int descriptor,+      descriptor_ops::state_type state, uint64_t offset,+      const MutableBufferSequence& buffers, func_type complete_func)+    : io_uring_operation(success_ec,+        &io_uring_descriptor_read_at_op_base::do_prepare,+        &io_uring_descriptor_read_at_op_base::do_perform, complete_func),+      descriptor_(descriptor),+      state_(state),+      offset_(offset),+      buffers_(buffers),+      bufs_(buffers)+  {+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_read_at_op_base* o(+        static_cast<io_uring_descriptor_read_at_op_base*>(base));++    if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+    {+      ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLIN);+    }+    else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer)+    {+      ::io_uring_prep_read_fixed(sqe, o->descriptor_,+          o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+          o->offset_, o->bufs_.registered_id().native_handle());+    }+    else+    {+      ::io_uring_prep_readv(sqe, o->descriptor_,+          o->bufs_.buffers(), o->bufs_.count(), o->offset_);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_read_at_op_base* o(+        static_cast<io_uring_descriptor_read_at_op_base*>(base));++    if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+    {+      if (o->bufs_.is_single_buffer)+      {+        return descriptor_ops::non_blocking_read_at1(o->descriptor_,+            o->offset_, o->bufs_.first(o->buffers_).data(),+            o->bufs_.first(o->buffers_).size(), o->ec_,+            o->bytes_transferred_);+      }+      else+      {+        return descriptor_ops::non_blocking_read_at(o->descriptor_,+            o->offset_, o->bufs_.buffers(), o->bufs_.count(),+            o->ec_, o->bytes_transferred_);+      }+    }+    else if (after_completion)+    {+      if (!o->ec_ && o->bytes_transferred_ == 0)+        o->ec_ = asio::error::eof;+    }++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= descriptor_ops::internal_non_blocking;+      return false;+    }++    return after_completion;+  }++private:+  int descriptor_;+  descriptor_ops::state_type state_;+  uint64_t offset_;+  MutableBufferSequence buffers_;+  buffer_sequence_adapter<asio::mutable_buffer,+      MutableBufferSequence> bufs_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class io_uring_descriptor_read_at_op+  : public io_uring_descriptor_read_at_op_base<MutableBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_read_at_op);++  io_uring_descriptor_read_at_op(const asio::error_code& success_ec,+      int descriptor, descriptor_ops::state_type state, uint64_t offset,+      const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+    : io_uring_descriptor_read_at_op_base<MutableBufferSequence>(+        success_ec, descriptor, state, offset, buffers,+        &io_uring_descriptor_read_at_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.+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_read_at_op* o+      (static_cast<io_uring_descriptor_read_at_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_AT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_op.hpp view
@@ -0,0 +1,190 @@+//+// detail/io_uring_descriptor_read_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_DESCRIPTOR_READ_OP_HPP+#define ASIO_DETAIL_IO_URING_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_HAS_IO_URING)++#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/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class io_uring_descriptor_read_op_base : public io_uring_operation+{+public:+  io_uring_descriptor_read_op_base(const asio::error_code& success_ec,+      int descriptor, descriptor_ops::state_type state,+      const MutableBufferSequence& buffers, func_type complete_func)+    : io_uring_operation(success_ec,+        &io_uring_descriptor_read_op_base::do_prepare,+        &io_uring_descriptor_read_op_base::do_perform, complete_func),+      descriptor_(descriptor),+      state_(state),+      buffers_(buffers),+      bufs_(buffers)+  {+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_read_op_base* o(+        static_cast<io_uring_descriptor_read_op_base*>(base));++    if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+    {+      ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLIN);+    }+    else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer)+    {+      ::io_uring_prep_read_fixed(sqe, o->descriptor_,+          o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+          0, o->bufs_.registered_id().native_handle());+    }+    else+    {+      ::io_uring_prep_readv(sqe, o->descriptor_,+          o->bufs_.buffers(), o->bufs_.count(), -1);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_read_op_base* o(+        static_cast<io_uring_descriptor_read_op_base*>(base));++    if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+    {+      if (o->bufs_.is_single_buffer)+      {+        return descriptor_ops::non_blocking_read1(+            o->descriptor_, o->bufs_.first(o->buffers_).data(),+            o->bufs_.first(o->buffers_).size(), o->ec_,+            o->bytes_transferred_);+      }+      else+      {+        return descriptor_ops::non_blocking_read(+            o->descriptor_, o->bufs_.buffers(), o->bufs_.count(),+            o->ec_, o->bytes_transferred_);+      }+    }+    else if (after_completion)+    {+      if (!o->ec_ && o->bytes_transferred_ == 0)+        o->ec_ = asio::error::eof;+    }++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= descriptor_ops::internal_non_blocking;+      return false;+    }++    return after_completion;+  }++private:+  int descriptor_;+  descriptor_ops::state_type state_;+  MutableBufferSequence buffers_;+  buffer_sequence_adapter<asio::mutable_buffer,+      MutableBufferSequence> bufs_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class io_uring_descriptor_read_op+  : public io_uring_descriptor_read_op_base<MutableBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_read_op);++  io_uring_descriptor_read_op(const asio::error_code& success_ec,+      int descriptor, descriptor_ops::state_type state,+      const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+    : io_uring_descriptor_read_op_base<MutableBufferSequence>(success_ec,+        descriptor, state, buffers, &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_read_op* o+      (static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_READ_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_service.hpp view
@@ -0,0 +1,687 @@+//+// detail/io_uring_descriptor_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_DESCRIPTOR_SERVICE_HPP+#define ASIO_DETAIL_IO_URING_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_HAS_IO_URING)++#include "asio/associated_cancellation_slot.hpp"+#include "asio/buffer.hpp"+#include "asio/cancellation_type.hpp"+#include "asio/execution_context.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/io_uring_descriptor_read_at_op.hpp"+#include "asio/detail/io_uring_descriptor_read_op.hpp"+#include "asio/detail/io_uring_descriptor_write_at_op.hpp"+#include "asio/detail/io_uring_descriptor_write_op.hpp"+#include "asio/detail/io_uring_null_buffers_op.hpp"+#include "asio/detail/io_uring_service.hpp"+#include "asio/detail/io_uring_wait_op.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/posix/descriptor_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class io_uring_descriptor_service :+  public execution_context_service_base<io_uring_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 io_uring_descriptor_service;++    // The native descriptor representation.+    int descriptor_;++    // The current state of the descriptor.+    descriptor_ops::state_type state_;++    // Per I/O object data used by the io_uring_service.+    io_uring_service::per_io_object_data io_object_data_;+  };++  // Constructor.+  ASIO_DECL io_uring_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,+      io_uring_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);++  // Release ownership of the native descriptor representation.+  native_handle_type release(implementation_type& impl,+      asio::error_code& ec)+  {+    ec = success_ec_;+    return release(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);+    ASIO_ERROR_LOCATION(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);+    ASIO_ERROR_LOCATION(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);+    ASIO_ERROR_LOCATION(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;+    }++    ASIO_ERROR_LOCATION(ec);+    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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    int op_type;+    int poll_flags;+    switch (w)+    {+    case posix::descriptor_base::wait_read:+      op_type = io_uring_service::read_op;+      poll_flags = POLLIN;+      break;+    case posix::descriptor_base::wait_write:+      op_type = io_uring_service::write_op;+      poll_flags = POLLOUT;+      break;+    case posix::descriptor_base::wait_error:+      op_type = io_uring_service::except_op;+      poll_flags = POLLPRI | POLLERR | POLLHUP;+      break;+    default:+      op_type = -1;+      poll_flags = -1;+      return;+    }++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.descriptor_,+        poll_flags, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected() && op_type != -1)+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(+            &io_uring_service_, &impl.io_object_data_, op_type);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "descriptor", &impl, impl.descriptor_, "async_wait"));++    start_op(impl, op_type, p.p, is_continuation, op_type == -1);+    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;++    size_t n;+    if (bufs_type::is_single_buffer)+    {+      n = descriptor_ops::sync_write1(impl.descriptor_,+          impl.state_, bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), ec);+    }+    else+    {+      bufs_type bufs(buffers);++      n = descriptor_ops::sync_write(impl.descriptor_, impl.state_,+          bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+    }++    ASIO_ERROR_LOCATION(ec);+    return n;+  }++  // 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);++    ASIO_ERROR_LOCATION(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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_,+        impl.state_, buffers, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::write_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "descriptor", &impl, impl.descriptor_, "async_write_some"));++    start_op(impl, io_uring_service::write_op, p.p, is_continuation,+        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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.descriptor_, POLLOUT, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::write_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(),+          *p.p, "descriptor", &impl, impl.descriptor_,+          "async_write_some(null_buffers)"));++    start_op(impl, io_uring_service::write_op, p.p, is_continuation, false);+    p.v = p.p = 0;+  }++  // Write some data to the descriptor at the specified offset.+  template <typename ConstBufferSequence>+  size_t write_some_at(implementation_type& impl, uint64_t offset,+      const ConstBufferSequence& buffers, asio::error_code& ec)+  {+    typedef buffer_sequence_adapter<asio::const_buffer,+        ConstBufferSequence> bufs_type;++    size_t n;+    if (bufs_type::is_single_buffer)+    {+      n = descriptor_ops::sync_write_at1(impl.descriptor_,+          impl.state_, offset, bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), ec);+    }+    else+    {+      bufs_type bufs(buffers);++      n = descriptor_ops::sync_write_at(impl.descriptor_, impl.state_,+          offset, bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+    }++    ASIO_ERROR_LOCATION(ec);+    return n;+  }++  // Wait until data can be written without blocking.+  size_t write_some_at(implementation_type& impl, uint64_t,+      const null_buffers& buffers, asio::error_code& ec)+  {+    return write_some(impl, buffers, ec);+  }++  // Start an asynchronous write at the specified offset. 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_at(implementation_type& impl, uint64_t offset,+      const ConstBufferSequence& buffers, Handler& handler,+      const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_descriptor_write_at_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_,+        impl.state_, offset, buffers, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::write_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "descriptor", &impl, impl.descriptor_, "async_write_some"));++    start_op(impl, io_uring_service::write_op, p.p, is_continuation,+        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_at(implementation_type& impl,+      const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex)+  {+    return async_write_some(impl, buffers, handler, io_ex);+  }++  // 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;++    size_t n;+    if (bufs_type::is_single_buffer)+    {+      n = descriptor_ops::sync_read1(impl.descriptor_,+          impl.state_, bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), ec);+    }+    else+    {+      bufs_type bufs(buffers);++      n = descriptor_ops::sync_read(impl.descriptor_, impl.state_,+          bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+    }++    ASIO_ERROR_LOCATION(ec);+    return n;+  }++  // 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);++    ASIO_ERROR_LOCATION(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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_,+        impl.state_, buffers, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::read_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "descriptor", &impl, impl.descriptor_, "async_read_some"));++    start_op(impl, io_uring_service::read_op, p.p, is_continuation,+        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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.descriptor_, POLLIN, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::read_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(),+          *p.p, "descriptor", &impl, impl.descriptor_,+          "async_read_some(null_buffers)"));++    start_op(impl, io_uring_service::read_op, p.p, is_continuation, false);+    p.v = p.p = 0;+  }++  // Read some data at the specified offset. Returns the number of bytes read.+  template <typename MutableBufferSequence>+  size_t read_some_at(implementation_type& impl, uint64_t offset,+      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_read_at1(impl.descriptor_,+          impl.state_, offset, bufs_type::first(buffers).data(),+          bufs_type::first(buffers).size(), ec);+    }+    else+    {+      bufs_type bufs(buffers);++      return descriptor_ops::sync_read_at(impl.descriptor_, impl.state_,+          offset, bufs.buffers(), bufs.count(), bufs.all_empty(), ec);+    }+  }++  // Wait until data can be read without blocking.+  size_t read_some_at(implementation_type& impl, uint64_t,+      const null_buffers& buffers, asio::error_code& ec)+  {+    return read_some(impl, buffers, ec);+  }++  // 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_at(implementation_type& impl,+      uint64_t offset, const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    bool is_continuation =+      asio_handler_cont_helpers::is_continuation(handler);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_descriptor_read_at_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_,+        impl.state_, offset, buffers, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::read_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "descriptor", &impl, impl.descriptor_, "async_read_some"));++    start_op(impl, io_uring_service::read_op, p.p, is_continuation,+        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_at(implementation_type& impl, uint64_t,+      const null_buffers& buffers, Handler& handler, const IoExecutor& io_ex)+  {+    return async_read_some(impl, buffers, handler, io_ex);+  }++private:+  // Start the asynchronous operation.+  ASIO_DECL void start_op(implementation_type& impl, int op_type,+      io_uring_operation* op, bool is_continuation, bool noop);++  // Helper class used to implement per-operation cancellation+  class io_uring_op_cancellation+  {+  public:+    io_uring_op_cancellation(io_uring_service* s,+        io_uring_service::per_io_object_data* p, int o)+      : io_uring_service_(s),+        io_object_data_(p),+        op_type_(o)+    {+    }++    void operator()(cancellation_type_t type)+    {+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        io_uring_service_->cancel_ops_by_key(*io_object_data_, op_type_, this);+      }+    }++  private:+    io_uring_service* io_uring_service_;+    io_uring_service::per_io_object_data* io_object_data_;+    int op_type_;+  };++  // The io_uring_service that performs event demultiplexing for the service.+  io_uring_service& io_uring_service_;++  // 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/io_uring_descriptor_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_at_op.hpp view
@@ -0,0 +1,189 @@+//+// detail/io_uring_descriptor_write_at_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_DESCRIPTOR_WRITE_AT_OP_HPP+#define ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_AT_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_IO_URING)++#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/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence>+class io_uring_descriptor_write_at_op_base : public io_uring_operation+{+public:+  io_uring_descriptor_write_at_op_base(+      const asio::error_code& success_ec, int descriptor,+      descriptor_ops::state_type state, uint64_t offset,+      const ConstBufferSequence& buffers, func_type complete_func)+    : io_uring_operation(success_ec,+        &io_uring_descriptor_write_at_op_base::do_prepare,+        &io_uring_descriptor_write_at_op_base::do_perform, complete_func),+      descriptor_(descriptor),+      state_(state),+      offset_(offset),+      buffers_(buffers),+      bufs_(buffers)+  {+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_write_at_op_base* o(+        static_cast<io_uring_descriptor_write_at_op_base*>(base));++    if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+    {+      ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLOUT);+    }+    else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer)+    {+      ::io_uring_prep_write_fixed(sqe, o->descriptor_,+          o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+          o->offset_, o->bufs_.registered_id().native_handle());+    }+    else+    {+      ::io_uring_prep_writev(sqe, o->descriptor_,+          o->bufs_.buffers(), o->bufs_.count(), o->offset_);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_write_at_op_base* o(+        static_cast<io_uring_descriptor_write_at_op_base*>(base));++    if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+    {+      if (o->bufs_.is_single_buffer)+      {+        return descriptor_ops::non_blocking_write_at1(o->descriptor_,+            o->offset_, o->bufs_.first(o->buffers_).data(),+            o->bufs_.first(o->buffers_).size(), o->ec_,+            o->bytes_transferred_);+      }+      else+      {+        return descriptor_ops::non_blocking_write_at(o->descriptor_,+            o->offset_, o->bufs_.buffers(), o->bufs_.count(),+            o->ec_, o->bytes_transferred_);+      }+    }++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= descriptor_ops::internal_non_blocking;+      return false;+    }++    return after_completion;+  }++private:+  int descriptor_;+  descriptor_ops::state_type state_;+  uint64_t offset_;+  ConstBufferSequence buffers_;+  buffer_sequence_adapter<asio::const_buffer,+      ConstBufferSequence> bufs_;+};++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class io_uring_descriptor_write_at_op+  : public io_uring_descriptor_write_at_op_base<ConstBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_write_at_op);++  io_uring_descriptor_write_at_op(const asio::error_code& success_ec,+      int descriptor, descriptor_ops::state_type state, uint64_t offset,+      const ConstBufferSequence& buffers, Handler& handler,+      const IoExecutor& io_ex)+    : io_uring_descriptor_write_at_op_base<ConstBufferSequence>(+        success_ec, descriptor, state, offset, buffers,+        &io_uring_descriptor_write_at_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.+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_write_at_op* o+      (static_cast<io_uring_descriptor_write_at_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_AT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_op.hpp view
@@ -0,0 +1,185 @@+//+// detail/io_uring_descriptor_write_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_DESCRIPTOR_WRITE_OP_HPP+#define ASIO_DETAIL_IO_URING_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_HAS_IO_URING)++#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/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence>+class io_uring_descriptor_write_op_base : public io_uring_operation+{+public:+  io_uring_descriptor_write_op_base(const asio::error_code& success_ec,+      int descriptor, descriptor_ops::state_type state,+      const ConstBufferSequence& buffers, func_type complete_func)+    : io_uring_operation(success_ec,+        &io_uring_descriptor_write_op_base::do_prepare,+        &io_uring_descriptor_write_op_base::do_perform, complete_func),+      descriptor_(descriptor),+      state_(state),+      buffers_(buffers),+      bufs_(buffers)+  {+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_write_op_base* o(+        static_cast<io_uring_descriptor_write_op_base*>(base));++    if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+    {+      ::io_uring_prep_poll_add(sqe, o->descriptor_, POLLOUT);+    }+    else if (o->bufs_.is_single_buffer && o->bufs_.is_registered_buffer)+    {+      ::io_uring_prep_write_fixed(sqe, o->descriptor_,+          o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+          0, o->bufs_.registered_id().native_handle());+    }+    else+    {+      ::io_uring_prep_writev(sqe, o->descriptor_,+          o->bufs_.buffers(), o->bufs_.count(), -1);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_write_op_base* o(+        static_cast<io_uring_descriptor_write_op_base*>(base));++    if ((o->state_ & descriptor_ops::internal_non_blocking) != 0)+    {+      if (o->bufs_.is_single_buffer)+      {+        return descriptor_ops::non_blocking_write1(+            o->descriptor_, o->bufs_.first(o->buffers_).data(),+            o->bufs_.first(o->buffers_).size(), o->ec_,+            o->bytes_transferred_);+      }+      else+      {+        return descriptor_ops::non_blocking_write(+            o->descriptor_, o->bufs_.buffers(), o->bufs_.count(),+            o->ec_, o->bytes_transferred_);+      }+    }++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= descriptor_ops::internal_non_blocking;+      return false;+    }++    return after_completion;+  }++private:+  int descriptor_;+  descriptor_ops::state_type state_;+  ConstBufferSequence buffers_;+  buffer_sequence_adapter<asio::const_buffer,+      ConstBufferSequence> bufs_;+};++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class io_uring_descriptor_write_op+  : public io_uring_descriptor_write_op_base<ConstBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_descriptor_write_op);++  io_uring_descriptor_write_op(const asio::error_code& success_ec,+      int descriptor, descriptor_ops::state_type state,+      const ConstBufferSequence& buffers, Handler& handler,+      const IoExecutor& io_ex)+    : io_uring_descriptor_write_op_base<ConstBufferSequence>(success_ec,+        descriptor, state, buffers, &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_descriptor_write_op* o+      (static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_DESCRIPTOR_WRITE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_file_service.hpp view
@@ -0,0 +1,261 @@+//+// detail/io_uring_file_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_FILE_SERVICE_HPP+#define ASIO_DETAIL_IO_URING_FILE_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_FILE) \+  && defined(ASIO_HAS_IO_URING)++#include <string>+#include "asio/detail/cstdint.hpp"+#include "asio/detail/descriptor_ops.hpp"+#include "asio/detail/io_uring_descriptor_service.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/file_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Extend the io_uring_descriptor_service to provide file support.+class io_uring_file_service :+  public execution_context_service_base<io_uring_file_service>+{+public:+  typedef io_uring_descriptor_service descriptor_service;++  // The native type of a file.+  typedef descriptor_service::native_handle_type native_handle_type;++  // The implementation type of the file.+  class implementation_type : descriptor_service::implementation_type+  {+  private:+    // Only this service will have access to the internal values.+    friend class io_uring_file_service;++    bool is_stream_;+  };++  ASIO_DECL io_uring_file_service(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Construct a new file implementation.+  void construct(implementation_type& impl)+  {+    descriptor_service_.construct(impl);+    impl.is_stream_ = false;+  }++  // Move-construct a new file implementation.+  void move_construct(implementation_type& impl,+      implementation_type& other_impl)+  {+    descriptor_service_.move_construct(impl, other_impl);+    impl.is_stream_ = other_impl.is_stream_;+  }++  // Move-assign from another file implementation.+  void move_assign(implementation_type& impl,+      io_uring_file_service& other_service,+      implementation_type& other_impl)+  {+    descriptor_service_.move_assign(impl,+        other_service.descriptor_service_, other_impl);+    impl.is_stream_ = other_impl.is_stream_;+  }++  // Destroy a file implementation.+  void destroy(implementation_type& impl)+  {+    descriptor_service_.destroy(impl);+  }++  // Open the file using the specified path name.+  ASIO_DECL asio::error_code open(implementation_type& impl,+      const char* path, file_base::flags open_flags,+      asio::error_code& ec);++  // Assign a native descriptor to a file 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);+  }++  // Set whether the implementation is stream-oriented.+  void set_is_stream(implementation_type& impl, bool is_stream)+  {+    impl.is_stream_ = is_stream;+  }++  // Determine whether the file is open.+  bool is_open(const implementation_type& impl) const+  {+    return descriptor_service_.is_open(impl);+  }++  // Destroy a file implementation.+  asio::error_code close(implementation_type& impl,+      asio::error_code& ec)+  {+    return descriptor_service_.close(impl, ec);+  }++  // Get the native file representation.+  native_handle_type native_handle(const implementation_type& impl) const+  {+    return descriptor_service_.native_handle(impl);+  }++  // Release ownership of the native descriptor representation.+  native_handle_type release(implementation_type& impl,+      asio::error_code& ec)+  {+    return descriptor_service_.release(impl, ec);+  }++  // Cancel all operations associated with the file.+  asio::error_code cancel(implementation_type& impl,+      asio::error_code& ec)+  {+    return descriptor_service_.cancel(impl, ec);+  }++  // Get the size of the file.+  ASIO_DECL uint64_t size(const implementation_type& impl,+      asio::error_code& ec) const;++  // Alter the size of the file.+  ASIO_DECL asio::error_code resize(implementation_type& impl,+      uint64_t n, asio::error_code& ec);++  // Synchronise the file to disk.+  ASIO_DECL asio::error_code sync_all(implementation_type& impl,+      asio::error_code& ec);++  // Synchronise the file data to disk.+  ASIO_DECL asio::error_code sync_data(implementation_type& impl,+      asio::error_code& ec);++  // Seek to a position in the file.+  ASIO_DECL uint64_t seek(implementation_type& impl, int64_t offset,+      file_base::seek_basis whence, 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 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);+  }++  // Write the given data at the specified location. 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)+  {+    return descriptor_service_.write_some_at(impl, offset, buffers, ec);+  }++  // Start an asynchronous write at the specified location. 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)+  {+    descriptor_service_.async_write_some_at(+        impl, offset, buffers, handler, io_ex);+  }++  // Read some data. Returns the number of bytes read.+  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 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)+  {+    descriptor_service_.async_read_some(impl, buffers, handler, io_ex);+  }++  // Read some data. Returns the number of bytes read.+  template <typename MutableBufferSequence>+  size_t read_some_at(implementation_type& impl, uint64_t offset,+      const MutableBufferSequence& buffers, asio::error_code& ec)+  {+    return descriptor_service_.read_some_at(impl, offset, buffers, ec);+  }++  // 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_at(implementation_type& impl,+      uint64_t offset, const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    descriptor_service_.async_read_some_at(+        impl, offset, buffers, handler, io_ex);+  }++private:+  // The implementation used for initiating asynchronous operations.+  descriptor_service descriptor_service_;++  // 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/io_uring_file_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_FILE)+       //   && defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_FILE_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_null_buffers_op.hpp view
@@ -0,0 +1,115 @@+//+// detail/io_uring_null_buffers_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_NULL_BUFFERS_OP_HPP+#define ASIO_DETAIL_IO_URING_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/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class io_uring_null_buffers_op : public io_uring_operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_null_buffers_op);++  io_uring_null_buffers_op(const asio::error_code& success_ec,+      int descriptor, int poll_flags, Handler& handler, const IoExecutor& io_ex)+    : io_uring_operation(success_ec,+        &io_uring_null_buffers_op::do_prepare,+        &io_uring_null_buffers_op::do_perform,+        &io_uring_null_buffers_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex),+      descriptor_(descriptor),+      poll_flags_(poll_flags)+  {+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_null_buffers_op* o(static_cast<io_uring_null_buffers_op*>(base));++    ::io_uring_prep_poll_add(sqe, o->descriptor_, o->poll_flags_);+  }++  static bool do_perform(io_uring_operation*, bool after_completion)+  {+    return after_completion;+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    io_uring_null_buffers_op* o(static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_;+  int descriptor_;+  int poll_flags_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IO_URING_NULL_BUFFERS_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_operation.hpp view
@@ -0,0 +1,84 @@+//+// detail/io_uring_operation.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_OPERATION_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#include <liburing.h>+#include "asio/detail/cstdint.hpp"+#include "asio/detail/operation.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++class io_uring_operation+  : 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_;++  // The operation key used for targeted cancellation.+  void* cancellation_key_;++  // Prepare the operation.+  void prepare(::io_uring_sqe* sqe)+  {+    return prepare_func_(this, sqe);+  }++  // Perform actions associated with the operation. Returns true when complete.+  bool perform(bool after_completion)+  {+    return perform_func_(this, after_completion);+  }++protected:+  typedef void (*prepare_func_type)(io_uring_operation*, ::io_uring_sqe*);+  typedef bool (*perform_func_type)(io_uring_operation*, bool);++  io_uring_operation(const asio::error_code& success_ec,+      prepare_func_type prepare_func, perform_func_type perform_func,+      func_type complete_func)+    : operation(complete_func),+      ec_(success_ec),+      bytes_transferred_(0),+      cancellation_key_(0),+      prepare_func_(prepare_func),+      perform_func_(perform_func)+  {+  }++private:+  prepare_func_type prepare_func_;+  perform_func_type perform_func_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_OPERATION_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_service.hpp view
@@ -0,0 +1,319 @@+//+// detail/io_uring_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SERVICE_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#include <liburing.h>+#include "asio/detail/atomic_count.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/conditionally_enabled_mutex.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/limits.hpp"+#include "asio/detail/object_pool.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/reactor.hpp"+#include "asio/detail/scheduler_task.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 io_uring_service+  : public execution_context_service_base<io_uring_service>,+    public scheduler_task+{+private:+  // The mutex type used by this reactor.+  typedef conditionally_enabled_mutex mutex;++public:+  enum op_types { read_op = 0, write_op = 1, except_op = 2, max_ops = 3 };++  class io_object;++  // An I/O queue stores operations that must run serially.+  class io_queue : operation+  {+    friend class io_uring_service;++    io_object* io_object_;+    op_queue<io_uring_operation> op_queue_;+    bool cancel_requested_;++    ASIO_DECL io_queue();+    void set_result(int r) { task_result_ = static_cast<unsigned>(r); }+    ASIO_DECL operation* perform_io(int result);+    ASIO_DECL static void do_complete(void* owner, operation* base,+        const asio::error_code& ec, std::size_t bytes_transferred);+  };++  // Per I/O object state.+  class io_object+  {+    friend class io_uring_service;+    friend class object_pool_access;++    io_object* next_;+    io_object* prev_;++    mutex mutex_;+    io_uring_service* service_;+    io_queue queues_[max_ops];+    bool shutdown_;++    ASIO_DECL io_object(bool locking);+  };++  // Per I/O object data.+  typedef io_object* per_io_object_data;++  // Constructor.+  ASIO_DECL io_uring_service(asio::execution_context& ctx);++  // Destructor.+  ASIO_DECL ~io_uring_service();++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Recreate internal state following a fork.+  ASIO_DECL void notify_fork(+      asio::execution_context::fork_event fork_ev);++  // Initialise the task.+  ASIO_DECL void init_task();++  // Register an I/O object with io_uring.+  ASIO_DECL void register_io_object(io_object*& io_obj);++  // Register an internal I/O object with io_uring.+  ASIO_DECL void register_internal_io_object(+      io_object*& io_obj, int op_type, io_uring_operation* op);++  // Register buffers with io_uring.+  ASIO_DECL void register_buffers(const ::iovec* v, unsigned n);++  // Unregister buffers from io_uring.+  ASIO_DECL void unregister_buffers();++  // Post an operation for immediate completion.+  void post_immediate_completion(operation* op, bool is_continuation);++  // Start a new operation. The operation will be prepared and submitted to the+  // io_uring when it is at the head of its I/O operation queue.+  ASIO_DECL void start_op(int op_type, per_io_object_data& io_obj,+      io_uring_operation* op, bool is_continuation);++  // Cancel all operations associated with the given I/O object. The handlers+  // associated with the I/O object will be invoked with the operation_aborted+  // error.+  ASIO_DECL void cancel_ops(per_io_object_data& io_obj);++  // Cancel all operations associated with the given I/O object and key. The+  // handlers associated with the object and key will be invoked with the+  // operation_aborted error.+  ASIO_DECL void cancel_ops_by_key(per_io_object_data& io_obj,+      int op_type, void* cancellation_key);++  // Cancel any operations that are running against the I/O object and remove+  // its registration from the service. The service resources associated with+  // the I/O object must be released by calling cleanup_io_object.+  ASIO_DECL void deregister_io_object(per_io_object_data& io_obj);++  // Perform any post-deregistration cleanup tasks associated with the I/O+  // object.+  ASIO_DECL void cleanup_io_object(per_io_object_data& io_obj);++  // 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)());++  // Cancel the timer operations associated with the given key.+  template <typename Time_Traits>+  void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data* timer,+      void* cancellation_key);++  // 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);++  // Wait on io_uring once until interrupted or events are ready to be+  // dispatched.+  ASIO_DECL void run(long usec, op_queue<operation>& ops);++  // Interrupt the io_uring wait.+  ASIO_DECL void interrupt();++private:+  // The hint to pass to io_uring_queue_init to size its data structures.+  enum { ring_size = 16384 };++  // The number of operations to submit in a batch.+  enum { submit_batch_size = 128 };++  // The number of operations to complete in a batch.+  enum { complete_batch_size = 128 };++  // The type used for processing eventfd readiness notifications.+  class event_fd_read_op;++  // Initialise the ring.+  ASIO_DECL void init_ring();++  // Register the eventfd descriptor for readiness notifications.+  ASIO_DECL void register_with_reactor();++  // Allocate a new I/O object.+  ASIO_DECL io_object* allocate_io_object();++  // Free an existing I/O object.+  ASIO_DECL void free_io_object(io_object* s);++  // Helper function to cancel all operations associated with the given I/O+  // object. This function must be called while the I/O object's mutex is held.+  // Returns true if there are operations for which cancellation is pending.+  ASIO_DECL bool do_cancel_ops(+      per_io_object_data& io_obj, op_queue<operation>& ops);++  // 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 current timeout value.+  ASIO_DECL __kernel_timespec get_timeout() const;++  // Get a new submission queue entry, flushing the queue if necessary.+  ASIO_DECL ::io_uring_sqe* get_sqe();++  // Submit pending submission queue entries.+  ASIO_DECL void submit_sqes();++  // Post an operation to submit the pending submission queue entries.+  ASIO_DECL void post_submit_sqes_op(mutex::scoped_lock& lock);++  // Push an operation to submit the pending submission queue entries.+  ASIO_DECL void push_submit_sqes_op(op_queue<operation>& ops);++  // Helper operation to submit pending submission queue entries.+  class submit_sqes_op : operation+  {+    friend class io_uring_service;++    io_uring_service* service_;++    ASIO_DECL submit_sqes_op(io_uring_service* s);+    ASIO_DECL static void do_complete(void* owner, operation* base,+        const asio::error_code& ec, std::size_t bytes_transferred);+  };++  // The scheduler implementation used to post completions.+  scheduler& scheduler_;++  // Mutex to protect access to internal data.+  mutex mutex_;++  // The ring.+  ::io_uring ring_;++  // The count of unfinished work.+  atomic_count outstanding_work_;++  // The operation used to submit the pending submission queue entries.+  submit_sqes_op submit_sqes_op_;++  // The number of pending submission queue entries_.+  int pending_sqes_;++  // Whether there is a pending submission operation.+  bool pending_submit_sqes_op_;++  // Whether the service has been shut down.+  bool shutdown_;++  // The timer queues.+  timer_queue_set timer_queues_;++  // The timespec for the pending timeout operation. Must remain valid while the+  // operation is outstanding.+  __kernel_timespec timeout_;++  // Mutex to protect access to the registered I/O objects.+  mutex registration_mutex_;++  // Keep track of all registered I/O objects.+  object_pool<io_object> registered_io_objects_;++  // Helper class to do post-perform_io cleanup.+  struct perform_io_cleanup_on_block_exit;+  friend struct perform_io_cleanup_on_block_exit;++  // The reactor used to register for eventfd readiness.+  reactor& reactor_;++  // The per-descriptor reactor data used for the eventfd.+  reactor::per_descriptor_data reactor_data_;++  // The eventfd descriptor used to wait for readiness.+  int event_fd_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/detail/impl/io_uring_service.hpp"+#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/io_uring_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_accept_op.hpp view
@@ -0,0 +1,285 @@+//+// detail/io_uring_socket_accept_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SOCKET_ACCEPT_OP_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#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/io_uring_operation.hpp"+#include "asio/detail/memory.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 io_uring_socket_accept_op_base : public io_uring_operation+{+public:+  io_uring_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)+    : io_uring_operation(success_ec,+        &io_uring_socket_accept_op_base::do_prepare,+        &io_uring_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 void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_accept_op_base* o(+        static_cast<io_uring_socket_accept_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      ::io_uring_prep_poll_add(sqe, o->socket_, POLLIN);+    }+    else+    {+      ::io_uring_prep_accept(sqe, o->socket_,+          o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,+          o->peer_endpoint_ ? &o->addrlen_ : 0, 0);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_accept_op_base* o(+        static_cast<io_uring_socket_accept_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      socket_type new_socket = invalid_socket;+      std::size_t addrlen = static_cast<std::size_t>(o->addrlen_);+      bool result = socket_ops::non_blocking_accept(o->socket_,+          o->state_, o->peer_endpoint_ ? o->peer_endpoint_->data() : 0,+          o->peer_endpoint_ ? &addrlen : 0, o->ec_, new_socket);+      o->new_socket_.reset(new_socket);+      o->addrlen_ = static_cast<socklen_t>(addrlen);+      return result;+    }++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= socket_ops::internal_non_blocking;+      return false;+    }++    if (after_completion && !o->ec_)+      o->new_socket_.reset(static_cast<int>(o->bytes_transferred_));++    return after_completion;+  }++  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_;+  socklen_t addrlen_;+};++template <typename Socket, typename Protocol,+    typename Handler, typename IoExecutor>+class io_uring_socket_accept_op :+  public io_uring_socket_accept_op_base<Socket, Protocol>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_socket_accept_op);++  io_uring_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)+    : io_uring_socket_accept_op_base<Socket, Protocol>(+        success_ec, socket, state, peer, protocol, peer_endpoint,+        &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_socket_accept_op* o(static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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::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 io_uring_socket_move_accept_op :+  private Protocol::socket::template rebind_executor<PeerIoExecutor>::other,+  public io_uring_socket_accept_op_base<+    typename Protocol::socket::template rebind_executor<PeerIoExecutor>::other,+    Protocol>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_socket_move_accept_op);++  io_uring_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),+      io_uring_socket_accept_op_base<peer_socket_type, Protocol>(+        success_ec, socket, state, *this, protocol, peer_endpoint,+        &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_socket_move_accept_op* o(+        static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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::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 // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_ACCEPT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_connect_op.hpp view
@@ -0,0 +1,141 @@+//+// detail/io_uring_socket_connect_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SOCKET_CONNECT_OP_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#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/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/socket_ops.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Protocol>+class io_uring_socket_connect_op_base : public io_uring_operation+{+public:+  io_uring_socket_connect_op_base(const asio::error_code& success_ec,+      socket_type socket, const typename Protocol::endpoint& endpoint,+      func_type complete_func)+    : io_uring_operation(success_ec,+        &io_uring_socket_connect_op_base::do_prepare,+        &io_uring_socket_connect_op_base::do_perform, complete_func),+      socket_(socket),+      endpoint_(endpoint)+  {+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_connect_op_base* o(+        static_cast<io_uring_socket_connect_op_base*>(base));++    ::io_uring_prep_connect(sqe, o->socket_,+        static_cast<sockaddr*>(o->endpoint_.data()),+        static_cast<socklen_t>(o->endpoint_.size()));+  }++  static bool do_perform(io_uring_operation*, bool after_completion)+  {+    return after_completion;+  }++private:+  socket_type socket_;+  typename Protocol::endpoint endpoint_;+};++template <typename Protocol, typename Handler, typename IoExecutor>+class io_uring_socket_connect_op :+  public io_uring_socket_connect_op_base<Protocol>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_socket_connect_op);++  io_uring_socket_connect_op(const asio::error_code& success_ec,+      socket_type socket, const typename Protocol::endpoint& endpoint,+      Handler& handler, const IoExecutor& io_ex)+    : io_uring_socket_connect_op_base<Protocol>(success_ec, socket,+        endpoint, &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_socket_connect_op* o+      (static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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::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 // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_CONNECT_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recv_op.hpp view
@@ -0,0 +1,205 @@+//+// detail/io_uring_socket_recv_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SOCKET_RECV_OP_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class io_uring_socket_recv_op_base : public io_uring_operation+{+public:+  io_uring_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)+    : io_uring_operation(success_ec,+        &io_uring_socket_recv_op_base::do_prepare,+        &io_uring_socket_recv_op_base::do_perform, complete_func),+      socket_(socket),+      state_(state),+      buffers_(buffers),+      flags_(flags),+      bufs_(buffers),+      msghdr_()+  {+    msghdr_.msg_iov = bufs_.buffers();+    msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_recv_op_base* o(+        static_cast<io_uring_socket_recv_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0;+      ::io_uring_prep_poll_add(sqe, o->socket_, except_op ? POLLPRI : POLLIN);+    }+    else if (o->bufs_.is_single_buffer+        && o->bufs_.is_registered_buffer && o->flags_ == 0)+    {+      ::io_uring_prep_read_fixed(sqe, o->socket_,+          o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+          0, o->bufs_.registered_id().native_handle());+    }+    else+    {+      ::io_uring_prep_recvmsg(sqe, o->socket_, &o->msghdr_, o->flags_);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_recv_op_base* o(+        static_cast<io_uring_socket_recv_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0;+      if (after_completion || !except_op)+      {+        if (o->bufs_.is_single_buffer)+        {+          return socket_ops::non_blocking_recv1(o->socket_,+              o->bufs_.first(o->buffers_).data(),+              o->bufs_.first(o->buffers_).size(), o->flags_,+              (o->state_ & socket_ops::stream_oriented) != 0,+              o->ec_, o->bytes_transferred_);+        }+        else+        {+          return socket_ops::non_blocking_recv(o->socket_,+              o->bufs_.buffers(), o->bufs_.count(), o->flags_,+              (o->state_ & socket_ops::stream_oriented) != 0,+              o->ec_, o->bytes_transferred_);+        }+      }+    }+    else if (after_completion)+    {+      if (!o->ec_ && o->bytes_transferred_ == 0)+        if ((o->state_ & socket_ops::stream_oriented) != 0)+          o->ec_ = asio::error::eof;+    }++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= socket_ops::internal_non_blocking;+      return false;+    }++    return after_completion;+  }++private:+  socket_type socket_;+  socket_ops::state_type state_;+  MutableBufferSequence buffers_;+  socket_base::message_flags flags_;+  buffer_sequence_adapter<asio::mutable_buffer,+      MutableBufferSequence> bufs_;+  msghdr msghdr_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class io_uring_socket_recv_op+  : public io_uring_socket_recv_op_base<MutableBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_socket_recv_op);++  io_uring_socket_recv_op(const asio::error_code& success_ec,+      int socket, socket_ops::state_type state,+      const MutableBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+    : io_uring_socket_recv_op_base<MutableBufferSequence>(success_ec,+        socket, state, buffers, flags, &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_socket_recv_op* o+      (static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_RECV_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvfrom_op.hpp view
@@ -0,0 +1,206 @@+//+// detail/io_uring_socket_recvfrom_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SOCKET_RECVFROM_OP_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence, typename Endpoint>+class io_uring_socket_recvfrom_op_base : public io_uring_operation+{+public:+  io_uring_socket_recvfrom_op_base(const asio::error_code& success_ec,+      socket_type socket, socket_ops::state_type state,+      const MutableBufferSequence& buffers, Endpoint& endpoint,+      socket_base::message_flags flags, func_type complete_func)+    : io_uring_operation(success_ec,+        &io_uring_socket_recvfrom_op_base::do_prepare,+        &io_uring_socket_recvfrom_op_base::do_perform, complete_func),+      socket_(socket),+      state_(state),+      buffers_(buffers),+      sender_endpoint_(endpoint),+      flags_(flags),+      bufs_(buffers),+      msghdr_()+  {+    msghdr_.msg_iov = bufs_.buffers();+    msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+    msghdr_.msg_name = static_cast<sockaddr*>(+        static_cast<void*>(sender_endpoint_.data()));+    msghdr_.msg_namelen = sender_endpoint_.capacity();+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_recvfrom_op_base* o(+        static_cast<io_uring_socket_recvfrom_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0;+      ::io_uring_prep_poll_add(sqe, o->socket_, except_op ? POLLPRI : POLLIN);+    }+    else+    {+      ::io_uring_prep_recvmsg(sqe, o->socket_, &o->msghdr_, o->flags_);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_recvfrom_op_base* o(+        static_cast<io_uring_socket_recvfrom_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      bool except_op = (o->flags_ & socket_base::message_out_of_band) != 0;+      if (after_completion || !except_op)+      {+        std::size_t addr_len = o->sender_endpoint_.capacity();+        bool result;+        if (o->bufs_.is_single_buffer)+        {+          result = socket_ops::non_blocking_recvfrom1(o->socket_,+              o->bufs_.first(o->buffers_).data(),+              o->bufs_.first(o->buffers_).size(), o->flags_,+              o->sender_endpoint_.data(), &addr_len,+              o->ec_, o->bytes_transferred_);+        }+        else+        {+          result = socket_ops::non_blocking_recvfrom(o->socket_,+              o->bufs_.buffers(), o->bufs_.count(), o->flags_,+              o->sender_endpoint_.data(), &addr_len,+              o->ec_, o->bytes_transferred_);+        }+        if (result && !o->ec_)+          o->sender_endpoint_.resize(addr_len);+      }+    }+    else if (after_completion && !o->ec_)+      o->sender_endpoint_.resize(o->msghdr_.msg_namelen);++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= socket_ops::internal_non_blocking;+      return false;+    }++    return after_completion;+  }++private:+  socket_type socket_;+  socket_ops::state_type state_;+  MutableBufferSequence buffers_;+  Endpoint& sender_endpoint_;+  socket_base::message_flags flags_;+  buffer_sequence_adapter<asio::mutable_buffer,+      MutableBufferSequence> bufs_;+  msghdr msghdr_;+};++template <typename MutableBufferSequence, typename Endpoint,+    typename Handler, typename IoExecutor>+class io_uring_socket_recvfrom_op+  : public io_uring_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_socket_recvfrom_op);++  io_uring_socket_recvfrom_op(const asio::error_code& success_ec,+      int socket, socket_ops::state_type state,+      const MutableBufferSequence& buffers, Endpoint& endpoint,+      socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+    : io_uring_socket_recvfrom_op_base<MutableBufferSequence, Endpoint>(+        success_ec, socket, state, buffers, endpoint, flags,+        &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_socket_recvfrom_op* o+      (static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_RECVFROM_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvmsg_op.hpp view
@@ -0,0 +1,192 @@+//+// detail/io_uring_socket_recvmsg_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SOCKET_RECVMSG_OP_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename MutableBufferSequence>+class io_uring_socket_recvmsg_op_base : public io_uring_operation+{+public:+  io_uring_socket_recvmsg_op_base(const asio::error_code& success_ec,+      socket_type socket, socket_ops::state_type state,+      const MutableBufferSequence& buffers, socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags, func_type complete_func)+    : io_uring_operation(success_ec,+        &io_uring_socket_recvmsg_op_base::do_prepare,+        &io_uring_socket_recvmsg_op_base::do_perform, complete_func),+      socket_(socket),+      state_(state),+      buffers_(buffers),+      in_flags_(in_flags),+      out_flags_(out_flags),+      bufs_(buffers),+      msghdr_()+  {+    msghdr_.msg_iov = bufs_.buffers();+    msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_recvmsg_op_base* o(+        static_cast<io_uring_socket_recvmsg_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      bool except_op = (o->in_flags_ & socket_base::message_out_of_band) != 0;+      ::io_uring_prep_poll_add(sqe, o->socket_, except_op ? POLLPRI : POLLIN);+    }+    else+    {+      ::io_uring_prep_recvmsg(sqe, o->socket_, &o->msghdr_, o->in_flags_);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_recvmsg_op_base* o(+        static_cast<io_uring_socket_recvmsg_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      bool except_op = (o->in_flags_ & socket_base::message_out_of_band) != 0;+      if (after_completion || !except_op)+      {+        return socket_ops::non_blocking_recvmsg(o->socket_,+            o->bufs_.buffers(), o->bufs_.count(), o->in_flags_,+            o->out_flags_, o->ec_, o->bytes_transferred_);+      }+    }+    else if (after_completion)+    {+      if (!o->ec_)+        o->out_flags_ = o->msghdr_.msg_flags;+      else+        o->out_flags_ = 0;+    }++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= socket_ops::internal_non_blocking;+      return false;+    }++    return after_completion;+  }++private:+  socket_type socket_;+  socket_ops::state_type state_;+  MutableBufferSequence buffers_;+  socket_base::message_flags in_flags_;+  socket_base::message_flags& out_flags_;+  buffer_sequence_adapter<asio::mutable_buffer,+      MutableBufferSequence> bufs_;+  msghdr msghdr_;+};++template <typename MutableBufferSequence, typename Handler, typename IoExecutor>+class io_uring_socket_recvmsg_op+  : public io_uring_socket_recvmsg_op_base<MutableBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_socket_recvmsg_op);++  io_uring_socket_recvmsg_op(const asio::error_code& success_ec,+      int socket, socket_ops::state_type state,+      const MutableBufferSequence& buffers,+      socket_base::message_flags in_flags,+      socket_base::message_flags& out_flags,+      Handler& handler, const IoExecutor& io_ex)+    : io_uring_socket_recvmsg_op_base<MutableBufferSequence>(success_ec,+        socket, state, buffers, in_flags, out_flags,+        &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_socket_recvmsg_op* o+      (static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_RECVMSG_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_send_op.hpp view
@@ -0,0 +1,191 @@+//+// detail/io_uring_socket_send_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SOCKET_SEND_OP_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence>+class io_uring_socket_send_op_base : public io_uring_operation+{+public:+  io_uring_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)+    : io_uring_operation(success_ec,+        &io_uring_socket_send_op_base::do_prepare,+        &io_uring_socket_send_op_base::do_perform, complete_func),+      socket_(socket),+      state_(state),+      buffers_(buffers),+      flags_(flags),+      bufs_(buffers),+      msghdr_()+  {+    msghdr_.msg_iov = bufs_.buffers();+    msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_send_op_base* o(+        static_cast<io_uring_socket_send_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      ::io_uring_prep_poll_add(sqe, o->socket_, POLLOUT);+    }+    else if (o->bufs_.is_single_buffer+        && o->bufs_.is_registered_buffer && o->flags_ == 0)+    {+      ::io_uring_prep_write_fixed(sqe, o->socket_,+          o->bufs_.buffers()->iov_base, o->bufs_.buffers()->iov_len,+          0, o->bufs_.registered_id().native_handle());+    }+    else+    {+      ::io_uring_prep_sendmsg(sqe, o->socket_, &o->msghdr_, o->flags_);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_send_op_base* o(+        static_cast<io_uring_socket_send_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      if (o->bufs_.is_single_buffer)+      {+        return socket_ops::non_blocking_send1(o->socket_,+            o->bufs_.first(o->buffers_).data(),+            o->bufs_.first(o->buffers_).size(), o->flags_,+            o->ec_, o->bytes_transferred_);+      }+      else+      {+        return socket_ops::non_blocking_send(o->socket_,+            o->bufs_.buffers(), o->bufs_.count(), o->flags_,+            o->ec_, o->bytes_transferred_);+      }+    }++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= socket_ops::internal_non_blocking;+      return false;+    }++    return after_completion;+  }++private:+  socket_type socket_;+  socket_ops::state_type state_;+  ConstBufferSequence buffers_;+  socket_base::message_flags flags_;+  buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_;+  msghdr msghdr_;+};++template <typename ConstBufferSequence, typename Handler, typename IoExecutor>+class io_uring_socket_send_op+  : public io_uring_socket_send_op_base<ConstBufferSequence>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_socket_send_op);++  io_uring_socket_send_op(const asio::error_code& success_ec,+      int socket, socket_ops::state_type state,+      const ConstBufferSequence& buffers, socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+    : io_uring_socket_send_op_base<ConstBufferSequence>(success_ec,+        socket, state, buffers, flags, &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_socket_send_op* o+      (static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_SEND_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_sendto_op.hpp view
@@ -0,0 +1,194 @@+//+// detail/io_uring_socket_sendto_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SOCKET_SENDTO_OP_HPP+#define ASIO_DETAIL_IO_URING_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"++#if defined(ASIO_HAS_IO_URING)++#include "asio/detail/bind_handler.hpp"+#include "asio/detail/buffer_sequence_adapter.hpp"+#include "asio/detail/socket_ops.hpp"+#include "asio/detail/fenced_block.hpp"+#include "asio/detail/handler_work.hpp"+#include "asio/detail/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename ConstBufferSequence, typename Endpoint>+class io_uring_socket_sendto_op_base : public io_uring_operation+{+public:+  io_uring_socket_sendto_op_base(const asio::error_code& success_ec,+      socket_type socket, socket_ops::state_type state,+      const ConstBufferSequence& buffers, const Endpoint& endpoint,+      socket_base::message_flags flags, func_type complete_func)+    : io_uring_operation(success_ec,+        &io_uring_socket_sendto_op_base::do_prepare,+        &io_uring_socket_sendto_op_base::do_perform, complete_func),+      socket_(socket),+      state_(state),+      buffers_(buffers),+      destination_(endpoint),+      flags_(flags),+      bufs_(buffers),+      msghdr_()+  {+    msghdr_.msg_iov = bufs_.buffers();+    msghdr_.msg_iovlen = static_cast<int>(bufs_.count());+    msghdr_.msg_name = static_cast<sockaddr*>(+        static_cast<void*>(destination_.data()));+    msghdr_.msg_namelen = destination_.size();+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_sendto_op_base* o(+        static_cast<io_uring_socket_sendto_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      ::io_uring_prep_poll_add(sqe, o->socket_, POLLOUT);+    }+    else+    {+      ::io_uring_prep_sendmsg(sqe, o->socket_, &o->msghdr_, o->flags_);+    }+  }++  static bool do_perform(io_uring_operation* base, bool after_completion)+  {+    ASIO_ASSUME(base != 0);+    io_uring_socket_sendto_op_base* o(+        static_cast<io_uring_socket_sendto_op_base*>(base));++    if ((o->state_ & socket_ops::internal_non_blocking) != 0)+    {+      if (o->bufs_.is_single_buffer)+      {+        return socket_ops::non_blocking_sendto1(o->socket_,+            o->bufs_.first(o->buffers_).data(),+            o->bufs_.first(o->buffers_).size(), o->flags_,+            o->destination_.data(), o->destination_.size(),+            o->ec_, o->bytes_transferred_);+      }+      else+      {+        return socket_ops::non_blocking_sendto(o->socket_,+            o->bufs_.buffers(), o->bufs_.count(), o->flags_,+            o->destination_.data(), o->destination_.size(),+            o->ec_, o->bytes_transferred_);+      }+    }++    if (o->ec_ && o->ec_ == asio::error::would_block)+    {+      o->state_ |= socket_ops::internal_non_blocking;+      return false;+    }++    return after_completion;+  }++private:+  socket_type socket_;+  socket_ops::state_type state_;+  ConstBufferSequence buffers_;+  Endpoint destination_;+  socket_base::message_flags flags_;+  buffer_sequence_adapter<asio::const_buffer, ConstBufferSequence> bufs_;+  msghdr msghdr_;+};++template <typename ConstBufferSequence, typename Endpoint,+    typename Handler, typename IoExecutor>+class io_uring_socket_sendto_op+  : public io_uring_socket_sendto_op_base<ConstBufferSequence, Endpoint>+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_socket_sendto_op);++  io_uring_socket_sendto_op(const asio::error_code& success_ec,+      int socket, socket_ops::state_type state,+      const ConstBufferSequence& buffers, const Endpoint& endpoint,+      socket_base::message_flags flags,+      Handler& handler, const IoExecutor& io_ex)+    : io_uring_socket_sendto_op_base<ConstBufferSequence, Endpoint>(+        success_ec, socket, state, buffers, endpoint, flags,+        &io_uring_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.+    ASIO_ASSUME(base != 0);+    io_uring_socket_sendto_op* o+      (static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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_, 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_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_SENDTO_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service.hpp view
@@ -0,0 +1,631 @@+//+// detail/io_uring_socket_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SOCKET_SERVICE_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#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/io_uring_null_buffers_op.hpp"+#include "asio/detail/io_uring_service.hpp"+#include "asio/detail/io_uring_socket_accept_op.hpp"+#include "asio/detail/io_uring_socket_connect_op.hpp"+#include "asio/detail/io_uring_socket_recvfrom_op.hpp"+#include "asio/detail/io_uring_socket_sendto_op.hpp"+#include "asio/detail/io_uring_socket_service_base.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 io_uring_socket_service :+  public execution_context_service_base<io_uring_socket_service<Protocol> >,+  public io_uring_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 :+    io_uring_socket_service_base::base_implementation_type+  {+    // Default constructor.+    implementation_type()+      : protocol_(endpoint_type().protocol())+    {+    }++    // The protocol associated with the socket.+    protocol_type protocol_;+  };++  // Constructor.+  io_uring_socket_service(execution_context& context)+    : execution_context_service_base<+        io_uring_socket_service<Protocol> >(context),+      io_uring_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,+      io_uring_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,+      io_uring_socket_service<Protocol1>&,+      typename io_uring_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;+    ASIO_ERROR_LOCATION(ec);+    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;+    ASIO_ERROR_LOCATION(ec);+    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);+    ASIO_ERROR_LOCATION(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);+    ASIO_ERROR_LOCATION(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);+    ASIO_ERROR_LOCATION(ec);+    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))+    {+      ASIO_ERROR_LOCATION(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))+    {+      ASIO_ERROR_LOCATION(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);+    ASIO_ERROR_LOCATION(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;++    size_t n;+    if (bufs_type::is_single_buffer)+    {+      n = 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);+      n = socket_ops::sync_sendto(impl.socket_, impl.state_,+          bufs.buffers(), bufs.count(), flags,+          destination.data(), destination.size(), ec);+    }++    ASIO_ERROR_LOCATION(ec);+    return n;+  }++  // 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);+    ASIO_ERROR_LOCATION(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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.state_,+        buffers, destination, flags, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::write_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "socket", &impl, impl.socket_, "async_send_to"));++    start_op(impl, io_uring_service::write_op, p.p, is_continuation, 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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.socket_, POLLOUT, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::write_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p, "socket",+          &impl, impl.socket_, "async_send_to(null_buffers)"));++    start_op(impl, io_uring_service::write_op, p.p, is_continuation, 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 n;+    if (bufs_type::is_single_buffer)+    {+      n = 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);+      n = 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);++    ASIO_ERROR_LOCATION(ec);+    return n;+  }++  // 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();++    ASIO_ERROR_LOCATION(ec);+    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);++    int op_type = (flags & socket_base::message_out_of_band)+      ? io_uring_service::except_op : io_uring_service::read_op;++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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(success_ec_, impl.socket_, impl.state_,+        buffers, sender_endpoint, flags, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(+            &io_uring_service_, &impl.io_object_data_, op_type);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "socket", &impl, impl.socket_, "async_receive_from"));++    start_op(impl, op_type, p.p, is_continuation, 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);++    int op_type;+    int poll_flags;+    if ((flags & socket_base::message_out_of_band) != 0)+    {+      op_type = io_uring_service::except_op;+      poll_flags = POLLPRI;+    }+    else+    {+      op_type = io_uring_service::read_op;+      poll_flags = POLLIN;+    }++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.socket_, poll_flags, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(+            &io_uring_service_, &impl.io_object_data_, op_type);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.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, op_type, p.p, is_continuation, 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;+      ASIO_ERROR_LOCATION(ec);+      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();+    }++    ASIO_ERROR_LOCATION(ec);+    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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected() && !peer.is_open())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::read_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::read_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_socket_connect_op<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_,+        peer_endpoint, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::write_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "socket", &impl, impl.socket_, "async_connect"));++    start_op(impl, io_uring_service::write_op, p.p, is_continuation, false);+    p.v = p.p = 0;+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service_base.hpp view
@@ -0,0 +1,663 @@+//+// detail/io_uring_socket_service_base.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_SOCKET_SERVICE_BASE_HPP+#define ASIO_DETAIL_IO_URING_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_IO_URING)++#include "asio/associated_cancellation_slot.hpp"+#include "asio/buffer.hpp"+#include "asio/cancellation_type.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/io_uring_null_buffers_op.hpp"+#include "asio/detail/io_uring_service.hpp"+#include "asio/detail/io_uring_socket_recv_op.hpp"+#include "asio/detail/io_uring_socket_recvmsg_op.hpp"+#include "asio/detail/io_uring_socket_send_op.hpp"+#include "asio/detail/io_uring_wait_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 io_uring_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 I/O object data used by the io_uring_service.+    io_uring_service::per_io_object_data io_object_data_;+  };++  // Constructor.+  ASIO_DECL io_uring_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,+      io_uring_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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    int op_type;+    int poll_flags;+    switch (w)+    {+    case socket_base::wait_read:+      op_type = io_uring_service::read_op;+      poll_flags = POLLIN;+      break;+    case socket_base::wait_write:+      op_type = io_uring_service::write_op;+      poll_flags = POLLOUT;+      break;+    case socket_base::wait_error:+      op_type = io_uring_service::except_op;+      poll_flags = POLLPRI | POLLERR | POLLHUP;+      break;+    default:+      op_type = -1;+      poll_flags = -1;+      return;+    }++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.socket_,+        poll_flags, handler, io_ex);++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "socket", &impl, impl.socket_, "async_wait"));++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(+            &io_uring_service_, &impl.io_object_data_, op_type);+    }++    start_op(impl, op_type, p.p, is_continuation, op_type == -1);+    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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::write_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "socket", &impl, impl.socket_, "async_send"));++    start_op(impl, io_uring_service::write_op, p.p, is_continuation,+        ((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);++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.socket_, POLLOUT, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(&io_uring_service_,+            &impl.io_object_data_, io_uring_service::write_op);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "socket", &impl, impl.socket_, "async_send(null_buffers)"));++    start_op(impl, io_uring_service::write_op, p.p, is_continuation, 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);++    int op_type = (flags & socket_base::message_out_of_band)+      ? io_uring_service::except_op : io_uring_service::read_op;++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(+            &io_uring_service_, &impl.io_object_data_, op_type);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "socket", &impl, impl.socket_, "async_receive"));++    start_op(impl, op_type, p.p, is_continuation,+        ((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);++    int op_type;+    int poll_flags;+    if ((flags & socket_base::message_out_of_band) != 0)+    {+      op_type = io_uring_service::except_op;+      poll_flags = POLLPRI;+    }+    else+    {+      op_type = io_uring_service::read_op;+      poll_flags = POLLIN;+    }++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.socket_, poll_flags, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(+            &io_uring_service_, &impl.io_object_data_, op_type);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "socket", &impl, impl.socket_, "async_receive(null_buffers)"));++    start_op(impl, op_type, p.p, is_continuation, 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);++    int op_type = (in_flags & socket_base::message_out_of_band)+      ? io_uring_service::except_op : io_uring_service::read_op;++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.state_,+        buffers, in_flags, out_flags, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(+            &io_uring_service_, &impl.io_object_data_, op_type);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.context(), *p.p,+          "socket", &impl, impl.socket_, "async_receive_with_flags"));++    start_op(impl, op_type, p.p, is_continuation, 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);++    int op_type;+    int poll_flags;+    if ((in_flags & socket_base::message_out_of_band) != 0)+    {+      op_type = io_uring_service::except_op;+      poll_flags = POLLPRI;+    }+    else+    {+      op_type = io_uring_service::read_op;+      poll_flags = POLLIN;+    }++    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef io_uring_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_, impl.socket_, poll_flags, handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<io_uring_op_cancellation>(+            &io_uring_service_, &impl.io_object_data_, op_type);+    }++    ASIO_HANDLER_CREATION((io_uring_service_.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, op_type, p.p, is_continuation, 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,+      io_uring_operation* op, bool is_continuation, bool noop);++  // Start the asynchronous accept operation.+  ASIO_DECL void start_accept_op(base_implementation_type& impl,+      io_uring_operation* op, bool is_continuation, bool peer_is_open);++  // Helper class used to implement per-operation cancellation+  class io_uring_op_cancellation+  {+  public:+    io_uring_op_cancellation(io_uring_service* s,+        io_uring_service::per_io_object_data* p, int o)+      : io_uring_service_(s),+        io_object_data_(p),+        op_type_(o)+    {+    }++    void operator()(cancellation_type_t type)+    {+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        io_uring_service_->cancel_ops_by_key(*io_object_data_, op_type_, this);+      }+    }++  private:+    io_uring_service* io_uring_service_;+    io_uring_service::per_io_object_data* io_object_data_;+    int op_type_;+  };++  // The io_uring_service that performs event demultiplexing for the service.+  io_uring_service& io_uring_service_;++  // 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/io_uring_socket_service_base.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IO_URING)++#endif // ASIO_DETAIL_IO_URING_SOCKET_SERVICE_BASE_HPP
+ link/modules/asio-standalone/asio/include/asio/detail/io_uring_wait_op.hpp view
@@ -0,0 +1,113 @@+//+// detail/io_uring_wait_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_URING_WAIT_OP_HPP+#define ASIO_DETAIL_IO_URING_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/io_uring_operation.hpp"+#include "asio/detail/memory.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++template <typename Handler, typename IoExecutor>+class io_uring_wait_op : public io_uring_operation+{+public:+  ASIO_DEFINE_HANDLER_PTR(io_uring_wait_op);++  io_uring_wait_op(const asio::error_code& success_ec, int descriptor,+      int poll_flags, Handler& handler, const IoExecutor& io_ex)+    : io_uring_operation(success_ec, &io_uring_wait_op::do_prepare,+        &io_uring_wait_op::do_perform, &io_uring_wait_op::do_complete),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex),+      descriptor_(descriptor),+      poll_flags_(poll_flags)+  {+  }++  static void do_prepare(io_uring_operation* base, ::io_uring_sqe* sqe)+  {+    ASIO_ASSUME(base != 0);+    io_uring_wait_op* o(static_cast<io_uring_wait_op*>(base));++    ::io_uring_prep_poll_add(sqe, o->descriptor_, o->poll_flags_);+  }++  static bool do_perform(io_uring_operation*, bool after_completion)+  {+    return after_completion;+  }++  static void do_complete(void* owner, operation* base,+      const asio::error_code& /*ec*/,+      std::size_t /*bytes_transferred*/)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    io_uring_wait_op* o(static_cast<io_uring_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_));++    ASIO_ERROR_LOCATION(o->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::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_, handler.arg2_));+      w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  handler_work<Handler, IoExecutor> work_;+  int descriptor_;+  int poll_flags_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_IO_URING_WAIT_OP_HPP
link/modules/asio-standalone/asio/include/asio/detail/is_buffer_sequence.hpp view
@@ -2,7 +2,7 @@ // detail/is_buffer_sequence.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,6 +24,8 @@  class mutable_buffer; class const_buffer;+class mutable_registered_buffer;+class const_registered_buffer;  namespace detail { @@ -254,6 +256,30 @@  template <> struct is_buffer_sequence<const_buffer, mutable_buffer>+  : false_type+{+};++template <>+struct is_buffer_sequence<mutable_registered_buffer, mutable_buffer>+  : true_type+{+};++template <>+struct is_buffer_sequence<mutable_registered_buffer, const_buffer>+  : true_type+{+};++template <>+struct is_buffer_sequence<const_registered_buffer, const_buffer>+  : true_type+{+};++template <>+struct is_buffer_sequence<const_registered_buffer, mutable_buffer>   : false_type { };
link/modules/asio-standalone/asio/include/asio/detail/is_executor.hpp view
@@ -2,7 +2,7 @@ // detail/is_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/keyword_tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/keyword_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/kqueue_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/kqueue_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -24,11 +24,12 @@ #include <sys/types.h> #include <sys/event.h> #include <sys/time.h>+#include "asio/detail/conditionally_enabled_mutex.hpp" #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/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp"@@ -50,7 +51,8 @@ class scheduler;  class kqueue_reactor-  : public execution_context_service_base<kqueue_reactor>+  : public execution_context_service_base<kqueue_reactor>,+    public scheduler_task { private:   // The mutex type used by this reactor.@@ -114,23 +116,44 @@       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);-  }+  void post_immediate_completion(operation* op, bool is_continuation) const; +  // Post a reactor operation for immediate completion.+  ASIO_DECL static void call_post_immediate_completion(+      operation* op, bool is_continuation, const void* self);+   // 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);+      bool is_continuation, bool allow_speculative,+      void (*on_immediate)(operation*, bool, const void*),+      const void* immediate_arg); +  // Start a new operation. The reactor operation will be performed when the+  // given descriptor is flagged as ready, or an error has occurred.+  void start_op(int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op,+      bool is_continuation, bool allow_speculative)+  {+    start_op(op_type, descriptor, descriptor_data,+        op, is_continuation, allow_speculative,+        &kqueue_reactor::call_post_immediate_completion, this);+  }+   // 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 all operations associated with the given descriptor and key. The+  // handlers associated with the descriptor will be invoked with the+  // operation_aborted error.+  ASIO_DECL void cancel_ops_by_key(socket_type descriptor,+      per_descriptor_data& descriptor_data,+      int op_type, void* cancellation_key);+   // 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.@@ -169,6 +192,12 @@   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)());++  // Cancel the timer operations associated with the given key.+  template <typename Time_Traits>+  void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data* timer,+      void* cancellation_key);    // Move the timer operations associated with the given timer.   template <typename Time_Traits>
link/modules/asio-standalone/asio/include/asio/detail/local_free_on_block_exit.hpp view
@@ -2,7 +2,7 @@ // detail/local_free_on_block_exit.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/macos_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/macos_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/memory.hpp view
@@ -2,7 +2,7 @@ // detail/memory.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,7 +16,12 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"+#include <cstddef>+#include <cstdlib> #include <memory>+#include <new>+#include "asio/detail/cstdint.hpp"+#include "asio/detail/throw_exception.hpp"  #if !defined(ASIO_HAS_STD_SHARED_PTR) # include <boost/make_shared.hpp>@@ -28,6 +33,14 @@ # include <boost/utility/addressof.hpp> #endif // !defined(ASIO_HAS_STD_ADDRESSOF) +#if !defined(ASIO_HAS_STD_ALIGNED_ALLOC) \+  && defined(ASIO_HAS_BOOST_ALIGN) \+  && defined(ASIO_HAS_ALIGNOF)+# include <boost/align/aligned_alloc.hpp>+#endif // !defined(ASIO_HAS_STD_ALIGNED_ALLOC)+       //   && defined(ASIO_HAS_BOOST_ALIGN)+       //   && defined(ASIO_HAS_ALIGNOF)+ namespace asio { namespace detail { @@ -47,6 +60,36 @@ using boost::addressof; #endif // defined(ASIO_HAS_STD_ADDRESSOF) +#if defined(ASIO_HAS_STD_TO_ADDRESS)+using std::to_address;+#else // defined(ASIO_HAS_STD_TO_ADDRESS)+template <typename T>+inline T* to_address(T* p) { return p; }+template <typename T>+inline const T* to_address(const T* p) { return p; }+template <typename T>+inline volatile T* to_address(volatile T* p) { return p; }+template <typename T>+inline const volatile T* to_address(const volatile T* p) { return p; }+#endif // defined(ASIO_HAS_STD_TO_ADDRESS)++inline void* align(std::size_t alignment,+    std::size_t size, void*& ptr, std::size_t& space)+{+#if defined(ASIO_HAS_STD_ALIGN)+  return std::align(alignment, size, ptr, space);+#else // defined(ASIO_HAS_STD_ALIGN)+	const uintptr_t intptr = reinterpret_cast<uintptr_t>(ptr);+	const uintptr_t aligned = (intptr - 1u + alignment) & -alignment;+	const std::size_t padding = aligned - intptr;+	if (size + padding > space)+    return 0;+	space -= padding;+	ptr = reinterpret_cast<void*>(aligned);+  return ptr;+#endif // defined(ASIO_HAS_STD_ALIGN)+}+ } // namespace detail  #if defined(ASIO_HAS_CXX11_ALLOCATORS)@@ -67,6 +110,57 @@   typename alloc::template rebind<t>::other   /**/ #endif // defined(ASIO_HAS_CXX11_ALLOCATORS)++inline void* aligned_new(std::size_t align, std::size_t size)+{+#if defined(ASIO_HAS_STD_ALIGNED_ALLOC) && defined(ASIO_HAS_ALIGNOF)+  align = (align < ASIO_DEFAULT_ALIGN) ? ASIO_DEFAULT_ALIGN : align;+  size = (size % align == 0) ? size : size + (align - size % align);+  void* ptr = std::aligned_alloc(align, size);+  if (!ptr)+  {+    std::bad_alloc ex;+    asio::detail::throw_exception(ex);+  }+  return ptr;+#elif defined(ASIO_HAS_BOOST_ALIGN) && defined(ASIO_HAS_ALIGNOF)+  align = (align < ASIO_DEFAULT_ALIGN) ? ASIO_DEFAULT_ALIGN : align;+  size = (size % align == 0) ? size : size + (align - size % align);+  void* ptr = boost::alignment::aligned_alloc(align, size);+  if (!ptr)+  {+    std::bad_alloc ex;+    asio::detail::throw_exception(ex);+  }+  return ptr;+#elif defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+  align = (align < ASIO_DEFAULT_ALIGN) ? ASIO_DEFAULT_ALIGN : align;+  size = (size % align == 0) ? size : size + (align - size % align);+  void* ptr = _aligned_malloc(size, align);+  if (!ptr)+  {+    std::bad_alloc ex;+    asio::detail::throw_exception(ex);+  }+  return ptr;+#else // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+  (void)align;+  return ::operator new(size);+#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+}++inline void aligned_delete(void* ptr)+{+#if defined(ASIO_HAS_STD_ALIGNED_ALLOC) && defined(ASIO_HAS_ALIGNOF)+  std::free(ptr);+#elif defined(ASIO_HAS_BOOST_ALIGN) && defined(ASIO_HAS_ALIGNOF)+  boost::alignment::aligned_free(ptr);+#elif defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+  _aligned_free(ptr);+#else // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+  ::operator delete(ptr);+#endif // defined(ASIO_MSVC) && defined(ASIO_HAS_ALIGNOF)+}  } // namespace asio 
link/modules/asio-standalone/asio/include/asio/detail/mutex.hpp view
@@ -2,7 +2,7 @@ // detail/mutex.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/non_const_lvalue.hpp view
@@ -2,7 +2,7 @@ // detail/non_const_lvalue.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/noncopyable.hpp view
@@ -2,7 +2,7 @@ // detail/noncopyable.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_event.hpp view
@@ -2,7 +2,7 @@ // detail/null_event.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/null_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_global.hpp view
@@ -2,7 +2,7 @@ // detail/null_global.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/null_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,8 +17,6 @@  #include "asio/detail/config.hpp" -#if !defined(ASIO_HAS_THREADS)- #include "asio/detail/noncopyable.hpp" #include "asio/detail/scoped_lock.hpp" @@ -58,7 +56,5 @@ } // 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
@@ -2,7 +2,7 @@ // detail/null_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,9 +17,12 @@  #include "asio/detail/config.hpp" -#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+#if defined(ASIO_HAS_IOCP) \+  || defined(ASIO_WINDOWS_RUNTIME) \+  || defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #include "asio/detail/scheduler_operation.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/execution_context.hpp"  #include "asio/detail/push_options.hpp"@@ -28,9 +31,14 @@ namespace detail {  class null_reactor-  : public execution_context_service_base<null_reactor>+  : public execution_context_service_base<null_reactor>,+    public scheduler_task { public:+  struct per_descriptor_data+  {+  };+   // Constructor.   null_reactor(asio::execution_context& ctx)     : execution_context_service_base<null_reactor>(ctx)@@ -42,6 +50,11 @@   {   } +  // Initialise the task.+  void init_task()+  {+  }+   // Destroy all user-defined handler objects owned by the service.   void shutdown()   {@@ -63,6 +76,8 @@  #include "asio/detail/pop_options.hpp" -#endif // defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+#endif // defined(ASIO_HAS_IOCP)+       //   || defined(ASIO_WINDOWS_RUNTIME)+       //   || defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #endif // ASIO_DETAIL_NULL_REACTOR_HPP
link/modules/asio-standalone/asio/include/asio/detail/null_signal_blocker.hpp view
@@ -2,7 +2,7 @@ // detail/null_signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_socket_service.hpp view
@@ -2,7 +2,7 @@ // detail/null_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/null_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_thread.hpp view
@@ -2,7 +2,7 @@ // detail/null_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/null_tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/null_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/object_pool.hpp view
@@ -2,7 +2,7 @@ // detail/object_pool.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/old_win_sdk_compat.hpp view
@@ -2,7 +2,7 @@ // detail/old_win_sdk_compat.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/op_queue.hpp view
@@ -2,7 +2,7 @@ // detail/op_queue.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/operation.hpp view
@@ -2,7 +2,7 @@ // detail/operation.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/pipe_select_interrupter.hpp view
@@ -2,7 +2,7 @@ // detail/pipe_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/pop_options.hpp view
@@ -2,7 +2,7 @@ // detail/pop_options.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -29,6 +29,10 @@ #  endif // !defined(ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma pop_macro ("emit")+# pragma pop_macro ("signal")+# pragma pop_macro ("slot")+ #elif defined(__clang__)  // Clang@@ -51,6 +55,10 @@  # pragma GCC diagnostic pop +# pragma pop_macro ("emit")+# pragma pop_macro ("signal")+# pragma pop_macro ("slot")+ #elif defined(__GNUC__)  // GNU C++@@ -77,6 +85,10 @@  # pragma GCC diagnostic pop +# pragma pop_macro ("emit")+# pragma pop_macro ("signal")+# pragma pop_macro ("slot")+ #elif defined(__KCC)  // Kai C++@@ -137,5 +149,9 @@ #   undef ASIO_CLR_WORKAROUND #  endif # endif++# pragma pop_macro ("emit")+# pragma pop_macro ("signal")+# pragma pop_macro ("slot")  #endif
link/modules/asio-standalone/asio/include/asio/detail/posix_event.hpp view
@@ -2,7 +2,7 @@ // detail/posix_event.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_fd_set_adapter.hpp view
@@ -2,7 +2,7 @@ // detail/posix_fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_global.hpp view
@@ -2,7 +2,7 @@ // detail/posix_global.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/posix_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/posix_serial_port_service.hpp view
@@ -0,0 +1,249 @@+//+// detail/posix_serial_port_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 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_POSIX_SERIAL_PORT_SERVICE_HPP+#define ASIO_DETAIL_POSIX_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"++#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_descriptor_service.hpp"+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/reactive_descriptor_service.hpp"+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Extend a descriptor_service to provide serial port support.+class posix_serial_port_service :+  public execution_context_service_base<posix_serial_port_service>+{+public:+#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  typedef io_uring_descriptor_service descriptor_service;+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  typedef reactive_descriptor_service descriptor_service;+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)++  // The native type of a serial port.+  typedef descriptor_service::native_handle_type native_handle_type;++  // The implementation type of the serial port.+  typedef descriptor_service::implementation_type implementation_type;++  ASIO_DECL posix_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,+      posix_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,+        &posix_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,+        &posix_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);+    ASIO_ERROR_LOCATION(ec);+    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.+  descriptor_service descriptor_service_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/posix_serial_port_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)+#endif // defined(ASIO_HAS_SERIAL_PORT)++#endif // ASIO_DETAIL_POSIX_SERIAL_PORT_SERVICE_HPP
link/modules/asio-standalone/asio/include/asio/detail/posix_signal_blocker.hpp view
@@ -2,7 +2,7 @@ // detail/posix_signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/posix_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_thread.hpp view
@@ -2,7 +2,7 @@ // detail/posix_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/posix_tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/posix_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/push_options.hpp view
@@ -2,7 +2,7 @@ // detail/push_options.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -29,6 +29,15 @@ #  endif // !defined(ASIO_DISABLE_VISIBILITY) # endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) || (__GNUC__ > 4) +# pragma push_macro ("emit")+# undef emit++# pragma push_macro ("signal")+# undef signal++# pragma push_macro ("slot")+# undef slot+ #elif defined(__clang__)  // Clang@@ -53,7 +62,19 @@  # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wnon-virtual-dtor"+# if (__clang_major__ >= 6)+#  pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"+# endif // (__clang_major__ >= 6) +# pragma push_macro ("emit")+# undef emit++# pragma push_macro ("signal")+# undef signal++# pragma push_macro ("slot")+# undef slot+ #elif defined(__GNUC__)  // GNU C++@@ -82,10 +103,22 @@  # pragma GCC diagnostic push # pragma GCC diagnostic ignored "-Wnon-virtual-dtor"+# if (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4)+#  pragma GCC diagnostic ignored "-Wzero-as-null-pointer-constant"+# endif // (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || (__GNUC__ > 4) # if (__GNUC__ >= 7) #  pragma GCC diagnostic ignored "-Wimplicit-fallthrough" # endif // (__GNUC__ >= 7) +# pragma push_macro ("emit")+# undef emit++# pragma push_macro ("signal")+# undef signal++# pragma push_macro ("slot")+# undef slot+ #elif defined(__KCC)  // Kai C++@@ -139,12 +172,13 @@ // // 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:4619) // suppress 'there is no warning number XXXX' # pragma warning (disable:4127) # pragma warning (disable:4180) # pragma warning (disable:4244)+# pragma warning (disable:4265) # pragma warning (disable:4355) # pragma warning (disable:4510) # pragma warning (disable:4512)@@ -181,5 +215,14 @@ #   endif #  endif # endif++# pragma push_macro ("emit")+# undef emit++# pragma push_macro ("signal")+# undef signal++# pragma push_macro ("slot")+# undef slot  #endif
link/modules/asio-standalone/asio/include/asio/detail/reactive_descriptor_service.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_descriptor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,9 +19,13 @@  #if !defined(ASIO_WINDOWS) \   && !defined(ASIO_WINDOWS_RUNTIME) \-  && !defined(__CYGWIN__)+  && !defined(__CYGWIN__) \+  && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) +#include "asio/associated_cancellation_slot.hpp"+#include "asio/associated_immediate_executor.hpp" #include "asio/buffer.hpp"+#include "asio/cancellation_type.hpp" #include "asio/execution_context.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/buffer_sequence_adapter.hpp"@@ -119,6 +123,14 @@   // Release ownership of the native descriptor representation.   ASIO_DECL native_handle_type release(implementation_type& impl); +  // Release ownership of the native descriptor representation.+  native_handle_type release(implementation_type& impl,+      asio::error_code& ec)+  {+    ec = success_ec_;+    return release(impl);+  }+   // Cancel all operations associated with the descriptor.   ASIO_DECL asio::error_code cancel(implementation_type& impl,       asio::error_code& ec);@@ -130,6 +142,7 @@   {     descriptor_ops::ioctl(impl.descriptor_, impl.state_,         command.name(), static_cast<ioctl_arg_type*>(command.data()), ec);+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -145,6 +158,7 @@   {     descriptor_ops::set_user_non_blocking(         impl.descriptor_, impl.state_, mode, ec);+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -184,6 +198,7 @@       break;     } +    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -197,6 +212,9 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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),@@ -210,22 +228,31 @@     switch (w)     {     case posix::descriptor_base::wait_read:-        op_type = reactor::read_op;-        break;+      op_type = reactor::read_op;+      break;     case posix::descriptor_base::wait_write:-        op_type = reactor::write_op;-        break;+      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;+      op_type = reactor::except_op;+      break;+    default:+      p.p->ec_ = asio::error::invalid_argument;+      start_op(impl, reactor::read_op, p.p,+          is_continuation, false, true, &io_ex, 0);+      p.v = p.p = 0;+      return;     } -    start_op(impl, op_type, p.p, is_continuation, false, false);+    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.descriptor_, op_type);+    }++    start_op(impl, op_type, p.p, is_continuation, false, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -237,9 +264,10 @@     typedef buffer_sequence_adapter<asio::const_buffer,         ConstBufferSequence> bufs_type; +    size_t n;     if (bufs_type::is_single_buffer)     {-      return descriptor_ops::sync_write1(impl.descriptor_,+      n = descriptor_ops::sync_write1(impl.descriptor_,           impl.state_, bufs_type::first(buffers).data(),           bufs_type::first(buffers).size(), ec);     }@@ -247,9 +275,12 @@     {       bufs_type bufs(buffers); -      return descriptor_ops::sync_write(impl.descriptor_, impl.state_,+      n = descriptor_ops::sync_write(impl.descriptor_, impl.state_,           bufs.buffers(), bufs.count(), bufs.all_empty(), ec);     }++    ASIO_ERROR_LOCATION(ec);+    return n;   }    // Wait until data can be written without blocking.@@ -258,7 +289,7 @@   {     // Wait for descriptor to become ready.     descriptor_ops::poll_write(impl.descriptor_, impl.state_, ec);-+    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -272,18 +303,30 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_,+            impl.descriptor_, reactor::write_op);+    }+     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));+          ConstBufferSequence>::all_empty(buffers), &io_ex, 0);     p.v = p.p = 0;   } @@ -295,16 +338,29 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_,+            impl.descriptor_, reactor::write_op);+    }+     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);+    start_op(impl, reactor::write_op, p.p,+        is_continuation, false, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -316,9 +372,10 @@     typedef buffer_sequence_adapter<asio::mutable_buffer,         MutableBufferSequence> bufs_type; +    size_t n;     if (bufs_type::is_single_buffer)     {-      return descriptor_ops::sync_read1(impl.descriptor_,+      n = descriptor_ops::sync_read1(impl.descriptor_,           impl.state_, bufs_type::first(buffers).data(),           bufs_type::first(buffers).size(), ec);     }@@ -326,9 +383,12 @@     {       bufs_type bufs(buffers); -      return descriptor_ops::sync_read(impl.descriptor_, impl.state_,+      n = descriptor_ops::sync_read(impl.descriptor_, impl.state_,           bufs.buffers(), bufs.count(), bufs.all_empty(), ec);     }++    ASIO_ERROR_LOCATION(ec);+    return n;   }    // Wait until data can be read without blocking.@@ -337,7 +397,7 @@   {     // Wait for descriptor to become ready.     descriptor_ops::poll_read(impl.descriptor_, impl.state_, ec);-+    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -352,18 +412,30 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_,+            impl.descriptor_, reactor::read_op);+    }+     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));+          MutableBufferSequence>::all_empty(buffers), &io_ex, 0);     p.v = p.p = 0;   } @@ -375,24 +447,101 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_,+            impl.descriptor_, reactor::read_op);+    }+     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);+    start_op(impl, reactor::read_op, p.p,+        is_continuation, false, false, &io_ex, 0);     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);+  ASIO_DECL void do_start_op(implementation_type& impl, int op_type,+      reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop,+      void (*on_immediate)(operation* op, bool, const void*),+      const void* immediate_arg); +  // Start the asynchronous operation for handlers that are specialised for+  // immediate completion.+  template <typename Op>+  void start_op(implementation_type& impl, int op_type, Op* op,+      bool is_continuation, bool is_non_blocking, bool noop,+      const void* io_ex, ...)+  {+    return do_start_op(impl, op_type, op, is_continuation,+        is_non_blocking, noop, &Op::do_immediate, io_ex);+  }++  // Start the asynchronous operation for handlers that are not specialised for+  // immediate completion.+  template <typename Op>+  void start_op(implementation_type& impl, int op_type, Op* op,+      bool is_continuation, bool is_non_blocking, bool noop, const void*,+      typename enable_if<+        is_same<+          typename associated_immediate_executor<+            typename Op::handler_type,+            typename Op::io_executor_type+          >::asio_associated_immediate_executor_is_unspecialised,+          void+        >::value+      >::type*)+  {+    return do_start_op(impl, op_type, op, is_continuation, is_non_blocking,+        noop, &reactor::call_post_immediate_completion, &reactor_);+  }++  // Helper class used to implement per-operation cancellation+  class reactor_op_cancellation+  {+  public:+    reactor_op_cancellation(reactor* r,+        reactor::per_descriptor_data* p, int d, int o)+      : reactor_(r),+        reactor_data_(p),+        descriptor_(d),+        op_type_(o)+    {+    }++    void operator()(cancellation_type_t type)+    {+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        reactor_->cancel_ops_by_key(descriptor_,+            *reactor_data_, op_type_, this);+      }+    }++  private:+    reactor* reactor_;+    reactor::per_descriptor_data* reactor_data_;+    int descriptor_;+    int op_type_;+  };+   // The selector that performs event demultiplexing for the service.   reactor& reactor_; @@ -412,5 +561,6 @@ #endif // !defined(ASIO_WINDOWS)        //   && !defined(ASIO_WINDOWS_RUNTIME)        //   && !defined(__CYGWIN__)+       //   && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #endif // ASIO_DETAIL_REACTIVE_DESCRIPTOR_SERVICE_HPP
link/modules/asio-standalone/asio/include/asio/detail/reactive_null_buffers_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_null_buffers_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -33,6 +33,9 @@ class reactive_null_buffers_op : public reactor_op { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_null_buffers_op);    reactive_null_buffers_op(const asio::error_code& success_ec,@@ -54,6 +57,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_null_buffers_op* o(static_cast<reactive_null_buffers_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -83,6 +87,36 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_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();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
− link/modules/asio-standalone/asio/include/asio/detail/reactive_serial_port_service.hpp
@@ -1,237 +0,0 @@-//-// 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
@@ -2,7 +2,7 @@ // detail/reactive_socket_accept_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -52,6 +52,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     reactive_socket_accept_op_base* o(         static_cast<reactive_socket_accept_op_base*>(base)); @@ -95,6 +96,9 @@   public reactive_socket_accept_op_base<Socket, Protocol> { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_socket_accept_op);    reactive_socket_accept_op(const asio::error_code& success_ec,@@ -114,6 +118,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_socket_accept_op* o(static_cast<reactive_socket_accept_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -128,6 +133,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -149,6 +156,41 @@     }   } +  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    o->do_assign();++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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::binder1<Handler, asio::error_code>+      handler(o->handler_, o->ec_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;+  }+ private:   Handler handler_;   handler_work<Handler, IoExecutor> work_;@@ -165,6 +207,9 @@     Protocol> { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_socket_move_accept_op);    reactive_socket_move_accept_op(const asio::error_code& success_ec,@@ -186,6 +231,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_socket_move_accept_op* o(         static_cast<reactive_socket_move_accept_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -201,6 +247,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -222,6 +270,44 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    o->do_assign();++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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::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();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, "..."));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_connect_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -43,6 +43,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     reactive_socket_connect_op_base* o(         static_cast<reactive_socket_connect_op_base*>(base)); @@ -62,6 +63,9 @@ class reactive_socket_connect_op : public reactive_socket_connect_op_base { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_socket_connect_op);    reactive_socket_connect_op(const asio::error_code& success_ec,@@ -78,6 +82,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_socket_connect_op* o       (static_cast<reactive_socket_connect_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -89,6 +94,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -108,6 +115,39 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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::binder1<Handler, asio::error_code>+      handler(o->handler_, o->ec_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recv_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -50,6 +50,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     reactive_socket_recv_op_base* o(         static_cast<reactive_socket_recv_op_base*>(base)); @@ -97,6 +98,9 @@   public reactive_socket_recv_op_base<MutableBufferSequence> { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_socket_recv_op);    reactive_socket_recv_op(const asio::error_code& success_ec,@@ -115,6 +119,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_socket_recv_op* o(static_cast<reactive_socket_recv_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -125,6 +130,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -144,6 +151,38 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_recvfrom_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,6 +51,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     reactive_socket_recvfrom_op_base* o(         static_cast<reactive_socket_recvfrom_op_base*>(base)); @@ -99,6 +100,9 @@   public reactive_socket_recvfrom_op_base<MutableBufferSequence, Endpoint> { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvfrom_op);    reactive_socket_recvfrom_op(const asio::error_code& success_ec,@@ -119,6 +123,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_socket_recvfrom_op* o(         static_cast<reactive_socket_recvfrom_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -130,6 +135,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -149,6 +156,39 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_recvmsg_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,6 +51,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     reactive_socket_recvmsg_op_base* o(         static_cast<reactive_socket_recvmsg_op_base*>(base)); @@ -80,6 +81,9 @@   public reactive_socket_recvmsg_op_base<MutableBufferSequence> { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_socket_recvmsg_op);    reactive_socket_recvmsg_op(const asio::error_code& success_ec,@@ -100,6 +104,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_socket_recvmsg_op* o(         static_cast<reactive_socket_recvmsg_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -111,6 +116,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -130,6 +137,39 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_send_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -50,6 +50,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     reactive_socket_send_op_base* o(         static_cast<reactive_socket_send_op_base*>(base)); @@ -100,6 +101,9 @@   public reactive_socket_send_op_base<ConstBufferSequence> { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_socket_send_op);    reactive_socket_send_op(const asio::error_code& success_ec,@@ -118,6 +122,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_socket_send_op* o(static_cast<reactive_socket_send_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -128,6 +133,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -148,6 +155,39 @@       ASIO_HANDLER_INVOCATION_END;     }   }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;+  }+  private:   Handler handler_;
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_sendto_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_sendto_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -50,6 +50,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     reactive_socket_sendto_op_base* o(         static_cast<reactive_socket_sendto_op_base*>(base)); @@ -93,6 +94,9 @@   public reactive_socket_sendto_op_base<ConstBufferSequence, Endpoint> { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_socket_sendto_op);    reactive_socket_sendto_op(const asio::error_code& success_ec,@@ -112,6 +116,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_socket_sendto_op* o(static_cast<reactive_socket_sendto_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -122,6 +127,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(o->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@@ -141,6 +148,38 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(+          o->work_));++    ASIO_ERROR_LOCATION(o->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_, o->ec_, o->bytes_transferred_);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_, handler.arg2_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,7 +17,8 @@  #include "asio/detail/config.hpp" -#if !defined(ASIO_HAS_IOCP)+#if !defined(ASIO_HAS_IOCP) \+  && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #include "asio/buffer.hpp" #include "asio/error.hpp"@@ -127,6 +128,8 @@     if (!do_open(impl, protocol.family(),           protocol.type(), protocol.protocol(), ec))       impl.protocol_ = protocol;++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -137,6 +140,8 @@   {     if (!do_assign(impl, protocol.type(), native_socket, ec))       impl.protocol_ = protocol;++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -151,6 +156,8 @@       const endpoint_type& endpoint, asio::error_code& ec)   {     socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -162,6 +169,8 @@     socket_ops::setsockopt(impl.socket_, impl.state_,         option.level(impl.protocol_), option.name(impl.protocol_),         option.data(impl.protocol_), option.size(impl.protocol_), ec);++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -176,6 +185,8 @@         option.data(impl.protocol_), &size, ec);     if (!ec)       option.resize(impl.protocol_, size);++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -186,7 +197,10 @@     endpoint_type endpoint;     std::size_t addr_len = endpoint.capacity();     if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))+    {+      ASIO_ERROR_LOCATION(ec);       return endpoint_type();+    }     endpoint.resize(addr_len);     return endpoint;   }@@ -199,7 +213,10 @@     std::size_t addr_len = endpoint.capacity();     if (socket_ops::getpeername(impl.socket_,           endpoint.data(), &addr_len, false, ec))+    {+      ASIO_ERROR_LOCATION(ec);       return endpoint_type();+    }     endpoint.resize(addr_len);     return endpoint;   }@@ -209,6 +226,8 @@       socket_base::shutdown_type what, asio::error_code& ec)   {     socket_ops::shutdown(impl.socket_, what, ec);++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -222,9 +241,10 @@     typedef buffer_sequence_adapter<asio::const_buffer,         ConstBufferSequence> bufs_type; +    size_t n;     if (bufs_type::is_single_buffer)     {-      return socket_ops::sync_sendto1(impl.socket_, impl.state_,+      n = socket_ops::sync_sendto1(impl.socket_, impl.state_,           bufs_type::first(buffers).data(),           bufs_type::first(buffers).size(), flags,           destination.data(), destination.size(), ec);@@ -232,10 +252,13 @@     else     {       bufs_type bufs(buffers);-      return socket_ops::sync_sendto(impl.socket_, impl.state_,+      n = socket_ops::sync_sendto(impl.socket_, impl.state_,           bufs.buffers(), bufs.count(), flags,           destination.data(), destination.size(), ec);     }++    ASIO_ERROR_LOCATION(ec);+    return n;   }    // Wait until data can be sent without blocking.@@ -246,6 +269,7 @@     // Wait for socket to become ready.     socket_ops::poll_write(impl.socket_, impl.state_, -1, ec); +    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -260,6 +284,9 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // Allocate and construct an operation to wrap the handler.     typedef reactive_socket_sendto_op<ConstBufferSequence,         endpoint_type, Handler, IoExecutor> op;@@ -268,10 +295,19 @@     p.p = new (p.v) op(success_ec_, impl.socket_,         buffers, destination, flags, handler, io_ex); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);+    }+     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);+    start_op(impl, reactor::write_op, p.p,+        is_continuation, true, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -284,16 +320,28 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);+    }+     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);+    start_op(impl, reactor::write_op, p.p,+        is_continuation, false, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -309,26 +357,25 @@         MutableBufferSequence> bufs_type;      std::size_t addr_len = sender_endpoint.capacity();-    std::size_t bytes_recvd;+    std::size_t n;     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);+      n = 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);+      n = 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;+    ASIO_ERROR_LOCATION(ec);+    return n;   }    // Wait until data can be received without blocking.@@ -342,6 +389,7 @@     // Reset endpoint since it can be given no sensible value at this time.     sender_endpoint = endpoint_type(); +    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -358,6 +406,9 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // Allocate and construct an operation to wrap the handler.     typedef reactive_socket_recvfrom_op<MutableBufferSequence,         endpoint_type, Handler, IoExecutor> op;@@ -367,13 +418,21 @@     p.p = new (p.v) op(success_ec_, impl.socket_, protocol,         buffers, sender_endpoint, flags, handler, io_ex); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+    }+     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.p, is_continuation, true, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -386,12 +445,23 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+    }+     ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",           &impl, impl.socket_, "async_receive_from(null_buffers)")); @@ -401,7 +471,7 @@     start_op(impl,         (flags & socket_base::message_out_of_band)           ? reactor::except_op : reactor::read_op,-        p.p, is_continuation, false, false);+        p.p, is_continuation, false, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -414,6 +484,7 @@     if (peer.is_open())     {       ec = asio::error::already_open;+      ASIO_ERROR_LOCATION(ec);       return ec;     } @@ -432,6 +503,7 @@         new_socket.release();     } +    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -444,6 +516,9 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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),@@ -451,10 +526,18 @@     p.p = new (p.v) op(success_ec_, impl.socket_, impl.state_,         peer, impl.protocol_, peer_endpoint, handler, io_ex); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected() && !peer.is_open())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+    }+     ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",           &impl, impl.socket_, "async_accept")); -    start_accept_op(impl, p.p, is_continuation, peer.is_open());+    start_accept_op(impl, p.p, is_continuation, peer.is_open(), &io_ex, 0);     p.v = p.p = 0;   } @@ -469,6 +552,9 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // Allocate and construct an operation to wrap the handler.     typedef reactive_socket_move_accept_op<Protocol,         PeerIoExecutor, Handler, IoExecutor> op;@@ -477,10 +563,18 @@     p.p = new (p.v) op(success_ec_, peer_io_ex, impl.socket_,         impl.state_, impl.protocol_, peer_endpoint, handler, io_ex); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+    }+     ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",           &impl, impl.socket_, "async_accept")); -    start_accept_op(impl, p.p, is_continuation, false);+    start_accept_op(impl, p.p, is_continuation, false, &io_ex, 0);     p.v = p.p = 0;   } #endif // defined(ASIO_HAS_MOVE)@@ -491,6 +585,7 @@   {     socket_ops::sync_connect(impl.socket_,         peer_endpoint.data(), peer_endpoint.size(), ec);+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -503,17 +598,28 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::connect_op);+    }+     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());+        peer_endpoint.data(), peer_endpoint.size(), &io_ex, 0);     p.v = p.p = 0;   } };@@ -524,5 +630,6 @@ #include "asio/detail/pop_options.hpp"  #endif // !defined(ASIO_HAS_IOCP)+       //   && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_HPP
link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service_base.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_socket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,9 +18,12 @@ #include "asio/detail/config.hpp"  #if !defined(ASIO_HAS_IOCP) \-  && !defined(ASIO_WINDOWS_RUNTIME)+  && !defined(ASIO_WINDOWS_RUNTIME) \+  && !defined(ASIO_HAS_IO_URING_AS_DEFAULT) +#include "asio/associated_cancellation_slot.hpp" #include "asio/buffer.hpp"+#include "asio/cancellation_type.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/socket_base.hpp"@@ -199,6 +202,9 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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),@@ -211,23 +217,32 @@     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;+    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;+      start_op(impl, reactor::read_op, p.p,+          is_continuation, false, true, &io_ex, 0);+      p.v = p.p = 0;+      return;     } -    start_op(impl, op_type, p.p, is_continuation, false, false);+    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, op_type);+    }++    start_op(impl, op_type, p.p, is_continuation, false, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -274,6 +289,9 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // Allocate and construct an operation to wrap the handler.     typedef reactive_socket_send_op<         ConstBufferSequence, Handler, IoExecutor> op;@@ -282,13 +300,21 @@     p.p = new (p.v) op(success_ec_, impl.socket_,         impl.state_, buffers, flags, handler, io_ex); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);+    }+     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)));+            ConstBufferSequence>::all_empty(buffers)), &io_ex, 0);     p.v = p.p = 0;   } @@ -300,16 +326,28 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::write_op);+    }+     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);+    start_op(impl, reactor::write_op, p.p,+        is_continuation, false, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -357,6 +395,9 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // Allocate and construct an operation to wrap the handler.     typedef reactive_socket_recv_op<         MutableBufferSequence, Handler, IoExecutor> op;@@ -365,6 +406,14 @@     p.p = new (p.v) op(success_ec_, impl.socket_,         impl.state_, buffers, flags, handler, io_ex); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+    }+     ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",           &impl, impl.socket_, "async_receive")); @@ -375,7 +424,7 @@         (flags & socket_base::message_out_of_band) == 0,         ((impl.state_ & socket_ops::stream_oriented)           && buffer_sequence_adapter<asio::mutable_buffer,-            MutableBufferSequence>::all_empty(buffers)));+            MutableBufferSequence>::all_empty(buffers)), &io_ex, 0);     p.v = p.p = 0;   } @@ -388,19 +437,30 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+    }+     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.p, is_continuation, false, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -446,6 +506,9 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // Allocate and construct an operation to wrap the handler.     typedef reactive_socket_recvmsg_op<         MutableBufferSequence, Handler, IoExecutor> op;@@ -454,6 +517,14 @@     p.p = new (p.v) op(success_ec_, impl.socket_,         buffers, in_flags, out_flags, handler, io_ex); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+    }+     ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",           &impl, impl.socket_, "async_receive_with_flags")); @@ -461,7 +532,7 @@         (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);+        (in_flags & socket_base::message_out_of_band) == 0, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -475,12 +546,23 @@     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); +    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<reactor_op_cancellation>(+            &reactor_, &impl.reactor_data_, impl.socket_, reactor::read_op);+    }+     ASIO_HANDLER_CREATION((reactor_.context(), *p.p, "socket",           &impl, impl.socket_, "async_receive_with_flags(null_buffers)")); @@ -491,7 +573,7 @@     start_op(impl,         (in_flags & socket_base::message_out_of_band)           ? reactor::except_op : reactor::read_op,-        p.p, is_continuation, false, false);+        p.p, is_continuation, false, false, &io_ex, 0);     p.v = p.p = 0;   } @@ -507,18 +589,144 @@       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);+  ASIO_DECL void do_start_op(base_implementation_type& impl, int op_type,+      reactor_op* op, bool is_continuation, bool is_non_blocking, bool noop,+      void (*on_immediate)(operation* op, bool, const void*),+      const void* immediate_arg); +  // Start the asynchronous operation for handlers that are specialised for+  // immediate completion.+  template <typename Op>+  void start_op(base_implementation_type& impl, int op_type, Op* op,+      bool is_continuation, bool is_non_blocking, bool noop,+      const void* io_ex, ...)+  {+    return do_start_op(impl, op_type, op, is_continuation,+        is_non_blocking, noop, &Op::do_immediate, io_ex);+  }++  // Start the asynchronous operation for handlers that are not specialised for+  // immediate completion.+  template <typename Op>+  void start_op(base_implementation_type& impl, int op_type, Op* op,+      bool is_continuation, bool is_non_blocking, bool noop, const void*,+      typename enable_if<+        is_same<+          typename associated_immediate_executor<+            typename Op::handler_type,+            typename Op::io_executor_type+          >::asio_associated_immediate_executor_is_unspecialised,+          void+        >::value+      >::type*)+  {+    return do_start_op(impl, op_type, op, is_continuation, is_non_blocking,+        noop, &reactor::call_post_immediate_completion, &reactor_);+  }+   // 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);+  ASIO_DECL void do_start_accept_op(base_implementation_type& impl,+      reactor_op* op, bool is_continuation, bool peer_is_open,+      void (*on_immediate)(operation* op, bool, const void*),+      const void* immediate_arg); +  // Start the asynchronous accept operation for handlers that are specialised+  // for immediate completion.+  template <typename Op>+  void start_accept_op(base_implementation_type& impl, Op* op,+      bool is_continuation, bool peer_is_open, const void* io_ex, ...)+  {+    return do_start_accept_op(impl, op, is_continuation,+        peer_is_open, &Op::do_immediate, io_ex);+  }++  // Start the asynchronous operation for handlers that are not specialised for+  // immediate completion.+  template <typename Op>+  void start_accept_op(base_implementation_type& impl, Op* op,+      bool is_continuation, bool peer_is_open, const void*,+      typename enable_if<+        is_same<+          typename associated_immediate_executor<+            typename Op::handler_type,+            typename Op::io_executor_type+          >::asio_associated_immediate_executor_is_unspecialised,+          void+        >::value+      >::type*)+  {+    return do_start_accept_op(impl, op, is_continuation, peer_is_open,+        &reactor::call_post_immediate_completion, &reactor_);+  }+   // 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);+  ASIO_DECL void do_start_connect_op(base_implementation_type& impl,+      reactor_op* op, bool is_continuation, const void* addr, size_t addrlen,+      void (*on_immediate)(operation* op, bool, const void*),+      const void* immediate_arg); +  // Start the asynchronous operation for handlers that are specialised for+  // immediate completion.+  template <typename Op>+  void start_connect_op(base_implementation_type& impl,+      Op* op, bool is_continuation, const void* addr,+      size_t addrlen, const void* io_ex, ...)+  {+    return do_start_connect_op(impl, op, is_continuation,+        addr, addrlen, &Op::do_immediate, io_ex);+  }++  // Start the asynchronous operation for handlers that are not specialised for+  // immediate completion.+  template <typename Op>+  void start_connect_op(base_implementation_type& impl, Op* op,+      bool is_continuation, const void* addr, size_t addrlen, const void*,+      typename enable_if<+        is_same<+          typename associated_immediate_executor<+            typename Op::handler_type,+            typename Op::io_executor_type+          >::asio_associated_immediate_executor_is_unspecialised,+          void+        >::value+      >::type*)+  {+    return do_start_connect_op(impl, op, is_continuation, addr,+        addrlen, &reactor::call_post_immediate_completion, &reactor_);+  }++  // Helper class used to implement per-operation cancellation+  class reactor_op_cancellation+  {+  public:+    reactor_op_cancellation(reactor* r,+        reactor::per_descriptor_data* p, int d, int o)+      : reactor_(r),+        reactor_data_(p),+        descriptor_(d),+        op_type_(o)+    {+    }++    void operator()(cancellation_type_t type)+    {+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        reactor_->cancel_ops_by_key(descriptor_,+            *reactor_data_, op_type_, this);+      }+    }++  private:+    reactor* reactor_;+    reactor::per_descriptor_data* reactor_data_;+    int descriptor_;+    int op_type_;+  };+   // The selector that performs event demultiplexing for the service.   reactor& reactor_; @@ -537,5 +745,6 @@  #endif // !defined(ASIO_HAS_IOCP)        //   && !defined(ASIO_WINDOWS_RUNTIME)+       //   && !defined(ASIO_HAS_IO_URING_AS_DEFAULT)  #endif // ASIO_DETAIL_REACTIVE_SOCKET_SERVICE_BASE_HPP
link/modules/asio-standalone/asio/include/asio/detail/reactive_wait_op.hpp view
@@ -2,7 +2,7 @@ // detail/reactive_wait_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -33,6 +33,9 @@ class reactive_wait_op : public reactor_op { public:+  typedef Handler handler_type;+  typedef IoExecutor io_executor_type;+   ASIO_DEFINE_HANDLER_PTR(reactive_wait_op);    reactive_wait_op(const asio::error_code& success_ec,@@ -54,6 +57,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);     reactive_wait_op* o(static_cast<reactive_wait_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -83,6 +87,36 @@       w.complete(handler, handler.handler_);       ASIO_HANDLER_INVOCATION_END;     }+  }++  static void do_immediate(operation* base, bool, const void* io_ex)+  {+    // Take ownership of the handler object.+    ASIO_ASSUME(base != 0);+    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.+    immediate_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();++    ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+    w.complete(handler, handler.handler_, io_ex);+    ASIO_HANDLER_INVOCATION_END;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/reactor.hpp view
@@ -2,7 +2,7 @@ // detail/reactor.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,18 +15,40 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/detail/reactor_fwd.hpp"+#include "asio/detail/config.hpp" -#if defined(ASIO_HAS_EPOLL)+#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+# include "asio/detail/null_reactor.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/null_reactor.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"-#elif defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)-# include "asio/detail/null_reactor.hpp" #else # include "asio/detail/select_reactor.hpp" #endif++namespace asio {+namespace detail {++#if defined(ASIO_HAS_IOCP) || defined(ASIO_WINDOWS_RUNTIME)+typedef null_reactor reactor;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+typedef null_reactor reactor;+#elif defined(ASIO_HAS_EPOLL)+typedef epoll_reactor reactor;+#elif defined(ASIO_HAS_KQUEUE)+typedef kqueue_reactor reactor;+#elif defined(ASIO_HAS_DEV_POLL)+typedef dev_poll_reactor reactor;+#else+typedef select_reactor reactor;+#endif++} // namespace detail+} // namespace asio  #endif // ASIO_DETAIL_REACTOR_HPP
− link/modules/asio-standalone/asio/include/asio/detail/reactor_fwd.hpp
@@ -1,40 +0,0 @@-//-// 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
@@ -2,7 +2,7 @@ // detail/reactor_op.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,6 +30,9 @@   // The error code to be passed to the completion handler.   asio::error_code ec_; +  // The operation key used for targeted cancellation.+  void* cancellation_key_;+   // The number of bytes transferred, to be passed to the completion handler.   std::size_t bytes_transferred_; @@ -50,6 +53,7 @@       perform_func_type perform_func, func_type complete_func)     : operation(complete_func),       ec_(success_ec),+      cancellation_key_(0),       bytes_transferred_(0),       perform_func_(perform_func)   {
link/modules/asio-standalone/asio/include/asio/detail/reactor_op_queue.hpp view
@@ -2,7 +2,7 @@ // detail/reactor_op_queue.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -98,6 +98,50 @@         asio::error::operation_aborted)   {     return this->cancel_operations(operations_.find(descriptor), ops, ec);+  }++  // Cancel operations associated with the descriptor identified by the+  // supplied iterator, and the specified cancellation key. Any operations+  // pending for the descriptor with the key 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_by_key(iterator i, op_queue<operation>& ops,+      void* cancellation_key, const asio::error_code& ec =+        asio::error::operation_aborted)+  {+    bool result = false;+    if (i != operations_.end())+    {+      op_queue<reactor_op> other_ops;+      while (reactor_op* op = i->second.front())+      {+        i->second.pop();+        if (op->cancellation_key_ == cancellation_key)+        {+          op->ec_ = ec;+          ops.push(op);+          result = true;+        }+        else+          other_ops.push(op);+      }+      i->second.push(other_ops);+      if (i->second.empty())+        operations_.erase(i);+    }+    return result;+  }++  // 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_by_key(Descriptor descriptor, op_queue<operation>& ops,+      void* cancellation_key, const asio::error_code& ec =+        asio::error::operation_aborted)+  {+    return this->cancel_operations_by_key(+        operations_.find(descriptor), ops, cancellation_key, ec);   }    // Whether there are no operations in the queue.
link/modules/asio-standalone/asio/include/asio/detail/recycling_allocator.hpp view
@@ -2,7 +2,7 @@ // detail/recycling_allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -48,17 +48,16 @@    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);+        thread_context::top_of_thread_call_stack(),+        sizeof(T) * n, ASIO_ALIGNOF(T));     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);+        thread_context::top_of_thread_call_stack(), p, sizeof(T) * n);   } }; 
link/modules/asio-standalone/asio/include/asio/detail/regex_fwd.hpp view
@@ -2,7 +2,7 @@ // detail/regex_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,7 +18,16 @@ #if defined(ASIO_HAS_BOOST_REGEX)  #include <boost/regex_fwd.hpp>-#include <boost/regex/v4/match_flags.hpp>+#include <boost/version.hpp>+#if BOOST_VERSION >= 107600+# if defined(BOOST_REGEX_CXX03)+#  include <boost/regex/v4/match_flags.hpp>+# else // defined(BOOST_REGEX_CXX03)+#  include <boost/regex/v5/match_flags.hpp>+# endif // defined(BOOST_REGEX_CXX03)+#else // BOOST_VERSION >= 107600+# include <boost/regex/v4/match_flags.hpp>+#endif // BOOST_VERSION >= 107600  namespace boost { 
link/modules/asio-standalone/asio/include/asio/detail/resolve_endpoint_op.hpp view
@@ -2,7 +2,7 @@ // detail/resolve_endpoint_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -70,6 +70,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     resolve_endpoint_op* o(static_cast<resolve_endpoint_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -79,8 +80,8 @@       // the resolver operation.            // Perform the blocking endpoint resolution operation.-      char host_name[NI_MAXHOST];-      char service_name[NI_MAXSERV];+      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_);
link/modules/asio-standalone/asio/include/asio/detail/resolve_op.hpp view
@@ -2,7 +2,7 @@ // detail/resolve_op.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/resolve_query_op.hpp view
@@ -2,7 +2,7 @@ // detail/resolve_query_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,11 +55,11 @@ #endif    resolve_query_op(socket_ops::weak_cancel_token_type cancel_token,-      const query_type& query, scheduler_impl& sched,+      const query_type& qry, scheduler_impl& sched,       Handler& handler, const IoExecutor& io_ex)     : resolve_op(&resolve_query_op::do_complete),       cancel_token_(cancel_token),-      query_(query),+      query_(qry),       scheduler_(sched),       handler_(ASIO_MOVE_CAST(Handler)(handler)),       work_(handler_, io_ex),@@ -78,6 +78,7 @@       std::size_t /*bytes_transferred*/)   {     // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     resolve_query_op* o(static_cast<resolve_query_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; 
link/modules/asio-standalone/asio/include/asio/detail/resolver_service.hpp view
@@ -2,7 +2,7 @@ // detail/resolver_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -71,29 +71,30 @@   }    // Resolve a query to a list of entries.-  results_type resolve(implementation_type&, const query_type& query,+  results_type resolve(implementation_type&, const query_type& qry,       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);+    socket_ops::getaddrinfo(qry.host_name().c_str(),+        qry.service_name().c_str(), qry.hints(), &address_info, ec);     auto_addrinfo auto_address_info(address_info); +    ASIO_ERROR_LOCATION(ec);     return ec ? results_type() : results_type::create(-        address_info, query.host_name(), query.service_name());+        address_info, qry.host_name(), qry.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,+  void async_resolve(implementation_type& impl, const query_type& qry,       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);+    p.p = new (p.v) op(impl, qry, scheduler_, handler, io_ex);      ASIO_HANDLER_CREATION((scheduler_.context(),           *p.p, "resolver", &impl, 0, "async_resolve"));@@ -112,6 +113,7 @@         host_name, NI_MAXHOST, service_name, NI_MAXSERV,         endpoint.protocol().type(), ec); +    ASIO_ERROR_LOCATION(ec);     return ec ? results_type() : results_type::create(         endpoint, host_name, service_name);   }
link/modules/asio-standalone/asio/include/asio/detail/resolver_service_base.hpp view
@@ -2,7 +2,7 @@ // detail/resolver_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -71,6 +71,21 @@   ASIO_DECL void move_assign(implementation_type& impl,       resolver_service_base& other_service,       implementation_type& other_impl);++  // Move-construct a new timer implementation.+  void converting_move_construct(implementation_type& impl,+      resolver_service_base&, implementation_type& other_impl)+  {+    move_construct(impl, other_impl);+  }++  // Move-assign from another timer implementation.+  void converting_move_assign(implementation_type& impl,+      resolver_service_base& other_service,+      implementation_type& other_impl)+  {+    move_assign(impl, other_service, other_impl);+  }    // Cancel pending asynchronous operations.   ASIO_DECL void cancel(implementation_type& impl);
link/modules/asio-standalone/asio/include/asio/detail/scheduler.hpp view
@@ -2,7 +2,7 @@ // detail/scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -23,8 +23,8 @@ #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/scheduler_task.hpp" #include "asio/detail/thread.hpp" #include "asio/detail/thread_context.hpp" @@ -42,10 +42,15 @@ public:   typedef scheduler_operation operation; +  // The type of a function used to obtain a task instance.+  typedef scheduler_task* (*get_task_func_type)(+      asio::execution_context&);+   // 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);+      int concurrency_hint = 0, bool own_thread = true,+      get_task_func_type get_task = &scheduler::get_default_task);    // Destructor.   ASIO_DECL ~scheduler();@@ -99,10 +104,7 @@   }    // Return whether a handler can be dispatched immediately.-  bool can_dispatch()-  {-    return thread_call_stack::contains(this) != 0;-  }+  ASIO_DECL bool can_dispatch();    /// Capture the current exception so it can be rethrown from a run function.   ASIO_DECL void capture_current_exception();@@ -168,6 +170,10 @@   ASIO_DECL void wake_one_thread_and_unlock(       mutex::scoped_lock& lock); +  // Get the default task.+  ASIO_DECL static scheduler_task* get_default_task(+      asio::execution_context& ctx);+   // Helper class to run the scheduler in its own thread.   class thread_function;   friend class thread_function;@@ -190,7 +196,10 @@   event wakeup_event_;    // The task to be run by this service.-  reactor* task_;+  scheduler_task* task_;++  // The function used to get the task.+  get_task_func_type get_task_;    // Operation object to represent the position of the task in the queue.   struct task_operation : operation
link/modules/asio-standalone/asio/include/asio/detail/scheduler_operation.hpp view
@@ -2,7 +2,7 @@ // detail/scheduler_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/scheduler_task.hpp view
@@ -0,0 +1,49 @@+//+// detail/scheduler_task.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_TASK_HPP+#define ASIO_DETAIL_SCHEDULER_TASK_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/push_options.hpp"++namespace asio {+namespace detail {++class scheduler_operation;++// Base class for all tasks that may be run by a scheduler.+class scheduler_task+{+public:+  // Run the task once until interrupted or events are ready to be dispatched.+  virtual void run(long usec, op_queue<scheduler_operation>& ops) = 0;++  // Interrupt the task.+  virtual void interrupt() = 0;++protected:+  // Prevent deletion through this type.+  ~scheduler_task()+  {+  }+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_DETAIL_SCHEDULER_TASK_HPP
link/modules/asio-standalone/asio/include/asio/detail/scheduler_thread_info.hpp view
@@ -2,7 +2,7 @@ // detail/scheduler_thread_info.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/scoped_lock.hpp view
@@ -2,7 +2,7 @@ // detail/scoped_lock.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/scoped_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/scoped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/select_interrupter.hpp view
@@ -2,7 +2,7 @@ // detail/select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/select_reactor.hpp view
@@ -2,7 +2,7 @@ // detail/select_reactor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,6 +30,7 @@ #include "asio/detail/op_queue.hpp" #include "asio/detail/reactor_op.hpp" #include "asio/detail/reactor_op_queue.hpp"+#include "asio/detail/scheduler_task.hpp" #include "asio/detail/select_interrupter.hpp" #include "asio/detail/socket_types.hpp" #include "asio/detail/timer_queue_base.hpp"@@ -48,6 +49,9 @@  class select_reactor   : public execution_context_service_base<select_reactor>+#if !defined(ASIO_HAS_IOCP)+    , public scheduler_task+#endif // !defined(ASIO_HAS_IOCP) { public: #if defined(ASIO_WINDOWS) || defined(__CYGWIN__)@@ -90,21 +94,42 @@       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);-  }+  void post_immediate_completion(operation* op, bool is_continuation) const; +  // Post a reactor operation for immediate completion.+  ASIO_DECL static void call_post_immediate_completion(+      operation* op, bool is_continuation, const void* self);+   // 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);+      per_descriptor_data&, reactor_op* op, bool is_continuation, bool,+      void (*on_immediate)(operation*, bool, const void*),+      const void* immediate_arg); +  // Start a new operation. The reactor operation will be performed when the+  // given descriptor is flagged as ready, or an error has occurred.+  void start_op(int op_type, socket_type descriptor,+      per_descriptor_data& descriptor_data, reactor_op* op,+      bool is_continuation, bool allow_speculative)+  {+    start_op(op_type, descriptor, descriptor_data,+        op, is_continuation, allow_speculative,+        &select_reactor::call_post_immediate_completion, this);+  }+   // 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 all operations associated with the given descriptor and key. The+  // handlers associated with the descriptor will be invoked with the+  // operation_aborted error.+  ASIO_DECL void cancel_ops_by_key(socket_type descriptor,+      per_descriptor_data& descriptor_data,+      int op_type, void* cancellation_key);+   // 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.@@ -148,6 +173,12 @@       typename timer_queue<Time_Traits>::per_timer_data& timer,       std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); +  // Cancel the timer operations associated with the given key.+  template <typename Time_Traits>+  void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data* timer,+      void* cancellation_key);+   // Move the timer operations associated with the given timer.   template <typename Time_Traits>   void move_timer(timer_queue<Time_Traits>& queue,@@ -213,6 +244,28 @@    // The thread that is running the reactor loop.   asio::detail::thread* thread_;++  // Helper class to join and restart the reactor thread.+  class restart_reactor : public operation+  {+  public:+    restart_reactor(select_reactor* r)+      : operation(&restart_reactor::do_complete),+        reactor_(r)+    {+    }++    ASIO_DECL static void do_complete(void* owner, operation* base,+        const asio::error_code& ec, std::size_t bytes_transferred);++  private:+    select_reactor* reactor_;+  };++  friend class restart_reactor;++  // Operation used to join and restart the reactor thread.+  restart_reactor restart_reactor_; #endif // defined(ASIO_HAS_IOCP)    // Whether the service has been shut down.
link/modules/asio-standalone/asio/include/asio/detail/service_registry.hpp view
@@ -2,7 +2,7 @@ // detail/service_registry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/signal_blocker.hpp view
@@ -2,7 +2,7 @@ // detail/signal_blocker.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/signal_handler.hpp view
@@ -2,7 +2,7 @@ // detail/signal_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/signal_init.hpp view
@@ -2,7 +2,7 @@ // detail/signal_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/signal_op.hpp view
@@ -2,7 +2,7 @@ // detail/signal_op.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,12 +30,16 @@   // The error code to be passed to the completion handler.   asio::error_code ec_; +  // The operation key used for targeted cancellation.+  void* cancellation_key_;+   // The signal number to be passed to the completion handler.   int signal_number_;  protected:   signal_op(func_type func)     : operation(func),+      cancellation_key_(0),       signal_number_(0)   {   }
link/modules/asio-standalone/asio/include/asio/detail/signal_set_service.hpp view
@@ -2,7 +2,7 @@ // detail/signal_set_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,8 +19,11 @@  #include <cstddef> #include <signal.h>+#include "asio/associated_cancellation_slot.hpp"+#include "asio/cancellation_type.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp"+#include "asio/signal_set_base.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/memory.hpp" #include "asio/detail/op_queue.hpp"@@ -35,7 +38,11 @@ #endif // defined(ASIO_HAS_IOCP)  #if !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)-# include "asio/detail/reactor.hpp"+# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+#  include "asio/detail/io_uring_service.hpp"+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+#  include "asio/detail/reactor.hpp"+# endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS) && !defined(__CYGWIN__)  #include "asio/detail/push_options.hpp"@@ -134,8 +141,16 @@   ASIO_DECL void destroy(implementation_type& impl);    // Add a signal to a signal_set.+  asio::error_code add(implementation_type& impl,+      int signal_number, asio::error_code& ec)+  {+    return add(impl, signal_number, signal_set_base::flags::dont_care, ec);+  }++  // Add a signal to a signal_set with the specified flags.   ASIO_DECL asio::error_code add(implementation_type& impl,-      int signal_number, asio::error_code& ec);+      int signal_number, signal_set_base::flags_t f,+      asio::error_code& ec);    // Remove a signal to a signal_set.   ASIO_DECL asio::error_code remove(implementation_type& impl,@@ -149,17 +164,31 @@   ASIO_DECL asio::error_code cancel(implementation_type& impl,       asio::error_code& ec); +  // Cancel a specific operation associated with the signal set.+  ASIO_DECL void cancel_ops_by_key(implementation_type& impl,+      void* cancellation_key);+   // 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)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<signal_op_cancellation>(this, &impl);+    }+     ASIO_HANDLER_CREATION((scheduler_.context(),           *p.p, "signal_set", &impl, 0, "async_wait")); @@ -186,6 +215,32 @@   // Helper function to start a wait operation.   ASIO_DECL void start_wait_op(implementation_type& impl, signal_op* op); +  // Helper class used to implement per-operation cancellation+  class signal_op_cancellation+  {+  public:+    signal_op_cancellation(signal_set_service* s, implementation_type* i)+      : service_(s),+        implementation_(i)+    {+    }++    void operator()(cancellation_type_t type)+    {+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        service_->cancel_ops_by_key(*implementation_, this);+      }+    }++  private:+    signal_set_service* service_;+    implementation_type* implementation_;+  };+   // The scheduler used for dispatching handlers. #if defined(ASIO_HAS_IOCP)   typedef class win_iocp_io_context scheduler_impl;@@ -197,14 +252,22 @@ #if !defined(ASIO_WINDOWS) \   && !defined(ASIO_WINDOWS_RUNTIME) \   && !defined(__CYGWIN__)-  // The type used for registering for pipe reactor notifications.+  // The type used for processing pipe readiness notifications.   class pipe_read_op; +# if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  // The io_uring service used for waiting for pipe readiness.+  io_uring_service& io_uring_service_;++  // The per I/O object data used for the pipe.+  io_uring_service::per_io_object_data io_object_data_;+# else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)   // 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_HAS_IO_URING_AS_DEFAULT) #endif // !defined(ASIO_WINDOWS)        //   && !defined(ASIO_WINDOWS_RUNTIME)        //   && !defined(__CYGWIN__)
link/modules/asio-standalone/asio/include/asio/detail/socket_holder.hpp view
@@ -2,7 +2,7 @@ // detail/socket_holder.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/socket_ops.hpp view
@@ -2,7 +2,7 @@ // detail/socket_ops.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -63,29 +63,27 @@  #if !defined(ASIO_WINDOWS_RUNTIME) -ASIO_DECL socket_type accept(socket_type s, socket_addr_type* addr,+ASIO_DECL socket_type accept(socket_type s, void* 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);+ASIO_DECL socket_type sync_accept(socket_type s, state_type state,+    void* 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,+ASIO_DECL void complete_iocp_accept(socket_type s, void* output_buffer,+    DWORD address_length, void* 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,+    state_type state, void* 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,+ASIO_DECL int bind(socket_type s, const void* addr,     std::size_t addrlen, asio::error_code& ec);  ASIO_DECL int close(socket_type s, state_type& state,@@ -100,10 +98,10 @@ 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,+ASIO_DECL int connect(socket_type s, const void* addr,     std::size_t addrlen, asio::error_code& ec); -ASIO_DECL void sync_connect(socket_type s, const socket_addr_type* addr,+ASIO_DECL void sync_connect(socket_type s, const void* addr,     std::size_t addrlen, asio::error_code& ec);  #if defined(ASIO_HAS_IOCP)@@ -166,20 +164,20 @@  #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,+ASIO_DECL signed_size_type recvfrom(socket_type s,+    buf* bufs, size_t count, int flags, void* 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,+ASIO_DECL signed_size_type recvfrom1(socket_type s,+    void* data, size_t size, int flags, void* 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,+    buf* bufs, size_t count, int flags, void* 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,+    void* data, size_t size, int flags, void* addr,     std::size_t* addrlen, asio::error_code& ec);  #if defined(ASIO_HAS_IOCP)@@ -190,14 +188,12 @@  #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_DECL bool non_blocking_recvfrom(socket_type s, buf* bufs,+    size_t count, int flags, void* 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_DECL bool non_blocking_recvfrom1(socket_type s, void* data,+    size_t size, int flags, void* addr, std::size_t* addrlen,     asio::error_code& ec, size_t& bytes_transferred);  #endif // defined(ASIO_HAS_IOCP)@@ -255,32 +251,30 @@  #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,+ASIO_DECL signed_size_type sendto(socket_type s,+    const buf* bufs, size_t count, int flags, const void* 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,+ASIO_DECL signed_size_type sendto1(socket_type s,+    const void* data, size_t size, int flags, const void* 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,+    const buf* bufs, size_t count, int flags, const void* 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,+    const void* data, size_t size, int flags, const void* 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_DECL bool non_blocking_sendto(socket_type s, const buf* bufs,+    size_t count, int flags, const void* 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_DECL bool non_blocking_sendto1(socket_type s, const void* data,+    size_t size, int flags, const void* addr, std::size_t addrlen,     asio::error_code& ec, size_t& bytes_transferred);  #endif // !defined(ASIO_HAS_IOCP)@@ -296,10 +290,10 @@     int level, int optname, void* optval,     size_t* optlen, asio::error_code& ec); -ASIO_DECL int getpeername(socket_type s, socket_addr_type* addr,+ASIO_DECL int getpeername(socket_type s, void* addr,     std::size_t* addrlen, bool cached, asio::error_code& ec); -ASIO_DECL int getsockname(socket_type s, socket_addr_type* addr,+ASIO_DECL int getsockname(socket_type s, void* addr,     std::size_t* addrlen, asio::error_code& ec);  ASIO_DECL int ioctl(socket_type s, state_type& state,@@ -344,19 +338,17 @@  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,+ASIO_DECL asio::error_code getnameinfo(const void* 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,+ASIO_DECL asio::error_code sync_getnameinfo(const void* 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,+    const void* addr, std::size_t addrlen,     char* host, std::size_t hostlen, char* serv,     std::size_t servlen, int sock_type, asio::error_code& ec); 
link/modules/asio-standalone/asio/include/asio/detail/socket_option.hpp view
@@ -2,7 +2,7 @@ // detail/socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/socket_select_interrupter.hpp view
@@ -2,7 +2,7 @@ // detail/socket_select_interrupter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/socket_types.hpp view
@@ -2,7 +2,7 @@ // detail/socket_types.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -89,6 +89,7 @@ #  include <sys/filio.h> #  include <sys/sockio.h> # endif+# include <signal.h> #endif  #include "asio/detail/push_options.hpp"@@ -178,6 +179,9 @@ # define ASIO_OS_DEF_AI_V4MAPPED 0x800 # define ASIO_OS_DEF_AI_ALL 0x100 # define ASIO_OS_DEF_AI_ADDRCONFIG 0x400+# define ASIO_OS_DEF_SA_RESTART 0x1+# define ASIO_OS_DEF_SA_NOCLDSTOP 0x2+# define ASIO_OS_DEF_SA_NOCLDWAIT 0x4 #elif defined(ASIO_WINDOWS) || defined(__CYGWIN__) typedef SOCKET socket_type; const SOCKET invalid_socket = INVALID_SOCKET;@@ -206,6 +210,7 @@ typedef u_long u_long_type; typedef u_short u_short_type; typedef int signed_size_type;+struct sockaddr_un_type { u_short sun_family; char sun_path[108]; }; # 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@@ -284,6 +289,9 @@ # else const int max_iov_len = 16; # endif+# define ASIO_OS_DEF_SA_RESTART 0x1+# define ASIO_OS_DEF_SA_NOCLDSTOP 0x2+# define ASIO_OS_DEF_SA_NOCLDWAIT 0x4 #else typedef int socket_type; const int invalid_socket = -1;@@ -403,6 +411,9 @@ // POSIX platforms are not required to define IOV_MAX. const int max_iov_len = 16; # endif+# define ASIO_OS_DEF_SA_RESTART SA_RESTART+# define ASIO_OS_DEF_SA_NOCLDSTOP SA_NOCLDSTOP+# define ASIO_OS_DEF_SA_NOCLDWAIT SA_NOCLDWAIT #endif const int custom_socket_option_level = 0xA5100000; const int enable_connection_aborted_option = 1;
link/modules/asio-standalone/asio/include/asio/detail/solaris_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/solaris_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/source_location.hpp view
@@ -2,7 +2,7 @@ // detail/source_location.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_event.hpp view
@@ -2,7 +2,7 @@ // detail/std_event.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -75,7 +75,7 @@    // Unlock the mutex and signal one waiter who may destroy us.   template <typename Lock>-  void unlock_and_signal_one(Lock& lock)+  void unlock_and_signal_one_for_destruction(Lock& lock)   {     ASIO_ASSERT(lock.locked());     state_ |= 1;
link/modules/asio-standalone/asio/include/asio/detail/std_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/std_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_global.hpp view
@@ -2,7 +2,7 @@ // detail/std_global.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/std_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/std_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/std_thread.hpp view
@@ -2,7 +2,7 @@ // detail/std_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/strand_executor_service.hpp view
@@ -2,7 +2,7 @@ // detail/strand_executor_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -130,6 +130,13 @@   // 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);++  // Transfers waiting handlers to the ready queue. Returns true if one or more+  // handlers were transferred.+  ASIO_DECL static bool push_waiting_to_ready(implementation_type& impl);++  // Invokes all ready-to-run handlers.+  ASIO_DECL static void run_ready_handlers(implementation_type& impl);    // Helper function to request invocation of the given function.   template <typename Executor, typename Function, typename Allocator>
link/modules/asio-standalone/asio/include/asio/detail/strand_service.hpp view
@@ -2,7 +2,7 @@ // detail/strand_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -96,11 +96,10 @@       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 function to dispatch a handler.+  ASIO_DECL void do_dispatch(implementation_type& impl, operation* op); -  // Helper fiunction to post a handler.+  // Helper function to post a handler.   ASIO_DECL void do_post(implementation_type& impl,       operation* op, bool is_continuation); 
link/modules/asio-standalone/asio/include/asio/detail/string_view.hpp view
@@ -2,7 +2,7 @@ // detail/string_view.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/thread.hpp view
@@ -2,7 +2,7 @@ // detail/thread.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,8 @@  #if !defined(ASIO_HAS_THREADS) # include "asio/detail/null_thread.hpp"+#elif defined(ASIO_HAS_PTHREADS)+# include "asio/detail/posix_thread.hpp" #elif defined(ASIO_WINDOWS) # if defined(UNDER_CE) #  include "asio/detail/wince_thread.hpp"@@ -27,8 +29,6 @@ # 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@@ -40,6 +40,8 @@  #if !defined(ASIO_HAS_THREADS) typedef null_thread thread;+#elif defined(ASIO_HAS_PTHREADS)+typedef posix_thread thread; #elif defined(ASIO_WINDOWS) # if defined(UNDER_CE) typedef wince_thread thread;@@ -48,8 +50,6 @@ # 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
link/modules/asio-standalone/asio/include/asio/detail/thread_context.hpp view
@@ -2,7 +2,7 @@ // detail/thread_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,6 +30,11 @@ class thread_context { public:+  // Obtain a pointer to the top of the thread call stack. Returns null when+  // not running inside a thread context.+  ASIO_DECL static thread_info_base* top_of_thread_call_stack();++protected:   // 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; };@@ -38,5 +43,9 @@ } // namespace asio  #include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/thread_context.ipp"+#endif // defined(ASIO_HEADER_ONLY)  #endif // ASIO_DETAIL_THREAD_CONTEXT_HPP
link/modules/asio-standalone/asio/include/asio/detail/thread_group.hpp view
@@ -2,7 +2,7 @@ // detail/thread_group.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,8 @@ #include "asio/detail/scoped_ptr.hpp" #include "asio/detail/thread.hpp" +#include "asio/detail/push_options.hpp"+ namespace asio { namespace detail { @@ -91,5 +93,7 @@  } // namespace detail } // namespace asio++#include "asio/detail/pop_options.hpp"  #endif // ASIO_DETAIL_THREAD_GROUP_HPP
link/modules/asio-standalone/asio/include/asio/detail/thread_info_base.hpp view
@@ -2,7 +2,7 @@ // detail/thread_info_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include <climits> #include <cstddef>+#include "asio/detail/memory.hpp" #include "asio/detail/noncopyable.hpp"  #if defined(ASIO_HAS_STD_EXCEPTION_PTR) \@@ -32,25 +33,66 @@ namespace asio { namespace detail { +#ifndef ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE+# define ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE 2+#endif // ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE+ class thread_info_base   : private noncopyable { public:   struct default_tag   {-    enum { mem_index = 0 };+    enum+    {+      cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+      begin_mem_index = 0,+      end_mem_index = cache_size+    };   };    struct awaitable_frame_tag   {-    enum { mem_index = 1 };+    enum+    {+      cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+      begin_mem_index = default_tag::end_mem_index,+      end_mem_index = begin_mem_index + cache_size+    };   };    struct executor_function_tag   {-    enum { mem_index = 2 };+    enum+    {+      cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+      begin_mem_index = awaitable_frame_tag::end_mem_index,+      end_mem_index = begin_mem_index + cache_size+    };   }; +  struct cancellation_signal_tag+  {+    enum+    {+      cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+      begin_mem_index = executor_function_tag::end_mem_index,+      end_mem_index = begin_mem_index + cache_size+    };+  };++  struct parallel_group_tag+  {+    enum+    {+      cache_size = ASIO_RECYCLING_ALLOCATOR_CACHE_SIZE,+      begin_mem_index = cancellation_signal_tag::end_mem_index,+      end_mem_index = begin_mem_index + cache_size+    };+  };++  enum { max_mem_index = parallel_group_tag::end_mem_index };+   thread_info_base() #if defined(ASIO_HAS_STD_EXCEPTION_PTR) \   && !defined(ASIO_NO_EXCEPTIONS)@@ -59,24 +101,25 @@        // && !defined(ASIO_NO_EXCEPTIONS)   {     for (int i = 0; i < max_mem_index; ++i)+      reusable_memory_[i] = 0;+  }++  ~thread_info_base()+  {+    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;+        aligned_delete(reusable_memory_[i]);     }   } -  ~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)+  static void* allocate(thread_info_base* this_thread,+      std::size_t size, std::size_t align = ASIO_DEFAULT_ALIGN)   {-    return allocate(default_tag(), this_thread, size);+    return allocate(default_tag(), this_thread, size, align);   }    static void deallocate(thread_info_base* this_thread,@@ -87,26 +130,43 @@    template <typename Purpose>   static void* allocate(Purpose, thread_info_base* this_thread,-      std::size_t size)+      std::size_t size, std::size_t align = ASIO_DEFAULT_ALIGN)   {     std::size_t chunks = (size + chunk_size - 1) / chunk_size; -    if (this_thread && this_thread->reusable_memory_[Purpose::mem_index])+    if (this_thread)     {-      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)+      for (int mem_index = Purpose::begin_mem_index;+          mem_index < Purpose::end_mem_index; ++mem_index)       {-        mem[size] = mem[0];-        return pointer;+        if (this_thread->reusable_memory_[mem_index])+        {+          void* const pointer = this_thread->reusable_memory_[mem_index];+          unsigned char* const mem = static_cast<unsigned char*>(pointer);+          if (static_cast<std::size_t>(mem[0]) >= chunks+              && reinterpret_cast<std::size_t>(pointer) % align == 0)+          {+            this_thread->reusable_memory_[mem_index] = 0;+            mem[size] = mem[0];+            return pointer;+          }+        }       } -      ::operator delete(pointer);+      for (int mem_index = Purpose::begin_mem_index;+          mem_index < Purpose::end_mem_index; ++mem_index)+      {+        if (this_thread->reusable_memory_[mem_index])+        {+          void* const pointer = this_thread->reusable_memory_[mem_index];+          this_thread->reusable_memory_[mem_index] = 0;+          aligned_delete(pointer);+          break;+        }+      }     } -    void* const pointer = ::operator new(chunks * chunk_size + 1);+    void* const pointer = aligned_new(align, 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;@@ -118,16 +178,23 @@   {     if (size <= chunk_size * UCHAR_MAX)     {-      if (this_thread && this_thread->reusable_memory_[Purpose::mem_index] == 0)+      if (this_thread)       {-        unsigned char* const mem = static_cast<unsigned char*>(pointer);-        mem[0] = mem[size];-        this_thread->reusable_memory_[Purpose::mem_index] = pointer;-        return;+        for (int mem_index = Purpose::begin_mem_index;+            mem_index < Purpose::end_mem_index; ++mem_index)+        {+          if (this_thread->reusable_memory_[mem_index] == 0)+          {+            unsigned char* const mem = static_cast<unsigned char*>(pointer);+            mem[0] = mem[size];+            this_thread->reusable_memory_[mem_index] = pointer;+            return;+          }+        }       }     } -    ::operator delete(pointer);+    aligned_delete(pointer);   }    void capture_current_exception()@@ -145,6 +212,7 @@       pending_exception_ =         std::make_exception_ptr<multiple_exceptions>(             multiple_exceptions(pending_exception_));+      break;     default:       break;     }@@ -169,8 +237,11 @@   }  private:+#if defined(ASIO_HAS_IO_URING)+  enum { chunk_size = 8 };+#else // defined(ASIO_HAS_IO_URING)   enum { chunk_size = 4 };-  enum { max_mem_index = 3 };+#endif // defined(ASIO_HAS_IO_URING)   void* reusable_memory_[max_mem_index];  #if defined(ASIO_HAS_STD_EXCEPTION_PTR) \
link/modules/asio-standalone/asio/include/asio/detail/throw_error.hpp view
@@ -2,7 +2,7 @@ // detail/throw_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"+#include "asio/detail/throw_exception.hpp" #include "asio/error_code.hpp"  #include "asio/detail/push_options.hpp"@@ -23,22 +24,30 @@ 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+    ASIO_SOURCE_LOCATION_PARAM); -ASIO_DECL void do_throw_error(const asio::error_code& err,-    const char* location);+ASIO_DECL void do_throw_error(+    const asio::error_code& err,+    const char* location+    ASIO_SOURCE_LOCATION_PARAM); -inline void throw_error(const asio::error_code& err)+inline void throw_error(+    const asio::error_code& err+    ASIO_SOURCE_LOCATION_DEFAULTED_PARAM) {   if (err)-    do_throw_error(err);+    do_throw_error(err ASIO_SOURCE_LOCATION_ARG); } -inline void throw_error(const asio::error_code& err,-    const char* location)+inline void throw_error(+    const asio::error_code& err,+    const char* location+    ASIO_SOURCE_LOCATION_DEFAULTED_PARAM) {   if (err)-    do_throw_error(err, location);+    do_throw_error(err, location ASIO_SOURCE_LOCATION_ARG); }  } // namespace detail
link/modules/asio-standalone/asio/include/asio/detail/throw_exception.hpp view
@@ -2,7 +2,7 @@ // detail/throw_exception.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,14 +30,18 @@  // Declare the throw_exception function for all targets. template <typename Exception>-void throw_exception(const Exception& e);+void throw_exception(+    const Exception& e+    ASIO_SOURCE_LOCATION_DEFAULTED_PARAM);  // 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)+void throw_exception(+    const Exception& e+    ASIO_SOURCE_LOCATION_PARAM) {   throw e; }
link/modules/asio-standalone/asio/include/asio/detail/timer_queue.hpp view
@@ -2,7 +2,7 @@ // detail/timer_queue.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -150,7 +150,12 @@       while (!heap_.empty() && !Time_Traits::less_than(now, heap_[0].time_))       {         per_timer_data* timer = heap_[0].timer_;-        ops.push(timer->op_queue_);+        while (wait_op* op = timer->op_queue_.front())+        {+          timer->op_queue_.pop();+          op->ec_ = asio::error_code();+          ops.push(op);+        }         remove_timer(*timer);       }     }@@ -190,6 +195,30 @@         remove_timer(timer);     }     return num_cancelled;+  }++  // Cancel and dequeue a specific operation for the given timer.+  void cancel_timer_by_key(per_timer_data* timer,+      op_queue<operation>& ops, void* cancellation_key)+  {+    if (timer->prev_ != 0 || timer == timers_)+    {+      op_queue<wait_op> other_ops;+      while (wait_op* op = timer->op_queue_.front())+      {+        timer->op_queue_.pop();+        if (op->cancellation_key_ == cancellation_key)+        {+          op->ec_ = asio::error::operation_aborted;+          ops.push(op);+        }+        else+          other_ops.push(op);+      }+      timer->op_queue_.push(other_ops);+      if (timer->op_queue_.empty())+        remove_timer(*timer);+    }   }    // Move operations from one timer to another, empty timer.
link/modules/asio-standalone/asio/include/asio/detail/timer_queue_base.hpp view
@@ -2,7 +2,7 @@ // detail/timer_queue_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/timer_queue_ptime.hpp view
@@ -2,7 +2,7 @@ // detail/timer_queue_ptime.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -76,6 +76,10 @@   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)());++  // Cancel and dequeue operations for the given timer and key.+  ASIO_DECL void cancel_timer_by_key(per_timer_data* timer,+      op_queue<operation>& ops, void* cancellation_key);    // Move operations from one timer to another, empty timer.   ASIO_DECL void move_timer(per_timer_data& target,
link/modules/asio-standalone/asio/include/asio/detail/timer_queue_set.hpp view
@@ -2,7 +2,7 @@ // detail/timer_queue_set.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler.hpp view
@@ -2,7 +2,7 @@ // detail/timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -22,6 +22,8 @@ # include "asio/detail/winrt_timer_scheduler.hpp" #elif defined(ASIO_HAS_IOCP) # include "asio/detail/win_iocp_io_context.hpp"+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_service.hpp" #elif defined(ASIO_HAS_EPOLL) # include "asio/detail/epoll_reactor.hpp" #elif defined(ASIO_HAS_KQUEUE)
link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler_fwd.hpp view
@@ -2,7 +2,7 @@ // detail/timer_scheduler_fwd.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,6 +24,8 @@ typedef class winrt_timer_scheduler timer_scheduler; #elif defined(ASIO_HAS_IOCP) typedef class win_iocp_io_context timer_scheduler;+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+typedef class io_uring_service timer_scheduler; #elif defined(ASIO_HAS_EPOLL) typedef class epoll_reactor timer_scheduler; #elif defined(ASIO_HAS_KQUEUE)
link/modules/asio-standalone/asio/include/asio/detail/tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/type_traits.hpp view
@@ -2,7 +2,7 @@ // detail/type_traits.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -38,6 +38,7 @@ # 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_pointer.hpp> # include <boost/type_traits/is_same.hpp> # include <boost/type_traits/remove_cv.hpp> # include <boost/type_traits/remove_pointer.hpp>@@ -52,7 +53,12 @@ #if defined(ASIO_HAS_STD_TYPE_TRAITS) using std::add_const; using std::add_lvalue_reference;+#if defined(ASIO_MSVC) && (_MSC_VER < 1900) using std::aligned_storage;+#else // defined(ASIO_MSVC) && (_MSC_VER < 1900)+template <std::size_t N, std::size_t A>+struct aligned_storage { struct type { alignas(A) unsigned char data[N]; }; };+#endif // defined(ASIO_MSVC) && (_MSC_VER < 1900) using std::alignment_of; using std::conditional; using std::decay;@@ -72,6 +78,7 @@ using std::is_nothrow_copy_constructible; using std::is_nothrow_destructible; using std::is_object;+using std::is_pointer; using std::is_reference; using std::is_same; using std::is_scalar;@@ -120,6 +127,7 @@ template <typename T> struct is_nothrow_destructible : boost::has_nothrow_destructor<T> {}; using boost::is_object;+using boost::is_pointer; using boost::is_reference; using boost::is_same; using boost::is_scalar;@@ -142,6 +150,14 @@   conditional<Head::value, conjunction<Tail...>, Head>::type {};  #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++struct defaulted_constraint+{+  ASIO_CONSTEXPR defaulted_constraint() {}+};++template <bool Condition, typename Type = int>+struct constraint : enable_if<Condition, Type> {};  } // namespace asio 
+ link/modules/asio-standalone/asio/include/asio/detail/utility.hpp view
@@ -0,0 +1,83 @@+//+// detail/utility.hpp+// ~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_UTILITY_HPP+#define ASIO_DETAIL_UTILITY_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <utility>++namespace asio {+namespace detail {++#if defined(ASIO_HAS_STD_INDEX_SEQUENCE)++using std::index_sequence;+using std::index_sequence_for;+using std::make_index_sequence;++#elif defined(ASIO_HAS_VARIADIC_TEMPLATES)++template <std::size_t...>+struct index_sequence+{+};++template <typename T, typename U>+struct join_index_sequences;++template <std::size_t... I, std::size_t... J>+struct join_index_sequences<index_sequence<I...>, index_sequence<J...> >+{+  using type = index_sequence<I..., J...>;+};++template <std::size_t First, std::size_t Last>+struct index_pack :+  join_index_sequences<+    typename index_pack<First, First + (Last - First + 1) / 2 - 1>::type,+    typename index_pack<First + (Last - First + 1) / 2, Last>::type+  >+{+};++template <std::size_t N>+struct index_pack<N, N>+{+  using type = index_sequence<N>;+};++template <std::size_t Begin, std::size_t End>+struct index_range : index_pack<Begin, End - 1>+{+};++template <std::size_t N>+struct index_range<N, N>+{+  using type = index_sequence<>;+};++template <typename... T>+using index_sequence_for = typename index_range<0, sizeof...(T)>::type;++template <std::size_t N>+using make_index_sequence = typename index_range<0, N>::type;++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)++} // namespace detail+} // namespace asio++#endif // ASIO_DETAIL_UTILITY_HPP
link/modules/asio-standalone/asio/include/asio/detail/variadic_templates.hpp view
@@ -2,7 +2,7 @@ // detail/variadic_templates.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/wait_handler.hpp view
@@ -2,7 +2,7 @@ // detail/wait_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/wait_op.hpp view
@@ -2,7 +2,7 @@ // detail/wait_op.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -30,9 +30,13 @@   // The error code to be passed to the completion handler.   asio::error_code ec_; +  // The operation key used for targeted cancellation.+  void* cancellation_key_;+ protected:   wait_op(func_type func)-    : operation(func)+    : operation(func),+      cancellation_key_(0)   {   } };
link/modules/asio-standalone/asio/include/asio/detail/win_event.hpp view
@@ -2,7 +2,7 @@ // detail/win_event.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_fd_set_adapter.hpp view
@@ -2,7 +2,7 @@ // detail/win_fd_set_adapter.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_fenced_block.hpp view
@@ -2,7 +2,7 @@ // detail/win_fenced_block.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_global.hpp view
@@ -2,7 +2,7 @@ // detail/win_global.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/detail/win_iocp_file_service.hpp view
@@ -0,0 +1,287 @@+//+// detail/win_iocp_file_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_FILE_SERVICE_HPP+#define ASIO_DETAIL_WIN_IOCP_FILE_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_FILE)++#include <string>+#include "asio/detail/cstdint.hpp"+#include "asio/detail/win_iocp_handle_service.hpp"+#include "asio/error.hpp"+#include "asio/execution_context.hpp"+#include "asio/file_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Extend win_iocp_handle_service to provide file support.+class win_iocp_file_service :+  public execution_context_service_base<win_iocp_file_service>+{+public:+  // The native type of a file.+  typedef win_iocp_handle_service::native_handle_type native_handle_type;++  // The implementation type of the file.+  class implementation_type : win_iocp_handle_service::implementation_type+  {+  private:+    // Only this service will have access to the internal values.+    friend class win_iocp_file_service;++    uint64_t offset_;+    bool is_stream_;+  };++  // Constructor.+  ASIO_DECL win_iocp_file_service(execution_context& context);++  // Destroy all user-defined handler objects owned by the service.+  ASIO_DECL void shutdown();++  // Construct a new file implementation.+  void construct(implementation_type& impl)+  {+    handle_service_.construct(impl);+    impl.offset_ = 0;+    impl.is_stream_ = false;+  }++  // Move-construct a new file implementation.+  void move_construct(implementation_type& impl,+      implementation_type& other_impl)+  {+    handle_service_.move_construct(impl, other_impl);+    impl.offset_ = other_impl.offset_;+    impl.is_stream_ = other_impl.is_stream_;+    other_impl.offset_ = 0;+  }++  // Move-assign from another file implementation.+  void move_assign(implementation_type& impl,+      win_iocp_file_service& other_service,+      implementation_type& other_impl)+  {+    handle_service_.move_assign(impl,+        other_service.handle_service_, other_impl);+    impl.offset_ = other_impl.offset_;+    impl.is_stream_ = other_impl.is_stream_;+    other_impl.offset_ = 0;+  }++  // Destroy a file implementation.+  void destroy(implementation_type& impl)+  {+    handle_service_.destroy(impl);+  }++  // Set whether the implementation is stream-oriented.+  void set_is_stream(implementation_type& impl, bool is_stream)+  {+    impl.is_stream_ = is_stream;+  }++  // Open the file using the specified path name.+  ASIO_DECL asio::error_code open(implementation_type& impl,+      const char* path, file_base::flags open_flags,+      asio::error_code& ec);++  // Assign a native handle to a file implementation.+  asio::error_code assign(implementation_type& impl,+      const native_handle_type& native_handle,+      asio::error_code& ec)+  {+    return handle_service_.assign(impl, native_handle, ec);+  }++  // Determine whether the file is open.+  bool is_open(const implementation_type& impl) const+  {+    return handle_service_.is_open(impl);+  }++  // Destroy a file implementation.+  asio::error_code close(implementation_type& impl,+      asio::error_code& ec)+  {+    return handle_service_.close(impl, ec);+  }++  // Get the native file representation.+  native_handle_type native_handle(const implementation_type& impl) const+  {+    return handle_service_.native_handle(impl);+  }++  // Release ownership of a file.+  native_handle_type release(implementation_type& impl,+      asio::error_code& ec)+  {+    return handle_service_.release(impl, ec);+  }++  // Cancel all operations associated with the file.+  asio::error_code cancel(implementation_type& impl,+      asio::error_code& ec)+  {+    return handle_service_.cancel(impl, ec);+  }++  // Get the size of the file.+  ASIO_DECL uint64_t size(const implementation_type& impl,+      asio::error_code& ec) const;++  // Alter the size of the file.+  ASIO_DECL asio::error_code resize(implementation_type& impl,+      uint64_t n, asio::error_code& ec);++  // Synchronise the file to disk.+  ASIO_DECL asio::error_code sync_all(implementation_type& impl,+      asio::error_code& ec);++  // Synchronise the file data to disk.+  ASIO_DECL asio::error_code sync_data(implementation_type& impl,+      asio::error_code& ec);++  // Seek to a position in the file.+  ASIO_DECL uint64_t seek(implementation_type& impl, int64_t offset,+      file_base::seek_basis whence, 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)+  {+    uint64_t offset = impl.offset_;+    impl.offset_ += asio::buffer_size(buffers);+    return handle_service_.write_some_at(impl, offset, 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)+  {+    uint64_t offset = impl.offset_;+    impl.offset_ += asio::buffer_size(buffers);+    handle_service_.async_write_some_at(impl, offset, buffers, handler, io_ex);+  }++  // Write the given data at the specified location. 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)+  {+    return handle_service_.write_some_at(impl, offset, buffers, ec);+  }++  // Start an asynchronous write at the specified location. 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)+  {+    handle_service_.async_write_some_at(impl, offset, buffers, handler, io_ex);+  }++  // Read some data. Returns the number of bytes read.+  template <typename MutableBufferSequence>+  size_t read_some(implementation_type& impl,+      const MutableBufferSequence& buffers, asio::error_code& ec)+  {+    uint64_t offset = impl.offset_;+    impl.offset_ += asio::buffer_size(buffers);+    return handle_service_.read_some_at(impl, offset, buffers, ec);+  }++  // 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)+  {+    uint64_t offset = impl.offset_;+    impl.offset_ += asio::buffer_size(buffers);+    handle_service_.async_read_some_at(impl, offset, buffers, handler, io_ex);+  }++  // Read some data. Returns the number of bytes read.+  template <typename MutableBufferSequence>+  size_t read_some_at(implementation_type& impl, uint64_t offset,+      const MutableBufferSequence& buffers, asio::error_code& ec)+  {+    return handle_service_.read_some_at(impl, offset, buffers, ec);+  }++  // 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_at(implementation_type& impl,+      uint64_t offset, const MutableBufferSequence& buffers,+      Handler& handler, const IoExecutor& io_ex)+  {+    handle_service_.async_read_some_at(impl, offset, buffers, handler, io_ex);+  }++private:+  // The implementation used for initiating asynchronous operations.+  win_iocp_handle_service handle_service_;++  // Emulation of Windows IO_STATUS_BLOCK structure.+  struct io_status_block+  {+    union u+    {+      LONG Status;+      void* Pointer;+    };+    ULONG_PTR Information;+  };++  // Emulation of flag passed to NtFlushBuffersFileEx.+  enum { flush_flags_file_data_sync_only = 4 };++  // The type of a NtFlushBuffersFileEx function pointer.+  typedef LONG (NTAPI *nt_flush_buffers_file_ex_fn)(+      HANDLE, ULONG, void*, ULONG, io_status_block*);++  // The NTFlushBuffersFileEx function pointer.+  nt_flush_buffers_file_ex_fn nt_flush_buffers_file_ex_;+};++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/detail/impl/win_iocp_file_service.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // defined(ASIO_HAS_IOCP) && defined(ASIO_HAS_FILE)++#endif // ASIO_DETAIL_WIN_IOCP_FILE_SERVICE_HPP
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_read_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_handle_read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -57,6 +57,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_handle_read_op* o(static_cast<win_iocp_handle_read_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -79,6 +80,8 @@     // Map non-portable errors to their portable counterparts.     if (ec.value() == ERROR_HANDLE_EOF)       ec = asio::error::eof;++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_service.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_handle_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -20,6 +20,7 @@  #if defined(ASIO_HAS_IOCP) +#include "asio/associated_cancellation_slot.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/detail/buffer_sequence_adapter.hpp"@@ -109,6 +110,10 @@   ASIO_DECL asio::error_code close(implementation_type& impl,       asio::error_code& ec); +  // Release ownership of a handle.+  ASIO_DECL native_handle_type release(implementation_type& impl,+      asio::error_code& ec);+   // Get the native handle representation.   native_handle_type native_handle(const implementation_type& impl) const   {@@ -147,19 +152,26 @@       const ConstBufferSequence& buffers,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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);+    operation* o = 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")); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+      o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);+     start_write_op(impl, 0,         buffer_sequence_adapter<asio::const_buffer,-          ConstBufferSequence>::first(buffers), p.p);+          ConstBufferSequence>::first(buffers), o);     p.v = p.p = 0;   } @@ -170,19 +182,26 @@       uint64_t offset, const ConstBufferSequence& buffers,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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);+    operation* o = 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")); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+      o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);+     start_write_op(impl, offset,         buffer_sequence_adapter<asio::const_buffer,-          ConstBufferSequence>::first(buffers), p.p);+          ConstBufferSequence>::first(buffers), o);     p.v = p.p = 0;   } @@ -214,19 +233,26 @@       const MutableBufferSequence& buffers,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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);+    operation* o = 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")); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+      o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);+     start_read_op(impl, 0,         buffer_sequence_adapter<asio::mutable_buffer,-          MutableBufferSequence>::first(buffers), p.p);+          MutableBufferSequence>::first(buffers), o);     p.v = p.p = 0;   } @@ -239,19 +265,26 @@       uint64_t offset, const MutableBufferSequence& buffers,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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);+    operation* o = 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")); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+      o = &slot.template emplace<iocp_op_cancellation>(impl.handle_, o);+     start_read_op(impl, offset,         buffer_sequence_adapter<asio::mutable_buffer,-          MutableBufferSequence>::first(buffers), p.p);+          MutableBufferSequence>::first(buffers), o);     p.v = p.p = 0;   } @@ -310,9 +343,72 @@   // destroyed.   ASIO_DECL void close_for_destruction(implementation_type& impl); +  // 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);++  // Helper class used to implement per operation cancellation.+  class iocp_op_cancellation : public operation+  {+  public:+    iocp_op_cancellation(HANDLE h, operation* target)+      : operation(&iocp_op_cancellation::do_complete),+        handle_(h),+        target_(target)+    {+    }++    static void do_complete(void* owner, operation* base,+        const asio::error_code& result_ec,+        std::size_t bytes_transferred)+    {+      iocp_op_cancellation* o = static_cast<iocp_op_cancellation*>(base);+      o->target_->complete(owner, result_ec, bytes_transferred);+    }++    void operator()(cancellation_type_t type)+    {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        ::CancelIoEx(handle_, this);+      }+#else // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+      (void)type;+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+    }++  private:+    HANDLE handle_;+    operation* target_;+  };+   // The IOCP service used for running asynchronous operations and dispatching   // handlers.   win_iocp_io_context& iocp_service_;++  // Pointer to NtSetInformationFile implementation.+  void* nt_set_info_;    // Mutex to protect access to the linked list of implementations.   mutex mutex_;
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_write_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_handle_write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -51,9 +51,12 @@   }    static void do_complete(void* owner, operation* base,-      const asio::error_code& ec, std::size_t bytes_transferred)+      const asio::error_code& result_ec, std::size_t bytes_transferred)   {+    asio::error_code ec(result_ec);+     // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_handle_write_op* o(static_cast<win_iocp_handle_write_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -72,6 +75,8 @@           ConstBufferSequence>::validate(o->buffers_);     } #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_io_context.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_io_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -109,10 +109,7 @@   }    // Return whether a handler can be dispatched immediately.-  bool can_dispatch()-  {-    return thread_call_stack::contains(this) != 0;-  }+  ASIO_DECL bool can_dispatch();    /// Capture the current exception so it can be rethrown from a run function.   ASIO_DECL void capture_current_exception();@@ -200,6 +197,12 @@       typename timer_queue<Time_Traits>::per_timer_data& timer,       std::size_t max_cancelled = (std::numeric_limits<std::size_t>::max)()); +  // Cancel the timer operations associated with the given key.+  template <typename Time_Traits>+  void cancel_timer_by_key(timer_queue<Time_Traits>& queue,+      typename timer_queue<Time_Traits>::per_timer_data* timer,+      void* cancellation_key);+   // Move the timer operations associated with the given timer.   template <typename Time_Traits>   void move_timer(timer_queue<Time_Traits>& queue,@@ -269,11 +272,13 @@    enum   {+#if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)     // 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,+#endif // !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600)      // Maximum waitable timer timeout, in milliseconds.     max_timeout_msec = 5 * 60 * 1000,
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_null_buffers_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_null_buffers_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -63,6 +63,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_null_buffers_op* o(static_cast<win_iocp_null_buffers_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -89,6 +90,8 @@     {       ec = asio::error::connection_refused;     }++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_operation.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,6 +51,16 @@     func_(0, this, asio::error_code(), 0);   } +  void reset()+  {+    Internal = 0;+    InternalHigh = 0;+    Offset = 0;+    OffsetHigh = 0;+    hEvent = 0;+    ready_ = 0;+  }+ protected:   typedef void (*func_type)(       void*, win_iocp_operation*,@@ -66,16 +76,6 @@   // Prevents deletion through this type.   ~win_iocp_operation()   {-  }--  void reset()-  {-    Internal = 0;-    InternalHigh = 0;-    Offset = 0;-    OffsetHigh = 0;-    hEvent = 0;-    ready_ = 0;   }  private:
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_overlapped_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -47,9 +47,12 @@   }    static void do_complete(void* owner, operation* base,-      const asio::error_code& ec, std::size_t bytes_transferred)+      const asio::error_code& result_ec, std::size_t bytes_transferred)   {+    asio::error_code ec(result_ec);+     // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_overlapped_op* o(static_cast<win_iocp_overlapped_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -59,6 +62,8 @@     handler_work<Handler, IoExecutor> w(         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_));++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_overlapped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_serial_port_service.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_serial_port_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -137,6 +137,7 @@       asio::error_code& ec)   {     ec = asio::error::operation_not_supported;+    ASIO_ERROR_LOCATION(ec);     return ec;   } 
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_accept_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_accept_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -53,6 +53,8 @@       protocol_(protocol),       peer_endpoint_(peer_endpoint),       enable_connection_aborted_(enable_connection_aborted),+      proxy_op_(0),+      cancel_requested_(0),       handler_(ASIO_MOVE_CAST(Handler)(handler)),       work_(handler_, io_ex)   {@@ -73,6 +75,12 @@     return sizeof(sockaddr_storage_type) + 16;   } +  void enable_cancellation(long* cancel_requested, operation* proxy_op)+  {+    cancel_requested_ = cancel_requested;+    proxy_op_ = proxy_op;+  }+   static void do_complete(void* owner, operation* base,       const asio::error_code& result_ec,       std::size_t /*bytes_transferred*/)@@ -80,6 +88,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_socket_accept_op* o(static_cast<win_iocp_socket_accept_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -98,10 +107,13 @@           && !o->enable_connection_aborted_)       {         o->reset();+        if (o->proxy_op_)+          o->proxy_op_->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);+            o->output_buffer(), o->address_length(),+            o->cancel_requested_, o->proxy_op_ ? o->proxy_op_ : o);         p.v = p.p = 0;         return;       }@@ -129,6 +141,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(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@@ -159,6 +173,8 @@   typename Protocol::endpoint* peer_endpoint_;   unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];   bool enable_connection_aborted_;+  operation* proxy_op_;+  long* cancel_requested_;   Handler handler_;   handler_work<Handler, IoExecutor> work_; };@@ -184,6 +200,8 @@       protocol_(protocol),       peer_endpoint_(peer_endpoint),       enable_connection_aborted_(enable_connection_aborted),+      cancel_requested_(0),+      proxy_op_(0),       handler_(ASIO_MOVE_CAST(Handler)(handler)),       work_(handler_, io_ex)   {@@ -204,6 +222,12 @@     return sizeof(sockaddr_storage_type) + 16;   } +  void enable_cancellation(long* cancel_requested, operation* proxy_op)+  {+    cancel_requested_ = cancel_requested;+    proxy_op_ = proxy_op;+  }+   static void do_complete(void* owner, operation* base,       const asio::error_code& result_ec,       std::size_t /*bytes_transferred*/)@@ -211,6 +235,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     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 };@@ -230,10 +255,13 @@           && !o->enable_connection_aborted_)       {         o->reset();+        if (o->proxy_op_)+          o->proxy_op_->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);+            o->output_buffer(), o->address_length(),+            o->cancel_requested_, o->proxy_op_ ? o->proxy_op_ : o);         p.v = p.p = 0;         return;       }@@ -261,6 +289,8 @@         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_)); +    ASIO_ERROR_LOCATION(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@@ -296,6 +326,8 @@   typename Protocol::endpoint* peer_endpoint_;   unsigned char output_buffer_[(sizeof(sockaddr_storage_type) + 16) * 2];   bool enable_connection_aborted_;+  long* cancel_requested_;+  operation* proxy_op_;   Handler handler_;   handler_work<Handler, IoExecutor> work_; };
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_connect_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -47,6 +47,7 @@    static status do_perform(reactor_op* base)   {+    ASIO_ASSUME(base != 0);     win_iocp_socket_connect_op_base* o(         static_cast<win_iocp_socket_connect_op_base*>(base)); @@ -80,6 +81,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_socket_connect_op* o(         static_cast<win_iocp_socket_connect_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -98,6 +100,8 @@     handler_work<Handler, IoExecutor> w(         ASIO_MOVE_CAST2(handler_work<Handler, IoExecutor>)(           o->work_));++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recv_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -61,6 +61,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_socket_recv_op* o(static_cast<win_iocp_socket_recv_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -84,6 +85,8 @@         buffer_sequence_adapter<asio::mutable_buffer,           MutableBufferSequence>::all_empty(o->buffers_),         ec, bytes_transferred);++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_recvfrom_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -68,6 +68,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_socket_recvfrom_op* o(         static_cast<win_iocp_socket_recvfrom_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -92,6 +93,8 @@      // Record the size of the endpoint returned by the operation.     o->endpoint_.resize(o->endpoint_size_);++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_recvmsg_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -63,6 +63,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_socket_recvmsg_op* o(         static_cast<win_iocp_socket_recvmsg_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o };@@ -85,6 +86,8 @@      socket_ops::complete_iocp_recvmsg(o->cancel_token_, ec);     o->out_flags_ = 0;++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_send_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -59,6 +59,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_socket_send_op* o(static_cast<win_iocp_socket_send_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -79,6 +80,8 @@ #endif // defined(ASIO_ENABLE_BUFFER_DEBUGGING)      socket_ops::complete_iocp_send(o->cancel_token_, ec);++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -205,6 +205,8 @@       impl.have_remote_endpoint_ = false;       impl.remote_endpoint_ = endpoint_type();     }++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -219,6 +221,8 @@       impl.have_remote_endpoint_ = native_socket.have_remote_endpoint();       impl.remote_endpoint_ = native_socket.remote_endpoint();     }++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -235,6 +239,8 @@       const endpoint_type& endpoint, asio::error_code& ec)   {     socket_ops::bind(impl.socket_, endpoint.data(), endpoint.size(), ec);++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -246,6 +252,8 @@     socket_ops::setsockopt(impl.socket_, impl.state_,         option.level(impl.protocol_), option.name(impl.protocol_),         option.data(impl.protocol_), option.size(impl.protocol_), ec);++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -260,6 +268,8 @@         option.data(impl.protocol_), &size, ec);     if (!ec)       option.resize(impl.protocol_, size);++    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -270,7 +280,10 @@     endpoint_type endpoint;     std::size_t addr_len = endpoint.capacity();     if (socket_ops::getsockname(impl.socket_, endpoint.data(), &addr_len, ec))+    {+      ASIO_ERROR_LOCATION(ec);       return endpoint_type();+    }     endpoint.resize(addr_len);     return endpoint;   }@@ -283,7 +296,10 @@     std::size_t addr_len = endpoint.capacity();     if (socket_ops::getpeername(impl.socket_, endpoint.data(),           &addr_len, impl.have_remote_endpoint_, ec))+    {+      ASIO_ERROR_LOCATION(ec);       return endpoint_type();+    }     endpoint.resize(addr_len);     return endpoint;   }@@ -306,9 +322,12 @@     buffer_sequence_adapter<asio::const_buffer,         ConstBufferSequence> bufs(buffers); -    return socket_ops::sync_sendto(impl.socket_, impl.state_,-        bufs.buffers(), bufs.count(), flags,+    size_t n = socket_ops::sync_sendto(impl.socket_,+        impl.state_, bufs.buffers(), bufs.count(), flags,         destination.data(), destination.size(), ec);++    ASIO_ERROR_LOCATION(ec);+    return n;   }    // Wait until data can be sent without blocking.@@ -318,7 +337,7 @@   {     // Wait for socket to become ready.     socket_ops::poll_write(impl.socket_, impl.state_, -1, ec);-+    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -330,12 +349,16 @@       socket_base::message_flags flags, Handler& handler,       const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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);+    operation* o = 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"));@@ -343,9 +366,13 @@     buffer_sequence_adapter<asio::const_buffer,         ConstBufferSequence> bufs(buffers); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+      o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);+     start_send_to_op(impl, bufs.buffers(), bufs.count(),         destination.data(), static_cast<int>(destination.size()),-        flags, p.p);+        flags, o);     p.v = p.p = 0;   } @@ -359,12 +386,12 @@     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);+    reactor_op* o = 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);+    start_reactor_op(impl, select_reactor::write_op, o);     p.v = p.p = 0;   } @@ -380,14 +407,15 @@         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);+    std::size_t n = 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;+    ASIO_ERROR_LOCATION(ec);+    return n;   }    // Wait until data can be received without blocking.@@ -401,6 +429,7 @@     // Reset endpoint since it can be given no sensible value at this time.     sender_endpoint = endpoint_type(); +    ASIO_ERROR_LOCATION(ec);     return 0;   } @@ -414,13 +443,16 @@       socket_base::message_flags flags, Handler& handler,       const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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);+    operation* o = 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"));@@ -428,8 +460,12 @@     buffer_sequence_adapter<asio::mutable_buffer,         MutableBufferSequence> bufs(buffers); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+      o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);+     start_receive_from_op(impl, bufs.buffers(), bufs.count(),-        sender_endp.data(), flags, &p.p->endpoint_size(), p.p);+        sender_endp.data(), flags, &p.p->endpoint_size(), o);     p.v = p.p = 0;   } @@ -439,6 +475,9 @@       endpoint_type& sender_endpoint, socket_base::message_flags flags,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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),@@ -451,8 +490,24 @@     // 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);+    // Optionally register for per-operation cancellation.+    operation* iocp_op = p.p;+    if (slot.is_connected())+    {+      p.p->cancellation_key_ = iocp_op =+        &slot.template emplace<reactor_op_cancellation>(+            impl.socket_, iocp_op);+    }++    int op_type = start_null_buffers_receive_op(impl, flags, p.p, iocp_op);     p.v = p.p = 0;++    // Update cancellation method if the reactor was used.+    if (slot.is_connected() && op_type != -1)+    {+      static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+          &get_reactor(), &impl.reactor_data_, op_type);+    }   }    // Accept a new connection.@@ -464,6 +519,7 @@     if (peer.is_open())     {       ec = asio::error::already_open;+      ASIO_ERROR_LOCATION(ec);       return ec;     } @@ -482,6 +538,7 @@         new_socket.release();     } +    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -491,6 +548,9 @@   void async_accept(implementation_type& impl, Socket& peer,       endpoint_type* peer_endpoint, Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // Allocate and construct an operation to wrap the handler.     typedef win_iocp_socket_accept_op<Socket,         protocol_type, Handler, IoExecutor> op;@@ -498,16 +558,25 @@       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_,+    operation* o = 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")); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      accept_op_cancellation* c =+        &slot.template emplace<accept_op_cancellation>(impl.socket_, o);+      p.p->enable_cancellation(c->get_cancel_requested(), c);+      o = c;+    }+     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.p->address_length(), o);     p.v = p.p = 0;   } @@ -519,6 +588,9 @@       const PeerIoExecutor& peer_io_ex, endpoint_type* peer_endpoint,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // Allocate and construct an operation to wrap the handler.     typedef win_iocp_socket_move_accept_op<         protocol_type, PeerIoExecutor, Handler, IoExecutor> op;@@ -526,17 +598,26 @@       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_,+    operation* o = 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")); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      accept_op_cancellation* c =+        &slot.template emplace<accept_op_cancellation>(impl.socket_, o);+      p.p->enable_cancellation(c->get_cancel_requested(), c);+      o = c;+    }+     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.p->address_length(), o);     p.v = p.p = 0;   } #endif // defined(ASIO_HAS_MOVE)@@ -547,6 +628,7 @@   {     socket_ops::sync_connect(impl.socket_,         peer_endpoint.data(), peer_endpoint.size(), ec);+    ASIO_ERROR_LOCATION(ec);     return ec;   } @@ -556,6 +638,9 @@       const endpoint_type& peer_endpoint, Handler& handler,       const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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),@@ -565,9 +650,26 @@     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);+    // Optionally register for per-operation cancellation.+    operation* iocp_op = p.p;+    if (slot.is_connected())+    {+      p.p->cancellation_key_ = iocp_op =+        &slot.template emplace<reactor_op_cancellation>(+            impl.socket_, iocp_op);+    }++    int op_type = start_connect_op(impl, impl.protocol_.family(),+        impl.protocol_.type(), peer_endpoint.data(),+        static_cast<int>(peer_endpoint.size()), p.p, iocp_op);     p.v = p.p = 0;++    // Update cancellation method if the reactor was used.+    if (slot.is_connected() && op_type != -1)+    {+      static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+          &get_reactor(), &impl.reactor_data_, op_type);+    }   } }; 
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service_base.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_socket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@  #if defined(ASIO_HAS_IOCP) +#include "asio/associated_cancellation_slot.hpp" #include "asio/error.hpp" #include "asio/execution_context.hpp" #include "asio/socket_base.hpp"@@ -213,6 +214,9 @@   void async_wait(base_implementation_type& impl,       socket_base::wait_type w, Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     bool is_continuation =       asio_handler_cont_helpers::is_continuation(handler); @@ -225,15 +229,27 @@     ASIO_HANDLER_CREATION((context_, *p.p, "socket",           &impl, impl.socket_, "async_wait")); +    // Optionally register for per-operation cancellation.+    operation* iocp_op = p.p;+    if (slot.is_connected())+    {+      p.p->cancellation_key_ = iocp_op =+        &slot.template emplace<reactor_op_cancellation>(+            impl.socket_, iocp_op);+    }++    int op_type = -1;     switch (w)     {       case socket_base::wait_read:-        start_null_buffers_receive_op(impl, 0, p.p);+        op_type = start_null_buffers_receive_op(impl, 0, p.p, iocp_op);         break;       case socket_base::wait_write:+        op_type = select_reactor::write_op;         start_reactor_op(impl, select_reactor::write_op, p.p);         break;       case socket_base::wait_error:+        op_type = select_reactor::read_op;         start_reactor_op(impl, select_reactor::except_op, p.p);         break;       default:@@ -243,6 +259,13 @@     }      p.v = p.p = 0;++    // Update cancellation method if the reactor was used.+    if (slot.is_connected() && op_type != -1)+    {+      static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+          &get_reactor(), &impl.reactor_data_, op_type);+    }   }    // Send the given data to the peer. Returns the number of bytes sent.@@ -275,12 +298,16 @@       const ConstBufferSequence& buffers, socket_base::message_flags flags,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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);+    operation* o = 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"));@@ -288,9 +315,13 @@     buffer_sequence_adapter<asio::const_buffer,         ConstBufferSequence> bufs(buffers); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+      o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);+     start_send_op(impl, bufs.buffers(), bufs.count(), flags,         (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),-        p.p);+        o);     p.v = p.p = 0;   } @@ -343,13 +374,16 @@       const MutableBufferSequence& buffers, socket_base::message_flags flags,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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);+    operation* o = 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"));@@ -357,9 +391,13 @@     buffer_sequence_adapter<asio::mutable_buffer,         MutableBufferSequence> bufs(buffers); +    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+      o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);+     start_receive_op(impl, bufs.buffers(), bufs.count(), flags,         (impl.state_ & socket_ops::stream_oriented) != 0 && bufs.all_empty(),-        p.p);+        o);     p.v = p.p = 0;   } @@ -369,6 +407,9 @@       const null_buffers&, socket_base::message_flags flags,       Handler& handler, const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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),@@ -378,8 +419,24 @@     ASIO_HANDLER_CREATION((context_, *p.p, "socket",           &impl, impl.socket_, "async_receive(null_buffers)")); -    start_null_buffers_receive_op(impl, flags, p.p);+    // Optionally register for per-operation cancellation.+    operation* iocp_op = p.p;+    if (slot.is_connected())+    {+      p.p->cancellation_key_ = iocp_op =+        &slot.template emplace<reactor_op_cancellation>(+            impl.socket_, iocp_op);+    }++    int op_type = start_null_buffers_receive_op(impl, flags, p.p, iocp_op);     p.v = p.p = 0;++    // Update cancellation method if the reactor was used.+    if (slot.is_connected() && op_type != -1)+    {+      static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+          &get_reactor(), &impl.reactor_data_, op_type);+    }   }    // Receive some data with associated flags. Returns the number of bytes@@ -421,12 +478,15 @@       socket_base::message_flags& out_flags, Handler& handler,       const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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_,+    operation* o = p.p = new (p.v) op(impl.cancel_token_,         buffers, out_flags, handler, io_ex);      ASIO_HANDLER_CREATION((context_, *p.p, "socket",@@ -435,7 +495,11 @@     buffer_sequence_adapter<asio::mutable_buffer,         MutableBufferSequence> bufs(buffers); -    start_receive_op(impl, bufs.buffers(), bufs.count(), in_flags, false, p.p);+    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+      o = &slot.template emplace<iocp_op_cancellation>(impl.socket_, o);++    start_receive_op(impl, bufs.buffers(), bufs.count(), in_flags, false, o);     p.v = p.p = 0;   } @@ -446,6 +510,9 @@       socket_base::message_flags& out_flags, Handler& handler,       const IoExecutor& io_ex)   {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);+     // 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),@@ -458,14 +525,31 @@     // 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);+    // Optionally register for per-operation cancellation.+    operation* iocp_op = p.p;+    if (slot.is_connected())+    {+      p.p->cancellation_key_ = iocp_op =+        &slot.template emplace<reactor_op_cancellation>(+            impl.socket_, iocp_op);+    }++    int op_type = start_null_buffers_receive_op(impl, in_flags, p.p, iocp_op);     p.v = p.p = 0;++    // Update cancellation method if the reactor was used.+    if (slot.is_connected() && op_type != -1)+    {+      static_cast<reactor_op_cancellation*>(iocp_op)->use_reactor(+          &get_reactor(), &impl.reactor_data_, op_type);+    }   }    // 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);+      socket_holder& new_socket, int family, int type,+      int protocol, void* output_buffer, DWORD address_length,+      long* cancel_requested, operation* op);  protected:   // Open a new socket implementation.@@ -485,9 +569,8 @@    // 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);+      WSABUF* buffers, std::size_t buffer_count, const void* 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,@@ -495,13 +578,13 @@       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);+  ASIO_DECL int start_null_buffers_receive_op(+      base_implementation_type& impl, socket_base::message_flags flags,+      reactor_op* op, operation* iocp_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,+      WSABUF* buffers, std::size_t buffer_count, void* addr,       socket_base::message_flags flags, int* addrlen, operation* op);    // Helper function to start an asynchronous accept operation.@@ -514,9 +597,9 @@       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);+  ASIO_DECL int start_connect_op(base_implementation_type& impl,+      int family, int type, const void* remote_addr, std::size_t remote_addrlen,+      win_iocp_socket_connect_op_base* op, operation* iocp_op);    // Helper function to close a socket when the associated object is being   // destroyed.@@ -561,6 +644,153 @@   // - 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);++  // Helper class used to implement per operation cancellation.+  class iocp_op_cancellation : public operation+  {+  public:+    iocp_op_cancellation(SOCKET s, operation* target)+      : operation(&iocp_op_cancellation::do_complete),+        socket_(s),+        target_(target)+    {+    }++    static void do_complete(void* owner, operation* base,+        const asio::error_code& result_ec,+        std::size_t bytes_transferred)+    {+      iocp_op_cancellation* o = static_cast<iocp_op_cancellation*>(base);+      o->target_->complete(owner, result_ec, bytes_transferred);+    }++    void operator()(cancellation_type_t type)+    {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        HANDLE sock_as_handle = reinterpret_cast<HANDLE>(socket_);+        ::CancelIoEx(sock_as_handle, this);+      }+#else // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+      (void)type;+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+    }++  private:+    SOCKET socket_;+    operation* target_;+  };++  // Helper class used to implement per operation cancellation.+  class accept_op_cancellation : public operation+  {+  public:+    accept_op_cancellation(SOCKET s, operation* target)+      : operation(&iocp_op_cancellation::do_complete),+        socket_(s),+        target_(target),+        cancel_requested_(0)+    {+    }++    static void do_complete(void* owner, operation* base,+        const asio::error_code& result_ec,+        std::size_t bytes_transferred)+    {+      accept_op_cancellation* o = static_cast<accept_op_cancellation*>(base);+      o->target_->complete(owner, result_ec, bytes_transferred);+    }++    long* get_cancel_requested()+    {+      return &cancel_requested_;+    }++    void operator()(cancellation_type_t type)+    {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        HANDLE sock_as_handle = reinterpret_cast<HANDLE>(socket_);+        ::CancelIoEx(sock_as_handle, this);+      }+#else // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+      (void)type;+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+    }++  private:+    SOCKET socket_;+    operation* target_;+    long cancel_requested_;+  };++  // Helper class used to implement per operation cancellation.+  class reactor_op_cancellation : public operation+  {+  public:+    reactor_op_cancellation(SOCKET s, operation* base)+      : operation(&reactor_op_cancellation::do_complete),+        socket_(s),+        target_(base),+        reactor_(0),+        reactor_data_(0),+        op_type_(-1)+    {+    }++    void use_reactor(select_reactor* r,+        select_reactor::per_descriptor_data* p, int o)+    {+      reactor_ = r;+      reactor_data_ = p;+      op_type_ = o;+    }++    static void do_complete(void* owner, operation* base,+        const asio::error_code& result_ec,+        std::size_t bytes_transferred)+    {+      reactor_op_cancellation* o = static_cast<reactor_op_cancellation*>(base);+      o->target_->complete(owner, result_ec, bytes_transferred);+    }++    void operator()(cancellation_type_t type)+    {+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        if (reactor_)+        {+          reactor_->cancel_ops_by_key(socket_,+              *reactor_data_, op_type_, this);+        }+        else+        {+#if defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+          HANDLE sock_as_handle = reinterpret_cast<HANDLE>(socket_);+          ::CancelIoEx(sock_as_handle, this);+#endif // defined(_WIN32_WINNT) && (_WIN32_WINNT >= 0x0600)+        }+      }+    }++  private:+    SOCKET socket_;+    operation* target_;+    select_reactor* reactor_;+    select_reactor::per_descriptor_data* reactor_data_;+    int op_type_;+  };    // The execution context used to obtain the reactor, if required.   execution_context& context_;
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_thread_info.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_thread_info.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_iocp_wait_op.hpp view
@@ -2,7 +2,7 @@ // detail/win_iocp_wait_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -64,6 +64,7 @@     asio::error_code ec(result_ec);      // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     win_iocp_wait_op* o(static_cast<win_iocp_wait_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; @@ -90,6 +91,8 @@     {       ec = asio::error::connection_refused;     }++    ASIO_ERROR_LOCATION(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
link/modules/asio-standalone/asio/include/asio/detail/win_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/win_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_object_handle_service.hpp view
@@ -2,7 +2,7 @@ // detail/win_object_handle_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/detail/win_static_mutex.hpp view
@@ -2,7 +2,7 @@ // detail/win_static_mutex.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_thread.hpp view
@@ -2,7 +2,7 @@ // detail/win_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/win_tss_ptr.hpp view
@@ -2,7 +2,7 @@ // detail/win_tss_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winapp_thread.hpp view
@@ -2,7 +2,7 @@ // detail/winapp_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/wince_thread.hpp view
@@ -2,7 +2,7 @@ // detail/wince_thread.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_async_manager.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_async_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_async_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_async_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_resolve_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_resolve_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -63,6 +63,7 @@       const asio::error_code&, std::size_t)   {     // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     winrt_resolve_op* o(static_cast<winrt_resolve_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; 
link/modules/asio-standalone/asio/include/asio/detail/winrt_resolver_service.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_resolver_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_connect_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_socket_connect_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -52,6 +52,7 @@       const asio::error_code&, std::size_t)   {     // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     winrt_socket_connect_op* o(static_cast<winrt_socket_connect_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; 
link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_recv_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_socket_recv_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,6 +55,7 @@       const asio::error_code&, std::size_t)   {     // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     winrt_socket_recv_op* o(static_cast<winrt_socket_recv_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; 
link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_send_op.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_socket_send_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -54,6 +54,7 @@       const asio::error_code&, std::size_t)   {     // Take ownership of the operation object.+    ASIO_ASSUME(base != 0);     winrt_socket_send_op* o(static_cast<winrt_socket_send_op*>(base));     ptr p = { asio::detail::addressof(o->handler_), o, o }; 
link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_ssocket_service.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service_base.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_ssocket_service_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_timer_scheduler.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_timer_scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winrt_utils.hpp view
@@ -2,7 +2,7 @@ // detail/winrt_utils.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/winsock_init.hpp view
@@ -2,7 +2,7 @@ // detail/winsock_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/detail/work_dispatcher.hpp view
@@ -2,7 +2,7 @@ // detail/work_dispatcher.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"+#include "asio/detail/bind_handler.hpp" #include "asio/detail/type_traits.hpp" #include "asio/associated_executor.hpp" #include "asio/associated_allocator.hpp"@@ -77,11 +78,18 @@    void operator()()   {+    typename associated_allocator<Handler>::type alloc(+        (get_associated_allocator)(handler_));+#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(executor_, execution::allocator(alloc)).execute(+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(Handler)(handler_)));+#else // defined(ASIO_NO_DEPRECATED)     execution::execute(-        asio::prefer(executor_,-          execution::blocking.possibly,-          execution::allocator((get_associated_allocator)(handler_))),-        ASIO_MOVE_CAST(Handler)(handler_));+        asio::prefer(executor_, execution::allocator(alloc)),+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(Handler)(handler_)));+#endif // defined(ASIO_NO_DEPRECATED)   }  private:@@ -129,7 +137,8 @@     typename associated_allocator<Handler>::type alloc(         (get_associated_allocator)(handler_));     work_.get_executor().dispatch(-        ASIO_MOVE_CAST(Handler)(handler_), alloc);+        asio::detail::bind_handler(+          ASIO_MOVE_CAST(Handler)(handler_)), alloc);     work_.reset();   } 
link/modules/asio-standalone/asio/include/asio/detail/wrapped_handler.hpp view
@@ -2,7 +2,7 @@ // detail/wrapped_handler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/dispatch.hpp view
@@ -2,7 +2,7 @@ // dispatch.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,7 @@  #include "asio/detail/config.hpp" #include "asio/async_result.hpp"+#include "asio/detail/initiate_dispatch.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp" #include "asio/execution/executor.hpp"@@ -32,27 +33,51 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode  *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{}, token)</tt>, where @c Init is a function object type defined+ * as:  *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @code class Init+ * {+ * public:+ *   template <typename CompletionHandler>+ *     void operator()(CompletionHandler&& completion_handler) const;+ * }; @endcode  *- * @li Obtains the handler's associated executor object @c ex by performing- * <tt>get_associated_executor(handler)</tt>.+ * The function call operator of @c Init:  *+ * @li Obtains the handler's associated executor object @c ex of type @c Ex by+ * performing @code auto ex = get_associated_executor(handler); @endcode+ *  * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode  *- * @li Performs <tt>ex.dispatch(std::move(handler), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(ex, execution::allocator(alloc)).execute(+ *     std::forward<CompletionHandler>(completion_handler)); @endcode  *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.dispatch(+ *     std::forward<CompletionHandler>(completion_handler),+ *     alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode  */-template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(-    ASIO_MOVE_ARG(CompletionToken) token);+template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) dispatch(+    ASIO_MOVE_ARG(NullaryToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<NullaryToken, void()>(+        declval<detail::initiate_dispatch>(), token)))+{+  return async_initiate<NullaryToken, void()>(+      detail::initiate_dispatch(), token);+}  /// Submits a completion token or function object for execution. /**@@ -60,62 +85,118 @@  * 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:+ * @param ex The target executor.  *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode  *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{ex}, token)</tt>, where @c Init is a function object type+ * defined as:  *- * @li Obtains the handler's associated executor object @c ex1 by performing- * <tt>get_associated_executor(handler)</tt>.+ * @code class Init+ * {+ * public:+ *   using executor_type = Executor;+ *   explicit Init(const Executor& ex) : ex_(ex) {}+ *   executor_type get_executor() const noexcept { return ex_; }+ *   template <typename CompletionHandler>+ *     void operator()(CompletionHandler&& completion_handler) const;+ * private:+ *   Executor ex_; // exposition only+ * }; @endcode  *- * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.+ * The function call operator of @c Init:  *+ * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by+ * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode+ *  * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode  *- * @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 If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a+ * function object @c f with a member @c executor_ that is initialised with+ * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c+ * handler_ that is a decay-copy of @c completion_handler, and a function call+ * operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * prefer(executor_, execution::allocator(a)).execute(std::move(handler_));+ * @endcode  *- * @li Performs <tt>Executor(ex).dispatch(std::move(f), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a+ * function object @c f with a member @c work_ that is initialised with+ * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of+ * @c completion_handler, and a function call operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * work_.get_executor().dispatch(std::move(handler_), a);+ * work_.reset(); @endcode  *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(ex, execution::allocator(alloc)).execute(std::move(f)); @endcode+ *+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.dispatch(std::move(f), alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode  */ template <typename Executor,-    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+    ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken       ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) dispatch(     const Executor& ex,-    ASIO_MOVE_ARG(CompletionToken) token+    ASIO_MOVE_ARG(NullaryToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<+    typename constraint<       execution::is_executor<Executor>::value || is_executor<Executor>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<NullaryToken, void()>(+        declval<detail::initiate_dispatch_with_executor<Executor> >(), token)))+{+  return async_initiate<NullaryToken, void()>(+      detail::initiate_dispatch_with_executor<Executor>(ex), token);+}  /// Submits a completion token or function object for execution. /**+ * @param ctx An execution context, from which the target executor is obtained.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode+ *  * @returns <tt>dispatch(ctx.get_executor(),- * forward<CompletionToken>(token))</tt>.+ * forward<NullaryToken>(token))</tt>.+ *+ * @par Completion Signature+ * @code void() @endcode  */ template <typename ExecutionContext,-    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+    ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken       ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(         typename ExecutionContext::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) dispatch(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) dispatch(     ExecutionContext& ctx,-    ASIO_MOVE_ARG(CompletionToken) token+    ASIO_MOVE_ARG(NullaryToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename ExecutionContext::executor_type),-    typename enable_if<is_convertible<-      ExecutionContext&, execution_context&>::value>::type* = 0);+    typename constraint<is_convertible<+      ExecutionContext&, execution_context&>::value>::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<NullaryToken, void()>(+        declval<detail::initiate_dispatch_with_executor<+          typename ExecutionContext::executor_type> >(), token)))+{+  return async_initiate<NullaryToken, void()>(+      detail::initiate_dispatch_with_executor<+        typename ExecutionContext::executor_type>(+          ctx.get_executor()), token);+}  } // 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
@@ -2,7 +2,7 @@ // error.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -222,6 +222,41 @@   /// The descriptor cannot fit into the select system call's fd_set.   fd_set_failure };++// boostify: non-boost code starts here+#if !defined(ASIO_ERROR_LOCATION)+# define ASIO_ERROR_LOCATION(e) (void)0+#endif // !defined(ASIO_ERROR_LOCATION)++// boostify: non-boost code ends here+#if !defined(ASIO_ERROR_LOCATION) \+  && !defined(ASIO_DISABLE_ERROR_LOCATION) \+  && defined(ASIO_HAS_BOOST_CONFIG) \+  && (BOOST_VERSION >= 107900)++# define ASIO_ERROR_LOCATION(e) \+  do { \+    BOOST_STATIC_CONSTEXPR boost::source_location loc \+      = BOOST_CURRENT_LOCATION; \+    (e).assign((e), &loc); \+  } while (false)++#else // !defined(ASIO_ERROR_LOCATION)+      //   && !defined(ASIO_DISABLE_ERROR_LOCATION)+      //   && defined(ASIO_HAS_BOOST_CONFIG)+      //   && (BOOST_VERSION >= 107900)++# define ASIO_ERROR_LOCATION(e) (void)0++#endif // !defined(ASIO_ERROR_LOCATION)+       //   && !defined(ASIO_DISABLE_ERROR_LOCATION)+       //   && defined(ASIO_HAS_BOOST_CONFIG)+       //   && (BOOST_VERSION >= 107900)++inline void clear(asio::error_code& ec)+{+  ec.assign(0, ec.category());+}  inline const asio::error_category& get_system_category() {
link/modules/asio-standalone/asio/include/asio/error_code.hpp view
@@ -2,7 +2,7 @@ // error_code.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution.hpp view
@@ -2,7 +2,7 @@ // execution.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/allocator.hpp view
@@ -2,7 +2,7 @@ // execution/allocator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -78,25 +78,73 @@ struct allocator_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);   ASIO_STATIC_CONSTEXPR(bool, is_preferable = true); +  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, allocator_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, allocator_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(allocator_t::static_query<E>())>@@ -132,10 +180,28 @@ struct allocator_t<void> { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -145,16 +211,46 @@   {   } +  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, allocator_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, allocator_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(allocator_t::static_query<E>())>@@ -203,8 +299,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -218,20 +325,20 @@ 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+    execution::allocator_t<ProtoAllocator>::template+      query_static_constexpr_member<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::allocator_t<ProtoAllocator> >::result_type result_type;+  typedef typename execution::allocator_t<ProtoAllocator>::template+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::allocator_t<ProtoAllocator> >::value();+    return execution::allocator_t<ProtoAllocator>::template+      query_static_constexpr_member<T>::value();   } }; 
link/modules/asio-standalone/asio/include/asio/execution/any_executor.hpp view
@@ -2,7 +2,7 @@ // execution/any_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@ #include <new> #include <typeinfo> #include "asio/detail/assert.hpp"+#include "asio/detail/atomic_count.hpp" #include "asio/detail/cstddef.hpp" #include "asio/detail/executor_function.hpp" #include "asio/detail/memory.hpp"@@ -64,10 +65,25 @@   template <class... OtherSupportableProperties>     any_executor(any_executor<OtherSupportableProperties...> e); +  /// Construct to point to the same target as another any_executor.+  template <class... OtherSupportableProperties>+    any_executor(std::nothrow_t,+      any_executor<OtherSupportableProperties...> e) noexcept;++  /// Construct to point to the same target as another any_executor.+  any_executor(std::nothrow_t, const any_executor& e) noexcept;++  /// Construct to point to the same target as another any_executor.+  any_executor(std::nothrow_t, any_executor&& e) noexcept;+   /// Construct a polymorphic wrapper for the specified executor.   template <typename Executor>   any_executor(Executor e); +  /// Construct a polymorphic wrapper for the specified executor.+  template <typename Executor>+  any_executor(std::nothrow_t, Executor e) noexcept;+   /// Assignment operator.   any_executor& operator=(const any_executor& e) noexcept; @@ -126,13 +142,6 @@    /// 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>@@ -481,13 +490,108 @@ { }; +template <typename Props>+struct is_valid_target_executor<int, Props> : false_type+{+};++class shared_target_executor+{+public:+  template <typename E>+  shared_target_executor(ASIO_MOVE_ARG(E) e,+      typename decay<E>::type*& target)+  {+    impl<typename decay<E>::type>* i =+      new impl<typename decay<E>::type>(ASIO_MOVE_CAST(E)(e));+    target = &i->ex_;+    impl_ = i;+  }++  template <typename E>+  shared_target_executor(std::nothrow_t, ASIO_MOVE_ARG(E) e,+      typename decay<E>::type*& target) ASIO_NOEXCEPT+  {+    impl<typename decay<E>::type>* i =+      new (std::nothrow) impl<typename decay<E>::type>(+        ASIO_MOVE_CAST(E)(e));+    target = i ? &i->ex_ : 0;+    impl_ = i;+  }++  shared_target_executor(+      const shared_target_executor& other) ASIO_NOEXCEPT+    : impl_(other.impl_)+  {+    if (impl_)+      asio::detail::ref_count_up(impl_->ref_count_);+  }++  shared_target_executor& operator=(+      const shared_target_executor& other) ASIO_NOEXCEPT+  {+    impl_ = other.impl_;+    if (impl_)+      asio::detail::ref_count_up(impl_->ref_count_);+    return *this;+  }++#if defined(ASIO_HAS_MOVE)+  shared_target_executor(+      shared_target_executor&& other) ASIO_NOEXCEPT+    : impl_(other.impl_)+  {+    other.impl_ = 0;+  }++  shared_target_executor& operator=(+      shared_target_executor&& other) ASIO_NOEXCEPT+  {+    impl_ = other.impl_;+    other.impl_ = 0;+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)++  ~shared_target_executor()+  {+    if (impl_)+      if (asio::detail::ref_count_down(impl_->ref_count_))+        delete impl_;+  }++  void* get() const ASIO_NOEXCEPT+  {+    return impl_ ? impl_->get() : 0;+  }++private:+  struct impl_base+  {+    impl_base() : ref_count_(1) {}+    virtual ~impl_base() {}+    virtual void* get() = 0;+    asio::detail::atomic_count ref_count_;+  };++  template <typename Executor>+  struct impl : impl_base+  {+    impl(Executor ex) : ex_(ASIO_MOVE_CAST(Executor)(ex)) {}+    virtual void* get() { return &ex_; }+    Executor ex_;+  };++  impl_base* impl_;+};+ class any_executor_base { public:   any_executor_base() ASIO_NOEXCEPT-    : object_fns_(object_fns_table<void>()),+    : object_fns_(0),       target_(0),-      target_fns_(target_fns_table<void>())+      target_fns_(0)   {   } @@ -506,28 +610,74 @@   }    template <ASIO_EXECUTION_EXECUTOR Executor>+  any_executor_base(std::nothrow_t, Executor ex, false_type) ASIO_NOEXCEPT+    : 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(std::nothrow, ex,+        integral_constant<bool,+          sizeof(Executor) <= sizeof(object_type)+            && alignment_of<Executor>::value <= alignment_of<object_type>::value+        >());+    if (target_ == 0)+    {+      object_fns_ = 0;+      target_fns_ = 0;+    }+  }++  template <ASIO_EXECUTION_EXECUTOR Executor>   any_executor_base(Executor other, true_type)-    : object_fns_(object_fns_table<asio::detail::shared_ptr<void> >()),+    : object_fns_(object_fns_table<shared_target_executor>()),       target_fns_(other.target_fns_)   {-    asio::detail::shared_ptr<Executor> p =-      asio::detail::make_shared<Executor>(-          ASIO_MOVE_CAST(Executor)(other));+    Executor* p = 0;+    new (&object_) shared_target_executor(+        ASIO_MOVE_CAST(Executor)(other), p);     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_),+  template <ASIO_EXECUTION_EXECUTOR Executor>+  any_executor_base(std::nothrow_t,+      Executor other, true_type) ASIO_NOEXCEPT+    : object_fns_(object_fns_table<shared_target_executor>()),       target_fns_(other.target_fns_)   {-    object_fns_->copy(*this, other);+    Executor* p = 0;+    new (&object_) shared_target_executor(+        std::nothrow, ASIO_MOVE_CAST(Executor)(other), p);+    if (p)+      target_ = p->template target<void>();+    else+    {+      target_ = 0;+      object_fns_ = 0;+      target_fns_ = 0;+    }   } +  any_executor_base(const any_executor_base& other) ASIO_NOEXCEPT+  {+    if (!!other)+    {+      object_fns_ = other.object_fns_;+      target_fns_ = other.target_fns_;+      object_fns_->copy(*this, other);+    }+    else+    {+      object_fns_ = 0;+      target_ = 0;+      target_fns_ = 0;+    }+  }+   ~any_executor_base() ASIO_NOEXCEPT   {-    object_fns_->destroy(*this);+    if (!!*this)+      object_fns_->destroy(*this);   }    any_executor_base& operator=(@@ -535,33 +685,53 @@   {     if (this != &other)     {-      object_fns_->destroy(*this);-      object_fns_ = other.object_fns_;-      target_fns_ = other.target_fns_;-      object_fns_->copy(*this, other);+      if (!!*this)+        object_fns_->destroy(*this);+      if (!!other)+      {+        object_fns_ = other.object_fns_;+        target_fns_ = other.target_fns_;+        object_fns_->copy(*this, other);+      }+      else+      {+        object_fns_ = 0;+        target_ = 0;+        target_fns_ = 0;+      }     }     return *this;   }    any_executor_base& operator=(nullptr_t) ASIO_NOEXCEPT   {-    object_fns_->destroy(*this);+    if (target_)+      object_fns_->destroy(*this);     target_ = 0;-    object_fns_ = object_fns_table<void>();-    target_fns_ = target_fns_table<void>();+    object_fns_ = 0;+    target_fns_ = 0;     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;+    if (other.target_)+    {+      object_fns_ = other.object_fns_;+      target_fns_ = other.target_fns_;+      other.object_fns_ = 0;+      other.target_fns_ = 0;+      object_fns_->move(*this, other);+      other.target_ = 0;+    }+    else+    {+      object_fns_ = 0;+      target_ = 0;+      target_fns_ = 0;+    }   }    any_executor_base& operator=(@@ -569,13 +739,23 @@   {     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;+      if (!!*this)+        object_fns_->destroy(*this);+      if (!!other)+      {+        object_fns_ = other.object_fns_;+        target_fns_ = other.target_fns_;+        other.object_fns_ = 0;+        other.target_fns_ = 0;+        object_fns_->move(*this, other);+        other.target_ = 0;+      }+      else+      {+        object_fns_ = 0;+        target_ = 0;+        target_fns_ = 0;+      }     }     return *this;   }@@ -595,34 +775,53 @@   template <typename F>   void execute(ASIO_MOVE_ARG(F) f) const   {-    if (target_fns_->blocking_execute != 0)+    if (target_)     {-      asio::detail::non_const_lvalue<F> f2(f);-      target_fns_->blocking_execute(*this, function_view(f2.value));+      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>()));+      }     }     else     {-      target_fns_->execute(*this,-          function(ASIO_MOVE_CAST(F)(f), std::allocator<void>()));+      bad_executor ex;+      asio::detail::throw_exception(ex);     }   }    template <typename Executor>   Executor* target()   {-    return static_cast<Executor*>(target_);+    return target_ && (is_same<Executor, void>::value+        || target_fns_->target_type() == target_type_ex<Executor>())+      ? static_cast<Executor*>(target_) : 0;   }    template <typename Executor>   const Executor* target() const   {-    return static_cast<Executor*>(target_);+    return target_ && (is_same<Executor, void>::value+        || target_fns_->target_type() == target_type_ex<Executor>())+      ? static_cast<const Executor*>(target_) : 0;   } +#if !defined(ASIO_NO_TYPEID)   const std::type_info& target_type() const   {-    return target_fns_->target_type();+    return target_ ? target_fns_->target_type() : typeid(void);   }+#else // !defined(ASIO_NO_TYPEID)+  const void* target_type() const+  {+    return target_ ? target_fns_->target_type() : 0;+  }+#endif // !defined(ASIO_NO_TYPEID)    struct unspecified_bool_type_t {};   typedef void (*unspecified_bool_type)(unspecified_bool_type_t);@@ -672,57 +871,22 @@     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;+    typedef shared_target_executor 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;+    typedef shared_target_executor 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;+    typedef shared_target_executor type;     new (&ex1.object_) type(ASIO_MOVE_CAST(type)(ex2.object<type>()));     ex1.target_ = ex2.target_;     ex2.object<type>().~type();@@ -730,14 +894,14 @@    static const void* target_shared(const any_executor_base& ex)   {-    typedef asio::detail::shared_ptr<void> type;+    typedef shared_target_executor 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+        is_same<Obj, shared_target_executor>::value       >::type* = 0)   {     static const object_fns fns =@@ -781,7 +945,7 @@   static const object_fns* object_fns_table(       typename enable_if<         !is_same<Obj, void>::value-          && !is_same<Obj, asio::detail::shared_ptr<void> >::value+          && !is_same<Obj, shared_target_executor>::value       >::type* = 0)   {     static const object_fns fns =@@ -799,75 +963,64 @@    struct target_fns   {+#if !defined(ASIO_NO_TYPEID)     const std::type_info& (*target_type)();+#else // !defined(ASIO_NO_TYPEID)+    const void* (*target_type)();+#endif // !defined(ASIO_NO_TYPEID)     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);-  }-+#if !defined(ASIO_NO_TYPEID)   template <typename Ex>-  static const target_fns* target_fns_table(-      typename enable_if<-        is_same<Ex, void>::value-      >::type* = 0)+  static const std::type_info& target_type_ex()   {-    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;+    return typeid(Ex);   }-+#else // !defined(ASIO_NO_TYPEID)   template <typename Ex>-  static const std::type_info& target_type_ex()+  static const void* target_type_ex()   {-    return typeid(Ex);+    static int unique_id;+    return &unique_id;   }+#endif // !defined(ASIO_NO_TYPEID)    template <typename Ex>   static bool equal_ex(const any_executor_base& ex1,       const any_executor_base& ex2)   {-    return *ex1.target<Ex>() == *ex2.target<Ex>();+    const Ex* p1 = ex1.target<Ex>();+    const Ex* p2 = ex2.target<Ex>();+    ASIO_ASSUME(p1 != 0 && p2 != 0);+    return *p1 == *p2;   }    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));+    const Ex* p = ex.target<Ex>();+    ASIO_ASSUME(p != 0);+#if defined(ASIO_NO_DEPRECATED)+    p->execute(ASIO_MOVE_CAST(function)(f));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(*p, ASIO_MOVE_CAST(function)(f));+#endif // defined(ASIO_NO_DEPRECATED)   }    template <typename Ex>   static void blocking_execute_ex(const any_executor_base& ex, function_view f)   {-    execution::execute(*ex.target<Ex>(), f);+    const Ex* p = ex.target<Ex>();+    ASIO_ASSUME(p != 0);+#if defined(ASIO_NO_DEPRECATED)+    p->execute(f);+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(*p, f);+#endif // defined(ASIO_NO_DEPRECATED)   }    template <typename Ex>@@ -1125,20 +1278,37 @@   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));+    object_fns_ = object_fns_table<shared_target_executor>();+    Executor* p = 0;+    new (&object_) shared_target_executor(+        ASIO_MOVE_CAST(Executor)(ex), p);+    target_ = p;   } +  template <typename Executor>+  void construct_object(std::nothrow_t,+      Executor& ex, true_type) ASIO_NOEXCEPT+  {+    object_fns_ = object_fns_table<Executor>();+    target_ = new (&object_) Executor(ASIO_MOVE_CAST(Executor)(ex));+  }++  template <typename Executor>+  void construct_object(std::nothrow_t,+      Executor& ex, false_type) ASIO_NOEXCEPT+  {+    object_fns_ = object_fns_table<shared_target_executor>();+    Executor* p = 0;+    new (&object_) shared_target_executor(+        std::nothrow, ASIO_MOVE_CAST(Executor)(ex), p);+    target_ = p;+  }+ /*private:*/public: //  template <typename...> friend class any_executor;    typedef aligned_storage<-      sizeof(asio::detail::shared_ptr<void>),+      sizeof(asio::detail::shared_ptr<void>) + sizeof(void*),       alignment_of<asio::detail::shared_ptr<void> >::value     >::type object_type; @@ -1198,6 +1368,21 @@   {   } +  template <typename Executor>+  any_executor(std::nothrow_t, 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) ASIO_NOEXCEPT+    : detail::any_executor_base(std::nothrow,+        ASIO_MOVE_CAST(Executor)(ex), false_type())+  {+  }+ #if defined(ASIO_HAS_VARIADIC_TEMPLATES)    template <typename... OtherSupportableProperties>@@ -1207,6 +1392,14 @@   {   } +  template <typename... OtherSupportableProperties>+  any_executor(std::nothrow_t,+      any_executor<OtherSupportableProperties...> other) ASIO_NOEXCEPT+    : 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,@@ -1217,6 +1410,15 @@   {   } +  template <typename U0, typename U1, typename U2, typename U3,+      typename U4, typename U5, typename U6, typename U7>+  any_executor(std::nothrow_t,+      any_executor<U0, U1, U2, U3, U4, U5, U6, U7> other) ASIO_NOEXCEPT+    : 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@@ -1225,6 +1427,12 @@   {   } +  any_executor(std::nothrow_t, 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)@@ -1250,6 +1458,13 @@   {   } +  any_executor(std::nothrow_t, 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)@@ -1279,39 +1494,65 @@   {     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);-}+  template <typename AnyExecutor1, typename AnyExecutor2>+  friend typename enable_if<+    is_base_of<any_executor, AnyExecutor1>::value+      || is_base_of<any_executor, AnyExecutor2>::value,+    bool+  >::type operator==(const AnyExecutor1& a,+      const AnyExecutor2& b) ASIO_NOEXCEPT+  {+    return static_cast<const any_executor&>(a).equality_helper(b);+  } -inline bool operator==(const any_executor<>& a, nullptr_t) ASIO_NOEXCEPT-{-  return !a;-}+  template <typename AnyExecutor>+  friend typename enable_if<+    is_same<AnyExecutor, any_executor>::value,+    bool+  >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT+  {+    return !a;+  } -inline bool operator==(nullptr_t, const any_executor<>& b) ASIO_NOEXCEPT-{-  return !b;-}+  template <typename AnyExecutor>+  friend typename enable_if<+    is_same<AnyExecutor, any_executor>::value,+    bool+  >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT+  {+    return !b;+  } -inline bool operator!=(const any_executor<>& a,-    const any_executor<>& b) ASIO_NOEXCEPT-{-  return !a.equality_helper(b);-}+  template <typename AnyExecutor1, typename AnyExecutor2>+  friend typename enable_if<+    is_base_of<any_executor, AnyExecutor1>::value+      || is_base_of<any_executor, AnyExecutor2>::value,+    bool+  >::type operator!=(const AnyExecutor1& a,+      const AnyExecutor2& b) ASIO_NOEXCEPT+  {+    return !static_cast<const any_executor&>(a).equality_helper(b);+  } -inline bool operator!=(const any_executor<>& a, nullptr_t) ASIO_NOEXCEPT-{-  return !!a;-}+  template <typename AnyExecutor>+  friend typename enable_if<+    is_same<AnyExecutor, any_executor>::value,+    bool+  >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT+  {+    return !!a;+  } -inline bool operator!=(nullptr_t, const any_executor<>& b) ASIO_NOEXCEPT-{-  return !!b;-}+  template <typename AnyExecutor>+  friend typename enable_if<+    is_same<AnyExecutor, any_executor>::value,+    bool+  >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT+  {+    return !!b;+  }+};  inline void swap(any_executor<>& a, any_executor<>& b) ASIO_NOEXCEPT {@@ -1358,6 +1599,25 @@   {   } +  template <typename Executor>+  any_executor(std::nothrow_t, 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) ASIO_NOEXCEPT+    : detail::any_executor_base(std::nothrow,+        ASIO_MOVE_CAST(Executor)(ex), false_type()),+      prop_fns_(prop_fns_table<Executor>())+  {+    if (this->template target<void>() == 0)+      prop_fns_ = prop_fns_table<void>();+  }+   template <typename... OtherSupportableProperties>   any_executor(any_executor<OtherSupportableProperties...> other,       typename enable_if<@@ -1378,6 +1638,29 @@   {   } +  template <typename... OtherSupportableProperties>+  any_executor(std::nothrow_t,+      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) ASIO_NOEXCEPT+    : detail::any_executor_base(std::nothrow, ASIO_MOVE_CAST(+          any_executor<OtherSupportableProperties...>)(other), true_type()),+      prop_fns_(prop_fns_table<any_executor<OtherSupportableProperties...> >())+  {+    if (this->template target<void>() == 0)+      prop_fns_ = prop_fns_table<void>();+  }+   any_executor(const any_executor& other) ASIO_NOEXCEPT     : detail::any_executor_base(         static_cast<const detail::any_executor_base&>(other)),@@ -1385,6 +1668,13 @@   {   } +  any_executor(std::nothrow_t, 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)@@ -1414,6 +1704,15 @@     other.prop_fns_ = prop_fns_table<void>();   } +  any_executor(std::nothrow_t, 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)@@ -1451,6 +1750,64 @@     return any_executor_base::equality_helper(other);   } +  template <typename AnyExecutor1, typename AnyExecutor2>+  friend typename enable_if<+    is_base_of<any_executor, AnyExecutor1>::value+      || is_base_of<any_executor, AnyExecutor2>::value,+    bool+  >::type operator==(const AnyExecutor1& a,+      const AnyExecutor2& b) ASIO_NOEXCEPT+  {+    return static_cast<const any_executor&>(a).equality_helper(b);+  }++  template <typename AnyExecutor>+  friend typename enable_if<+    is_same<AnyExecutor, any_executor>::value,+    bool+  >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT+  {+    return !a;+  }++  template <typename AnyExecutor>+  friend typename enable_if<+    is_same<AnyExecutor, any_executor>::value,+    bool+  >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT+  {+    return !b;+  }++  template <typename AnyExecutor1, typename AnyExecutor2>+  friend typename enable_if<+    is_base_of<any_executor, AnyExecutor1>::value+      || is_base_of<any_executor, AnyExecutor2>::value,+    bool+  >::type operator!=(const AnyExecutor1& a,+      const AnyExecutor2& b) ASIO_NOEXCEPT+  {+    return !static_cast<const any_executor&>(a).equality_helper(b);+  }++  template <typename AnyExecutor>+  friend typename enable_if<+    is_same<AnyExecutor, any_executor>::value,+    bool+  >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT+  {+    return !!a;+  }++  template <typename AnyExecutor>+  friend typename enable_if<+    is_same<AnyExecutor, any_executor>::value,+    bool+  >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT+  {+    return !!b;+  }+   template <typename T>   struct find_convertible_property :       detail::supportable_properties<@@ -1596,48 +1953,6 @@ };  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 {@@ -1717,6 +2032,15 @@     other.prop_fns_ = prop_fns_table<void>(); \   } \   \+  any_executor(std::nothrow_t, 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) \@@ -1774,6 +2098,25 @@     { \     } \     \+    template <ASIO_EXECUTION_EXECUTOR Executor> \+    any_executor(std::nothrow_t, 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) ASIO_NOEXCEPT \+      : detail::any_executor_base(std::nothrow, \+          ASIO_MOVE_CAST(Executor)(ex), false_type()), \+        prop_fns_(prop_fns_table<Executor>()) \+    { \+      if (this->template target<void>() == 0) \+        prop_fns_ = prop_fns_table<void>(); \+    } \+    \     any_executor(const any_executor& other) ASIO_NOEXCEPT \       : detail::any_executor_base( \           static_cast<const detail::any_executor_base&>(other)), \@@ -1781,6 +2124,16 @@     { \     } \     \+    any_executor(std::nothrow_t, \+        const any_executor& other) ASIO_NOEXCEPT \+      : detail::any_executor_base( \+          static_cast<const detail::any_executor_base&>(other)), \+        prop_fns_(other.prop_fns_) \+    { \+      if (this->template target<void>() == 0) \+        prop_fns_ = prop_fns_table<void>(); \+    } \+    \     any_executor(any_executor<> other) \       : detail::any_executor_base(ASIO_MOVE_CAST( \             any_executor<>)(other), true_type()), \@@ -1788,6 +2141,15 @@     { \     } \     \+    any_executor(std::nothrow_t, any_executor<> other) ASIO_NOEXCEPT \+      : detail::any_executor_base(std::nothrow, \+          ASIO_MOVE_CAST(any_executor<>)(other), true_type()), \+        prop_fns_(prop_fns_table<any_executor<> >()) \+    { \+      if (this->template target<void>() == 0) \+        prop_fns_ = prop_fns_table<void>(); \+    } \+    \     template <typename OtherAnyExecutor> \     any_executor(OtherAnyExecutor other, \         typename enable_if< \@@ -1807,6 +2169,27 @@     { \     } \     \+    template <typename OtherAnyExecutor> \+    any_executor(std::nothrow_t, 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) ASIO_NOEXCEPT \+      : detail::any_executor_base(std::nothrow, \+          ASIO_MOVE_CAST(OtherAnyExecutor)(other), true_type()), \+        prop_fns_(prop_fns_table<OtherAnyExecutor>()) \+    { \+      if (this->template target<void>() == 0) \+        prop_fns_ = prop_fns_table<void>(); \+    } \+    \     any_executor& operator=(const any_executor& other) ASIO_NOEXCEPT \     { \       if (this != &other) \@@ -1850,6 +2233,64 @@       return any_executor_base::equality_helper(other); \     } \     \+    template <typename AnyExecutor1, typename AnyExecutor2> \+    friend typename enable_if< \+      is_base_of<any_executor, AnyExecutor1>::value \+        || is_base_of<any_executor, AnyExecutor2>::value, \+      bool \+    >::type operator==(const AnyExecutor1& a, \+        const AnyExecutor2& b) ASIO_NOEXCEPT \+    { \+      return static_cast<const any_executor&>(a).equality_helper(b); \+    } \+    \+    template <typename AnyExecutor> \+    friend typename enable_if< \+      is_same<AnyExecutor, any_executor>::value, \+      bool \+    >::type operator==(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \+    { \+      return !a; \+    } \+    \+    template <typename AnyExecutor> \+    friend typename enable_if< \+      is_same<AnyExecutor, any_executor>::value, \+      bool \+    >::type operator==(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \+    { \+      return !b; \+    } \+    \+    template <typename AnyExecutor1, typename AnyExecutor2> \+    friend typename enable_if< \+      is_base_of<any_executor, AnyExecutor1>::value \+        || is_base_of<any_executor, AnyExecutor2>::value, \+      bool \+    >::type operator!=(const AnyExecutor1& a, \+        const AnyExecutor2& b) ASIO_NOEXCEPT \+    { \+      return !static_cast<const any_executor&>(a).equality_helper(b); \+    } \+    \+    template <typename AnyExecutor> \+    friend typename enable_if< \+      is_same<AnyExecutor, any_executor>::value, \+      bool \+    >::type operator!=(const AnyExecutor& a, nullptr_t) ASIO_NOEXCEPT \+    { \+      return !!a; \+    } \+    \+    template <typename AnyExecutor> \+    friend typename enable_if< \+      is_same<AnyExecutor, any_executor>::value, \+      bool \+    >::type operator!=(nullptr_t, const AnyExecutor& b) ASIO_NOEXCEPT \+    { \+      return !!b; \+    } \+    \     template <typename T> \     struct find_convertible_property : \         detail::supportable_properties< \@@ -1987,48 +2428,6 @@     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, \
link/modules/asio-standalone/asio/include/asio/execution/bad_executor.hpp view
@@ -2,7 +2,7 @@ // execution/bad_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/blocking.hpp view
@@ -2,7 +2,7 @@ // execution/blocking.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,6 +25,7 @@ #include "asio/prefer.hpp" #include "asio/query.hpp" #include "asio/require.hpp"+#include "asio/traits/execute_member.hpp" #include "asio/traits/query_free.hpp" #include "asio/traits/query_member.hpp" #include "asio/traits/query_static_constexpr_member.hpp"@@ -208,10 +209,28 @@ struct blocking_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -242,16 +261,74 @@   {   } +  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto query(ASIO_MOVE_ARG(P) p) const+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().query(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().query(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+  };++  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_member :+    traits::query_member<typename proxy<T>::type, blocking_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, blocking_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, blocking_t>::result_type+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, blocking_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, blocking_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename T>@@ -259,9 +336,13 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, possibly_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, possibly_t>::value();@@ -272,10 +353,16 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, possibly_t>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, always_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, always_t>::value();@@ -286,11 +373,19 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, possibly_t>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, always_t>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, never_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, never_t>::value();@@ -343,7 +438,9 @@       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,+      typename enable_if<+        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.@@ -363,8 +460,12 @@       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,+      typename enable_if<+        !can_query<const Executor&, always_t>::value+      >::type* = 0,+      typename enable_if<+        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.@@ -418,10 +519,28 @@ struct possibly_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -432,26 +551,44 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename blocking_t<I>::template proxy<T>::type, possibly_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename blocking_t<I>::template static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, possibly_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, possibly_t>::value();+    return query_static_constexpr_member<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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::query_free<T, possibly_t>::is_valid+      >::type* = 0,+      typename enable_if<+        !can_query<T, always_t<I> >::value+      >::type* = 0,+      typename enable_if<+        !can_query<T, never_t<I> >::value       >::type* = 0) ASIO_NOEXCEPT   {     return possibly_t();@@ -622,7 +759,11 @@    template <typename Function>   typename enable_if<+#if defined(ASIO_NO_DEPRECATED)+    traits::execute_member<const Executor&, Function>::is_valid+#else // defined(ASIO_NO_DEPRECATED)     execution::can_execute<const Executor&, Function>::value+#endif // defined(ASIO_NO_DEPRECATED)   >::type execute(ASIO_MOVE_ARG(Function) f) const   {     blocking_adaptation::blocking_execute(@@ -647,10 +788,28 @@ struct always_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -661,16 +820,26 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename blocking_t<I>::template proxy<T>::type, always_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename blocking_t<I>::template static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, always_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, always_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(always_t::static_query<E>())>@@ -725,7 +894,9 @@       const Executor& e, const always_t&,       typename enable_if<         is_executor<Executor>::value-        && traits::static_require<+      >::type* = 0,+      typename enable_if<+        traits::static_require<           const Executor&,           blocking_adaptation::allowed_t<0>         >::is_valid@@ -746,10 +917,28 @@ struct never_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -760,16 +949,26 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename blocking_t<I>::template proxy<T>::type, never_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename blocking_t<I>::template static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, never_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, never_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(never_t::static_query<E>())>@@ -845,8 +1044,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -854,8 +1064,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -863,8 +1084,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -872,8 +1104,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -933,28 +1176,29 @@ template <typename T> struct static_query<T, execution::blocking_t,   typename enable_if<-    traits::query_static_constexpr_member<T,-      execution::blocking_t>::is_valid+    execution::detail::blocking_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::blocking_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::blocking_t>::value();+    return execution::blocking_t::query_static_constexpr_member<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+    !execution::detail::blocking_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::blocking_t<0>::+        query_member<T>::is_valid       && traits::static_query<T, execution::blocking_t::possibly_t>::is_valid   >::type> {@@ -973,8 +1217,10 @@ 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+    !execution::detail::blocking_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::blocking_t<0>::+        query_member<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>@@ -994,8 +1240,10 @@ 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+    !execution::detail::blocking_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::blocking_t<0>::+        query_member<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@@ -1016,29 +1264,30 @@ 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+    execution::detail::blocking::possibly_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::blocking::possibly_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::blocking_t::possibly_t>::value();+    return execution::detail::blocking::possibly_t<0>::+      query_static_constexpr_member<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+    !execution::detail::blocking::possibly_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::blocking::possibly_t<0>::+        query_member<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@@ -1058,40 +1307,40 @@ 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+    execution::detail::blocking::always_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::blocking::always_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::blocking_t::always_t>::value();+    return execution::detail::blocking::always_t<0>::+      query_static_constexpr_member<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+    execution::detail::blocking::never_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::blocking::never_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::blocking_t::never_t>::value();+    return execution::detail::blocking::never_t<0>::+      query_static_constexpr_member<T>::value();   } }; 
link/modules/asio-standalone/asio/include/asio/execution/blocking_adaptation.hpp view
@@ -2,7 +2,7 @@ // execution/blocking_adaptation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -164,10 +164,28 @@ struct blocking_adaptation_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -192,20 +210,74 @@   {   } +  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto query(ASIO_MOVE_ARG(P) p) const+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().query(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().query(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+  };++  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_member :+    traits::query_member<typename proxy<T>::type, blocking_adaptation_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, blocking_adaptation_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, blocking_adaptation_t>::result_type+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<-        T, blocking_adaptation_t-      >::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<-        T, blocking_adaptation_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename T>@@ -213,10 +285,13 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, disallowed_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, disallowed_t>::value();@@ -227,11 +302,16 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, disallowed_t>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, allowed_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, allowed_t>::value();@@ -289,7 +369,9 @@       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,+      typename enable_if<+        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.@@ -342,10 +424,28 @@ struct disallowed_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -356,25 +456,43 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename blocking_adaptation_t<I>::template proxy<T>::type,+        disallowed_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename blocking_adaptation_t<I>::template static_proxy<T>::type,+        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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, disallowed_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, disallowed_t>::value();+    return query_static_constexpr_member<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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::query_free<T, disallowed_t>::is_valid+      >::type* = 0,+      typename enable_if<+        !can_query<T, allowed_t<I> >::value       >::type* = 0) ASIO_NOEXCEPT   {     return disallowed_t();@@ -502,10 +620,18 @@    template <typename Function>   typename enable_if<+#if defined(ASIO_NO_DEPRECATED)+    traits::execute_member<const Executor&, Function>::is_valid+#else // defined(ASIO_NO_DEPRECATED)     execution::can_execute<const Executor&, Function>::value+#endif // defined(ASIO_NO_DEPRECATED)   >::type execute(ASIO_MOVE_ARG(Function) f) const   {+#if defined(ASIO_NO_DEPRECATED)+    executor_.execute(ASIO_MOVE_CAST(Function)(f));+#else // defined(ASIO_NO_DEPRECATED)     execution::execute(executor_, ASIO_MOVE_CAST(Function)(f));+#endif // defined(ASIO_NO_DEPRECATED)   }    friend bool operator==(const adapter& a, const adapter& b) ASIO_NOEXCEPT@@ -526,10 +652,28 @@ struct allowed_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -540,16 +684,28 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename blocking_adaptation_t<I>::template proxy<T>::type,+        allowed_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename blocking_adaptation_t<I>::template static_proxy<T>::type,+        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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, allowed_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, allowed_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(allowed_t::static_query<E>())>@@ -608,7 +764,11 @@   void execute_and_wait(ASIO_MOVE_ARG(Executor) ex)   {     handler h = { this };+#if defined(ASIO_NO_DEPRECATED)+    ex.execute(h);+#else // defined(ASIO_NO_DEPRECATED)     execution::execute(ASIO_MOVE_CAST(Executor)(ex), h);+#endif // defined(ASIO_NO_DEPRECATED)     asio::detail::mutex::scoped_lock lock(mutex_);     while (!is_complete_)       event_.wait(lock);@@ -673,8 +833,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -682,8 +853,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -691,8 +873,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -737,30 +930,30 @@ 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+    execution::detail::blocking_adaptation_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::blocking_adaptation_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::blocking_adaptation_t>::value();+    return execution::detail::blocking_adaptation_t<0>::+      query_static_constexpr_member<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+    !execution::detail::blocking_adaptation_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::blocking_adaptation_t<0>::+        query_member<T>::is_valid       && traits::static_query<T,         execution::blocking_adaptation_t::disallowed_t>::is_valid   >::type>@@ -781,10 +974,10 @@ 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+    !execution::detail::blocking_adaptation_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::blocking_adaptation_t<0>::+        query_member<T>::is_valid       && !traits::static_query<T,         execution::blocking_adaptation_t::disallowed_t>::is_valid       && traits::static_query<T,@@ -807,30 +1000,30 @@ 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+    execution::detail::blocking_adaptation::disallowed_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::blocking_adaptation::disallowed_t<0>::+    query_static_constexpr_member<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();+    return execution::detail::blocking_adaptation::disallowed_t<0>::+      query_static_constexpr_member<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+    !execution::detail::blocking_adaptation::disallowed_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::blocking_adaptation::disallowed_t<0>::+        query_member<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@@ -850,20 +1043,20 @@ 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+    execution::detail::blocking_adaptation::allowed_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::blocking_adaptation::allowed_t<0>::+    query_static_constexpr_member<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();+    return execution::detail::blocking_adaptation::allowed_t<0>::+      query_static_constexpr_member<T>::value();   } }; 
link/modules/asio-standalone/asio/include/asio/execution/bulk_execute.hpp view
@@ -2,7 +2,7 @@ // execution/bulk_execute.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/bulk_guarantee.hpp" #include "asio/execution/detail/bulk_sender.hpp"@@ -124,7 +127,8 @@   ill_formed }; -template <typename S, typename Args, typename = void>+template <typename S, typename Args, typename = void, typename = void,+    typename = void, typename = void, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -135,15 +139,15 @@ 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-    )+    is_convertible<N, std::size_t>::value+  >::type,+  typename enable_if<+    bulk_execute_member<S, F, N>::is_valid+  >::type,+  typename enable_if<+    is_sender<+      typename bulk_execute_member<S, F, N>::result_type+    >::value   >::type> :   bulk_execute_member<S, F, N> {@@ -153,17 +157,18 @@ 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-    )+    is_convertible<N, std::size_t>::value+  >::type,+  typename enable_if<+    !bulk_execute_member<S, F, N>::is_valid+  >::type,+  typename enable_if<+    bulk_execute_free<S, F, N>::is_valid+  >::type,+  typename enable_if<+    is_sender<+      typename bulk_execute_free<S, F, N>::result_type+    >::value   >::type> :   bulk_execute_free<S, F, N> {@@ -173,26 +178,29 @@ 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-    )+    is_convertible<N, std::size_t>::value+  >::type,+  typename enable_if<+    !bulk_execute_member<S, F, N>::is_valid+  >::type,+  typename enable_if<+    !bulk_execute_free<S, F, N>::is_valid+  >::type,+  typename enable_if<+    is_sender<S>::value+  >::type,+  typename enable_if<+    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+  >::type,+  typename enable_if<+    static_require<S, bulk_guarantee_t::unsequenced_t>::is_valid   >::type> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);@@ -346,8 +354,9 @@ 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>+    asio_execution_bulk_execute_fn::call_traits<+      S, void(F, N)>::overload !=+        asio_execution_bulk_execute_fn::ill_formed> { }; @@ -361,7 +370,8 @@ 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>+    asio_execution_bulk_execute_fn::call_traits<+      S, void(F, N)>::is_noexcept> { }; @@ -386,5 +396,7 @@ #endif // defined(GENERATING_DOCUMENTATION)  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_BULK_EXECUTE_HPP
link/modules/asio-standalone/asio/include/asio/execution/bulk_guarantee.hpp view
@@ -2,7 +2,7 @@ // execution/bulk_guarantee.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" #include "asio/execution/scheduler.hpp"@@ -196,10 +199,28 @@ struct bulk_guarantee_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -230,17 +251,74 @@   {   } +  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto query(ASIO_MOVE_ARG(P) p) const+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().query(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().query(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+  };++  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_member :+    traits::query_member<typename proxy<T>::type, bulk_guarantee_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, bulk_guarantee_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, bulk_guarantee_t>::result_type+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, bulk_guarantee_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, bulk_guarantee_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename T>@@ -248,9 +326,13 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, unsequenced_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, unsequenced_t>::value();@@ -261,10 +343,16 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, unsequenced_t>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, sequenced_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, sequenced_t>::value();@@ -275,11 +363,19 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, unsequenced_t>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, sequenced_t>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, parallel_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, parallel_t>::value();@@ -334,7 +430,9 @@       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,+      typename enable_if<+        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.@@ -355,8 +453,12 @@       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,+      typename enable_if<+        !can_query<const Executor&, sequenced_t>::value+      >::type* = 0,+      typename enable_if<+        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.@@ -413,10 +515,28 @@ struct unsequenced_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -427,26 +547,46 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename bulk_guarantee_t<I>::template proxy<T>::type,+        unsequenced_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename bulk_guarantee_t<I>::template static_proxy<T>::type,+        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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, unsequenced_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, unsequenced_t>::value();+    return query_static_constexpr_member<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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::query_free<T, unsequenced_t>::is_valid+      >::type* = 0,+      typename enable_if<+        !can_query<T, sequenced_t<I> >::value+      >::type* = 0,+      typename enable_if<+        !can_query<T, parallel_t<I> >::value       >::type* = 0) ASIO_NOEXCEPT   {     return unsequenced_t();@@ -511,10 +651,28 @@ struct sequenced_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -525,16 +683,28 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename bulk_guarantee_t<I>::template proxy<T>::type,+        sequenced_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename bulk_guarantee_t<I>::template static_proxy<T>::type,+        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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, sequenced_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, sequenced_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(sequenced_t::static_query<E>())>@@ -596,10 +766,28 @@ struct parallel_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -610,16 +798,28 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename bulk_guarantee_t<I>::template proxy<T>::type,+        parallel_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename bulk_guarantee_t<I>::template static_proxy<T>::type,+        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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, parallel_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, parallel_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(parallel_t::static_query<E>())>@@ -697,8 +897,16 @@ 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>+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value> { }; @@ -706,8 +914,16 @@ 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>+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value> { }; @@ -715,8 +931,16 @@ 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>+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value> { }; @@ -724,8 +948,16 @@ 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>+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value> { }; @@ -785,30 +1017,30 @@ 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+    execution::detail::bulk_guarantee_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::bulk_guarantee_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::bulk_guarantee_t>::value();+    return execution::detail::bulk_guarantee_t<0>::+      query_static_constexpr_member<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+    !execution::detail::bulk_guarantee_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::bulk_guarantee_t<0>::+        query_member<T>::is_valid       && traits::static_query<T,         execution::bulk_guarantee_t::unsequenced_t>::is_valid   >::type>@@ -829,10 +1061,10 @@ 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+    !execution::detail::bulk_guarantee_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::bulk_guarantee_t<0>::+        query_member<T>::is_valid       && !traits::static_query<T,         execution::bulk_guarantee_t::unsequenced_t>::is_valid       && traits::static_query<T,@@ -855,10 +1087,10 @@ 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+    !execution::detail::bulk_guarantee_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::bulk_guarantee_t<0>::+        query_member<T>::is_valid       && !traits::static_query<T,         execution::bulk_guarantee_t::unsequenced_t>::is_valid       && !traits::static_query<T,@@ -883,30 +1115,30 @@ 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+    execution::detail::bulk_guarantee::unsequenced_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::bulk_guarantee::unsequenced_t<0>::+    query_static_constexpr_member<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();+    return execution::detail::bulk_guarantee::unsequenced_t<0>::+      query_static_constexpr_member<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+    !execution::detail::bulk_guarantee::unsequenced_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::bulk_guarantee::unsequenced_t<0>::+        query_member<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@@ -927,40 +1159,40 @@ 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+    execution::detail::bulk_guarantee::sequenced_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::bulk_guarantee::sequenced_t<0>::+    query_static_constexpr_member<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();+    return execution::detail::bulk_guarantee::sequenced_t<0>::+      query_static_constexpr_member<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+    execution::detail::bulk_guarantee::parallel_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::bulk_guarantee::parallel_t<0>::+    query_static_constexpr_member<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();+    return execution::detail::bulk_guarantee::parallel_t<0>::+      query_static_constexpr_member<T>::value();   } }; @@ -1014,5 +1246,7 @@ } // namespace asio  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_BULK_GUARANTEE_HPP
link/modules/asio-standalone/asio/include/asio/execution/connect.hpp view
@@ -2,7 +2,7 @@ // execution/connect.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/detail/as_invocable.hpp" #include "asio/execution/detail/as_operation.hpp"@@ -157,7 +160,8 @@   ill_formed }; -template <typename S, typename R, typename = void>+template <typename S, typename R, typename = void,+   typename = void, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -168,13 +172,13 @@ 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-    )+    connect_member<S, R>::is_valid+  >::type,+  typename enable_if<+    is_operation_state<typename connect_member<S, R>::result_type>::value+  >::type,+  typename enable_if<+    is_sender<typename remove_cvref<S>::type>::value   >::type> :   connect_member<S, R> {@@ -184,15 +188,16 @@ 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-    )+    !connect_member<S, R>::is_valid+  >::type,+  typename enable_if<+    connect_free<S, R>::is_valid+  >::type,+  typename enable_if<+    is_operation_state<typename connect_free<S, R>::result_type>::value+  >::type,+  typename enable_if<+    is_sender<typename remove_cvref<S>::type>::value   >::type> :   connect_free<S, R> {@@ -202,24 +207,25 @@ 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-    )+    !connect_member<S, R>::is_valid+  >::type,+  typename enable_if<+    !connect_free<S, R>::is_valid+  >::type,+  typename enable_if<+    is_receiver<R>::value+  >::type,+  typename enable_if<+    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);@@ -482,5 +488,7 @@ #endif // defined(GENERATING_DOCUMENTATION)  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_CONNECT_HPP
link/modules/asio-standalone/asio/include/asio/execution/context.hpp view
@@ -2,7 +2,7 @@ // execution/context.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -69,10 +69,28 @@ struct context_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -86,16 +104,46 @@   {   } +  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, context_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, context_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(context_t::static_query<E>())>@@ -139,8 +187,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -154,20 +213,20 @@ template <typename T> struct static_query<T, execution::context_t,   typename enable_if<-    traits::query_static_constexpr_member<T,-      execution::context_t>::is_valid+    execution::detail::context_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::context_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::context_t>::value();+    return execution::detail::context_t<0>::+      query_static_constexpr_member<T>::value();   } }; 
link/modules/asio-standalone/asio/include/asio/execution/context_as.hpp view
@@ -2,7 +2,7 @@ // execution/context_as.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -68,10 +68,28 @@ struct context_as_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename U>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<U>::value-      || is_sender<U>::value || is_scheduler<U>::value);+    is_applicable_property_v = (+      is_executor<U>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename U>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<U>::value+        || conditional<+            is_executor<U>::value,+            false_type,+            is_sender<U>+          >::type::value+        || conditional<+            is_executor<U>::value,+            false_type,+            is_scheduler<U>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -91,12 +109,12 @@   && defined(ASIO_HAS_SFINAE_VARIABLE_TEMPLATES)   template <typename E>   static ASIO_CONSTEXPR-  typename traits::query_static_constexpr_member<E, context_t>::result_type+  typename context_t::query_static_constexpr_member<E>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<E, context_t>::is_noexcept))+      context_t::query_static_constexpr_member<E>::is_noexcept))   {-    return traits::query_static_constexpr_member<E, context_t>::value();+    return context_t::query_static_constexpr_member<E>::value();   }    template <typename E, typename U = decltype(context_as_t::static_query<E>())>@@ -110,7 +128,9 @@       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,+      typename enable_if<+        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.@@ -150,8 +170,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; 
link/modules/asio-standalone/asio/include/asio/execution/detail/as_invocable.hpp view
@@ -2,7 +2,7 @@ // execution/detail/as_invocable.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/detail/as_operation.hpp view
@@ -2,7 +2,7 @@ // execution/detail/as_operation.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -54,8 +54,12 @@     try     { #endif // !defined(ASIO_NO_EXCEPTIONS)+#if defined(ASIO_NO_DEPRECATED)+      ex_.execute(+#else // defined(ASIO_NO_DEPRECATED)       execution::execute(           ASIO_MOVE_CAST(typename remove_cvref<Executor>::type)(ex_),+#endif // defined(ASIO_NO_DEPRECATED)           as_invocable<typename remove_cvref<Receiver>::type,               Executor>(receiver_ #if !defined(ASIO_HAS_MOVE)
link/modules/asio-standalone/asio/include/asio/execution/detail/as_receiver.hpp view
@@ -2,7 +2,7 @@ // execution/detail/as_receiver.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/detail/bulk_sender.hpp view
@@ -2,7 +2,7 @@ // execution/detail/bulk_sender.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/detail/submit_receiver.hpp view
@@ -2,7 +2,7 @@ // execution/detail/submit_receiver.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/detail/void_receiver.hpp view
@@ -2,7 +2,7 @@ // execution/detail/void_receiver.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/execute.hpp view
@@ -2,7 +2,7 @@ // execution/execute.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/detail/as_invocable.hpp" #include "asio/execution/detail/as_receiver.hpp"@@ -29,7 +32,8 @@ namespace asio { namespace execution { -/// A customisation point that executes a function on an executor.+/// (Deprecated: Use @c execute member function.) A customisation point that+/// executes a function on an executor. /**  * The name <tt>execution::execute</tt> denotes a customisation point object.  *@@ -53,7 +57,8 @@  */ inline constexpr unspecified execute = unspecified; -/// A type trait that determines whether a @c execute expression is well-formed.+/// (Deprecated.) A type trait that determines whether an @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>(),@@ -98,6 +103,7 @@ using asio::traits::execute_free; using asio::traits::execute_member; using asio::true_type;+using asio::void_type;  void execute(); @@ -109,61 +115,52 @@   ill_formed }; -template <typename T, typename F, typename = void>+template <typename Impl, typename T, typename F, typename = void,+    typename = void, typename = void, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed); }; -template <typename T, typename F>-struct call_traits<T, void(F),+template <typename Impl, typename T, typename F>+struct call_traits<Impl, T, void(F),   typename enable_if<-    (-      execute_member<T, F>::is_valid-    )+    execute_member<typename Impl::template proxy<T>::type, F>::is_valid   >::type> :-  execute_member<T, F>+  execute_member<typename Impl::template proxy<T>::type, F> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; -template <typename T, typename F>-struct call_traits<T, void(F),+template <typename Impl, typename T, typename F>+struct call_traits<Impl, T, void(F),   typename enable_if<-    (-      !execute_member<T, F>::is_valid-      &&-      execute_free<T, F>::is_valid-    )+    !execute_member<typename Impl::template proxy<T>, F>::is_valid+  >::type,+  typename enable_if<+    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),+template <typename Impl, typename T, typename F>+struct call_traits<Impl, 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-    )+    !execute_member<typename Impl::template proxy<T>::type, F>::is_valid+  >::type,+  typename enable_if<+    !execute_free<T, F>::is_valid+  >::type,+  typename void_type<+   typename result_of<typename decay<F>::type&()>::type+  >::type,+  typename enable_if<+    !is_as_invocable<typename decay<F>::type>::value+  >::type,+  typename enable_if<+    is_sender_to<T, as_receiver<typename decay<F>::type, T> >::value   >::type> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);@@ -174,44 +171,68 @@  struct impl {+  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)+    struct type+    {+      template <typename F>+      auto execute(ASIO_MOVE_ARG(F) f)+        noexcept(+          noexcept(+            declval<typename conditional<true, T, F>::type>().execute(+              ASIO_MOVE_CAST(F)(f))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, F>::type>().execute(+            ASIO_MOVE_CAST(F)(f))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)+  };+   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+    call_traits<impl, T, void(F)>::overload == call_member,+    typename call_traits<impl, 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))+      call_traits<impl, 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+    call_traits<impl, T, void(F)>::overload == call_free,+    typename call_traits<impl, 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))+      call_traits<impl, 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+    call_traits<impl, T, void(F)>::overload == adapter,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(F)>::is_noexcept))   {     return asio::execution::detail::submit_helper(         ASIO_MOVE_CAST(T)(t),@@ -239,11 +260,14 @@  } // namespace +typedef asio_execution_execute_fn::impl execute_t;+ 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>+    asio_execution_execute_fn::call_traits<+      execute_t, T, void(F)>::overload !=+        asio_execution_execute_fn::ill_formed> { }; @@ -260,5 +284,7 @@ #endif // defined(GENERATING_DOCUMENTATION)  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_EXECUTE_HPP
link/modules/asio-standalone/asio/include/asio/execution/executor.hpp view
@@ -2,7 +2,7 @@ // execution/executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,10 +17,14 @@  #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"+#include "asio/traits/execute_member.hpp" +#if !defined(ASIO_NO_DEPRECATED)+# include "asio/execution/execute.hpp"+#endif // !defined(ASIO_NO_DEPRECATED)+ #if defined(ASIO_HAS_DEDUCED_EXECUTE_FREE_TRAIT) \   && defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) \   && defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT)@@ -35,34 +39,54 @@ 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,+    typename = void, typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void, typename = void>+struct is_executor_of_impl : false_type { };  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+struct is_executor_of_impl<T, F,+#if defined(ASIO_NO_DEPRECATED)+  typename enable_if<+    traits::execute_member<typename add_const<T>::type, F>::is_valid+  >::type,+#else // defined(ASIO_NO_DEPRECATED)+  typename enable_if<+    can_execute<typename add_const<T>::type, F>::value+  >::type,+#endif // defined(ASIO_NO_DEPRECATED)+  typename void_type<+    typename result_of<typename decay<F>::type&()>::type+  >::type,+  typename enable_if<+    is_constructible<typename decay<F>::type, F>::value+  >::type,+  typename enable_if<+    is_move_constructible<typename decay<F>::type>::value+  >::type,+#if defined(ASIO_HAS_NOEXCEPT)+  typename enable_if<+    is_nothrow_copy_constructible<T>::value+  >::type,+  typename enable_if<+    is_nothrow_destructible<T>::value+  >::type,+#else // defined(ASIO_HAS_NOEXCEPT)+  typename enable_if<+    is_copy_constructible<T>::value+  >::type,+  typename enable_if<+    is_destructible<T>::value+  >::type,+#endif // defined(ASIO_HAS_NOEXCEPT)+  typename enable_if<+    traits::equality_comparable<T>::is_valid+  >::type,+  typename enable_if<+    traits::equality_comparable<T>::is_noexcept+  >::type> : true_type { }; 
link/modules/asio-standalone/asio/include/asio/execution/impl/bad_executor.ipp view
@@ -2,7 +2,7 @@ // exection/impl/bad_executor.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/impl/receiver_invocation_error.ipp view
@@ -2,7 +2,7 @@ // exection/impl/receiver_invocation_error.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/invocable_archetype.hpp view
@@ -2,7 +2,7 @@ // execution/invocable_archetype.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/mapping.hpp view
@@ -2,7 +2,7 @@ // execution/mapping.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -192,10 +192,28 @@ struct mapping_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -226,16 +244,74 @@   {   } +  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto query(ASIO_MOVE_ARG(P) p) const+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().query(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().query(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+  };++  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_member :+    traits::query_member<typename proxy<T>::type, mapping_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, mapping_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, mapping_t>::result_type+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, mapping_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, mapping_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename T>@@ -243,9 +319,13 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, thread_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, thread_t>::value();@@ -256,10 +336,16 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, thread_t>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, new_thread_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, new_thread_t>::value();@@ -270,11 +356,19 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, thread_t>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, new_thread_t>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, other_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, other_t>::value();@@ -327,7 +421,9 @@       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,+      typename enable_if<+        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.@@ -347,8 +443,12 @@       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,+      typename enable_if<+        !can_query<const Executor&, new_thread_t>::value+      >::type* = 0,+      typename enable_if<+        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.@@ -402,10 +502,28 @@ struct thread_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -416,26 +534,44 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename mapping_t<I>::template proxy<T>::type, thread_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename mapping_t<I>::template static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, thread_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, thread_t>::value();+    return query_static_constexpr_member<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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::query_free<T, thread_t>::is_valid+      >::type* = 0,+      typename enable_if<+        !can_query<T, new_thread_t<I> >::value+      >::type* = 0,+      typename enable_if<+        !can_query<T, other_t<I> >::value       >::type* = 0) ASIO_NOEXCEPT   {     return thread_t();@@ -476,10 +612,28 @@ struct new_thread_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -490,16 +644,26 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename mapping_t<I>::template proxy<T>::type, new_thread_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename mapping_t<I>::template static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, new_thread_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, new_thread_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(new_thread_t::static_query<E>())>@@ -537,10 +701,28 @@ struct other_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -551,16 +733,26 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename mapping_t<I>::template proxy<T>::type, other_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename mapping_t<I>::template static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, other_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, other_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(other_t::static_query<E>())>@@ -613,8 +805,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -622,8 +825,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -631,8 +845,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -640,8 +865,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -701,28 +937,30 @@ template <typename T> struct static_query<T, execution::mapping_t,   typename enable_if<-    traits::query_static_constexpr_member<T,-      execution::mapping_t>::is_valid+    execution::detail::mapping_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::mapping_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::mapping_t>::value();+    return execution::detail::mapping_t<0>::+      query_static_constexpr_member<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+    !execution::detail::mapping_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::mapping_t<0>::+        query_member<T>::is_valid       && traits::static_query<T, execution::mapping_t::thread_t>::is_valid   >::type> {@@ -741,8 +979,10 @@ 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+    !execution::detail::mapping_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::mapping_t<0>::+        query_member<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>@@ -762,8 +1002,10 @@ 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+    !execution::detail::mapping_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::mapping_t<0>::+        query_member<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@@ -784,29 +1026,30 @@ 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+    execution::detail::mapping::thread_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::mapping::thread_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::mapping_t::thread_t>::value();+    return execution::detail::mapping::thread_t<0>::+      query_static_constexpr_member<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+    !execution::detail::mapping::thread_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::mapping::thread_t<0>::+        query_member<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@@ -826,40 +1069,40 @@ 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+    execution::detail::mapping::new_thread_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::mapping::new_thread_t<0>::+    query_static_constexpr_member<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();+    return execution::detail::mapping::new_thread_t<0>::+      query_static_constexpr_member<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+    execution::detail::mapping::other_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::mapping::other_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::mapping_t::other_t>::value();+    return execution::detail::mapping::other_t<0>::+      query_static_constexpr_member<T>::value();   } }; 
link/modules/asio-standalone/asio/include/asio/execution/occupancy.hpp view
@@ -2,7 +2,7 @@ // execution/occupancy.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -65,10 +65,28 @@ struct occupancy_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -79,16 +97,46 @@   {   } +  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, occupancy_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, occupancy_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(occupancy_t::static_query<E>())>@@ -132,8 +180,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -147,20 +206,20 @@ template <typename T> struct static_query<T, execution::occupancy_t,   typename enable_if<-    traits::query_static_constexpr_member<T,-      execution::occupancy_t>::is_valid+    execution::detail::occupancy_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::occupancy_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::occupancy_t>::value();+    return execution::detail::occupancy_t<0>::+      query_static_constexpr_member<T>::value();   } }; 
link/modules/asio-standalone/asio/include/asio/execution/operation_state.hpp view
@@ -2,7 +2,7 @@ // execution/operation_state.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/start.hpp" @@ -90,5 +93,7 @@ } // namespace asio  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_OPERATION_STATE_HPP
link/modules/asio-standalone/asio/include/asio/execution/outstanding_work.hpp view
@@ -2,7 +2,7 @@ // execution/outstanding_work.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -158,10 +158,28 @@ struct outstanding_work_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -186,20 +204,74 @@   {   } +  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto query(ASIO_MOVE_ARG(P) p) const+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().query(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().query(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+  };++  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_member :+    traits::query_member<typename proxy<T>::type, outstanding_work_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, outstanding_work_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, outstanding_work_t>::result_type+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<-        T, outstanding_work_t-      >::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<-        T, outstanding_work_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename T>@@ -207,10 +279,13 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, untracked_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, untracked_t>::value();@@ -221,11 +296,16 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, untracked_t>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, tracked_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, tracked_t>::value();@@ -282,7 +362,9 @@       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,+      typename enable_if<+        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.@@ -335,10 +417,28 @@ struct untracked_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -349,25 +449,42 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename outstanding_work_t<I>::template proxy<T>::type, untracked_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename outstanding_work_t<I>::template static_proxy<T>::type,+        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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, untracked_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, untracked_t>::value();+    return query_static_constexpr_member<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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::query_free<T, untracked_t>::is_valid+      >::type* = 0,+      typename enable_if<+        !can_query<T, tracked_t<I> >::value       >::type* = 0) ASIO_NOEXCEPT   {     return untracked_t();@@ -408,10 +525,28 @@ struct tracked_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -422,16 +557,27 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename outstanding_work_t<I>::template proxy<T>::type, tracked_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename outstanding_work_t<I>::template static_proxy<T>::type,+        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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, tracked_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, tracked_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E, typename T = decltype(tracked_t::static_query<E>())>@@ -485,8 +631,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -494,8 +651,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -503,8 +671,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -549,30 +728,30 @@ 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+    execution::detail::outstanding_work_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::outstanding_work_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::outstanding_work_t>::value();+    return execution::detail::outstanding_work_t<0>::+      query_static_constexpr_member<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+    !execution::detail::outstanding_work_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::outstanding_work_t<0>::+        query_member<T>::is_valid       && traits::static_query<T,         execution::outstanding_work_t::untracked_t>::is_valid   >::type>@@ -593,10 +772,10 @@ 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+    !execution::detail::outstanding_work_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::outstanding_work_t<0>::+        query_member<T>::is_valid       && !traits::static_query<T,         execution::outstanding_work_t::untracked_t>::is_valid       && traits::static_query<T,@@ -619,30 +798,30 @@ 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+    execution::detail::outstanding_work::untracked_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::outstanding_work::untracked_t<0>::+    query_static_constexpr_member<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();+    return execution::detail::outstanding_work::untracked_t<0>::+      query_static_constexpr_member<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+    !execution::detail::outstanding_work::untracked_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::outstanding_work::untracked_t<0>::+          query_member<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@@ -662,20 +841,20 @@ 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+    execution::detail::outstanding_work::tracked_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::outstanding_work::tracked_t<0>::+    query_static_constexpr_member<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();+    return execution::detail::outstanding_work::tracked_t<0>::+      query_static_constexpr_member<T>::value();   } }; 
link/modules/asio-standalone/asio/include/asio/execution/prefer_only.hpp view
@@ -2,7 +2,7 @@ // execution/prefer_only.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -220,7 +220,9 @@   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,+      typename enable_if<+        can_prefer<const Executor&, const InnerProperty&>::value       >::type* = 0) #if !defined(ASIO_MSVC) \   && !defined(__clang__) // Clang crashes if noexcept is used here.@@ -238,7 +240,9 @@   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,+      typename enable_if<+        can_query<const Executor&, const InnerProperty&>::value       >::type* = 0) #if !defined(ASIO_MSVC) \   && !defined(__clang__) // Clang crashes if noexcept is used here.
link/modules/asio-standalone/asio/include/asio/execution/receiver.hpp view
@@ -2,7 +2,7 @@ // execution/receiver.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/detail/variadic_templates.hpp" #include "asio/execution/set_done.hpp"@@ -276,5 +279,7 @@ } // namespace asio  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_RECEIVER_HPP
link/modules/asio-standalone/asio/include/asio/execution/receiver_invocation_error.hpp view
@@ -2,7 +2,7 @@ // execution/receiver_invocation_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/execution/relationship.hpp view
@@ -2,7 +2,7 @@ // execution/relationship.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -157,10 +157,28 @@ struct relationship_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = false);@@ -185,20 +203,74 @@   {   } +  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto query(ASIO_MOVE_ARG(P) p) const+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().query(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().query(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+  };++  template <typename T>+  struct static_proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      static constexpr auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          conditional<true, T, P>::type::query(ASIO_MOVE_CAST(P)(p))+        )+      {+        return T::query(ASIO_MOVE_CAST(P)(p));+      }+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)+  };++  template <typename T>+  struct query_member :+    traits::query_member<typename proxy<T>::type, relationship_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename static_proxy<T>::type, relationship_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, relationship_t>::result_type+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<-        T, relationship_t-      >::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<-        T, relationship_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename T>@@ -206,10 +278,13 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, fork_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, fork_t>::value();@@ -220,11 +295,16 @@   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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::static_query<T, fork_t>::is_valid+      >::type* = 0,+      typename enable_if<+        traits::static_query<T, continuation_t>::is_valid       >::type* = 0) ASIO_NOEXCEPT   {     return traits::static_query<T, continuation_t>::value();@@ -280,7 +360,9 @@       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,+      typename enable_if<+        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.@@ -333,10 +415,28 @@ struct fork_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -347,25 +447,41 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename relationship_t<I>::template proxy<T>::type, fork_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename relationship_t<I>::template static_proxy<T>::type, 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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, fork_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, fork_t>::value();+    return query_static_constexpr_member<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+        !query_static_constexpr_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !query_member<T>::is_valid+      >::type* = 0,+      typename enable_if<+        !traits::query_free<T, fork_t>::is_valid+      >::type* = 0,+      typename enable_if<+        !can_query<T, continuation_t<I> >::value       >::type* = 0) ASIO_NOEXCEPT   {     return fork_t();@@ -406,10 +522,28 @@ struct continuation_t { #if defined(ASIO_HAS_VARIABLE_TEMPLATES)+# if defined(ASIO_NO_DEPRECATED)   template <typename T>   ASIO_STATIC_CONSTEXPR(bool,-    is_applicable_property_v = is_executor<T>::value-      || is_sender<T>::value || is_scheduler<T>::value);+    is_applicable_property_v = (+      is_executor<T>::value));+# else // defined(ASIO_NO_DEPRECATED)+  template <typename T>+  ASIO_STATIC_CONSTEXPR(bool,+    is_applicable_property_v = (+      is_executor<T>::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_sender<T>+          >::type::value+        || conditional<+            is_executor<T>::value,+            false_type,+            is_scheduler<T>+          >::type::value+      ));+# endif // defined(ASIO_NO_DEPRECATED) #endif // defined(ASIO_HAS_VARIABLE_TEMPLATES)    ASIO_STATIC_CONSTEXPR(bool, is_requirable = true);@@ -420,16 +554,27 @@   {   } +  template <typename T>+  struct query_member :+    traits::query_member<+      typename relationship_t<I>::template proxy<T>::type, continuation_t> {};++  template <typename T>+  struct query_static_constexpr_member :+    traits::query_static_constexpr_member<+      typename relationship_t<I>::template static_proxy<T>::type,+        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+  typename query_static_constexpr_member<T>::result_type   static_query()     ASIO_NOEXCEPT_IF((-      traits::query_static_constexpr_member<T, continuation_t>::is_noexcept))+      query_static_constexpr_member<T>::is_noexcept))   {-    return traits::query_static_constexpr_member<T, continuation_t>::value();+    return query_static_constexpr_member<T>::value();   }    template <typename E,@@ -484,8 +629,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -493,8 +649,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -502,8 +669,19 @@ 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>+#if !defined(ASIO_NO_DEPRECATED)+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_sender<T>+          >::type::value+        || conditional<+            execution::is_executor<T>::value,+            false_type,+            execution::is_scheduler<T>+          >::type::value+#endif // !defined(ASIO_NO_DEPRECATED)+    > { }; @@ -548,30 +726,30 @@ template <typename T> struct static_query<T, execution::relationship_t,   typename enable_if<-    traits::query_static_constexpr_member<T,-      execution::relationship_t>::is_valid+    execution::detail::relationship_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::relationship_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::relationship_t>::value();+    return execution::detail::relationship_t<0>::+      query_static_constexpr_member<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+    !execution::detail::relationship_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::relationship_t<0>::+        query_member<T>::is_valid       && traits::static_query<T,         execution::relationship_t::fork_t>::is_valid   >::type>@@ -592,10 +770,10 @@ 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+    !execution::detail::relationship_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::relationship_t<0>::+        query_member<T>::is_valid       && !traits::static_query<T,         execution::relationship_t::fork_t>::is_valid       && traits::static_query<T,@@ -618,30 +796,30 @@ 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+    execution::detail::relationship::fork_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::relationship::fork_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::relationship_t::fork_t>::value();+    return execution::detail::relationship::fork_t<0>::+      query_static_constexpr_member<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+    !execution::detail::relationship::fork_t<0>::+        query_static_constexpr_member<T>::is_valid+      && !execution::detail::relationship::fork_t<0>::+        query_member<T>::is_valid       && !traits::query_free<T,         execution::relationship_t::fork_t>::is_valid       && !can_query<T, execution::relationship_t::continuation_t>::value@@ -661,20 +839,20 @@ 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+    execution::detail::relationship::continuation_t<0>::+      query_static_constexpr_member<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;+  typedef typename execution::detail::relationship::continuation_t<0>::+    query_static_constexpr_member<T>::result_type result_type;    static ASIO_CONSTEXPR result_type value()   {-    return traits::query_static_constexpr_member<T,-      execution::relationship_t::continuation_t>::value();+    return execution::detail::relationship::continuation_t<0>::+      query_static_constexpr_member<T>::value();   } }; 
link/modules/asio-standalone/asio/include/asio/execution/schedule.hpp view
@@ -2,7 +2,7 @@ // execution/schedule.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/executor.hpp" #include "asio/traits/schedule_member.hpp"@@ -86,7 +89,7 @@   ill_formed }; -template <typename S, typename = void>+template <typename S, typename = void, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -97,9 +100,7 @@ template <typename S> struct call_traits<S,   typename enable_if<-    (-      schedule_member<S>::is_valid-    )+    schedule_member<S>::is_valid   >::type> :   schedule_member<S> {@@ -109,11 +110,10 @@ template <typename S> struct call_traits<S,   typename enable_if<-    (-      !schedule_member<S>::is_valid-      &&-      schedule_free<S>::is_valid-    )+    !schedule_member<S>::is_valid+  >::type,+  typename enable_if<+    schedule_free<S>::is_valid   >::type> :   schedule_free<S> {@@ -123,13 +123,13 @@ 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-    )+    !schedule_member<S>::is_valid+  >::type,+  typename enable_if<+    !schedule_free<S>::is_valid+  >::type,+  typename enable_if<+    is_executor<typename decay<S>::type>::value   >::type> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -286,5 +286,7 @@ #endif // defined(GENERATING_DOCUMENTATION)  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_SCHEDULE_HPP
link/modules/asio-standalone/asio/include/asio/execution/scheduler.hpp view
@@ -2,7 +2,7 @@ // execution/scheduler.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/schedule.hpp" #include "asio/traits/equality_comparable.hpp"@@ -82,5 +85,7 @@ } // namespace asio  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_SCHEDULER_HPP
link/modules/asio-standalone/asio/include/asio/execution/sender.hpp view
@@ -2,7 +2,7 @@ // execution/sender.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/detail/as_invocable.hpp" #include "asio/execution/detail/void_receiver.hpp"@@ -307,5 +310,7 @@ #include "asio/detail/pop_options.hpp"  #include "asio/execution/connect.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_SENDER_HPP
link/modules/asio-standalone/asio/include/asio/execution/set_done.hpp view
@@ -2,7 +2,7 @@ // execution/set_done.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/traits/set_done_member.hpp" #include "asio/traits/set_done_free.hpp"@@ -83,7 +86,7 @@   ill_formed }; -template <typename R, typename = void>+template <typename R, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -94,9 +97,7 @@ template <typename R> struct call_traits<R,   typename enable_if<-    (-      set_done_member<R>::is_valid-    )+    set_done_member<R>::is_valid   >::type> :   set_done_member<R> {@@ -106,11 +107,10 @@ template <typename R> struct call_traits<R,   typename enable_if<-    (-      !set_done_member<R>::is_valid-      &&-      set_done_free<R>::is_valid-    )+    !set_done_member<R>::is_valid+  >::type,+  typename enable_if<+    set_done_free<R>::is_valid   >::type> :   set_done_free<R> {@@ -249,5 +249,7 @@ #endif // defined(GENERATING_DOCUMENTATION)  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_SET_DONE_HPP
link/modules/asio-standalone/asio/include/asio/execution/set_error.hpp view
@@ -2,7 +2,7 @@ // execution/set_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/traits/set_error_member.hpp" #include "asio/traits/set_error_free.hpp"@@ -83,7 +86,7 @@   ill_formed }; -template <typename R, typename E, typename = void>+template <typename R, typename E, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -94,9 +97,7 @@ template <typename R, typename E> struct call_traits<R, void(E),   typename enable_if<-    (-      set_error_member<R, E>::is_valid-    )+    set_error_member<R, E>::is_valid   >::type> :   set_error_member<R, E> {@@ -106,11 +107,10 @@ 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-    )+    !set_error_member<R, E>::is_valid+  >::type,+  typename enable_if<+    set_error_free<R, E>::is_valid   >::type> :   set_error_free<R, E> {@@ -249,5 +249,7 @@ #endif // defined(GENERATING_DOCUMENTATION)  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_SET_ERROR_HPP
link/modules/asio-standalone/asio/include/asio/execution/set_value.hpp view
@@ -2,7 +2,7 @@ // execution/set_value.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/detail/variadic_templates.hpp" #include "asio/traits/set_value_member.hpp"@@ -86,7 +89,7 @@   ill_formed }; -template <typename R, typename Vs, typename = void>+template <typename R, typename Vs, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -97,9 +100,7 @@ template <typename R, typename Vs> struct call_traits<R, Vs,   typename enable_if<-    (-      set_value_member<R, Vs>::is_valid-    )+    set_value_member<R, Vs>::is_valid   >::type> :   set_value_member<R, Vs> {@@ -109,11 +110,10 @@ 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-    )+    !set_value_member<R, Vs>::is_valid+  >::type,+  typename enable_if<+    set_value_free<R, Vs>::is_valid   >::type> :   set_value_free<R, Vs> {@@ -482,5 +482,7 @@ #endif // defined(GENERATING_DOCUMENTATION)  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_SET_VALUE_HPP
link/modules/asio-standalone/asio/include/asio/execution/start.hpp view
@@ -2,7 +2,7 @@ // execution/start.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/traits/start_member.hpp" #include "asio/traits/start_free.hpp"@@ -80,7 +83,7 @@   ill_formed }; -template <typename R, typename = void>+template <typename R, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -91,9 +94,7 @@ template <typename R> struct call_traits<R,   typename enable_if<-    (-      start_member<R>::is_valid-    )+    start_member<R>::is_valid   >::type> :   start_member<R> {@@ -103,11 +104,10 @@ template <typename R> struct call_traits<R,   typename enable_if<-    (-      !start_member<R>::is_valid-      &&-      start_free<R>::is_valid-    )+    !start_member<R>::is_valid+  >::type,+  typename enable_if<+    start_free<R>::is_valid   >::type> :   start_free<R> {@@ -246,5 +246,7 @@ #endif // defined(GENERATING_DOCUMENTATION)  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_START_HPP
link/modules/asio-standalone/asio/include/asio/execution/submit.hpp view
@@ -2,7 +2,7 @@ // execution/submit.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,9 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"++#if !defined(ASIO_NO_DEPRECATED)+ #include "asio/detail/type_traits.hpp" #include "asio/execution/detail/submit_receiver.hpp" #include "asio/execution/executor.hpp"@@ -125,7 +128,8 @@   ill_formed }; -template <typename S, typename R, typename = void>+template <typename S, typename R, typename = void,+    typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -136,11 +140,10 @@ 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-    )+    submit_member<S, R>::is_valid+  >::type,+  typename enable_if<+    is_sender_to<S, R>::value   >::type> :   submit_member<S, R> {@@ -150,13 +153,13 @@ 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-    )+    !submit_member<S, R>::is_valid+  >::type,+  typename enable_if<+    submit_free<S, R>::is_valid+  >::type,+  typename enable_if<+    is_sender_to<S, R>::value   >::type> :   submit_free<S, R> {@@ -166,13 +169,13 @@ 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-    )+    !submit_member<S, R>::is_valid+  >::type,+  typename enable_if<+    !submit_free<S, R>::is_valid+  >::type,+  typename enable_if<+    is_sender_to<S, R>::value   >::type> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = adapter);@@ -446,5 +449,7 @@ #endif // defined(GENERATING_DOCUMENTATION)  #include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_NO_DEPRECATED)  #endif // ASIO_EXECUTION_SUBMIT_HPP
link/modules/asio-standalone/asio/include/asio/execution_context.hpp view
@@ -2,7 +2,7 @@ // execution_context.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/executor.hpp view
@@ -2,7 +2,7 @@ // executor.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/executor_work_guard.hpp view
@@ -2,7 +2,7 @@ // executor_work_guard.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,8 +17,6 @@  #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"@@ -31,18 +29,16 @@ #if !defined(ASIO_EXECUTOR_WORK_GUARD_DECL) #define ASIO_EXECUTOR_WORK_GUARD_DECL -template <typename Executor, typename = void>+template <typename Executor, typename = void, 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)++/// An object of type @c executor_work_guard controls ownership of outstanding+/// executor work within a scope. template <typename Executor>-#else // defined(GENERATING_DOCUMENTATION)-template <typename Executor, typename>-#endif // defined(GENERATING_DOCUMENTATION) class executor_work_guard { public:@@ -53,6 +49,50 @@   /**    * 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;++  /// Copy constructor.+  executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT;++  /// Move constructor.+  executor_work_guard(executor_work_guard&& other) ASIO_NOEXCEPT;++  /// 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();++  /// Obtain the associated executor.+  executor_type get_executor() const ASIO_NOEXCEPT;++  /// Whether the executor_work_guard object owns some outstanding work.+  bool owns_work() const ASIO_NOEXCEPT;++  /// 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;+};++#endif // defined(GENERATING_DOCUMENTATION)++#if !defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Executor>+class executor_work_guard<Executor,+    typename enable_if<+      is_executor<Executor>::value+    >::type>+{+public:+  typedef Executor executor_type;+   explicit executor_work_guard(const executor_type& e) ASIO_NOEXCEPT     : executor_(e),       owns_(true)@@ -60,7 +100,6 @@     executor_.on_work_started();   } -  /// Copy constructor.   executor_work_guard(const executor_work_guard& other) ASIO_NOEXCEPT     : executor_(other.executor_),       owns_(other.owns_)@@ -69,44 +108,31 @@       executor_.on_work_started();   } -#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)-  /// Move constructor.+#if defined(ASIO_HAS_MOVE)   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)+#endif // defined(ASIO_HAS_MOVE) -  /// 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_)@@ -124,12 +150,15 @@   bool owns_; }; -#if !defined(GENERATING_DOCUMENTATION)+#endif // !defined(ASIO_NO_TS_EXECUTORS)  template <typename Executor> class executor_work_guard<Executor,     typename enable_if<-      !is_executor<Executor>::value && execution::is_executor<Executor>::value+      !is_executor<Executor>::value+    >::type,+    typename enable_if<+      execution::is_executor<Executor>::value     >::type> { public:@@ -215,62 +244,115 @@ #endif // !defined(GENERATING_DOCUMENTATION)  /// Create an @ref executor_work_guard object.+/**+ * @param ex An executor.+ *+ * @returns A work guard constructed with the specified executor.+ */ template <typename Executor>-inline executor_work_guard<Executor> make_work_guard(const Executor& ex,-    typename enable_if<+ASIO_NODISCARD inline executor_work_guard<Executor>+make_work_guard(const Executor& ex,+    typename constraint<       is_executor<Executor>::value || execution::is_executor<Executor>::value-    >::type* = 0)+    >::type = 0) {   return executor_work_guard<Executor>(ex); }  /// Create an @ref executor_work_guard object.+/**+ * @param ctx An execution context, from which an executor will be obtained.+ *+ * @returns A work guard constructed with the execution context's executor,+ * obtained by performing <tt>ctx.get_executor()</tt>.+ */ template <typename ExecutionContext>-inline executor_work_guard<typename ExecutionContext::executor_type>+ASIO_NODISCARD inline+executor_work_guard<typename ExecutionContext::executor_type> make_work_guard(ExecutionContext& ctx,-    typename enable_if<+    typename constraint<       is_convertible<ExecutionContext&, execution_context&>::value-    >::type* = 0)+    >::type = 0) {   return executor_work_guard<typename ExecutionContext::executor_type>(       ctx.get_executor()); }  /// Create an @ref executor_work_guard object.+/**+ * @param t An arbitrary object, such as a completion handler, for which the+ * associated executor will be obtained.+ *+ * @returns A work guard constructed with the associated executor of the object+ * @c t, which is obtained as if by calling <tt>get_associated_executor(t)</tt>.+ */ 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)+ASIO_NODISCARD inline+executor_work_guard<+    typename constraint<+      !is_executor<T>::value+        && !execution::is_executor<T>::value+        && !is_convertible<T&, execution_context&>::value,+      associated_executor<T>+    >::type::type>+make_work_guard(const T& t) {   return executor_work_guard<typename associated_executor<T>::type>(       associated_executor<T>::get(t)); }  /// Create an @ref executor_work_guard object.+/**+ * @param t An arbitrary object, such as a completion handler, for which the+ * associated executor will be obtained.+ *+ * @param ex An executor to be used as the candidate object when determining the+ * associated executor.+ *+ * @returns A work guard constructed with the associated executor of the object+ * @c t, which is obtained as if by calling <tt>get_associated_executor(t,+ * ex)</tt>.+ */ template <typename T, typename Executor>-inline executor_work_guard<typename associated_executor<T, Executor>::type>+ASIO_NODISCARD inline+executor_work_guard<typename associated_executor<T, Executor>::type> make_work_guard(const T& t, const Executor& ex,-    typename enable_if<+    typename constraint<       is_executor<Executor>::value || execution::is_executor<Executor>::value-    >::type* = 0)+    >::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.+/**+ * @param t An arbitrary object, such as a completion handler, for which the+ * associated executor will be obtained.+ *+ * @param ctx An execution context, from which an executor is obtained to use as+ * the candidate object for determining the associated executor.+ *+ * @returns A work guard constructed with the associated executor of the object+ * @c t, which is obtained as if by calling <tt>get_associated_executor(t,+ * ctx.get_executor())</tt>.+ */ template <typename T, typename ExecutionContext>-inline executor_work_guard<typename associated_executor<T,+ASIO_NODISCARD 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)+    typename constraint<+      !is_executor<T>::value+    >::type = 0,+    typename constraint<+      !execution::is_executor<T>::value+    >::type = 0,+    typename constraint<+      !is_convertible<T&, execution_context&>::value+    >::type = 0,+    typename constraint<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type = 0) {   return executor_work_guard<typename associated_executor<T,     typename ExecutionContext::executor_type>::type>(@@ -281,7 +363,5 @@ } // 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/experimental/append.hpp view
@@ -0,0 +1,36 @@+//+// experimental/append.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_APPEND_HPP+#define ASIO_EXPERIMENTAL_APPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/append.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if !defined(ASIO_NO_DEPRECATED)+using asio::append_t;+using asio::append;+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_APPEND_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/as_single.hpp view
@@ -0,0 +1,136 @@+//+// experimental/as_single.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_AS_SINGLE_HPP+#define ASIO_EXPERIMENTAL_AS_SINGLE_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 experimental {++/// A @ref completion_token adapter used to specify that the completion handler+/// arguments should be combined into a single argument.+/**+ * The as_single_t class is used to indicate that any arguments to the+ * completion handler should be combined and passed as a single argument.+ * If there is already one argument, that argument is passed as-is. If+ * there is more than argument, the arguments are first moved into a+ * @c std::tuple and that tuple is then passed to the completion handler.+ */+template <typename CompletionToken>+class as_single_t+{+public:+  /// Tag type used to prevent the "default" constructor from being used for+  /// conversions.+  struct default_constructor_tag {};++  /// Default constructor.+  /**+   * This constructor is only valid if the underlying completion token is+   * default constructible and move constructible. The underlying completion+   * token is itself defaulted as an argument to allow it to capture a source+   * location.+   */+  ASIO_CONSTEXPR as_single_t(+      default_constructor_tag = default_constructor_tag(),+      CompletionToken token = CompletionToken())+    : token_(ASIO_MOVE_CAST(CompletionToken)(token))+  {+  }++  /// Constructor.+  template <typename T>+  ASIO_CONSTEXPR explicit as_single_t(+      ASIO_MOVE_ARG(T) completion_token)+    : token_(ASIO_MOVE_CAST(T)(completion_token))+  {+  }++  /// Adapts an executor to add the @c as_single_t completion token as the+  /// default.+  template <typename InnerExecutor>+  struct executor_with_default : InnerExecutor+  {+    /// Specify @c as_single_t as the default completion token type.+    typedef as_single_t default_completion_token_type;++    /// Construct the adapted executor from the inner executor type.+    executor_with_default(const InnerExecutor& ex) ASIO_NOEXCEPT+      : InnerExecutor(ex)+    {+    }++    /// Convert the specified executor to the inner executor type, then use+    /// that to construct the adapted executor.+    template <typename OtherExecutor>+    executor_with_default(const OtherExecutor& ex,+        typename constraint<+          is_convertible<OtherExecutor, InnerExecutor>::value+        >::type = 0) ASIO_NOEXCEPT+      : InnerExecutor(ex)+    {+    }+  };++  /// Type alias to adapt an I/O object to use @c as_single_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 as_single_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));+  }++//private:+  CompletionToken token_;+};++/// Adapt a @ref completion_token to specify that the completion handler+/// arguments should be combined into a single argument.+template <typename CompletionToken>+ASIO_NODISCARD inline+ASIO_CONSTEXPR as_single_t<typename decay<CompletionToken>::type>+as_single(ASIO_MOVE_ARG(CompletionToken) completion_token)+{+  return as_single_t<typename decay<CompletionToken>::type>(+      ASIO_MOVE_CAST(CompletionToken)(completion_token));+}++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/as_single.hpp"++#endif // ASIO_EXPERIMENTAL_AS_SINGLE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/as_tuple.hpp view
@@ -0,0 +1,36 @@+//+// experimental/as_tuple.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_AS_TUPLE_HPP+#define ASIO_EXPERIMENTAL_AS_TUPLE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/as_tuple.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if !defined(ASIO_NO_DEPRECATED)+using asio::as_tuple_t;+using asio::as_tuple;+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_AS_TUPLE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/awaitable_operators.hpp view
@@ -0,0 +1,536 @@+//+// experimental/awaitable_operators.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_AWAITABLE_OPERATORS_HPP+#define ASIO_EXPERIMENTAL_AWAITABLE_OPERATORS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <optional>+#include <stdexcept>+#include <tuple>+#include <variant>+#include "asio/awaitable.hpp"+#include "asio/co_spawn.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/experimental/deferred.hpp"+#include "asio/experimental/parallel_group.hpp"+#include "asio/multiple_exceptions.hpp"+#include "asio/this_coro.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace awaitable_operators {+namespace detail {++template <typename T, typename Executor>+awaitable<T, Executor> awaitable_wrap(awaitable<T, Executor> a,+    typename constraint<is_constructible<T>::value>::type* = 0)+{+  return a;+}++template <typename T, typename Executor>+awaitable<std::optional<T>, Executor> awaitable_wrap(awaitable<T, Executor> a,+    typename constraint<!is_constructible<T>::value>::type* = 0)+{+  co_return std::optional<T>(co_await std::move(a));+}++template <typename T>+T& awaitable_unwrap(typename conditional<true, T, void>::type& r,+    typename constraint<is_constructible<T>::value>::type* = 0)+{+  return r;+}++template <typename T>+T& awaitable_unwrap(std::optional<typename conditional<true, T, void>::type>& r,+    typename constraint<!is_constructible<T>::value>::type* = 0)+{+  return *r;+}++} // namespace detail++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename Executor>+awaitable<void, Executor> operator&&(+    awaitable<void, Executor> t, awaitable<void, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, ex1] =+    co_await make_parallel_group(+      co_spawn(ex, std::move(t), deferred),+      co_spawn(ex, std::move(u), deferred)+    ).async_wait(+      wait_for_one_error(),+      deferred+    );++  if (ex0 && ex1)+    throw multiple_exceptions(ex0);+  if (ex0)+    std::rethrow_exception(ex0);+  if (ex1)+    std::rethrow_exception(ex1);+  co_return;+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename U, typename Executor>+awaitable<U, Executor> operator&&(+    awaitable<void, Executor> t, awaitable<U, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, ex1, r1] =+    co_await make_parallel_group(+      co_spawn(ex, std::move(t), deferred),+      co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+    ).async_wait(+      wait_for_one_error(),+      deferred+    );++  if (ex0 && ex1)+    throw multiple_exceptions(ex0);+  if (ex0)+    std::rethrow_exception(ex0);+  if (ex1)+    std::rethrow_exception(ex1);+  co_return std::move(detail::awaitable_unwrap<U>(r1));+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename T, typename Executor>+awaitable<T, Executor> operator&&(+    awaitable<T, Executor> t, awaitable<void, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, r0, ex1] =+    co_await make_parallel_group(+      co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+      co_spawn(ex, std::move(u), deferred)+    ).async_wait(+      wait_for_one_error(),+      deferred+    );++  if (ex0 && ex1)+    throw multiple_exceptions(ex0);+  if (ex0)+    std::rethrow_exception(ex0);+  if (ex1)+    std::rethrow_exception(ex1);+  co_return std::move(detail::awaitable_unwrap<T>(r0));+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename T, typename U, typename Executor>+awaitable<std::tuple<T, U>, Executor> operator&&(+    awaitable<T, Executor> t, awaitable<U, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, r0, ex1, r1] =+    co_await make_parallel_group(+      co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+      co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+    ).async_wait(+      wait_for_one_error(),+      deferred+    );++  if (ex0 && ex1)+    throw multiple_exceptions(ex0);+  if (ex0)+    std::rethrow_exception(ex0);+  if (ex1)+    std::rethrow_exception(ex1);+  co_return std::make_tuple(+      std::move(detail::awaitable_unwrap<T>(r0)),+      std::move(detail::awaitable_unwrap<U>(r1)));+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename... T, typename Executor>+awaitable<std::tuple<T..., std::monostate>, Executor> operator&&(+    awaitable<std::tuple<T...>, Executor> t, awaitable<void, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, r0, ex1, r1] =+    co_await make_parallel_group(+      co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+      co_spawn(ex, std::move(u), deferred)+    ).async_wait(+      wait_for_one_error(),+      deferred+    );++  if (ex0 && ex1)+    throw multiple_exceptions(ex0);+  if (ex0)+    std::rethrow_exception(ex0);+  if (ex1)+    std::rethrow_exception(ex1);+  co_return std::move(detail::awaitable_unwrap<std::tuple<T...>>(r0));+}++/// Wait for both operations to succeed.+/**+ * If one operations fails, the other is cancelled as the AND-condition can no+ * longer be satisfied.+ */+template <typename... T, typename U, typename Executor>+awaitable<std::tuple<T..., U>, Executor> operator&&(+    awaitable<std::tuple<T...>, Executor> t, awaitable<U, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, r0, ex1, r1] =+    co_await make_parallel_group(+      co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+      co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+    ).async_wait(+      wait_for_one_error(),+      deferred+    );++  if (ex0 && ex1)+    throw multiple_exceptions(ex0);+  if (ex0)+    std::rethrow_exception(ex0);+  if (ex1)+    std::rethrow_exception(ex1);+  co_return std::tuple_cat(+      std::move(detail::awaitable_unwrap<std::tuple<T...>>(r0)),+      std::make_tuple(std::move(detail::awaitable_unwrap<U>(r1))));+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename Executor>+awaitable<std::variant<std::monostate, std::monostate>, Executor> operator||(+    awaitable<void, Executor> t, awaitable<void, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, ex1] =+    co_await make_parallel_group(+      co_spawn(ex, std::move(t), deferred),+      co_spawn(ex, std::move(u), deferred)+    ).async_wait(+      wait_for_one_success(),+      deferred+    );++  if (order[0] == 0)+  {+    if (!ex0)+      co_return std::variant<std::monostate, std::monostate>{+          std::in_place_index<0>};+    if (!ex1)+      co_return std::variant<std::monostate, std::monostate>{+          std::in_place_index<1>};+    throw multiple_exceptions(ex0);+  }+  else+  {+    if (!ex1)+      co_return std::variant<std::monostate, std::monostate>{+          std::in_place_index<1>};+    if (!ex0)+      co_return std::variant<std::monostate, std::monostate>{+          std::in_place_index<0>};+    throw multiple_exceptions(ex1);+  }+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename U, typename Executor>+awaitable<std::variant<std::monostate, U>, Executor> operator||(+    awaitable<void, Executor> t, awaitable<U, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, ex1, r1] =+    co_await make_parallel_group(+      co_spawn(ex, std::move(t), deferred),+      co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+    ).async_wait(+      wait_for_one_success(),+      deferred+    );++  if (order[0] == 0)+  {+    if (!ex0)+      co_return std::variant<std::monostate, U>{+          std::in_place_index<0>};+    if (!ex1)+      co_return std::variant<std::monostate, U>{+          std::in_place_index<1>,+          std::move(detail::awaitable_unwrap<U>(r1))};+    throw multiple_exceptions(ex0);+  }+  else+  {+    if (!ex1)+      co_return std::variant<std::monostate, U>{+          std::in_place_index<1>,+          std::move(detail::awaitable_unwrap<U>(r1))};+    if (!ex0)+      co_return std::variant<std::monostate, U>{+          std::in_place_index<0>};+    throw multiple_exceptions(ex1);+  }+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename T, typename Executor>+awaitable<std::variant<T, std::monostate>, Executor> operator||(+    awaitable<T, Executor> t, awaitable<void, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, r0, ex1] =+    co_await make_parallel_group(+      co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+      co_spawn(ex, std::move(u), deferred)+    ).async_wait(+      wait_for_one_success(),+      deferred+    );++  if (order[0] == 0)+  {+    if (!ex0)+      co_return std::variant<T, std::monostate>{+          std::in_place_index<0>,+          std::move(detail::awaitable_unwrap<T>(r0))};+    if (!ex1)+      co_return std::variant<T, std::monostate>{+          std::in_place_index<1>};+    throw multiple_exceptions(ex0);+  }+  else+  {+    if (!ex1)+      co_return std::variant<T, std::monostate>{+          std::in_place_index<1>};+    if (!ex0)+      co_return std::variant<T, std::monostate>{+          std::in_place_index<0>,+          std::move(detail::awaitable_unwrap<T>(r0))};+    throw multiple_exceptions(ex1);+  }+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename T, typename U, typename Executor>+awaitable<std::variant<T, U>, Executor> operator||(+    awaitable<T, Executor> t, awaitable<U, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, r0, ex1, r1] =+    co_await make_parallel_group(+      co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+      co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+    ).async_wait(+      wait_for_one_success(),+      deferred+    );++  if (order[0] == 0)+  {+    if (!ex0)+      co_return std::variant<T, U>{+          std::in_place_index<0>,+          std::move(detail::awaitable_unwrap<T>(r0))};+    if (!ex1)+      co_return std::variant<T, U>{+          std::in_place_index<1>,+          std::move(detail::awaitable_unwrap<U>(r1))};+    throw multiple_exceptions(ex0);+  }+  else+  {+    if (!ex1)+      co_return std::variant<T, U>{+          std::in_place_index<1>,+          std::move(detail::awaitable_unwrap<U>(r1))};+    if (!ex0)+      co_return std::variant<T, U>{+          std::in_place_index<0>,+          std::move(detail::awaitable_unwrap<T>(r0))};+    throw multiple_exceptions(ex1);+  }+}++namespace detail {++template <typename... T>+struct widen_variant+{+  template <std::size_t I, typename SourceVariant>+  static std::variant<T...> call(SourceVariant& source)+  {+    if (source.index() == I)+      return std::variant<T...>{+          std::in_place_index<I>, std::move(std::get<I>(source))};+    else if constexpr (I + 1 < std::variant_size_v<SourceVariant>)+      return call<I + 1>(source);+    else+      throw std::logic_error("empty variant");+  }+};++} // namespace detail++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename... T, typename Executor>+awaitable<std::variant<T..., std::monostate>, Executor> operator||(+    awaitable<std::variant<T...>, Executor> t, awaitable<void, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, r0, ex1] =+    co_await make_parallel_group(+      co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+      co_spawn(ex, std::move(u), deferred)+    ).async_wait(+      wait_for_one_success(),+      deferred+    );++  using widen = detail::widen_variant<T..., std::monostate>;+  if (order[0] == 0)+  {+    if (!ex0)+      co_return widen::template call<0>(+          detail::awaitable_unwrap<std::variant<T...>>(r0));+    if (!ex1)+      co_return std::variant<T..., std::monostate>{+          std::in_place_index<sizeof...(T)>};+    throw multiple_exceptions(ex0);+  }+  else+  {+    if (!ex1)+      co_return std::variant<T..., std::monostate>{+          std::in_place_index<sizeof...(T)>};+    if (!ex0)+      co_return widen::template call<0>(+          detail::awaitable_unwrap<std::variant<T...>>(r0));+    throw multiple_exceptions(ex1);+  }+}++/// Wait for one operation to succeed.+/**+ * If one operations succeeds, the other is cancelled as the OR-condition is+ * already satisfied.+ */+template <typename... T, typename U, typename Executor>+awaitable<std::variant<T..., U>, Executor> operator||(+    awaitable<std::variant<T...>, Executor> t, awaitable<U, Executor> u)+{+  auto ex = co_await this_coro::executor;++  auto [order, ex0, r0, ex1, r1] =+    co_await make_parallel_group(+      co_spawn(ex, detail::awaitable_wrap(std::move(t)), deferred),+      co_spawn(ex, detail::awaitable_wrap(std::move(u)), deferred)+    ).async_wait(+      wait_for_one_success(),+      deferred+    );++  using widen = detail::widen_variant<T..., U>;+  if (order[0] == 0)+  {+    if (!ex0)+      co_return widen::template call<0>(+          detail::awaitable_unwrap<std::variant<T...>>(r0));+    if (!ex1)+      co_return std::variant<T..., U>{+          std::in_place_index<sizeof...(T)>,+          std::move(detail::awaitable_unwrap<U>(r1))};+    throw multiple_exceptions(ex0);+  }+  else+  {+    if (!ex1)+      co_return std::variant<T..., U>{+          std::in_place_index<sizeof...(T)>,+          std::move(detail::awaitable_unwrap<U>(r1))};+    if (!ex0)+      co_return widen::template call<0>(+          detail::awaitable_unwrap<std::variant<T...>>(r0));+    throw multiple_exceptions(ex1);+  }+}++} // namespace awaitable_operators+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_AWAITABLE_OPERATORS_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/basic_channel.hpp view
@@ -0,0 +1,491 @@+//+// experimental/basic_channel.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_BASIC_CHANNEL_HPP+#define ASIO_EXPERIMENTAL_BASIC_CHANNEL_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/non_const_lvalue.hpp"+#include "asio/detail/null_mutex.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution_context.hpp"+#include "asio/experimental/detail/channel_send_functions.hpp"+#include "asio/experimental/detail/channel_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++} // namespace detail++/// A channel for messages.+/**+ * The basic_channel class template is used for sending messages between+ * different parts of the same application. A <em>message</em> is defined as a+ * collection of arguments to be passed to a completion handler, and the set of+ * messages supported by a channel is specified by its @c Traits and+ * <tt>Signatures...</tt> template parameters. Messages may be sent and received+ * using asynchronous or non-blocking synchronous operations.+ *+ * Unless customising the traits, applications will typically use the @c+ * experimental::channel alias template. For example:+ * @code void send_loop(int i, steady_timer& timer,+ *     channel<void(error_code, int)>& ch)+ * {+ *   if (i < 10)+ *   {+ *     timer.expires_after(chrono::seconds(1));+ *     timer.async_wait(+ *         [i, &timer, &ch](error_code error)+ *         {+ *           if (!error)+ *           {+ *             ch.async_send(error_code(), i,+ *                 [i, &timer, &ch](error_code error)+ *                 {+ *                   if (!error)+ *                   {+ *                     send_loop(i + 1, timer, ch);+ *                   }+ *                 });+ *           }+ *         });+ *   }+ *   else+ *   {+ *     ch.close();+ *   }+ * }+ *+ * void receive_loop(channel<void(error_code, int)>& ch)+ * {+ *   ch.async_receive(+ *       [&ch](error_code error, int i)+ *       {+ *         if (!error)+ *         {+ *           std::cout << "Received " << i << "\n";+ *           receive_loop(ch);+ *         }+ *       });+ * } @endcode+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Unsafe.+ *+ * The basic_channel class template is not thread-safe, and would typically be+ * used for passing messages between application code that runs on the same+ * thread or in the same strand. Consider using @ref basic_concurrent_channel,+ * and its alias template @c experimental::concurrent_channel, to pass messages+ * between code running in different threads.+ */+template <typename Executor, typename Traits, typename... Signatures>+class basic_channel+#if !defined(GENERATING_DOCUMENTATION)+  : public detail::channel_send_functions<+      basic_channel<Executor, Traits, Signatures...>,+      Executor, Signatures...>+#endif // !defined(GENERATING_DOCUMENTATION)+{+private:+  class initiate_async_send;+  class initiate_async_receive;+  typedef detail::channel_service<asio::detail::null_mutex> service_type;+  typedef typename service_type::template implementation_type<+      Traits, Signatures...>::payload_type payload_type;++  template <typename... PayloadSignatures,+      ASIO_COMPLETION_TOKEN_FOR(PayloadSignatures...) CompletionToken>+  auto do_async_receive(detail::channel_payload<PayloadSignatures...>*,+      ASIO_MOVE_ARG(CompletionToken) token)+    -> decltype(+        async_initiate<CompletionToken, PayloadSignatures...>(+          declval<initiate_async_receive>(), token))+  {+    return async_initiate<CompletionToken, PayloadSignatures...>(+        initiate_async_receive(this), token);+  }++public:+  /// The type of the executor associated with the channel.+  typedef Executor executor_type;++  /// Rebinds the channel type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The channel type when rebound to the specified executor.+    typedef basic_channel<Executor1, Traits, Signatures...> other;+  };++  /// The traits type associated with the channel.+  typedef typename Traits::template rebind<Signatures...>::other traits_type;++  /// Construct a basic_channel.+  /**+   * This constructor creates and channel.+   *+   * @param ex The I/O executor that the channel will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the channel.+   *+   * @param max_buffer_size The maximum number of messages that may be buffered+   * in the channel.+   */+  basic_channel(const executor_type& ex, std::size_t max_buffer_size = 0)+    : service_(&asio::use_service<service_type>(+            basic_channel::get_context(ex))),+      impl_(),+      executor_(ex)+  {+    service_->construct(impl_, max_buffer_size);+  }++  /// Construct and open a basic_channel.+  /**+   * This constructor creates and opens a channel.+   *+   * @param context An execution context which provides the I/O executor that+   * the channel will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the channel.+   *+   * @param max_buffer_size The maximum number of messages that may be buffered+   * in the channel.+   */+  template <typename ExecutionContext>+  basic_channel(ExecutionContext& context, std::size_t max_buffer_size = 0,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : service_(&asio::use_service<service_type>(context)),+      impl_(),+      executor_(context.get_executor())+  {+    service_->construct(impl_, max_buffer_size);+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_channel from another.+  /**+   * This constructor moves a channel from one object to another.+   *+   * @param other The other basic_channel 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_channel(const executor_type&) constructor.+   */+  basic_channel(basic_channel&& other)+    : service_(other.service_),+      executor_(other.executor_)+  {+    service_->move_construct(impl_, other.impl_);+  }++  /// Move-assign a basic_channel from another.+  /**+   * This assignment operator moves a channel from one object to another.+   * Cancels any outstanding asynchronous operations associated with the target+   * object.+   *+   * @param other The other basic_channel 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_channel(const executor_type&)+   * constructor.+   */+  basic_channel& operator=(basic_channel&& other)+  {+    if (this != &other)+    {+      service_->move_assign(impl_, *other.service_, other.impl_);+      executor_.~executor_type();+      new (&executor_) executor_type(other.executor_);+      service_ = other.service_;+    }+    return *this;+  }++  // All channels have access to each other's implementations.+  template <typename, typename, typename...>+  friend class basic_channel;++  /// Move-construct a basic_channel from another.+  /**+   * This constructor moves a channel from one object to another.+   *+   * @param other The other basic_channel 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_channel(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  basic_channel(+      basic_channel<Executor1, Traits, Signatures...>&& other,+      typename constraint<+          is_convertible<Executor1, Executor>::value+      >::type = 0)+    : service_(other.service_),+      executor_(other.executor_)+  {+    service_->move_construct(impl_, *other.service_, other.impl_);+  }++  /// Move-assign a basic_channel from another.+  /**+   * This assignment operator moves a channel from one object to another.+   * Cancels any outstanding asynchronous operations associated with the target+   * object.+   *+   * @param other The other basic_channel 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_channel(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_channel&+  >::type operator=(basic_channel<Executor1, Traits, Signatures...>&& other)+  {+    if (this != &other)+    {+      service_->move_assign(impl_, *other.service_, other.impl_);+      executor_.~executor_type();+      new (&executor_) executor_type(other.executor_);+      service_ = other.service_;+    }+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  ~basic_channel()+  {+    service_->destroy(impl_);+  }++  /// Get the executor associated with the object.+  const executor_type& get_executor() ASIO_NOEXCEPT+  {+    return executor_;+  }++  /// Get the capacity of the channel's buffer.+  std::size_t capacity() ASIO_NOEXCEPT+  {+    return service_->capacity(impl_);+  }++  /// Determine whether the channel is open.+  bool is_open() const ASIO_NOEXCEPT+  {+    return service_->is_open(impl_);+  }++  /// Reset the channel to its initial state.+  void reset()+  {+    service_->reset(impl_);+  }++  /// Close the channel.+  void close()+  {+    service_->close(impl_);+  }++  /// Cancel all asynchronous operations waiting on the channel.+  /**+   * All outstanding send operations will complete with the error+   * @c asio::experimental::error::channel_cancelled. Outstanding receive+   * operations complete with the result as determined by the channel traits.+   */+  void cancel()+  {+    service_->cancel(impl_);+  }++  /// Determine whether a message can be received without blocking.+  bool ready() const ASIO_NOEXCEPT+  {+    return service_->ready(impl_);+  }++#if defined(GENERATING_DOCUMENTATION)++  /// Try to send a message without blocking.+  /**+   * Fails if the buffer is full and there are no waiting receive operations.+   *+   * @returns @c true on success, @c false on failure.+   */+  template <typename... Args>+  bool try_send(ASIO_MOVE_ARG(Args)... args);++  /// Try to send a number of messages without blocking.+  /**+   * @returns The number of messages that were sent.+   */+  template <typename... Args>+  std::size_t try_send_n(std::size_t count, ASIO_MOVE_ARG(Args)... args);++  /// Asynchronously send a message.+  /**+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   */+  template <typename... Args,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  auto async_send(ASIO_MOVE_ARG(Args)... args,+      ASIO_MOVE_ARG(CompletionToken) token);++#endif // defined(GENERATING_DOCUMENTATION)++  /// Try to receive a message without blocking.+  /**+   * Fails if the buffer is full and there are no waiting receive operations.+   *+   * @returns @c true on success, @c false on failure.+   */+  template <typename Handler>+  bool try_receive(ASIO_MOVE_ARG(Handler) handler)+  {+    return service_->try_receive(impl_, ASIO_MOVE_CAST(Handler)(handler));+  }++  /// Asynchronously receive a message.+  /**+   * @par Completion Signature+   * As determined by the <tt>Signatures...</tt> template parameter and the+   * channel traits.+   */+  template <typename CompletionToken+      ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  auto async_receive(+      ASIO_MOVE_ARG(CompletionToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+#if !defined(GENERATING_DOCUMENTATION)+    -> decltype(+        this->do_async_receive(static_cast<payload_type*>(0),+          ASIO_MOVE_CAST(CompletionToken)(token)))+#endif // !defined(GENERATING_DOCUMENTATION)+  {+    return this->do_async_receive(static_cast<payload_type*>(0),+        ASIO_MOVE_CAST(CompletionToken)(token));+  }++private:+  // Disallow copying and assignment.+  basic_channel(const basic_channel&) ASIO_DELETED;+  basic_channel& operator=(const basic_channel&) ASIO_DELETED;++  template <typename, typename, typename...>+  friend class detail::channel_send_functions;++  // 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();+  }++  class initiate_async_send+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_send(basic_channel* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename SendHandler>+    void operator()(ASIO_MOVE_ARG(SendHandler) handler,+        ASIO_MOVE_ARG(payload_type) payload) const+    {+      asio::detail::non_const_lvalue<SendHandler> handler2(handler);+      self_->service_->async_send(self_->impl_,+          ASIO_MOVE_CAST(payload_type)(payload),+          handler2.value, self_->get_executor());+    }++  private:+    basic_channel* self_;+  };++  class initiate_async_receive+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_receive(basic_channel* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename ReceiveHandler>+    void operator()(ASIO_MOVE_ARG(ReceiveHandler) handler) const+    {+      asio::detail::non_const_lvalue<ReceiveHandler> handler2(handler);+      self_->service_->async_receive(self_->impl_,+          handler2.value, self_->get_executor());+    }++  private:+    basic_channel* self_;+  };++  // The service associated with the I/O object.+  service_type* service_;++  // The underlying implementation of the I/O object.+  typename service_type::template implementation_type<+      Traits, Signatures...> impl_;++  // The associated executor.+  Executor executor_;+};++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_BASIC_CHANNEL_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/basic_concurrent_channel.hpp view
@@ -0,0 +1,491 @@+//+// experimental/basic_concurrent_channel.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_BASIC_CONCURRENT_CHANNEL_HPP+#define ASIO_EXPERIMENTAL_BASIC_CONCURRENT_CHANNEL_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/non_const_lvalue.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/execution/executor.hpp"+#include "asio/execution_context.hpp"+#include "asio/experimental/detail/channel_send_functions.hpp"+#include "asio/experimental/detail/channel_service.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++} // namespace detail++/// A channel for messages.+/**+ * The basic_concurrent_channel class template is used for sending messages+ * between different parts of the same application. A <em>message</em> is+ * defined as a collection of arguments to be passed to a completion handler,+ * and the set of messages supported by a channel is specified by its @c Traits+ * and <tt>Signatures...</tt> template parameters. Messages may be sent and+ * received using asynchronous or non-blocking synchronous operations.+ *+ * Unless customising the traits, applications will typically use the @c+ * experimental::concurrent_channel alias template. For example:+ * @code void send_loop(int i, steady_timer& timer,+ *     concurrent_channel<void(error_code, int)>& ch)+ * {+ *   if (i < 10)+ *   {+ *     timer.expires_after(chrono::seconds(1));+ *     timer.async_wait(+ *         [i, &timer, &ch](error_code error)+ *         {+ *           if (!error)+ *           {+ *             ch.async_send(error_code(), i,+ *                 [i, &timer, &ch](error_code error)+ *                 {+ *                   if (!error)+ *                   {+ *                     send_loop(i + 1, timer, ch);+ *                   }+ *                 });+ *           }+ *         });+ *   }+ *   else+ *   {+ *     ch.close();+ *   }+ * }+ *+ * void receive_loop(concurent_channel<void(error_code, int)>& ch)+ * {+ *   ch.async_receive(+ *       [&ch](error_code error, int i)+ *       {+ *         if (!error)+ *         {+ *           std::cout << "Received " << i << "\n";+ *           receive_loop(ch);+ *         }+ *       });+ * } @endcode+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * The basic_concurrent_channel class template is thread-safe, and would+ * typically be used for passing messages between application code that run on+ * different threads. Consider using @ref basic_channel, and its alias template+ * @c experimental::channel, to pass messages between code running in a single+ * thread or on the same strand.+ */+template <typename Executor, typename Traits, typename... Signatures>+class basic_concurrent_channel+#if !defined(GENERATING_DOCUMENTATION)+  : public detail::channel_send_functions<+      basic_concurrent_channel<Executor, Traits, Signatures...>,+      Executor, Signatures...>+#endif // !defined(GENERATING_DOCUMENTATION)+{+private:+  class initiate_async_send;+  class initiate_async_receive;+  typedef detail::channel_service<asio::detail::mutex> service_type;+  typedef typename service_type::template implementation_type<+      Traits, Signatures...>::payload_type payload_type;++  template <typename... PayloadSignatures,+      ASIO_COMPLETION_TOKEN_FOR(PayloadSignatures...) CompletionToken>+  auto do_async_receive(detail::channel_payload<PayloadSignatures...>*,+      ASIO_MOVE_ARG(CompletionToken) token)+    -> decltype(+        async_initiate<CompletionToken, PayloadSignatures...>(+          declval<initiate_async_receive>(), token))+  {+    return async_initiate<CompletionToken, PayloadSignatures...>(+        initiate_async_receive(this), token);+  }++public:+  /// The type of the executor associated with the channel.+  typedef Executor executor_type;++  /// Rebinds the channel type to another executor.+  template <typename Executor1>+  struct rebind_executor+  {+    /// The channel type when rebound to the specified executor.+    typedef basic_concurrent_channel<Executor1, Traits, Signatures...> other;+  };++  /// The traits type associated with the channel.+  typedef typename Traits::template rebind<Signatures...>::other traits_type;++  /// Construct a basic_concurrent_channel.+  /**+   * This constructor creates and channel.+   *+   * @param ex The I/O executor that the channel will use, by default, to+   * dispatch handlers for any asynchronous operations performed on the channel.+   *+   * @param max_buffer_size The maximum number of messages that may be buffered+   * in the channel.+   */+  basic_concurrent_channel(const executor_type& ex,+      std::size_t max_buffer_size = 0)+    : service_(&asio::use_service<service_type>(+            basic_concurrent_channel::get_context(ex))),+      impl_(),+      executor_(ex)+  {+    service_->construct(impl_, max_buffer_size);+  }++  /// Construct and open a basic_concurrent_channel.+  /**+   * This constructor creates and opens a channel.+   *+   * @param context An execution context which provides the I/O executor that+   * the channel will use, by default, to dispatch handlers for any asynchronous+   * operations performed on the channel.+   *+   * @param max_buffer_size The maximum number of messages that may be buffered+   * in the channel.+   */+  template <typename ExecutionContext>+  basic_concurrent_channel(ExecutionContext& context,+      std::size_t max_buffer_size = 0,+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : service_(&asio::use_service<service_type>(context)),+      impl_(),+      executor_(context.get_executor())+  {+    service_->construct(impl_, max_buffer_size);+  }++#if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)+  /// Move-construct a basic_concurrent_channel from another.+  /**+   * This constructor moves a channel from one object to another.+   *+   * @param other The other basic_concurrent_channel 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_concurrent_channel(const executor_type&)+   * constructor.+   */+  basic_concurrent_channel(basic_concurrent_channel&& other)+    : service_(other.service_),+      executor_(other.executor_)+  {+    service_->move_construct(impl_, other.impl_);+  }++  /// Move-assign a basic_concurrent_channel from another.+  /**+   * This assignment operator moves a channel from one object to another.+   * Cancels any outstanding asynchronous operations associated with the target+   * object.+   *+   * @param other The other basic_concurrent_channel 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_concurrent_channel(const executor_type&)+   * constructor.+   */+  basic_concurrent_channel& operator=(basic_concurrent_channel&& other)+  {+    if (this != &other)+    {+      service_->move_assign(impl_, *other.service_, other.impl_);+      executor_.~executor_type();+      new (&executor_) executor_type(other.executor_);+      service_ = other.service_;+    }+    return *this;+  }++  // All channels have access to each other's implementations.+  template <typename, typename, typename...>+  friend class basic_concurrent_channel;++  /// Move-construct a basic_concurrent_channel from another.+  /**+   * This constructor moves a channel from one object to another.+   *+   * @param other The other basic_concurrent_channel 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_concurrent_channel(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  basic_concurrent_channel(+      basic_concurrent_channel<Executor1, Traits, Signatures...>&& other,+      typename constraint<+          is_convertible<Executor1, Executor>::value+      >::type = 0)+    : service_(other.service_),+      executor_(other.executor_)+  {+    service_->move_construct(impl_, *other.service_, other.impl_);+  }++  /// Move-assign a basic_concurrent_channel from another.+  /**+   * This assignment operator moves a channel from one object to another.+   * Cancels any outstanding asynchronous operations associated with the target+   * object.+   *+   * @param other The other basic_concurrent_channel 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_concurrent_channel(const executor_type&)+   * constructor.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_concurrent_channel&+  >::type operator=(+      basic_concurrent_channel<Executor1, Traits, Signatures...>&& other)+  {+    if (this != &other)+    {+      service_->move_assign(impl_, *other.service_, other.impl_);+      executor_.~executor_type();+      new (&executor_) executor_type(other.executor_);+      service_ = other.service_;+    }+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)++  /// Destructor.+  ~basic_concurrent_channel()+  {+    service_->destroy(impl_);+  }++  /// Get the executor associated with the object.+  const executor_type& get_executor() ASIO_NOEXCEPT+  {+    return executor_;+  }++  /// Get the capacity of the channel's buffer.+  std::size_t capacity() ASIO_NOEXCEPT+  {+    return service_->capacity(impl_);+  }++  /// Determine whether the channel is open.+  bool is_open() const ASIO_NOEXCEPT+  {+    return service_->is_open(impl_);+  }++  /// Reset the channel to its initial state.+  void reset()+  {+    service_->reset(impl_);+  }++  /// Close the channel.+  void close()+  {+    service_->close(impl_);+  }++  /// Cancel all asynchronous operations waiting on the channel.+  /**+   * All outstanding send operations will complete with the error+   * @c asio::experimental::error::channel_cancelled. Outstanding receive+   * operations complete with the result as determined by the channel traits.+   */+  void cancel()+  {+    service_->cancel(impl_);+  }++  /// Determine whether a message can be received without blocking.+  bool ready() const ASIO_NOEXCEPT+  {+    return service_->ready(impl_);+  }++#if defined(GENERATING_DOCUMENTATION)++  /// Try to send a message without blocking.+  /**+   * Fails if the buffer is full and there are no waiting receive operations.+   *+   * @returns @c true on success, @c false on failure.+   */+  template <typename... Args>+  bool try_send(ASIO_MOVE_ARG(Args)... args);++  /// Try to send a number of messages without blocking.+  /**+   * @returns The number of messages that were sent.+   */+  template <typename... Args>+  std::size_t try_send_n(std::size_t count, ASIO_MOVE_ARG(Args)... args);++  /// Asynchronously send a message.+  template <typename... Args,+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  auto async_send(ASIO_MOVE_ARG(Args)... args,+      ASIO_MOVE_ARG(CompletionToken) token);++#endif // defined(GENERATING_DOCUMENTATION)++  /// Try to receive a message without blocking.+  /**+   * Fails if the buffer is full and there are no waiting receive operations.+   *+   * @returns @c true on success, @c false on failure.+   */+  template <typename Handler>+  bool try_receive(ASIO_MOVE_ARG(Handler) handler)+  {+    return service_->try_receive(impl_, ASIO_MOVE_CAST(Handler)(handler));+  }++  /// Asynchronously receive a message.+  template <typename CompletionToken+      ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  auto async_receive(+      ASIO_MOVE_ARG(CompletionToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+#if !defined(GENERATING_DOCUMENTATION)+    -> decltype(+        this->do_async_receive(static_cast<payload_type*>(0),+          ASIO_MOVE_CAST(CompletionToken)(token)))+#endif // !defined(GENERATING_DOCUMENTATION)+  {+    return this->do_async_receive(static_cast<payload_type*>(0),+        ASIO_MOVE_CAST(CompletionToken)(token));+  }++private:+  // Disallow copying and assignment.+  basic_concurrent_channel(+      const basic_concurrent_channel&) ASIO_DELETED;+  basic_concurrent_channel& operator=(+      const basic_concurrent_channel&) ASIO_DELETED;++  template <typename, typename, typename...>+  friend class detail::channel_send_functions;++  // 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();+  }++  class initiate_async_send+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_send(basic_concurrent_channel* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename SendHandler>+    void operator()(ASIO_MOVE_ARG(SendHandler) handler,+        ASIO_MOVE_ARG(payload_type) payload) const+    {+      asio::detail::non_const_lvalue<SendHandler> handler2(handler);+      self_->service_->async_send(self_->impl_,+          ASIO_MOVE_CAST(payload_type)(payload),+          handler2.value, self_->get_executor());+    }++  private:+    basic_concurrent_channel* self_;+  };++  class initiate_async_receive+  {+  public:+    typedef Executor executor_type;++    explicit initiate_async_receive(basic_concurrent_channel* self)+      : self_(self)+    {+    }++    const executor_type& get_executor() const ASIO_NOEXCEPT+    {+      return self_->get_executor();+    }++    template <typename ReceiveHandler>+    void operator()(ASIO_MOVE_ARG(ReceiveHandler) handler) const+    {+      asio::detail::non_const_lvalue<ReceiveHandler> handler2(handler);+      self_->service_->async_receive(self_->impl_,+          handler2.value, self_->get_executor());+    }++  private:+    basic_concurrent_channel* self_;+  };++  // The service associated with the I/O object.+  service_type* service_;++  // The underlying implementation of the I/O object.+  typename service_type::template implementation_type<+      Traits, Signatures...> impl_;++  // The associated executor.+  Executor executor_;+};++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_BASIC_CONCURRENT_CHANNEL_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/cancellation_condition.hpp view
@@ -0,0 +1,155 @@+//+// experimental/cancellation_condition.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CANCELLATION_CONDITION_HPP+#define ASIO_EXPERIMENTAL_CANCELLATION_CONDITION_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/cancellation_type.hpp"+#include "asio/error_code.hpp"+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++/// Wait for all operations to complete.+class wait_for_all+{+public:+  template <typename... Args>+  ASIO_CONSTEXPR cancellation_type_t operator()(+      Args&&...) const ASIO_NOEXCEPT+  {+    return cancellation_type::none;+  }+};++/// Wait until an operation completes, then cancel the others.+class wait_for_one+{+public:+  ASIO_CONSTEXPR explicit wait_for_one(+      cancellation_type_t cancel_type = cancellation_type::all)+    : cancel_type_(cancel_type)+  {+  }++  template <typename... Args>+  ASIO_CONSTEXPR cancellation_type_t operator()(+      Args&&...) const ASIO_NOEXCEPT+  {+    return cancel_type_;+  }++private:+  cancellation_type_t cancel_type_;+};++/// Wait until an operation completes without an error, then cancel the others.+/**+ * If no operation completes without an error, waits for completion of all+ * operations.+ */+class wait_for_one_success+{+public:+  ASIO_CONSTEXPR explicit wait_for_one_success(+      cancellation_type_t cancel_type = cancellation_type::all)+    : cancel_type_(cancel_type)+  {+  }++  ASIO_CONSTEXPR cancellation_type_t+  operator()() const ASIO_NOEXCEPT+  {+    return cancel_type_;+  }++  template <typename E, typename... Args>+  ASIO_CONSTEXPR typename constraint<+    !is_same<typename decay<E>::type, asio::error_code>::value+      && !is_same<typename decay<E>::type, std::exception_ptr>::value,+    cancellation_type_t+  >::type operator()(const E&, Args&&...) const ASIO_NOEXCEPT+  {+    return cancel_type_;+  }++  template <typename E, typename... Args>+  ASIO_CONSTEXPR typename constraint<+      is_same<typename decay<E>::type, asio::error_code>::value+        || is_same<typename decay<E>::type, std::exception_ptr>::value,+      cancellation_type_t+  >::type operator()(const E& e, Args&&...) const ASIO_NOEXCEPT+  {+    return !!e ? cancellation_type::none : cancel_type_;+  }++private:+  cancellation_type_t cancel_type_;+};++/// Wait until an operation completes with an error, then cancel the others.+/**+ * If no operation completes with an error, waits for completion of all+ * operations.+ */+class wait_for_one_error+{+public:+  ASIO_CONSTEXPR explicit wait_for_one_error(+      cancellation_type_t cancel_type = cancellation_type::all)+    : cancel_type_(cancel_type)+  {+  }++  ASIO_CONSTEXPR cancellation_type_t+  operator()() const ASIO_NOEXCEPT+  {+    return cancellation_type::none;+  }++  template <typename E, typename... Args>+  ASIO_CONSTEXPR typename constraint<+    !is_same<typename decay<E>::type, asio::error_code>::value+      && !is_same<typename decay<E>::type, std::exception_ptr>::value,+    cancellation_type_t+  >::type operator()(const E&, Args&&...) const ASIO_NOEXCEPT+  {+    return cancellation_type::none;+  }++  template <typename E, typename... Args>+  ASIO_CONSTEXPR typename constraint<+      is_same<typename decay<E>::type, asio::error_code>::value+        || is_same<typename decay<E>::type, std::exception_ptr>::value,+      cancellation_type_t+  >::type operator()(const E& e, Args&&...) const ASIO_NOEXCEPT+  {+    return !!e ? cancel_type_ : cancellation_type::none;+  }++private:+  cancellation_type_t cancel_type_;+};++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_CANCELLATION_CONDITION_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/channel.hpp view
@@ -0,0 +1,70 @@+//+// experimental/channel.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CHANNEL_HPP+#define ASIO_EXPERIMENTAL_CHANNEL_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/detail/type_traits.hpp"+#include "asio/execution/executor.hpp"+#include "asio/is_executor.hpp"+#include "asio/experimental/basic_channel.hpp"+#include "asio/experimental/channel_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename ExecutorOrSignature, typename = void>+struct channel_type+{+  template <typename... Signatures>+  struct inner+  {+    typedef basic_channel<any_io_executor, channel_traits<>,+        ExecutorOrSignature, Signatures...> type;+  };+};++template <typename ExecutorOrSignature>+struct channel_type<ExecutorOrSignature,+    typename enable_if<+      is_executor<ExecutorOrSignature>::value+        || execution::is_executor<ExecutorOrSignature>::value+    >::type>+{+  template <typename... Signatures>+  struct inner+  {+    typedef basic_channel<ExecutorOrSignature,+        channel_traits<>, Signatures...> type;+  };+};++} // namespace detail++/// Template type alias for common use of channel.+template <typename ExecutorOrSignature, typename... Signatures>+using channel = typename detail::channel_type<+    ExecutorOrSignature>::template inner<Signatures...>::type;++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_CHANNEL_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/channel_error.hpp view
@@ -0,0 +1,84 @@+//+// experimental/channel_error.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CHANNEL_ERROR_HPP+#define ASIO_EXPERIMENTAL_CHANNEL_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 experimental {+namespace error {++enum channel_errors+{+  /// The channel was closed.+  channel_closed = 1,++  /// The channel was cancelled.+  channel_cancelled = 2+};++extern ASIO_DECL+const asio::error_category& get_channel_category();++static const asio::error_category&+  channel_category ASIO_UNUSED_VARIABLE+  = asio::experimental::error::get_channel_category();++} // namespace error+namespace channel_errc {+  // Simulates a scoped enum.+  using error::channel_closed;+  using error::channel_cancelled;+} // namespace channel_errc+} // namespace experimental+} // namespace asio++#if defined(ASIO_HAS_STD_SYSTEM_ERROR)+namespace std {++template<> struct is_error_code_enum<+    asio::experimental::error::channel_errors>+{+  static const bool value = true;+};++} // namespace std+#endif // defined(ASIO_HAS_STD_SYSTEM_ERROR)++namespace asio {+namespace experimental {+namespace error {++inline asio::error_code make_error_code(channel_errors e)+{+  return asio::error_code(+      static_cast<int>(e), get_channel_category());+}++} // namespace error+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#if defined(ASIO_HEADER_ONLY)+# include "asio/experimental/impl/channel_error.ipp"+#endif // defined(ASIO_HEADER_ONLY)++#endif // ASIO_EXPERIMENTAL_CHANNEL_ERROR_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/channel_traits.hpp view
@@ -0,0 +1,301 @@+//+// experimental/channel_traits.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CHANNEL_TRAITS_HPP+#define ASIO_EXPERIMENTAL_CHANNEL_TRAITS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <deque>+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"+#include "asio/experimental/channel_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if defined(GENERATING_DOCUMENTATION)++template <typename... Signatures>+struct channel_traits+{+  /// Rebind the traits to a new set of signatures.+  /**+   * This nested structure must have a single nested type @c other that+   * aliases a traits type with the specified set of signatures.+   */+  template <typename... NewSignatures>+  struct rebind+  {+    typedef user_defined other;+  };++  /// Determine the container for the specified elements.+  /**+   * This nested structure must have a single nested type @c other that+   * aliases a container type for the specified element type.+   */+  template <typename Element>+  struct container+  {+    typedef user_defined type;+  };++  /// The signature of a channel cancellation notification.+  typedef void receive_cancelled_signature(...);++  /// Invoke the specified handler with a cancellation notification.+  template <typename F>+  static void invoke_receive_cancelled(F f);++  /// The signature of a channel closed notification.+  typedef void receive_closed_signature(...);++  /// Invoke the specified handler with a closed notification.+  template <typename F>+  static void invoke_receive_closed(F f);+};++#else // defined(GENERATING_DOCUMENTATION)++/// Traits used for customising channel behaviour.+template <typename... Signatures>+struct channel_traits+{+  template <typename... NewSignatures>+  struct rebind+  {+    typedef channel_traits<NewSignatures...> other;+  };+};++template <typename R>+struct channel_traits<R(asio::error_code)>+{+  template <typename... NewSignatures>+  struct rebind+  {+    typedef channel_traits<NewSignatures...> other;+  };++  template <typename Element>+  struct container+  {+    typedef std::deque<Element> type;+  };++  typedef R receive_cancelled_signature(asio::error_code);++  template <typename F>+  static void invoke_receive_cancelled(F f)+  {+    const asio::error_code e = error::channel_cancelled;+    ASIO_MOVE_OR_LVALUE(F)(f)(e);+  }++  typedef R receive_closed_signature(asio::error_code);++  template <typename F>+  static void invoke_receive_closed(F f)+  {+    const asio::error_code e = error::channel_closed;+    ASIO_MOVE_OR_LVALUE(F)(f)(e);+  }+};++template <typename R, typename... Args, typename... Signatures>+struct channel_traits<R(asio::error_code, Args...), Signatures...>+{+  template <typename... NewSignatures>+  struct rebind+  {+    typedef channel_traits<NewSignatures...> other;+  };++  template <typename Element>+  struct container+  {+    typedef std::deque<Element> type;+  };++  typedef R receive_cancelled_signature(asio::error_code, Args...);++  template <typename F>+  static void invoke_receive_cancelled(F f)+  {+    const asio::error_code e = error::channel_cancelled;+    ASIO_MOVE_OR_LVALUE(F)(f)(e, typename decay<Args>::type()...);+  }++  typedef R receive_closed_signature(asio::error_code, Args...);++  template <typename F>+  static void invoke_receive_closed(F f)+  {+    const asio::error_code e = error::channel_closed;+    ASIO_MOVE_OR_LVALUE(F)(f)(e, typename decay<Args>::type()...);+  }+};++template <typename R>+struct channel_traits<R(std::exception_ptr)>+{+  template <typename... NewSignatures>+  struct rebind+  {+    typedef channel_traits<NewSignatures...> other;+  };++  template <typename Element>+  struct container+  {+    typedef std::deque<Element> type;+  };++  typedef R receive_cancelled_signature(std::exception_ptr);++  template <typename F>+  static void invoke_receive_cancelled(F f)+  {+    const asio::error_code e = error::channel_cancelled;+    ASIO_MOVE_OR_LVALUE(F)(f)(+        std::make_exception_ptr(asio::system_error(e)));+  }++  typedef R receive_closed_signature(std::exception_ptr);++  template <typename F>+  static void invoke_receive_closed(F f)+  {+    const asio::error_code e = error::channel_closed;+    ASIO_MOVE_OR_LVALUE(F)(f)(+        std::make_exception_ptr(asio::system_error(e)));+  }+};++template <typename R, typename... Args, typename... Signatures>+struct channel_traits<R(std::exception_ptr, Args...), Signatures...>+{+  template <typename... NewSignatures>+  struct rebind+  {+    typedef channel_traits<NewSignatures...> other;+  };++  template <typename Element>+  struct container+  {+    typedef std::deque<Element> type;+  };++  typedef R receive_cancelled_signature(std::exception_ptr, Args...);++  template <typename F>+  static void invoke_receive_cancelled(F f)+  {+    const asio::error_code e = error::channel_cancelled;+    ASIO_MOVE_OR_LVALUE(F)(f)(+        std::make_exception_ptr(asio::system_error(e)),+        typename decay<Args>::type()...);+  }++  typedef R receive_closed_signature(std::exception_ptr, Args...);++  template <typename F>+  static void invoke_receive_closed(F f)+  {+    const asio::error_code e = error::channel_closed;+    ASIO_MOVE_OR_LVALUE(F)(f)(+        std::make_exception_ptr(asio::system_error(e)),+        typename decay<Args>::type()...);+  }+};++template <typename R>+struct channel_traits<R()>+{+  template <typename... NewSignatures>+  struct rebind+  {+    typedef channel_traits<NewSignatures...> other;+  };++  template <typename Element>+  struct container+  {+    typedef std::deque<Element> type;+  };++  typedef R receive_cancelled_signature(asio::error_code);++  template <typename F>+  static void invoke_receive_cancelled(F f)+  {+    const asio::error_code e = error::channel_cancelled;+    ASIO_MOVE_OR_LVALUE(F)(f)(e);+  }++  typedef R receive_closed_signature(asio::error_code);++  template <typename F>+  static void invoke_receive_closed(F f)+  {+    const asio::error_code e = error::channel_closed;+    ASIO_MOVE_OR_LVALUE(F)(f)(e);+  }+};++template <typename R, typename T>+struct channel_traits<R(T)>+{+  template <typename... NewSignatures>+  struct rebind+  {+    typedef channel_traits<NewSignatures...> other;+  };++  template <typename Element>+  struct container+  {+    typedef std::deque<Element> type;+  };++  typedef R receive_cancelled_signature(asio::error_code);++  template <typename F>+  static void invoke_receive_cancelled(F f)+  {+    const asio::error_code e = error::channel_cancelled;+    ASIO_MOVE_OR_LVALUE(F)(f)(e);+  }++  typedef R receive_closed_signature(asio::error_code);++  template <typename F>+  static void invoke_receive_closed(F f)+  {+    const asio::error_code e = error::channel_closed;+    ASIO_MOVE_OR_LVALUE(F)(f)(e);+  }+};++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_CHANNEL_TRAITS_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/co_composed.hpp view
@@ -0,0 +1,144 @@+//+// experimental/co_composed.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CO_COMPOSED_HPP+#define ASIO_EXPERIMENTAL_CO_COMPOSED_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 experimental {++/// Creates an initiation function object that may be used to launch a+/// coroutine-based composed asynchronous operation.+/**+ * The experimental::co_composed utility simplifies the implementation of+ * composed asynchronous operations by automatically adapting a coroutine to be+ * an initiation function object for use with @c async_initiate. When awaiting+ * asynchronous operations, the coroutine automatically uses a conforming+ * intermediate completion handler.+ *+ * @param implementation A function object that contains the coroutine-based+ * implementation of the composed asynchronous operation. The first argument to+ * the function object represents the state of the operation, and may be used+ * to test for cancellation. The remaining arguments are those passed to @c+ * async_initiate after 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 while the operation is incomplete.+ *+ * @par Per-Operation Cancellation+ * By default, per-operation cancellation is disabled for composed operations+ * that use experimental::co_composed. It must be explicitly enabled by calling+ * the state's @c reset_cancellation_state function.+ *+ * @par Examples+ * The following example illustrates manual error handling and explicit checks+ * for cancellation. The completion handler is invoked via a @c co_yield to the+ * state's @c complete function, which never returns.+ *+ * @code template <typename CompletionToken>+ * auto async_echo(tcp::socket& socket,+ *     CompletionToken&& token)+ * {+ *   return asio::async_initiate<+ *     CompletionToken, void(std::error_code)>(+ *       asio::experimental::co_composed(+ *         [](auto state, tcp::socket& socket) -> void+ *         {+ *           state.reset_cancellation_state(+ *             asio::enable_terminal_cancellation());+ *+ *           while (!state.cancelled())+ *           {+ *             char data[1024];+ *             auto [e1, n1] =+ *               co_await socket.async_read_some(+ *                 asio::buffer(data),+ *                 asio::as_tuple(asio::deferred));+ *+ *             if (e1)+ *               co_yield state.complete(e1);+ *+ *             if (!!state.cancelled())+ *               co_yield state.complete(+ *                 make_error_code(asio::error::operation_aborted));+ *+ *             auto [e2, n2] =+ *               co_await asio::async_write(socket,+ *                 asio::buffer(data, n1),+ *                 asio::as_tuple(asio::deferred));+ *+ *             if (e2)+ *               co_yield state.complete(e2);+ *           }+ *         }, socket),+ *       token, std::ref(socket));+ * } @endcode+ *+ * This next example shows exception-based error handling and implicit checks+ * for cancellation. The completion handler is invoked after returning from the+ * coroutine via @c co_return. Valid @c co_return values are specified using+ * completion signatures passed to the @c co_composed function.+ *+ * @code template <typename CompletionToken>+ * auto async_echo(tcp::socket& socket,+ *     CompletionToken&& token)+ * {+ *   return asio::async_initiate<+ *     CompletionToken, void(std::error_code)>(+ *       asio::experimental::co_composed<+ *         void(std::error_code)>(+ *           [](auto state, tcp::socket& socket) -> void+ *           {+ *             try+ *             {+ *               state.throw_if_cancelled(true);+ *               state.reset_cancellation_state(+ *                 asio::enable_terminal_cancellation());+ *+ *               for (;;)+ *               {+ *                 char data[1024];+ *                 std::size_t n = co_await socket.async_read_some(+ *                     asio::buffer(data), asio::deferred);+ *+ *                 co_await asio::async_write(socket,+ *                     asio::buffer(data, n), asio::deferred);+ *               }+ *             }+ *             catch (const std::system_error& e)+ *             {+ *               co_return {e.code()};+ *             }+ *           }, socket),+ *       token, std::ref(socket));+ * } @endcode+ */+template <completion_signature... Signatures,+    typename Implementation, typename... IoObjectsOrExecutors>+auto co_composed(Implementation&& implementation,+    IoObjectsOrExecutors&&... io_objects_or_executors);++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/co_composed.hpp"++#endif // ASIO_EXPERIMENTAL_CO_COMPOSED_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/co_spawn.hpp view
@@ -0,0 +1,187 @@+//+// experimental/co_spawn.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//+#ifndef ASIO_EXPERIMENTAL_CO_SPAWN_HPP+#define ASIO_EXPERIMENTAL_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 <utility>+#include "asio/compose.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/experimental/coro.hpp"+#include "asio/experimental/deferred.hpp"+#include "asio/experimental/prepend.hpp"+#include "asio/redirect_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename T, typename U, typename Executor>+struct coro_spawn_op+{+  coro<T, U, Executor> c;++  void operator()(auto& self)+  {+    auto op = c.async_resume(deferred);+    std::move(op)((prepend)(std::move(self), 0));+  }++  void operator()(auto& self, int, auto... res)+  {+    self.complete(std::move(res)...);+  }+};++} // namespace detail++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename T, typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(+    CompletionToken, void(std::exception_ptr, T))+co_spawn(coro<void, T, Executor> c, CompletionToken&& token)+{+  auto exec = c.get_executor();+  return async_compose<CompletionToken, void(std::exception_ptr, T)>(+      detail::coro_spawn_op<void, T, Executor>{std::move(c)},+      token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename T, typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(+    CompletionToken, void(std::exception_ptr, T))+co_spawn(coro<void(), T, Executor> c, CompletionToken&& token)+{+  auto exec = c.get_executor();+  return async_compose<CompletionToken, void(std::exception_ptr, T)>(+      detail::coro_spawn_op<void(), T, Executor>{std::move(c)},+      token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename T, typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(T))+co_spawn(coro<void() noexcept, T, Executor> c, CompletionToken&& token)+{+  auto exec = c.get_executor();+  return async_compose<CompletionToken, void(T)>(+      detail::coro_spawn_op<void() noexcept, T, Executor>{std::move(c)},+      token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(+    CompletionToken, void(std::exception_ptr))+co_spawn(coro<void, void, Executor> c, CompletionToken&& token)+{+  auto exec = c.get_executor();+  return async_compose<CompletionToken, void(std::exception_ptr)>(+      detail::coro_spawn_op<void, void, Executor>{std::move(c)},+      token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(+    CompletionToken, void(std::exception_ptr))+co_spawn(coro<void(), void, Executor> c, CompletionToken&& token)+{+  auto exec = c.get_executor();+  return async_compose<CompletionToken, void(std::exception_ptr)>(+      detail::coro_spawn_op<void(), void, Executor>{std::move(c)},+      token, exec);+}++/// Spawn a resumable coroutine.+/**+ * This function spawns the coroutine for execution on its executor. It binds+ * the lifetime of the coroutine to the executor.+ *+ * @param c The coroutine+ *+ * @param token The completion token+ *+ * @returns Implementation defined+ */+template <typename Executor, typename CompletionToken>+ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void())+co_spawn(coro<void() noexcept, void, Executor> c, CompletionToken&& token)+{+  auto exec = c.get_executor();+  return async_compose<CompletionToken, void()>(+      detail::coro_spawn_op<void() noexcept, void, Executor>{std::move(c)},+      token, exec);+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif //ASIO_EXPERIMENTAL_CO_SPAWN_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/concurrent_channel.hpp view
@@ -0,0 +1,70 @@+//+// experimental/concurrent_channel.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CONCURRENT_CHANNEL_HPP+#define ASIO_EXPERIMENTAL_CONCURRENT_CHANNEL_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/detail/type_traits.hpp"+#include "asio/execution/executor.hpp"+#include "asio/is_executor.hpp"+#include "asio/experimental/basic_concurrent_channel.hpp"+#include "asio/experimental/channel_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename ExecutorOrSignature, typename = void>+struct concurrent_channel_type+{+  template <typename... Signatures>+  struct inner+  {+    typedef basic_concurrent_channel<any_io_executor, channel_traits<>,+        ExecutorOrSignature, Signatures...> type;+  };+};++template <typename ExecutorOrSignature>+struct concurrent_channel_type<ExecutorOrSignature,+    typename enable_if<+      is_executor<ExecutorOrSignature>::value+        || execution::is_executor<ExecutorOrSignature>::value+    >::type>+{+  template <typename... Signatures>+  struct inner+  {+    typedef basic_concurrent_channel<ExecutorOrSignature,+        channel_traits<>, Signatures...> type;+  };+};++} // namespace detail++/// Template type alias for common use of channel.+template <typename ExecutorOrSignature, typename... Signatures>+using concurrent_channel = typename detail::concurrent_channel_type<+    ExecutorOrSignature>::template inner<Signatures...>::type;++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_CONCURRENT_CHANNEL_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/coro.hpp view
@@ -0,0 +1,293 @@+//+// experimental/coro.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_CORO_HPP+#define ASIO_EXPERIMENTAL_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/dispatch.hpp"+#include "asio/error.hpp"+#include "asio/error_code.hpp"+#include "asio/experimental/coro_traits.hpp"+#include "asio/experimental/detail/coro_promise_allocator.hpp"+#include "asio/experimental/detail/partial_promise.hpp"+#include "asio/post.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Signature, typename Return,+    typename Executor, typename Allocator>+struct coro_promise;++template <typename T, typename Coroutine>+struct coro_with_arg;++} // namespace detail++/// The main type of a resumable coroutine.+/**+ * Template parameter @c Yield specifies type or signature used by co_yield,+ * @c Return specifies the type used for co_return, and @c Executor specifies+ * the underlying executor type.+ */+template <typename Yield = void, typename Return = void,+    typename Executor = any_io_executor,+    typename Allocator = std::allocator<void>>+struct coro+{+  /// The traits of the coroutine. See asio::experimental::coro_traits+  /// for details.+  using traits = coro_traits<Yield, Return, Executor>;++  /// The value that can be passed into a symmetrical cororoutine. @c void if+  /// asymmetrical.+  using input_type = typename traits::input_type;++  /// The type that can be passed out through a co_yield.+  using yield_type = typename traits::yield_type;++  /// The type that can be passed out through a co_return.+  using return_type = typename traits::return_type;++  /// The type received by a co_await or async_resume. Its a combination of+  /// yield and return.+  using result_type = typename traits::result_type;++  /// The signature used by the async_resume.+  using signature_type = typename traits::signature_type;++  /// Whether or not the coroutine is noexcept.+  constexpr static bool is_noexcept = traits::is_noexcept;++  /// The error type of the coroutine. Void for noexcept+  using error_type = typename traits::error_type;++  /// Completion handler type used by async_resume.+  using completion_handler = typename traits::completion_handler;++  /// The internal promise-type of the coroutine.+  using promise_type = detail::coro_promise<Yield, Return, Executor, Allocator>;++#if !defined(GENERATING_DOCUMENTATION)+  template <typename T, typename Coroutine>+  friend struct detail::coro_with_arg;+#endif // !defined(GENERATING_DOCUMENTATION)++  /// The executor type.+  using executor_type = Executor;++  /// The allocator type.+  using allocator_type = Allocator;++#if !defined(GENERATING_DOCUMENTATION)+  friend struct detail::coro_promise<Yield, Return, Executor, Allocator>;+#endif // !defined(GENERATING_DOCUMENTATION)++  /// The default constructor, gives an invalid coroutine.+  coro() = default;++  /// Move constructor.+  coro(coro&& lhs) noexcept+    : coro_(std::exchange(lhs.coro_, nullptr))+  {+  }++  coro(const coro&) = delete;++  /// Move assignment.+  coro& operator=(coro&& lhs) noexcept+  {+    std::swap(coro_, lhs.coro_);+    return *this;+  }++  coro& operator=(const coro&) = delete;++  /// Destructor. Destroys the coroutine, if it holds a valid one.+  /**+   * @note This does not cancel an active coroutine. Destructing a resumable+   * coroutine, i.e. one with a call to async_resume that has not completed, is+   * undefined behaviour.+   */+  ~coro()+  {+    if (coro_ != nullptr)+    {+      struct destroyer+      {+        detail::coroutine_handle<promise_type> handle;++        destroyer(const detail::coroutine_handle<promise_type>& handle)+          : handle(handle)+        { }++        destroyer(destroyer&& lhs)+          : handle(std::exchange(lhs.handle, nullptr))+        {+        }++        destroyer(const destroyer&) = delete;++        void operator()() {}++        ~destroyer()+        {+          if (handle)+            handle.destroy();+        }+      };++      auto handle =+        detail::coroutine_handle<promise_type>::from_promise(*coro_);+      if (handle)+        asio::dispatch(coro_->get_executor(), destroyer{handle});+    }+  }++  /// Get the used executor.+  executor_type get_executor() const+  {+    if (coro_)+      return coro_->get_executor();++    if constexpr (std::is_default_constructible_v<Executor>)+      return Executor{};+    else+      throw std::logic_error("Coroutine has no executor");+  }++  /// Get the used allocator.+  allocator_type get_allocator() const+  {+    if (coro_)+      return coro_->get_allocator();++    if constexpr (std::is_default_constructible_v<Allocator>)+      return Allocator{};+    else+      throw std::logic_error(+          "Coroutine has no available allocator without a constructed promise");+  }++  /// Resume the coroutine.+  /**+   * @param token The completion token of the async resume.+   *+   * @attention Calling an invalid coroutine with a noexcept signature is+   * undefined behaviour.+   *+   * @note This overload is only available for coroutines without an input+   * value.+   */+  template <typename CompletionToken>+    requires std::is_void_v<input_type>+  auto async_resume(CompletionToken&& token) &+  {+    return async_initiate<CompletionToken,+        typename traits::completion_handler>(+          initiate_async_resume(this), token);+  }++  /// Resume the coroutine.+  /**+   * @param token The completion token of the async resume.+   *+   * @attention Calling an invalid coroutine with a noexcept signature is+   * undefined behaviour.+   *+   * @note This overload is only available for coroutines with an input value.+   */+  template <typename CompletionToken, detail::convertible_to<input_type> T>+  auto async_resume(T&& ip, CompletionToken&& token) &+  {+    return async_initiate<CompletionToken,+        typename traits::completion_handler>(+          initiate_async_resume(this), token, std::forward<T>(ip));+  }++  /// Operator used for coroutines without input value.+  auto operator co_await() requires (std::is_void_v<input_type>)+  {+    return awaitable_t{*this};+  }++  /// Operator used for coroutines with input value.+  /**+   * @param ip The input value+   *+   * @returns An awaitable handle.+   *+   * @code+   * coro<void> push_values(coro<double(int)> c)+   * {+   *    std::optional<double> res = co_await c(42);+   * }+   * @endcode+   */+  template <detail::convertible_to<input_type> T>+  auto operator()(T&& ip)+  {+    return detail::coro_with_arg<std::decay_t<T>, coro>{+        std::forward<T>(ip), *this};+  }++  /// Check whether the coroutine is open, i.e. can be resumed.+  bool is_open() const+  {+    if (coro_)+    {+      auto handle =+        detail::coroutine_handle<promise_type>::from_promise(*coro_);+      return handle && !handle.done();+    }+    else+      return false;+  }++  /// Check whether the coroutine is open, i.e. can be resumed.+  explicit operator bool() const { return is_open(); }++private:+  struct awaitable_t;++  struct initiate_async_resume;++  explicit coro(promise_type* const cr) : coro_(cr) {}++  promise_type* coro_{nullptr};+};++/// A generator is a coro that returns void and yields value.+template<typename T, typename Executor = asio::any_io_executor,+    typename Allocator = std::allocator<void>>+using generator = coro<T, void, Executor, Allocator>;++/// A task is a coro that does not yield values+template<typename T, typename Executor = asio::any_io_executor,+    typename Allocator = std::allocator<void>>+using task = coro<void(), T, Executor, Allocator>;++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/coro.hpp"++#endif // ASIO_EXPERIMENTAL_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/coro_traits.hpp view
@@ -0,0 +1,228 @@+//+// experimental/detail/coro_traits.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <optional>+#include <variant>+#include "asio/any_io_executor.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <class From, class To>+concept convertible_to = std::is_convertible_v<From, To>;++template <typename T>+concept decays_to_executor = execution::executor<std::decay_t<T>>;++template <typename T, typename Executor = any_io_executor>+concept execution_context = requires (T& t)+{+  {t.get_executor()} -> convertible_to<Executor>;+};++template <typename Yield, typename Return>+struct coro_result+{+  using type = std::variant<Yield, Return>;+};++template <typename Yield>+struct coro_result<Yield, void>+{+  using type = std::optional<Yield>;+};++template <typename Return>+struct coro_result<void, Return>+{+  using type = Return;+};++template <typename YieldReturn>+struct coro_result<YieldReturn, YieldReturn>+{+  using type = YieldReturn;+};++template <>+struct coro_result<void, void>+{+  using type = void;+};++template <typename Yield, typename Return>+using coro_result_t = typename coro_result<Yield, Return>::type;++template <typename Result, bool IsNoexcept>+struct coro_handler;++template <>+struct coro_handler<void, false>+{+  using type = void(std::exception_ptr);+};++template <>+struct coro_handler<void, true>+{+  using type = void();+};++template <typename T>+struct coro_handler<T, false>+{+  using type = void(std::exception_ptr, T);+};++template <typename T>+struct coro_handler<T, true>+{+  using type = void(T);+};++template <typename Result, bool IsNoexcept>+using coro_handler_t = typename coro_handler<Result, IsNoexcept>::type;++} // namespace detail++#if defined(GENERATING_DOCUMENTATION)++/// The traits describing the resumable coroutine behaviour.+/**+ * Template parameter @c Yield specifies type or signature used by co_yield,+ * @c Return specifies the type used for co_return, and @c Executor specifies+ * the underlying executor type.+ */+template <typename Yield, typename Return, typename Executor>+struct coro_traits+{+  /// The value that can be passed into a symmetrical cororoutine. @c void if+  /// asymmetrical.+  using input_type = argument_dependent;++  /// The type that can be passed out through a co_yield.+  using yield_type = argument_dependent;++  /// The type that can be passed out through a co_return.+  using return_type = argument_dependent;++  /// The type received by a co_await or async_resume. It's a combination of+  /// yield and return.+  using result_type = argument_dependent;++  /// The signature used by the async_resume.+  using signature_type = argument_dependent;++  /// Whether or not the coroutine is noexcept.+  constexpr static bool is_noexcept = argument_dependent;++  /// The error type of the coroutine. @c void for noexcept.+  using error_type = argument_dependent;++  /// Completion handler type used by async_resume.+  using completion_handler = argument_dependent;+};++#else // defined(GENERATING_DOCUMENTATION)++template <typename Yield, typename Return, typename Executor>+struct coro_traits+{+  using input_type  = void;+  using yield_type  = Yield;+  using return_type = Return;+  using result_type = detail::coro_result_t<yield_type, return_type>;+  using signature_type = result_type();+  constexpr static bool is_noexcept = false;+  using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+  using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename T, typename Return, typename Executor>+struct coro_traits<T(), Return, Executor>+{+  using input_type = void;+  using yield_type = T;+  using return_type = Return;+  using result_type = detail::coro_result_t<yield_type, return_type>;+  using signature_type = result_type();+  constexpr static bool is_noexcept = false;+  using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+  using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename T, typename Return, typename Executor>+struct coro_traits<T() noexcept, Return, Executor>+{+  using input_type = void;+  using yield_type = T;+  using return_type = Return;+  using result_type = detail::coro_result_t<yield_type, return_type>;+  using signature_type = result_type();+  constexpr static bool is_noexcept = true;+  using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+  using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename T, typename U, typename Return, typename Executor>+struct coro_traits<T(U), Return, Executor>+{+  using input_type = U;+  using yield_type = T;+  using return_type = Return;+  using result_type = detail::coro_result_t<yield_type, return_type>;+  using signature_type = result_type(input_type);+  constexpr static bool is_noexcept = false;+  using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+  using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename T, typename U, typename Return, typename Executor>+struct coro_traits<T(U) noexcept, Return, Executor>+{+  using input_type = U;+  using yield_type = T;+  using return_type = Return;+  using result_type = detail::coro_result_t<yield_type, return_type>;+  using signature_type = result_type(input_type);+  constexpr static bool is_noexcept = true;+  using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+  using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++template <typename Executor>+struct coro_traits<void() noexcept, void, Executor>+{+  using input_type = void;+  using yield_type = void;+  using return_type = void;+  using result_type = detail::coro_result_t<yield_type, return_type>;+  using signature_type = result_type(input_type);+  constexpr static bool is_noexcept = true;+  using error_type = std::conditional_t<is_noexcept, void, std::exception_ptr>;+  using completion_handler = detail::coro_handler_t<result_type, is_noexcept>;+};++#endif // defined(GENERATING_DOCUMENTATION)++} // namespace experimental+} // namespace asio++#endif // ASIO_EXPERIMENTAL_DETAIL_CORO_TRAITS_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/deferred.hpp view
@@ -0,0 +1,36 @@+//+// experimental/deferred.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DEFERRED_HPP+#define ASIO_EXPERIMENTAL_DEFERRED_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/deferred.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if !defined(ASIO_NO_DEPRECATED)+using asio::deferred_t;+using asio::deferred;+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DEFERRED_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_handler.hpp view
@@ -0,0 +1,80 @@+//+// experimental/detail/channel_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_HANDLER_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_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/associator.hpp"+#include "asio/experimental/detail/channel_payload.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Payload, typename Handler>+class channel_handler+{+public:+  channel_handler(ASIO_MOVE_ARG(Payload) p, Handler& h)+    : payload_(ASIO_MOVE_CAST(Payload)(p)),+      handler_(ASIO_MOVE_CAST(Handler)(h))+  {+  }++  void operator()()+  {+    payload_.receive(handler_);+  }++//private:+  Payload payload_;+  Handler handler_;+};++} // namespace detail+} // namespace experimental++template <template <typename, typename> class Associator,+    typename Payload, typename Handler, typename DefaultCandidate>+struct associator<Associator,+    experimental::detail::channel_handler<Payload, Handler>,+    DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const experimental::detail::channel_handler<Payload, Handler>& h)+    ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const experimental::detail::channel_handler<Payload, Handler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_HANDLER_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_message.hpp view
@@ -0,0 +1,129 @@+//+// experimental/detail/channel_message.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_MESSAGE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_MESSAGE_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/detail/type_traits.hpp"+#include "asio/detail/utility.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Signature>+class channel_message;++template <typename R>+class channel_message<R()>+{+public:+  channel_message(int)+  {+  }++  template <typename Handler>+  void receive(Handler& handler)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler)();+  }+};++template <typename R, typename Arg0>+class channel_message<R(Arg0)>+{+public:+  template <typename T0>+  channel_message(int, ASIO_MOVE_ARG(T0) t0)+    : arg0_(ASIO_MOVE_CAST(T0)(t0))+  {+  }++  template <typename Handler>+  void receive(Handler& handler)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler)(+        ASIO_MOVE_CAST(arg0_type)(arg0_));+  }++private:+  typedef typename decay<Arg0>::type arg0_type;+  arg0_type arg0_;+};++template <typename R, typename Arg0, typename Arg1>+class channel_message<R(Arg0, Arg1)>+{+public:+  template <typename T0, typename T1>+  channel_message(int, ASIO_MOVE_ARG(T0) t0, ASIO_MOVE_ARG(T1) t1)+    : arg0_(ASIO_MOVE_CAST(T0)(t0)),+      arg1_(ASIO_MOVE_CAST(T1)(t1))+  {+  }++  template <typename Handler>+  void receive(Handler& handler)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler)(+        ASIO_MOVE_CAST(arg0_type)(arg0_),+        ASIO_MOVE_CAST(arg1_type)(arg1_));+  }++private:+  typedef typename decay<Arg0>::type arg0_type;+  arg0_type arg0_;+  typedef typename decay<Arg1>::type arg1_type;+  arg1_type arg1_;+};++template <typename R, typename... Args>+class channel_message<R(Args...)>+{+public:+  template <typename... T>+  channel_message(int, ASIO_MOVE_ARG(T)... t)+    : args_(ASIO_MOVE_CAST(T)(t)...)+  {+  }++  template <typename Handler>+  void receive(Handler& h)+  {+    this->do_receive(h, asio::detail::index_sequence_for<Args...>());+  }++private:+  template <typename Handler, std::size_t... I>+  void do_receive(Handler& h, asio::detail::index_sequence<I...>)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(h)(+        std::get<I>(ASIO_MOVE_CAST(args_type)(args_))...);+  }++  typedef std::tuple<typename decay<Args>::type...> args_type;+  args_type args_;+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_MESSAGE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_operation.hpp view
@@ -0,0 +1,284 @@+//+// experimental/detail/channel_operation.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_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/associated_allocator.hpp"+#include "asio/associated_executor.hpp"+#include "asio/associated_immediate_executor.hpp"+#include "asio/detail/initiate_post.hpp"+#include "asio/detail/initiate_dispatch.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/detail/type_traits.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 {+namespace experimental {+namespace detail {++// Base class for all channel operations. A function pointer is used instead of+// virtual functions to avoid the associated overhead.+class channel_operation ASIO_INHERIT_TRACKED_HANDLER+{+public:+  template <typename Executor, typename = void>+  class handler_work_base;++  template <typename Handler, typename IoExecutor, typename = void>+  class handler_work;++  void destroy()+  {+    func_(this, destroy_op, 0);+  }++protected:+  enum action+  {+    destroy_op = 0,+    immediate_op = 1,+    complete_op = 2,+    cancel_op = 3,+    close_op = 4+  };++  typedef void (*func_type)(channel_operation*, action, void*);++  channel_operation(func_type func)+    : next_(0),+      func_(func),+      cancellation_key_(0)+  {+  }++  // Prevents deletion through this type.+  ~channel_operation()+  {+  }++  friend class asio::detail::op_queue_access;+  channel_operation* next_;+  func_type func_;++public:+  // The operation key used for targeted cancellation.+  void* cancellation_key_;+};++template <typename Executor, typename>+class channel_operation::handler_work_base+{+public:+  typedef typename decay<+      typename prefer_result<Executor,+        execution::outstanding_work_t::tracked_t+      >::type+    >::type executor_type;++  handler_work_base(int, const Executor& ex)+    : executor_(asio::prefer(ex, execution::outstanding_work.tracked))+  {+  }++  const executor_type& get_executor() const ASIO_NOEXCEPT+  {+    return executor_;+  }++  template <typename Function, typename Handler>+  void post(Function& function, Handler& handler)+  {+    typename associated_allocator<Handler>::type allocator =+      (get_associated_allocator)(handler);++#if defined(ASIO_NO_DEPRECATED)+    asio::prefer(+        asio::require(executor_, execution::blocking.never),+        execution::allocator(allocator)+      ).execute(ASIO_MOVE_CAST(Function)(function));+#else // defined(ASIO_NO_DEPRECATED)+    execution::execute(+        asio::prefer(+          asio::require(executor_, execution::blocking.never),+          execution::allocator(allocator)),+        ASIO_MOVE_CAST(Function)(function));+#endif // defined(ASIO_NO_DEPRECATED)+  }++private:+  executor_type executor_;+};++#if !defined(ASIO_NO_TS_EXECUTORS)++template <typename Executor>+class channel_operation::handler_work_base<Executor,+    typename enable_if<+      !execution::is_executor<Executor>::value+    >::type>+{+public:+  typedef Executor executor_type;++  handler_work_base(int, const Executor& ex)+    : work_(ex)+  {+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return work_.get_executor();+  }++  template <typename Function, typename Handler>+  void post(Function& function, Handler& handler)+  {+    typename associated_allocator<Handler>::type allocator =+      (get_associated_allocator)(handler);++    work_.get_executor().post(+        ASIO_MOVE_CAST(Function)(function), allocator);+  }++private:+  executor_work_guard<Executor> work_;+};++#endif // !defined(ASIO_NO_TS_EXECUTORS)++template <typename Handler, typename IoExecutor, typename>+class channel_operation::handler_work :+  channel_operation::handler_work_base<IoExecutor>,+  channel_operation::handler_work_base<+      typename associated_executor<Handler, IoExecutor>::type, IoExecutor>+{+public:+  typedef channel_operation::handler_work_base<IoExecutor> base1_type;++  typedef channel_operation::handler_work_base<+      typename associated_executor<Handler, IoExecutor>::type, IoExecutor>+    base2_type;++  handler_work(Handler& handler, const IoExecutor& io_ex) ASIO_NOEXCEPT+    : base1_type(0, io_ex),+      base2_type(0, (get_associated_executor)(handler, io_ex))+  {+  }++  template <typename Function>+  void complete(Function& function, Handler& handler)+  {+    base2_type::post(function, handler);+  }++  template <typename Function>+  void immediate(Function& function, Handler& handler, ...)+  {+    typedef typename associated_immediate_executor<Handler,+      typename base1_type::executor_type>::type immediate_ex_type;++    immediate_ex_type immediate_ex = (get_associated_immediate_executor)(+        handler, base1_type::get_executor());++    (asio::detail::initiate_dispatch_with_executor<immediate_ex_type>(+          immediate_ex))(ASIO_MOVE_CAST(Function)(function));+  }++  template <typename Function>+  void immediate(Function& function, Handler&,+      typename enable_if<+        is_same<+          typename associated_immediate_executor<+            typename conditional<false, Function, Handler>::type,+            typename base1_type::executor_type>::+              asio_associated_immediate_executor_is_unspecialised,+          void+        >::value+      >::type*)+  {+    (asio::detail::initiate_post_with_executor<+        typename base1_type::executor_type>(+          base1_type::get_executor()))(+        ASIO_MOVE_CAST(Function)(function));+  }+};++template <typename Handler, typename IoExecutor>+class channel_operation::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 channel_operation::handler_work_base<IoExecutor> base1_type;++  handler_work(Handler&, const IoExecutor& io_ex) ASIO_NOEXCEPT+    : base1_type(0, io_ex)+  {+  }++  template <typename Function>+  void complete(Function& function, Handler& handler)+  {+    base1_type::post(function, handler);+  }++  template <typename Function>+  void immediate(Function& function, Handler& handler, ...)+  {+    typedef typename associated_immediate_executor<Handler,+      typename base1_type::executor_type>::type immediate_ex_type;++    immediate_ex_type immediate_ex = (get_associated_immediate_executor)(+        handler, base1_type::get_executor());++    (asio::detail::initiate_dispatch_with_executor<immediate_ex_type>(+          immediate_ex))(ASIO_MOVE_CAST(Function)(function));+  }++  template <typename Function>+  void immediate(Function& function, Handler& handler,+      typename enable_if<+        is_same<+          typename associated_immediate_executor<+            typename conditional<false, Function, Handler>::type,+            typename base1_type::executor_type>::+              asio_associated_immediate_executor_is_unspecialised,+          void+        >::value+      >::type*)+  {+    base1_type::post(function, handler);+  }+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_OPERATION_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_payload.hpp view
@@ -0,0 +1,139 @@+//+// experimental/detail/channel_payload.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_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/experimental/detail/channel_message.hpp"++#if defined(ASIO_HAS_STD_VARIANT)+# include <variant>+#endif // defined(ASIO_HAS_STD_VARIANT)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename... Signatures>+class channel_payload;++template <typename R>+class channel_payload<R()>+{+public:+  explicit channel_payload(channel_message<R()>)+  {+  }++  template <typename Handler>+  void receive(Handler& handler)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler)();+  }+};++template <typename Signature>+class channel_payload<Signature>+{+public:+  channel_payload(ASIO_MOVE_ARG(channel_message<Signature>) m)+    : message_(ASIO_MOVE_CAST(channel_message<Signature>)(m))+  {+  }++  template <typename Handler>+  void receive(Handler& handler)+  {+    message_.receive(handler);+  }++private:+  channel_message<Signature> message_;+};++#if defined(ASIO_HAS_STD_VARIANT)++template <typename... Signatures>+class channel_payload+{+public:+  template <typename Signature>+  channel_payload(ASIO_MOVE_ARG(channel_message<Signature>) m)+    : message_(ASIO_MOVE_CAST(channel_message<Signature>)(m))+  {+  }++  template <typename Handler>+  void receive(Handler& handler)+  {+    std::visit(+        [&](auto& message)+        {+          message.receive(handler);+        }, message_);+  }++private:+  std::variant<channel_message<Signatures>...> message_;+};++#else // defined(ASIO_HAS_STD_VARIANT)++template <typename R1, typename R2>+class channel_payload<R1(), R2(asio::error_code)>+{+public:+  typedef channel_message<R1()> void_message_type;+  typedef channel_message<R2(asio::error_code)> error_message_type;++  channel_payload(ASIO_MOVE_ARG(void_message_type))+    : message_(0, asio::error_code()),+      empty_(true)+  {+  }++  channel_payload(ASIO_MOVE_ARG(error_message_type) m)+    : message_(ASIO_MOVE_CAST(error_message_type)(m)),+      empty_(false)+  {+  }++  template <typename Handler>+  void receive(Handler& handler)+  {+    if (empty_)+      channel_message<R1()>(0).receive(handler);+    else+      message_.receive(handler);+  }++private:+  error_message_type message_;+  bool empty_;+};++#endif // defined(ASIO_HAS_STD_VARIANT)++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_PAYLOAD_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_receive_op.hpp view
@@ -0,0 +1,120 @@+//+// experimental/detail/channel_receive_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_RECEIVE_OP_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_RECEIVE_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/handler_alloc_helpers.hpp"+#include "asio/error.hpp"+#include "asio/experimental/detail/channel_handler.hpp"+#include "asio/experimental/detail/channel_operation.hpp"+#include "asio/experimental/detail/channel_payload.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Payload>+class channel_receive : public channel_operation+{+public:+  void immediate(Payload payload)+  {+    func_(this, immediate_op, &payload);+  }++  void complete(Payload payload)+  {+    func_(this, complete_op, &payload);+  }++protected:+  channel_receive(func_type func)+    : channel_operation(func)+  {+  }+};++template <typename Payload, typename Handler, typename IoExecutor>+class channel_receive_op : public channel_receive<Payload>+{+public:+  ASIO_DEFINE_HANDLER_PTR(channel_receive_op);++  template <typename... Args>+  channel_receive_op(Handler& handler, const IoExecutor& io_ex)+    : channel_receive<Payload>(&channel_receive_op::do_action),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_action(channel_operation* base,+      channel_operation::action a, void* v)+  {+    // Take ownership of the operation object.+    channel_receive_op* o(static_cast<channel_receive_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    channel_operation::handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(channel_operation::handler_work<+          Handler, IoExecutor>)(o->work_));++    // Make a copy of the handler so that the memory can be deallocated before+    // the handler is posted. Even if we're not about to post the handler, 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.+    if (a != channel_operation::destroy_op)+    {+      Payload* payload = static_cast<Payload*>(v);+      channel_handler<Payload, Handler> handler(+          ASIO_MOVE_CAST(Payload)(*payload), o->handler_);+      p.h = asio::detail::addressof(handler.handler_);+      p.reset();+      ASIO_HANDLER_INVOCATION_BEGIN(());+      if (a == channel_operation::immediate_op)+        w.immediate(handler, handler.handler_, 0);+      else+        w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+    else+    {+      asio::detail::binder0<Handler> handler(o->handler_);+      p.h = asio::detail::addressof(handler.handler_);+      p.reset();+    }+  }++private:+  Handler handler_;+  channel_operation::handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_RECEIVE_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_functions.hpp view
@@ -0,0 +1,144 @@+//+// experimental/detail/channel_send_functions.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_FUNCTIONS_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_FUNCTIONS_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/error_code.hpp"+#include "asio/experimental/detail/channel_message.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Derived, typename Executor, typename... Signatures>+class channel_send_functions;++template <typename Derived, typename Executor, typename R, typename... Args>+class channel_send_functions<Derived, Executor, R(Args...)>+{+public:+  template <typename... Args2>+  typename enable_if<+    is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value,+    bool+  >::type try_send(ASIO_MOVE_ARG(Args2)... args)+  {+    typedef typename detail::channel_message<R(Args...)> message_type;+    Derived* self = static_cast<Derived*>(this);+    return self->service_->template try_send<message_type>(+        self->impl_, ASIO_MOVE_CAST(Args2)(args)...);+  }++  template <typename... Args2>+  typename enable_if<+    is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value,+    std::size_t+  >::type try_send_n(std::size_t count, ASIO_MOVE_ARG(Args2)... args)+  {+    typedef typename detail::channel_message<R(Args...)> message_type;+    Derived* self = static_cast<Derived*>(this);+    return self->service_->template try_send_n<message_type>(+        self->impl_, count, ASIO_MOVE_CAST(Args2)(args)...);+  }++  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+  auto async_send(Args... args,+      ASIO_MOVE_ARG(CompletionToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+    -> decltype(+        async_initiate<CompletionToken, void (asio::error_code)>(+          declval<typename conditional<false, CompletionToken,+            Derived>::type::initiate_async_send>(), token,+          declval<typename conditional<false, CompletionToken,+            Derived>::type::payload_type>()))+  {+    typedef typename Derived::payload_type payload_type;+    typedef typename detail::channel_message<R(Args...)> message_type;+    Derived* self = static_cast<Derived*>(this);+    return async_initiate<CompletionToken, void (asio::error_code)>(+        typename Derived::initiate_async_send(self), token,+        payload_type(message_type(0, ASIO_MOVE_CAST(Args)(args)...)));+  }+};++template <typename Derived, typename Executor,+    typename R, typename... Args, typename... Signatures>+class channel_send_functions<Derived, Executor, R(Args...), Signatures...> :+  public channel_send_functions<Derived, Executor, Signatures...>+{+public:+  using channel_send_functions<Derived, Executor, Signatures...>::try_send;+  using channel_send_functions<Derived, Executor, Signatures...>::async_send;++  template <typename... Args2>+  typename enable_if<+    is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value,+    bool+  >::type try_send(ASIO_MOVE_ARG(Args2)... args)+  {+    typedef typename detail::channel_message<R(Args...)> message_type;+    Derived* self = static_cast<Derived*>(this);+    return self->service_->template try_send<message_type>(+        self->impl_, ASIO_MOVE_CAST(Args2)(args)...);+  }++  template <typename... Args2>+  typename enable_if<+    is_constructible<detail::channel_message<R(Args...)>, int, Args2...>::value,+    std::size_t+  >::type try_send_n(std::size_t count, ASIO_MOVE_ARG(Args2)... args)+  {+    typedef typename detail::channel_message<R(Args...)> message_type;+    Derived* self = static_cast<Derived*>(this);+    return self->service_->template try_send_n<message_type>(+        self->impl_, count, ASIO_MOVE_CAST(Args2)(args)...);+  }++  template <+      ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))+        CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+  auto async_send(Args... args,+      ASIO_MOVE_ARG(CompletionToken) token+        ASIO_DEFAULT_COMPLETION_TOKEN(Executor))+    -> decltype(+        async_initiate<CompletionToken, void (asio::error_code)>(+          declval<typename conditional<false, CompletionToken,+            Derived>::type::initiate_async_send>(), token,+          declval<typename conditional<false, CompletionToken,+            Derived>::type::payload_type>()))+  {+    typedef typename Derived::payload_type payload_type;+    typedef typename detail::channel_message<R(Args...)> message_type;+    Derived* self = static_cast<Derived*>(this);+    return async_initiate<CompletionToken, void (asio::error_code)>(+        typename Derived::initiate_async_send(self), token,+        payload_type(message_type(0, ASIO_MOVE_CAST(Args)(args)...)));+  }+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_FUNCTIONS_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_op.hpp view
@@ -0,0 +1,148 @@+//+// experimental/detail/channel_send_op.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_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/handler_alloc_helpers.hpp"+#include "asio/error.hpp"+#include "asio/experimental/channel_error.hpp"+#include "asio/experimental/detail/channel_operation.hpp"+#include "asio/experimental/detail/channel_payload.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Payload>+class channel_send : public channel_operation+{+public:+  Payload get_payload()+  {+    return ASIO_MOVE_CAST(Payload)(payload_);+  }++  void immediate()+  {+    func_(this, immediate_op, 0);+  }++  void complete()+  {+    func_(this, complete_op, 0);+  }++  void cancel()+  {+    func_(this, cancel_op, 0);+  }++  void close()+  {+    func_(this, close_op, 0);+  }++protected:+  channel_send(func_type func, ASIO_MOVE_ARG(Payload) payload)+    : channel_operation(func),+      payload_(ASIO_MOVE_CAST(Payload)(payload))+  {+  }++private:+  Payload payload_;+};++template <typename Payload, typename Handler, typename IoExecutor>+class channel_send_op : public channel_send<Payload>+{+public:+  ASIO_DEFINE_HANDLER_PTR(channel_send_op);++  channel_send_op(ASIO_MOVE_ARG(Payload) payload,+      Handler& handler, const IoExecutor& io_ex)+    : channel_send<Payload>(&channel_send_op::do_action,+        ASIO_MOVE_CAST(Payload)(payload)),+      handler_(ASIO_MOVE_CAST(Handler)(handler)),+      work_(handler_, io_ex)+  {+  }++  static void do_action(channel_operation* base,+      channel_operation::action a, void*)+  {+    // Take ownership of the operation object.+    channel_send_op* o(static_cast<channel_send_op*>(base));+    ptr p = { asio::detail::addressof(o->handler_), o, o };++    ASIO_HANDLER_COMPLETION((*o));++    // Take ownership of the operation's outstanding work.+    channel_operation::handler_work<Handler, IoExecutor> w(+        ASIO_MOVE_CAST2(channel_operation::handler_work<+          Handler, IoExecutor>)(o->work_));++    asio::error_code ec;+    switch (a)+    {+    case channel_operation::cancel_op:+      ec = error::channel_cancelled;+      break;+    case channel_operation::close_op:+      ec = error::channel_closed;+      break;+    default:+      break;+    }++    // Make a copy of the handler so that the memory can be deallocated before+    // the handler is posted. Even if we're not about to post the handler, 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.+    asio::detail::binder1<Handler, asio::error_code>+      handler(o->handler_, ec);+    p.h = asio::detail::addressof(handler.handler_);+    p.reset();++    // Post the completion if required.+    if (a != channel_operation::destroy_op)+    {+      ASIO_HANDLER_INVOCATION_BEGIN((handler.arg1_));+      if (a == channel_operation::immediate_op)+        w.immediate(handler, handler.handler_, 0);+      else+        w.complete(handler, handler.handler_);+      ASIO_HANDLER_INVOCATION_END;+    }+  }++private:+  Handler handler_;+  channel_operation::handler_work<Handler, IoExecutor> work_;+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SEND_OP_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_service.hpp view
@@ -0,0 +1,677 @@+//+// experimental/detail/channel_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SERVICE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CHANNEL_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/associated_cancellation_slot.hpp"+#include "asio/cancellation_type.hpp"+#include "asio/detail/mutex.hpp"+#include "asio/detail/op_queue.hpp"+#include "asio/execution_context.hpp"+#include "asio/experimental/detail/channel_message.hpp"+#include "asio/experimental/detail/channel_receive_op.hpp"+#include "asio/experimental/detail/channel_send_op.hpp"+#include "asio/experimental/detail/has_signature.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Mutex>+class channel_service+  : public asio::detail::execution_context_service_base<+      channel_service<Mutex> >+{+public:+  // Possible states for a channel end.+  enum state+  {+    buffer = 0,+    waiter = 1,+    block = 2,+    closed = 3+  };++  // The base implementation type of all channels.+  struct base_implementation_type+  {+    // Default constructor.+    base_implementation_type()+      : receive_state_(block),+        send_state_(block),+        max_buffer_size_(0),+        next_(0),+        prev_(0)+    {+    }++    // The current state of the channel.+    state receive_state_ : 16;+    state send_state_ : 16;++    // The maximum number of elements that may be buffered in the channel.+    std::size_t max_buffer_size_;++    // The operations that are waiting on the channel.+    asio::detail::op_queue<channel_operation> waiters_;++    // Pointers to adjacent channel implementations in linked list.+    base_implementation_type* next_;+    base_implementation_type* prev_;++    // The mutex type to protect the internal implementation.+    mutable Mutex mutex_;+  };++  // The implementation for a specific value type.+  template <typename Traits, typename... Signatures>+  struct implementation_type;++  // Constructor.+  channel_service(execution_context& ctx);++  // Destroy all user-defined handler objects owned by the service.+  void shutdown();++  // Construct a new channel implementation.+  void construct(base_implementation_type& impl, std::size_t max_buffer_size);++  // Destroy a channel implementation.+  template <typename Traits, typename... Signatures>+  void destroy(implementation_type<Traits, Signatures...>& impl);++  // Move-construct a new channel implementation.+  template <typename Traits, typename... Signatures>+  void move_construct(implementation_type<Traits, Signatures...>& impl,+      implementation_type<Traits, Signatures...>& other_impl);++  // Move-assign from another channel implementation.+  template <typename Traits, typename... Signatures>+  void move_assign(implementation_type<Traits, Signatures...>& impl,+      channel_service& other_service,+      implementation_type<Traits, Signatures...>& other_impl);++  // Get the capacity of the channel.+  std::size_t capacity(+      const base_implementation_type& impl) const ASIO_NOEXCEPT;++  // Determine whether the channel is open.+  bool is_open(const base_implementation_type& impl) const ASIO_NOEXCEPT;++  // Reset the channel to its initial state.+  template <typename Traits, typename... Signatures>+  void reset(implementation_type<Traits, Signatures...>& impl);++  // Close the channel.+  template <typename Traits, typename... Signatures>+  void close(implementation_type<Traits, Signatures...>& impl);++  // Cancel all operations associated with the channel.+  template <typename Traits, typename... Signatures>+  void cancel(implementation_type<Traits, Signatures...>& impl);++  // Cancel the operation associated with the channel that has the given key.+  template <typename Traits, typename... Signatures>+  void cancel_by_key(implementation_type<Traits, Signatures...>& impl,+      void* cancellation_key);++  // Determine whether a value can be read from the channel without blocking.+  bool ready(const base_implementation_type& impl) const ASIO_NOEXCEPT;++  // Synchronously send a new value into the channel.+  template <typename Message, typename Traits,+      typename... Signatures, typename... Args>+  bool try_send(implementation_type<Traits, Signatures...>& impl,+      ASIO_MOVE_ARG(Args)... args);++  // Synchronously send a number of new values into the channel.+  template <typename Message, typename Traits,+      typename... Signatures, typename... Args>+  std::size_t try_send_n(implementation_type<Traits, Signatures...>& impl,+      std::size_t count, ASIO_MOVE_ARG(Args)... args);++  // Asynchronously send a new value into the channel.+  template <typename Traits, typename... Signatures,+      typename Handler, typename IoExecutor>+  void async_send(implementation_type<Traits, Signatures...>& impl,+      ASIO_MOVE_ARG2(typename implementation_type<+        Traits, Signatures...>::payload_type) payload,+      Handler& handler, const IoExecutor& io_ex)+  {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef channel_send_op<+      typename implementation_type<Traits, Signatures...>::payload_type,+        Handler, IoExecutor> op;+    typename op::ptr p = { asio::detail::addressof(handler),+      op::ptr::allocate(handler), 0 };+    p.p = new (p.v) op(ASIO_MOVE_CAST2(typename implementation_type<+          Traits, Signatures...>::payload_type)(payload), handler, io_ex);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<op_cancellation<Traits, Signatures...> >(+            this, &impl);+    }++    ASIO_HANDLER_CREATION((this->context(), *p.p,+          "channel", &impl, 0, "async_send"));++    start_send_op(impl, p.p);+    p.v = p.p = 0;+  }++  // Synchronously receive a value from the channel.+  template <typename Traits, typename... Signatures, typename Handler>+  bool try_receive(implementation_type<Traits, Signatures...>& impl,+      ASIO_MOVE_ARG(Handler) handler);++  // Asynchronously receive a value from the channel.+  template <typename Traits, typename... Signatures,+      typename Handler, typename IoExecutor>+  void async_receive(implementation_type<Traits, Signatures...>& impl,+      Handler& handler, const IoExecutor& io_ex)+  {+    typename associated_cancellation_slot<Handler>::type slot+      = asio::get_associated_cancellation_slot(handler);++    // Allocate and construct an operation to wrap the handler.+    typedef channel_receive_op<+      typename implementation_type<Traits, Signatures...>::payload_type,+        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);++    // Optionally register for per-operation cancellation.+    if (slot.is_connected())+    {+      p.p->cancellation_key_ =+        &slot.template emplace<op_cancellation<Traits, Signatures...> >(+            this, &impl);+    }++    ASIO_HANDLER_CREATION((this->context(), *p.p,+          "channel", &impl, 0, "async_receive"));++    start_receive_op(impl, p.p);+    p.v = p.p = 0;+  }++private:+  // Helper function object to handle a closed notification.+  template <typename Payload, typename Signature>+  struct complete_receive+  {+    explicit complete_receive(channel_receive<Payload>* op)+      : op_(op)+    {+    }++    template <typename... Args>+    void operator()(ASIO_MOVE_ARG(Args)... args)+    {+      op_->complete(+          channel_message<Signature>(0,+            ASIO_MOVE_CAST(Args)(args)...));+    }++    channel_receive<Payload>* op_;+  };++  // Destroy a base channel implementation.+  void base_destroy(base_implementation_type& impl);++  // Helper function to start an asynchronous put operation.+  template <typename Traits, typename... Signatures>+  void start_send_op(implementation_type<Traits, Signatures...>& impl,+      channel_send<typename implementation_type<+        Traits, Signatures...>::payload_type>* send_op);++  // Helper function to start an asynchronous get operation.+  template <typename Traits, typename... Signatures>+  void start_receive_op(implementation_type<Traits, Signatures...>& impl,+      channel_receive<typename implementation_type<+        Traits, Signatures...>::payload_type>* receive_op);++  // Helper class used to implement per-operation cancellation.+  template <typename Traits, typename... Signatures>+  class op_cancellation+  {+  public:+    op_cancellation(channel_service* s,+        implementation_type<Traits, Signatures...>* impl)+      : service_(s),+        impl_(impl)+    {+    }++    void operator()(cancellation_type_t type)+    {+      if (!!(type &+            (cancellation_type::terminal+              | cancellation_type::partial+              | cancellation_type::total)))+      {+        service_->cancel_by_key(*impl_, this);+      }+    }++  private:+    channel_service* service_;+    implementation_type<Traits, Signatures...>* impl_;+  };++  // 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_;+};++// The implementation for a specific value type.+template <typename Mutex>+template <typename Traits, typename... Signatures>+struct channel_service<Mutex>::implementation_type : base_implementation_type+{+  // The traits type associated with the channel.+  typedef typename Traits::template rebind<Signatures...>::other traits_type;++  // Type of an element stored in the buffer.+  typedef typename conditional<+      has_signature<+        typename traits_type::receive_cancelled_signature,+        Signatures...+      >::value,+      typename conditional<+        has_signature<+          typename traits_type::receive_closed_signature,+          Signatures...+        >::value,+        channel_payload<Signatures...>,+        channel_payload<+          Signatures...,+          typename traits_type::receive_closed_signature+        >+      >::type,+      typename conditional<+        has_signature<+          typename traits_type::receive_closed_signature,+          Signatures...,+          typename traits_type::receive_cancelled_signature+        >::value,+        channel_payload<+          Signatures...,+          typename traits_type::receive_cancelled_signature+        >,+        channel_payload<+          Signatures...,+          typename traits_type::receive_cancelled_signature,+          typename traits_type::receive_closed_signature+        >+      >::type+    >::type payload_type;++  // Move from another buffer.+  void buffer_move_from(implementation_type& other)+  {+    buffer_ = ASIO_MOVE_CAST(+        typename traits_type::template container<+          payload_type>::type)(other.buffer_);+    other.buffer_clear();+  }++  // Get number of buffered elements.+  std::size_t buffer_size() const+  {+    return buffer_.size();+  }++  // Push a new value to the back of the buffer.+  void buffer_push(payload_type payload)+  {+    buffer_.push_back(ASIO_MOVE_CAST(payload_type)(payload));+  }++  // Push new values to the back of the buffer.+  std::size_t buffer_push_n(std::size_t count, payload_type payload)+  {+    std::size_t i = 0;+    for (; i < count && buffer_.size() < this->max_buffer_size_; ++i)+      buffer_.push_back(payload);+    return i;+  }++  // Get the element at the front of the buffer.+  payload_type buffer_front()+  {+    return ASIO_MOVE_CAST(payload_type)(buffer_.front());+  }++  // Pop a value from the front of the buffer.+  void buffer_pop()+  {+    buffer_.pop_front();+  }++  // Clear all buffered values.+  void buffer_clear()+  {+    buffer_.clear();+  }++private:+  // Buffered values.+  typename traits_type::template container<payload_type>::type buffer_;+};++// The implementation for a void value type.+template <typename Mutex>+template <typename Traits, typename R>+struct channel_service<Mutex>::implementation_type<Traits, R()>+  : channel_service::base_implementation_type+{+  // The traits type associated with the channel.+  typedef typename Traits::template rebind<R()>::other traits_type;++  // Type of an element stored in the buffer.+  typedef typename conditional<+      has_signature<+        typename traits_type::receive_cancelled_signature,+        R()+      >::value,+      typename conditional<+        has_signature<+          typename traits_type::receive_closed_signature,+          R()+        >::value,+        channel_payload<R()>,+        channel_payload<+          R(),+          typename traits_type::receive_closed_signature+        >+      >::type,+      typename conditional<+        has_signature<+          typename traits_type::receive_closed_signature,+          R(),+          typename traits_type::receive_cancelled_signature+        >::value,+        channel_payload<+          R(),+          typename traits_type::receive_cancelled_signature+        >,+        channel_payload<+          R(),+          typename traits_type::receive_cancelled_signature,+          typename traits_type::receive_closed_signature+        >+      >::type+    >::type payload_type;++  // Construct with empty buffer.+  implementation_type()+    : buffer_(0)+  {+  }++  // Move from another buffer.+  void buffer_move_from(implementation_type& other)+  {+    buffer_ = other.buffer_;+    other.buffer_ = 0;+  }++  // Get number of buffered elements.+  std::size_t buffer_size() const+  {+    return buffer_;+  }++  // Push a new value to the back of the buffer.+  void buffer_push(payload_type)+  {+    ++buffer_;+  }++  // Push new values to the back of the buffer.+  std::size_t buffer_push_n(std::size_t count, payload_type)+  {+    std::size_t available = this->max_buffer_size_ - buffer_;+    count = (count < available) ? count : available;+    buffer_ += count;+    return count;+  }++  // Get the element at the front of the buffer.+  payload_type buffer_front()+  {+    return payload_type(channel_message<R()>(0));+  }++  // Pop a value from the front of the buffer.+  void buffer_pop()+  {+    --buffer_;+  }++  // Clear all values from the buffer.+  void buffer_clear()+  {+    buffer_ = 0;+  }++private:+  // Number of buffered "values".+  std::size_t buffer_;+};++// The implementation for an error_code signature.+template <typename Mutex>+template <typename Traits, typename R>+struct channel_service<Mutex>::implementation_type<+    Traits, R(asio::error_code)>+  : channel_service::base_implementation_type+{+  // The traits type associated with the channel.+  typedef typename Traits::template rebind<R(asio::error_code)>::other+    traits_type;++  // Type of an element stored in the buffer.+  typedef typename conditional<+      has_signature<+        typename traits_type::receive_cancelled_signature,+        R(asio::error_code)+      >::value,+      typename conditional<+        has_signature<+          typename traits_type::receive_closed_signature,+          R(asio::error_code)+        >::value,+        channel_payload<R(asio::error_code)>,+        channel_payload<+          R(asio::error_code),+          typename traits_type::receive_closed_signature+        >+      >::type,+      typename conditional<+        has_signature<+          typename traits_type::receive_closed_signature,+          R(asio::error_code),+          typename traits_type::receive_cancelled_signature+        >::value,+        channel_payload<+          R(asio::error_code),+          typename traits_type::receive_cancelled_signature+        >,+        channel_payload<+          R(asio::error_code),+          typename traits_type::receive_cancelled_signature,+          typename traits_type::receive_closed_signature+        >+      >::type+    >::type payload_type;++  // Construct with empty buffer.+  implementation_type()+    : size_(0)+  {+    first_.count_ = 0;+  }++  // Move from another buffer.+  void buffer_move_from(implementation_type& other)+  {+    size_ = other.buffer_;+    other.size_ = 0;+    first_ = other.first_;+    other.first.count_ = 0;+    rest_ = ASIO_MOVE_CAST(+        typename traits_type::template container<+          buffered_value>::type)(other.rest_);+    other.buffer_clear();+  }++  // Get number of buffered elements.+  std::size_t buffer_size() const+  {+    return size_;+  }++  // Push a new value to the back of the buffer.+  void buffer_push(payload_type payload)+  {+    buffered_value& last = rest_.empty() ? first_ : rest_.back();+    if (last.count_ == 0)+    {+      value_handler handler{last.value_};+      payload.receive(handler);+      last.count_ = 1;+    }+    else+    {+      asio::error_code value{last.value_};+      value_handler handler{value};+      payload.receive(handler);+      if (last.value_ == value)+        ++last.count_;+      else+        rest_.push_back({value, 1});+    }+    ++size_;+  }++  // Push new values to the back of the buffer.+  std::size_t buffer_push_n(std::size_t count, payload_type payload)+  {+    std::size_t available = this->max_buffer_size_ - size_;+    count = (count < available) ? count : available;+    if (count > 0)+    {+      buffered_value& last = rest_.empty() ? first_ : rest_.back();+      if (last.count_ == 0)+      {+        payload.receive(value_handler{last.value_});+        last.count_ = count;+      }+      else+      {+        asio::error_code value{last.value_};+        payload.receive(value_handler{value});+        if (last.value_ == value)+          last.count_ += count;+        else+          rest_.push_back({value, count});+      }+      size_ += count;+    }+    return count;+  }++  // Get the element at the front of the buffer.+  payload_type buffer_front()+  {+    return payload_type({0, first_.value_});+  }++  // Pop a value from the front of the buffer.+  void buffer_pop()+  {+    --size_;+    if (--first_.count_ == 0 && !rest_.empty())+    {+      first_ = rest_.front();+      rest_.pop_front();+    }+  }++  // Clear all values from the buffer.+  void buffer_clear()+  {+    size_ = 0;+    first_.count_ == 0;+    rest_.clear();+  }++private:+  struct buffered_value+  {+    asio::error_code value_;+    std::size_t count_;+  };++  struct value_handler+  {+    asio::error_code& target_;++    template <typename... Args>+    void operator()(const asio::error_code& value, Args&&...)+    {+      target_ = value;+    }+  };++  buffered_value& last_value()+  {+    return rest_.empty() ? first_ : rest_.back();+  }++  // Total number of buffered values.+  std::size_t size_;++  // The first buffered value is maintained as a separate data member to avoid+  // allocating space in the container in the common case.+  buffered_value first_;++  // The rest of the buffered values.+  typename traits_type::template container<buffered_value>::type rest_;+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/detail/impl/channel_service.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CHANNEL_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_completion_handler.hpp view
@@ -0,0 +1,169 @@+//+// experimental/detail/coro_completion_handler.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CORO_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/deferred.hpp"+#include "asio/experimental/coro.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++template <typename Promise, typename... Args>+struct coro_completion_handler+{+  coro_completion_handler(coroutine_handle<Promise> h,+      std::optional<std::tuple<Args...>>& result)+    : self(h),+      result(result)+  {+  }++  coro_completion_handler(coro_completion_handler&&) = default;++  coroutine_handle<Promise> self;++  std::optional<std::tuple<Args...>>& result;++  using promise_type = Promise;++  void operator()(Args... args)+  {+    result.emplace(std::move(args)...);+    self.resume();+  }++  using allocator_type = typename promise_type::allocator_type;+  allocator_type get_allocator() const noexcept+  {+    return self.promise().get_allocator();+  }++  using executor_type = typename promise_type::executor_type;+  executor_type get_executor() const noexcept+  {+    return self.promise().get_executor();+  }++  using cancellation_slot_type = typename promise_type::cancellation_slot_type;+  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return self.promise().get_cancellation_slot();+  }+};++template <typename Signature>+struct coro_completion_handler_type;++template <typename... Args>+struct coro_completion_handler_type<void(Args...)>+{+  using type = std::tuple<Args...>;++  template <typename Promise>+  using completion_handler = coro_completion_handler<Promise, Args...>;+};++template <typename Signature>+using coro_completion_handler_type_t =+  typename coro_completion_handler_type<Signature>::type;++inline void coro_interpret_result(std::tuple<>&&)+{+}++template <typename... Args>+inline auto coro_interpret_result(std::tuple<Args...>&& args)+{+  return std::move(args);+}++template <typename... Args>+auto coro_interpret_result(std::tuple<std::exception_ptr, Args...>&& args)+{+  if (std::get<0>(args))+    std::rethrow_exception(std::get<0>(args));++  return std::apply(+      [](auto, auto&&... rest)+      {+        return std::make_tuple(std::move(rest)...);+      }, std::move(args));+}++template <typename... Args>+auto coro_interpret_result(+    std::tuple<asio::error_code, Args...>&& args)+{+  if (std::get<0>(args))+    asio::detail::throw_exception(+        asio::system_error(std::get<0>(args)));++  return std::apply(+      [](auto, auto&&... rest)+      {+        return std::make_tuple(std::move(rest)...);+      }, std::move(args));+}++template <typename  Arg>+inline auto coro_interpret_result(std::tuple<Arg>&& args)+{+  return std::get<0>(std::move(args));+}++template <typename Arg>+auto coro_interpret_result(std::tuple<std::exception_ptr, Arg>&& args)+{+  if (std::get<0>(args))+    std::rethrow_exception(std::get<0>(args));+  return std::get<1>(std::move(args));+}++inline auto coro_interpret_result(+    std::tuple<asio::error_code>&& args)+{+  if (std::get<0>(args))+    asio::detail::throw_exception(+        asio::system_error(std::get<0>(args)));+}++inline auto coro_interpret_result(std::tuple<std::exception_ptr>&& args)+{+  if (std::get<0>(args))+    std::rethrow_exception(std::get<0>(args));+}++template <typename Arg>+auto coro_interpret_result(std::tuple<asio::error_code, Arg>&& args)+{+  if (std::get<0>(args))+    asio::detail::throw_exception(+        asio::system_error(std::get<0>(args)));+  return std::get<1>(std::move(args));+}++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_CORO_COMPLETION_HANDLER_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_promise_allocator.hpp view
@@ -0,0 +1,141 @@+//+// experimental/detail/coro_promise_allocator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP+#define ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP++#include "asio/detail/config.hpp"+#include "asio/experimental/coro_traits.hpp"++namespace asio {+namespace experimental {+namespace detail {++/// Allocate the memory and put the allocator behind the coro memory+template <typename AllocatorType>+void* allocate_coroutine(const std::size_t size, AllocatorType alloc_)+{+  using alloc_type = typename std::allocator_traits<AllocatorType>::template+    rebind_alloc<unsigned char>;+  alloc_type alloc{alloc_};++  const auto align_needed = size % alignof(alloc_type);+  const auto align_offset = align_needed != 0+    ? alignof(alloc_type) - align_needed : 0ull;+  const auto alloc_size = size + sizeof(alloc_type) + align_offset;+  const auto raw =+    std::allocator_traits<alloc_type>::allocate(alloc, alloc_size);+  new(raw + size + align_offset) alloc_type(std::move(alloc));++  return raw;+}++/// Deallocate the memory and destroy the allocator in the coro memory.+template <typename AllocatorType>+void deallocate_coroutine(void* raw_, const std::size_t size)+{+  using alloc_type = typename std::allocator_traits<AllocatorType>::template+    rebind_alloc<unsigned char>;++  const auto raw = static_cast<unsigned char *>(raw_);++  const auto align_needed = size % alignof(alloc_type);+  const auto align_offset = align_needed != 0+    ? alignof(alloc_type) - align_needed : 0ull;+  const auto alloc_size = size + sizeof(alloc_type) + align_offset;++  auto alloc_p = reinterpret_cast<alloc_type *>(raw + size + align_offset);+  auto alloc = std::move(*alloc_p);+  alloc_p->~alloc_type();+  std::allocator_traits<alloc_type>::deallocate(alloc, raw, alloc_size);+}++template <typename T>+constexpr std::size_t variadic_first(std::size_t = 0u)+{+  return std::numeric_limits<std::size_t>::max();+}+++template <typename T, typename First, typename... Args>+constexpr std::size_t variadic_first(std::size_t pos = 0u)+{+  if constexpr (std::is_same_v<std::decay_t<First>, T>)+    return pos;+  else+    return variadic_first<T, Args...>(pos+1);+}++template <std::size_t Idx, typename First, typename... Args>+  requires (Idx <= sizeof...(Args))+constexpr decltype(auto) get_variadic(First&& first, Args&&... args)+{+  if constexpr (Idx == 0u)+    return static_cast<First>(first);+  else+    return get_variadic<Idx-1u>(static_cast<Args>(args)...);+}++template <std::size_t Idx>+constexpr decltype(auto) get_variadic();++template <typename Allocator>+struct coro_promise_allocator+{+  using allocator_type = Allocator;+  allocator_type get_allocator() const {return alloc_;}++  template <typename... Args>+  void* operator new(const std::size_t size, Args & ... args)+  {+    return allocate_coroutine(size,+        get_variadic<variadic_first<std::allocator_arg_t,+          std::decay_t<Args>...>() + 1u>(args...));+  }++  void operator delete(void* raw, const std::size_t size)+  {+    deallocate_coroutine<allocator_type>(raw, size);+  }++  template <typename... Args>+  coro_promise_allocator(Args&& ... args)+    : alloc_(+        get_variadic<variadic_first<std::allocator_arg_t,+          std::decay_t<Args>...>() + 1u>(args...))+  {+  }++private:+  allocator_type alloc_;+};++template <>+struct coro_promise_allocator<std::allocator<void>>+{+  using allocator_type = std::allocator<void>;++  template <typename... Args>+  coro_promise_allocator(Args&&...)+  {+  }++  allocator_type get_allocator() const+  {+    return {};+  }+};++} // namespace detail+} // namespace experimental+} // namespace asio++#endif // ASIO_EXPERIMENTAL_DETAIL_CORO_PROMISE_ALLOCATOR_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/has_signature.hpp view
@@ -0,0 +1,54 @@+//+// experimental/detail/has_signature.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_HAS_SIGNATURE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_HAS_SIGNATURE_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 experimental {+namespace detail {++template <typename S, typename... Signatures>+struct has_signature;++template <typename S, typename... Signatures>+struct has_signature;++template <typename S>+struct has_signature<S> : false_type+{+};++template <typename S, typename... Signatures>+struct has_signature<S, S, Signatures...> : true_type+{+};++template <typename S, typename Head, typename... Tail>+struct has_signature<S, Head, Tail...> : has_signature<S, Tail...>+{+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_HAS_SIGNATURE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/impl/channel_service.hpp view
@@ -0,0 +1,612 @@+//+// experimental/detail/impl/channel_service.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_IMPL_CHANNEL_SERVICE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_IMPL_CHANNEL_SERVICE_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 experimental {+namespace detail {++template <typename Mutex>+inline channel_service<Mutex>::channel_service(execution_context& ctx)+  : asio::detail::execution_context_service_base<channel_service>(ctx),+    mutex_(),+    impl_list_(0)+{+}++template <typename Mutex>+inline void channel_service<Mutex>::shutdown()+{+  // Abandon all pending operations.+  asio::detail::op_queue<channel_operation> ops;+  asio::detail::mutex::scoped_lock lock(mutex_);+  base_implementation_type* impl = impl_list_;+  while (impl)+  {+    ops.push(impl->waiters_);+    impl = impl->next_;+  }+}++template <typename Mutex>+inline void channel_service<Mutex>::construct(+    channel_service<Mutex>::base_implementation_type& impl,+    std::size_t max_buffer_size)+{+  impl.max_buffer_size_ = max_buffer_size;+  impl.receive_state_ = block;+  impl.send_state_ = max_buffer_size ? buffer : block;++  // 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;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::destroy(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl)+{+  cancel(impl);+  base_destroy(impl);+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::move_construct(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+    channel_service<Mutex>::implementation_type<+      Traits, Signatures...>& other_impl)+{+  impl.max_buffer_size_ = other_impl.max_buffer_size_;+  impl.receive_state_ = other_impl.receive_state_;+  other_impl.receive_state_ = block;+  impl.send_state_ = other_impl.send_state_;+  other_impl.send_state_ = other_impl.max_buffer_size_ ? buffer : block;+  impl.buffer_move_from(other_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;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::move_assign(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+    channel_service& other_service,+    channel_service<Mutex>::implementation_type<+      Traits, Signatures...>& other_impl)+{+  cancel(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.max_buffer_size_ = other_impl.max_buffer_size_;+  impl.receive_state_ = other_impl.receive_state_;+  other_impl.receive_state_ = block;+  impl.send_state_ = other_impl.send_state_;+  other_impl.send_state_ = other_impl.max_buffer_size_ ? buffer : block;+  impl.buffer_move_from(other_impl);++  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;+  }+}++template <typename Mutex>+inline void channel_service<Mutex>::base_destroy(+    channel_service<Mutex>::base_implementation_type& 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;+}++template <typename Mutex>+inline std::size_t channel_service<Mutex>::capacity(+    const channel_service<Mutex>::base_implementation_type& impl)+  const ASIO_NOEXCEPT+{+  typename Mutex::scoped_lock lock(impl.mutex_);++  return impl.max_buffer_size_;+}++template <typename Mutex>+inline bool channel_service<Mutex>::is_open(+    const channel_service<Mutex>::base_implementation_type& impl)+  const ASIO_NOEXCEPT+{+  typename Mutex::scoped_lock lock(impl.mutex_);++  return impl.send_state_ != closed;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::reset(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl)+{+  cancel(impl);++  typename Mutex::scoped_lock lock(impl.mutex_);++  impl.receive_state_ = block;+  impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+  impl.buffer_clear();+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::close(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl)+{+  typedef typename implementation_type<Traits,+      Signatures...>::traits_type traits_type;+  typedef typename implementation_type<Traits,+      Signatures...>::payload_type payload_type;++  typename Mutex::scoped_lock lock(impl.mutex_);++  if (impl.receive_state_ == block)+  {+    while (channel_operation* op = impl.waiters_.front())+    {+      impl.waiters_.pop();+      traits_type::invoke_receive_closed(+          complete_receive<payload_type,+            typename traits_type::receive_closed_signature>(+              static_cast<channel_receive<payload_type>*>(op)));+    }+  }++  impl.send_state_ = closed;+  if (impl.receive_state_ != buffer)+    impl.receive_state_ = closed;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::cancel(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl)+{+  typedef typename implementation_type<Traits,+      Signatures...>::traits_type traits_type;+  typedef typename implementation_type<Traits,+      Signatures...>::payload_type payload_type;++  typename Mutex::scoped_lock lock(impl.mutex_);++  while (channel_operation* op = impl.waiters_.front())+  {+    if (impl.send_state_ == block)+    {+      impl.waiters_.pop();+      static_cast<channel_send<payload_type>*>(op)->cancel();+    }+    else+    {+      impl.waiters_.pop();+      traits_type::invoke_receive_cancelled(+          complete_receive<payload_type,+            typename traits_type::receive_cancelled_signature>(+              static_cast<channel_receive<payload_type>*>(op)));+    }+  }++  if (impl.receive_state_ == waiter)+    impl.receive_state_ = block;+  if (impl.send_state_ == waiter)+    impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::cancel_by_key(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+    void* cancellation_key)+{+  typedef typename implementation_type<Traits,+      Signatures...>::traits_type traits_type;+  typedef typename implementation_type<Traits,+      Signatures...>::payload_type payload_type;++  typename Mutex::scoped_lock lock(impl.mutex_);++  asio::detail::op_queue<channel_operation> other_ops;+  while (channel_operation* op = impl.waiters_.front())+  {+    if (op->cancellation_key_ == cancellation_key)+    {+      if (impl.send_state_ == block)+      {+        impl.waiters_.pop();+        static_cast<channel_send<payload_type>*>(op)->cancel();+      }+      else+      {+        impl.waiters_.pop();+        traits_type::invoke_receive_cancelled(+            complete_receive<payload_type,+              typename traits_type::receive_cancelled_signature>(+                static_cast<channel_receive<payload_type>*>(op)));+      }+    }+    else+    {+      impl.waiters_.pop();+      other_ops.push(op);+    }+  }+  impl.waiters_.push(other_ops);++  if (impl.waiters_.empty())+  {+    if (impl.receive_state_ == waiter)+      impl.receive_state_ = block;+    if (impl.send_state_ == waiter)+      impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+  }+}++template <typename Mutex>+inline bool channel_service<Mutex>::ready(+    const channel_service<Mutex>::base_implementation_type& impl)+  const ASIO_NOEXCEPT+{+  typename Mutex::scoped_lock lock(impl.mutex_);++  return impl.receive_state_ != block;+}++template <typename Mutex>+template <typename Message, typename Traits,+    typename... Signatures, typename... Args>+bool channel_service<Mutex>::try_send(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+    ASIO_MOVE_ARG(Args)... args)+{+  typedef typename implementation_type<Traits,+      Signatures...>::payload_type payload_type;++  typename Mutex::scoped_lock lock(impl.mutex_);++  switch (impl.send_state_)+  {+  case block:+    {+      return false;+    }+  case buffer:+    {+      impl.buffer_push(Message(0, ASIO_MOVE_CAST(Args)(args)...));+      impl.receive_state_ = buffer;+      if (impl.buffer_size() == impl.max_buffer_size_)+        impl.send_state_ = block;+      return true;+    }+  case waiter:+    {+      payload_type payload(Message(0, ASIO_MOVE_CAST(Args)(args)...));+      channel_receive<payload_type>* receive_op =+        static_cast<channel_receive<payload_type>*>(impl.waiters_.front());+      impl.waiters_.pop();+      receive_op->complete(ASIO_MOVE_CAST(payload_type)(payload));+      if (impl.waiters_.empty())+        impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+      return true;+    }+  case closed:+  default:+    {+      return false;+    }+  }+}++template <typename Mutex>+template <typename Message, typename Traits,+    typename... Signatures, typename... Args>+std::size_t channel_service<Mutex>::try_send_n(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+		std::size_t count, ASIO_MOVE_ARG(Args)... args)+{+  typedef typename implementation_type<Traits,+      Signatures...>::payload_type payload_type;++  typename Mutex::scoped_lock lock(impl.mutex_);++  if (count == 0)+    return 0;++  switch (impl.send_state_)+  {+  case block:+    return 0;+  case buffer:+  case waiter:+    break;+  case closed:+  default:+    return 0;+  }++  payload_type payload(Message(0, ASIO_MOVE_CAST(Args)(args)...));++  for (std::size_t i = 0; i < count; ++i)+  {+    switch (impl.send_state_)+    {+    case block:+      {+        return i;+      }+    case buffer:+      {+        i += impl.buffer_push_n(count - i,+            ASIO_MOVE_CAST(payload_type)(payload));+        impl.receive_state_ = buffer;+        if (impl.buffer_size() == impl.max_buffer_size_)+          impl.send_state_ = block;+        return i;+      }+    case waiter:+      {+        channel_receive<payload_type>* receive_op =+          static_cast<channel_receive<payload_type>*>(impl.waiters_.front());+        impl.waiters_.pop();+        receive_op->complete(payload);+        if (impl.waiters_.empty())+          impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+        break;+      }+    case closed:+    default:+      {+        return i;+      }+    }+  }++  return count;+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::start_send_op(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+		channel_send<typename implementation_type<+			Traits, Signatures...>::payload_type>* send_op)+{+  typedef typename implementation_type<Traits,+      Signatures...>::payload_type payload_type;++  typename Mutex::scoped_lock lock(impl.mutex_);++  switch (impl.send_state_)+  {+  case block:+    {+      impl.waiters_.push(send_op);+      if (impl.receive_state_ == block)+        impl.receive_state_ = waiter;+      return;+    }+  case buffer:+    {+      impl.buffer_push(send_op->get_payload());+      impl.receive_state_ = buffer;+      if (impl.buffer_size() == impl.max_buffer_size_)+        impl.send_state_ = block;+      send_op->immediate();+      break;+    }+  case waiter:+    {+      channel_receive<payload_type>* receive_op =+        static_cast<channel_receive<payload_type>*>(impl.waiters_.front());+      impl.waiters_.pop();+      receive_op->complete(send_op->get_payload());+      if (impl.waiters_.empty())+        impl.send_state_ = impl.max_buffer_size_ ? buffer : block;+      send_op->immediate();+      break;+    }+  case closed:+  default:+    {+      send_op->close();+      break;+    }+  }+}++template <typename Mutex>+template <typename Traits, typename... Signatures, typename Handler>+bool channel_service<Mutex>::try_receive(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+		ASIO_MOVE_ARG(Handler) handler)+{+  typedef typename implementation_type<Traits,+      Signatures...>::payload_type payload_type;++  typename Mutex::scoped_lock lock(impl.mutex_);++  switch (impl.receive_state_)+  {+  case block:+    {+      return false;+    }+  case buffer:+    {+      payload_type payload(impl.buffer_front());+      if (channel_send<payload_type>* send_op =+          static_cast<channel_send<payload_type>*>(impl.waiters_.front()))+      {+        impl.buffer_pop();+        impl.buffer_push(send_op->get_payload());+        impl.waiters_.pop();+        send_op->complete();+      }+      else+      {+        impl.buffer_pop();+        if (impl.buffer_size() == 0)+          impl.receive_state_ = (impl.send_state_ == closed) ? closed : block;+        impl.send_state_ = (impl.send_state_ == closed) ? closed : buffer;+      }+      lock.unlock();+      asio::detail::non_const_lvalue<Handler> handler2(handler);+      channel_handler<payload_type, typename decay<Handler>::type>(+          ASIO_MOVE_CAST(payload_type)(payload), handler2.value)();+      return true;+    }+  case waiter:+    {+      channel_send<payload_type>* send_op =+        static_cast<channel_send<payload_type>*>(impl.waiters_.front());+      payload_type payload = send_op->get_payload();+      impl.waiters_.pop();+      send_op->complete();+      if (impl.waiters_.front() == 0)+        impl.receive_state_ = (impl.send_state_ == closed) ? closed : block;+      lock.unlock();+      asio::detail::non_const_lvalue<Handler> handler2(handler);+      channel_handler<payload_type, typename decay<Handler>::type>(+          ASIO_MOVE_CAST(payload_type)(payload), handler2.value)();+      return true;+    }+  case closed:+  default:+    {+      return false;+    }+  }+}++template <typename Mutex>+template <typename Traits, typename... Signatures>+void channel_service<Mutex>::start_receive_op(+    channel_service<Mutex>::implementation_type<Traits, Signatures...>& impl,+		channel_receive<typename implementation_type<+			Traits, Signatures...>::payload_type>* receive_op)+{+  typedef typename implementation_type<Traits,+      Signatures...>::traits_type traits_type;+  typedef typename implementation_type<Traits,+      Signatures...>::payload_type payload_type;++  typename Mutex::scoped_lock lock(impl.mutex_);++  switch (impl.receive_state_)+  {+  case block:+    {+      impl.waiters_.push(receive_op);+      if (impl.send_state_ != closed)+        impl.send_state_ = waiter;+      return;+    }+  case buffer:+    {+      payload_type payload(+          ASIO_MOVE_CAST(payload_type)(impl.buffer_front()));+      if (channel_send<payload_type>* send_op =+          static_cast<channel_send<payload_type>*>(impl.waiters_.front()))+      {+        impl.buffer_pop();+        impl.buffer_push(send_op->get_payload());+        impl.waiters_.pop();+        send_op->complete();+      }+      else+      {+        impl.buffer_pop();+        if (impl.buffer_size() == 0)+          impl.receive_state_ = (impl.send_state_ == closed) ? closed : block;+        impl.send_state_ = (impl.send_state_ == closed) ? closed : buffer;+      }+      receive_op->immediate(ASIO_MOVE_CAST(payload_type)(payload));+      break;+    }+  case waiter:+    {+      channel_send<payload_type>* send_op =+        static_cast<channel_send<payload_type>*>(impl.waiters_.front());+      payload_type payload = send_op->get_payload();+      impl.waiters_.pop();+      send_op->complete();+      if (impl.waiters_.front() == 0)+        impl.receive_state_ = (impl.send_state_ == closed) ? closed : block;+      receive_op->immediate(ASIO_MOVE_CAST(payload_type)(payload));+      break;+    }+  case closed:+  default:+    {+      traits_type::invoke_receive_closed(+          complete_receive<payload_type,+            typename traits_type::receive_closed_signature>(receive_op));+      break;+    }+  }+}++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_DETAIL_IMPL_CHANNEL_SERVICE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/detail/partial_promise.hpp view
@@ -0,0 +1,197 @@+//+// experimental/detail/partial_promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP+#define ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP++#include "asio/detail/config.hpp"+#include "asio/append.hpp"+#include "asio/awaitable.hpp"+#include "asio/experimental/coro_traits.hpp"++#if defined(ASIO_HAS_STD_COROUTINE)+# include <coroutine>+#else // defined(ASIO_HAS_STD_COROUTINE)+# include <experimental/coroutine>+#endif // defined(ASIO_HAS_STD_COROUTINE)++namespace asio {+namespace experimental {+namespace detail {++#if defined(ASIO_HAS_STD_COROUTINE)++using std::coroutine_handle;+using std::coroutine_traits;+using std::suspend_never;+using std::suspend_always;+using std::noop_coroutine;++#else // defined(ASIO_HAS_STD_COROUTINE)++using std::experimental::coroutine_handle;+using std::experimental::coroutine_traits;+using std::experimental::suspend_never;+using std::experimental::suspend_always;+using std::experimental::noop_coroutine;++#endif // defined(ASIO_HAS_STD_COROUTINE)++struct partial_coro+{+  coroutine_handle<void> handle{nullptr};+};++template <typename Allocator>+struct partial_promise_base+{+  template <typename Executor, typename Token, typename... Args>+  void* operator new(const std::size_t size, Executor&, Token& tk, Args&...)+  {+    return allocate_coroutine<Allocator>(size, get_associated_allocator(tk));+  }++  void operator delete(void* raw, const std::size_t size)+  {+    deallocate_coroutine<Allocator>(raw, size);+  }+};++template <>+struct partial_promise_base<std::allocator<void>>+{+};++template <typename Allocator>+struct partial_promise : partial_promise_base<Allocator>+{+  auto initial_suspend() noexcept+  {+    return asio::detail::suspend_always{};+  }++  auto final_suspend() noexcept+  {+    struct awaitable_t+    {+      partial_promise *p;++      constexpr bool await_ready() noexcept { return true; }++      auto await_suspend(asio::detail::coroutine_handle<>) noexcept+      {+        p->get_return_object().handle.destroy();+      }++      constexpr void await_resume() noexcept {}+    };++    return awaitable_t{this};+  }++  void return_void() {}++  partial_coro get_return_object()+  {+    return partial_coro{coroutine_handle<partial_promise>::from_promise(*this)};+  }++  void unhandled_exception()+  {+    assert(false);+  }+};++++}; // namespace detail+} // namespace experimental+} // namespace asio++#if defined(ASIO_HAS_STD_COROUTINE)++namespace std {++template <typename Executor, typename Completion, typename... Args>+struct coroutine_traits<+    asio::experimental::detail::partial_coro,+    Executor, Completion, Args...>+{+  using promise_type =+    asio::experimental::detail::partial_promise<+      asio::associated_allocator_t<Completion>>;+};++} // namespace std++#else // defined(ASIO_HAS_STD_COROUTINE)++namespace std { namespace experimental {++template <typename Executor, typename Completion, typename... Args>+struct coroutine_traits<+    asio::experimental::detail::partial_coro,+    Executor, Completion, Args...>+{+  using promise_type =+    asio::experimental::detail::partial_promise<+      asio::associated_allocator_t<Completion>>;+};++}} // namespace std::experimental++#endif // defined(ASIO_HAS_STD_COROUTINE)++namespace asio {+namespace experimental {+namespace detail {++template <execution::executor Executor,+    typename CompletionToken, typename... Args>+partial_coro post_coroutine(Executor exec,+    CompletionToken token, Args&&... args) noexcept+{+  post(exec, asio::append(std::move(token), std::move(args)...));+  co_return;+}++template <detail::execution_context Context,+    typename CompletionToken, typename... Args>+partial_coro post_coroutine(Context& ctx,+    CompletionToken token, Args&&... args) noexcept+{+  post(ctx, asio::append(std::move(token), std::move(args)...));+  co_return;+}++template <execution::executor Executor,+    typename CompletionToken, typename... Args>+partial_coro dispatch_coroutine(Executor exec,+    CompletionToken token, Args&&... args) noexcept+{+  dispatch(exec, asio::append(std::move(token), std::move(args)...));+  co_return;+}++template <detail::execution_context Context,+    typename CompletionToken, typename... Args>+partial_coro dispatch_coroutine(Context& ctx,+    CompletionToken token, Args &&... args) noexcept+{+  dispatch(ctx, asio::append(std::move(token), std::move(args)...));+  co_return;+}++} // namespace detail+} // namespace experimental+} // namespace asio++#endif // ASIO_EXPERIMENTAL_DETAIL_PARTIAL_PROMISE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/as_single.hpp view
@@ -0,0 +1,239 @@+//+// experimental/impl/as_single.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_EXPERIMENTAL_AS_SINGLE_HPP+#define ASIO_IMPL_EXPERIMENTAL_AS_SINGLE_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/associator.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/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++// Class to adapt a as_single_t as a completion handler.+template <typename Handler>+class as_single_handler+{+public:+  typedef void result_type;++  template <typename CompletionToken>+  as_single_handler(as_single_t<CompletionToken> e)+    : handler_(ASIO_MOVE_CAST(CompletionToken)(e.token_))+  {+  }++  template <typename RedirectedHandler>+  as_single_handler(ASIO_MOVE_ARG(RedirectedHandler) h)+    : handler_(ASIO_MOVE_CAST(RedirectedHandler)(h))+  {+  }++  void operator()()+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)();+  }++  template <typename Arg>+  void operator()(ASIO_MOVE_ARG(Arg) arg)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        ASIO_MOVE_CAST(Arg)(arg));+  }++  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)... args)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        std::make_tuple(ASIO_MOVE_CAST(Args)(args)...));+  }++//private:+  Handler handler_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    as_single_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,+    as_single_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(+    as_single_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,+    as_single_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,+    as_single_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 as_single_signature+{+  typedef Signature type;+};++template <typename R>+struct as_single_signature<R()>+{+  typedef R type();+};++template <typename R, typename Arg>+struct as_single_signature<R(Arg)>+{+  typedef R type(Arg);+};++template <typename R, typename... Args>+struct as_single_signature<R(Args...)>+{+  typedef R type(std::tuple<typename decay<Args>::type...>);+};++} // namespace detail+} // namespace experimental++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename Signature>+struct async_result<experimental::as_single_t<CompletionToken>, Signature>+{+  typedef typename async_result<CompletionToken,+    typename experimental::detail::as_single_signature<Signature>::type>+      ::return_type return_type;++  template <typename Initiation>+  struct init_wrapper+  {+    init_wrapper(Initiation init)+      : initiation_(ASIO_MOVE_CAST(Initiation)(init))+    {+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          experimental::detail::as_single_handler<+            typename decay<Handler>::type>(+              ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    Initiation initiation_;+  };++  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 experimental::detail::as_single_signature<Signature>::type>(+        init_wrapper<typename decay<Initiation>::type>(+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.token_, ASIO_MOVE_CAST(Args)(args)...);+  }+};++template <template <typename, typename> class Associator,+    typename Handler, typename DefaultCandidate>+struct associator<Associator,+    experimental::detail::as_single_handler<Handler>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const experimental::detail::as_single_handler<Handler>& h)+    ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const experimental::detail::as_single_handler<Handler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_EXPERIMENTAL_AS_SINGLE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/channel_error.ipp view
@@ -0,0 +1,61 @@+//+// experimental/impl/channel_error.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_IMPL_CHANNEL_ERROR_IPP+#define ASIO_EXPERIMENTAL_IMPL_CHANNEL_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/experimental/channel_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace error {+namespace detail {++class channel_category : public asio::error_category+{+public:+  const char* name() const ASIO_ERROR_CATEGORY_NOEXCEPT+  {+    return "asio.channel";+  }++  std::string message(int value) const+  {+    switch (value)+    {+    case channel_closed: return "Channel closed";+    case channel_cancelled: return "Channel cancelled";+    default: return "asio.channel error";+    }+  }+};++} // namespace detail++const asio::error_category& get_channel_category()+{+  static detail::channel_category instance;+  return instance;+}++} // namespace error+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_CHANNEL_ERROR_IPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/co_composed.hpp view
@@ -0,0 +1,1175 @@+//+// experimental/impl/co_composed.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_EXPERIMENTAL_CO_COMPOSED_HPP+#define ASIO_IMPL_EXPERIMENTAL_CO_COMPOSED_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 <tuple>+#include <variant>+#include "asio/associated_cancellation_slot.hpp"+#include "asio/associator.hpp"+#include "asio/async_result.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/detail/composed_work.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/detail/throw_error.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/error.hpp"++#if defined(ASIO_HAS_STD_COROUTINE)+# include <coroutine>+#else // defined(ASIO_HAS_STD_COROUTINE)+# include <experimental/coroutine>+#endif // defined(ASIO_HAS_STD_COROUTINE)++#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 {+namespace experimental {+namespace detail {++#if defined(ASIO_HAS_STD_COROUTINE)+using std::coroutine_handle;+using std::suspend_always;+using std::suspend_never;+#else // defined(ASIO_HAS_STD_COROUTINE)+using std::experimental::coroutine_handle;+using std::experimental::suspend_always;+using std::experimental::suspend_never;+#endif // defined(ASIO_HAS_STD_COROUTINE)++using asio::detail::composed_io_executors;+using asio::detail::composed_work;+using asio::detail::composed_work_guard;+using asio::detail::get_composed_io_executor;+using asio::detail::make_composed_io_executors;+using asio::detail::recycling_allocator;+using asio::detail::throw_error;++template <typename Executors, typename Handler, typename Return>+class co_composed_state;++template <typename Executors, typename Handler, typename Return>+class co_composed_handler_base;++template <typename Executors, typename Handler, typename Return>+class co_composed_promise;++template <completion_signature... Signatures>+class co_composed_returns+{+};++struct co_composed_on_suspend+{+  void (*fn_)(void*) = nullptr;+  void* arg_ = nullptr;+};++template <typename... T>+struct co_composed_completion : std::tuple<T&&...>+{+  template <typename... U>+  co_composed_completion(U&&... u) noexcept+    : std::tuple<T&&...>(std::forward<U>(u)...)+  {+  }+};++template <typename Executors, typename Handler,+    typename Return, typename Signature>+class co_composed_state_return_overload;++template <typename Executors, typename Handler,+    typename Return, typename R, typename... Args>+class co_composed_state_return_overload<+    Executors, Handler, Return, R(Args...)>+{+public:+  using derived_type = co_composed_state<Executors, Handler, Return>;+  using promise_type = co_composed_promise<Executors, Handler, Return>;+  using return_type = std::tuple<Args...>;++  void on_cancellation_complete_with(Args... args)+  {+    derived_type& state = *static_cast<derived_type*>(this);+    state.return_value_ = std::make_tuple(std::move(args)...);+    state.cancellation_on_suspend_fn(+        [](void* p)+        {+          auto& promise = *static_cast<promise_type*>(p);++          co_composed_handler_base<Executors, Handler,+            Return> composed_handler(promise);++          Handler handler(std::move(promise.state().handler_));+          return_type result(+              std::move(std::get<return_type>(promise.state().return_value_)));++          co_composed_handler_base<Executors, Handler,+            Return>(std::move(composed_handler));++          std::apply(std::move(handler), std::move(result));+        });+  }+};++template <typename Executors, typename Handler, typename Return>+class co_composed_state_return;++template <typename Executors, typename Handler, typename... Signatures>+class co_composed_state_return<+    Executors, Handler, co_composed_returns<Signatures...>>+  : public co_composed_state_return_overload<Executors,+      Handler, co_composed_returns<Signatures...>, Signatures>...+{+public:+  using co_composed_state_return_overload<Executors,+    Handler, co_composed_returns<Signatures...>,+      Signatures>::on_cancellation_complete_with...;++private:+  template <typename, typename, typename, typename>+    friend class co_composed_promise_return_overload;+  template <typename, typename, typename, typename>+    friend class co_composed_state_return_overload;++  std::variant<std::monostate,+    typename co_composed_state_return_overload<+      Executors, Handler, co_composed_returns<Signatures...>,+        Signatures>::return_type...> return_value_;+};++template <typename Executors, typename Handler,+    typename Return, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend_impl;++template <typename Executors, typename Handler, typename Return>+struct co_composed_state_default_cancellation_on_suspend_impl<+    Executors, Handler, Return>+{+  static constexpr void (*fn())(void*)+  {+    return nullptr;+  }+};++template <typename Executors, typename Handler, typename Return,+    typename R, typename... Args, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend_impl<+    Executors, Handler, Return, R(Args...), Signatures...>+{+  static constexpr void (*fn())(void*)+  {+    return co_composed_state_default_cancellation_on_suspend_impl<+      Executors, Handler, Return, Signatures...>::fn();+  }+};++template <typename Executors, typename Handler, typename Return,+    typename R, typename... Args, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend_impl<Executors,+    Handler, Return, R(asio::error_code, Args...), Signatures...>+{+  using promise_type = co_composed_promise<Executors, Handler, Return>;+  using return_type = std::tuple<asio::error_code, Args...>;++  static constexpr void (*fn())(void*)+  {+    if constexpr ((is_constructible<Args>::value && ...))+    {+      return [](void* p)+      {+        auto& promise = *static_cast<promise_type*>(p);++        co_composed_handler_base<Executors, Handler,+          Return> composed_handler(promise);++        Handler handler(std::move(promise.state().handler_));++        co_composed_handler_base<Executors, Handler,+          Return>(std::move(composed_handler));++        std::move(handler)(+            asio::error_code(asio::error::operation_aborted),+            Args{}...);+      };+    }+    else+    {+      return co_composed_state_default_cancellation_on_suspend_impl<+        Executors, Handler, Return, Signatures...>::fn();+    }+  }+};++template <typename Executors, typename Handler, typename Return,+    typename R, typename... Args, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend_impl<Executors,+    Handler, Return, R(std::exception_ptr, Args...), Signatures...>+{+  using promise_type = co_composed_promise<Executors, Handler, Return>;+  using return_type = std::tuple<std::exception_ptr, Args...>;++  static constexpr void (*fn())(void*)+  {+    if constexpr ((is_constructible<Args>::value && ...))+    {+      return [](void* p)+      {+        auto& promise = *static_cast<promise_type*>(p);++        co_composed_handler_base<Executors, Handler,+          Return> composed_handler(promise);++        Handler handler(std::move(promise.state().handler_));++        co_composed_handler_base<Executors, Handler,+          Return>(std::move(composed_handler));++        std::move(handler)(+            std::make_exception_ptr(+              asio::system_error(+                asio::error::operation_aborted, "co_await")),+            Args{}...);+      };+    }+    else+    {+      return co_composed_state_default_cancellation_on_suspend_impl<+        Executors, Handler, Return, Signatures...>::fn();+    }+  }+};++template <typename Executors, typename Handler, typename Return>+struct co_composed_state_default_cancellation_on_suspend;++template <typename Executors, typename Handler, typename... Signatures>+struct co_composed_state_default_cancellation_on_suspend<+    Executors, Handler, co_composed_returns<Signatures...>>+  : co_composed_state_default_cancellation_on_suspend_impl<Executors,+      Handler, co_composed_returns<Signatures...>, Signatures...>+{+};++template <typename Executors, typename Handler, typename Return>+class co_composed_state_cancellation+{+public:+  using cancellation_slot_type = cancellation_slot;++  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return cancellation_state_.slot();+  }++  cancellation_state get_cancellation_state() const noexcept+  {+    return cancellation_state_;+  }++  void reset_cancellation_state()+  {+    cancellation_state_ = cancellation_state(+        (get_associated_cancellation_slot)(+          static_cast<co_composed_state<Executors, Handler, Return>*>(+            this)->handler()));+  }++  template <typename Filter>+  void reset_cancellation_state(Filter filter)+  {+    cancellation_state_ = cancellation_state(+        (get_associated_cancellation_slot)(+          static_cast<co_composed_state<Executors, Handler, Return>*>(+            this)->handler()), filter, filter);+  }++  template <typename InFilter, typename OutFilter>+  void reset_cancellation_state(InFilter&& in_filter, OutFilter&& out_filter)+  {+    cancellation_state_ = cancellation_state(+        (get_associated_cancellation_slot)(+          static_cast<co_composed_state<Executors, Handler, Return>*>(+            this)->handler()),+        std::forward<InFilter>(in_filter),+        std::forward<OutFilter>(out_filter));+  }++  cancellation_type_t cancelled() const noexcept+  {+    return cancellation_state_.cancelled();+  }++  void clear_cancellation_slot() noexcept+  {+    cancellation_state_.slot().clear();+  }++  [[nodiscard]] bool throw_if_cancelled() const noexcept+  {+    return throw_if_cancelled_;+  }++  void throw_if_cancelled(bool b) noexcept+  {+    throw_if_cancelled_ = b;+  }++  [[nodiscard]] bool complete_if_cancelled() const noexcept+  {+    return complete_if_cancelled_;+  }++  void complete_if_cancelled(bool b) noexcept+  {+    complete_if_cancelled_ = b;+  }++private:+  template <typename, typename, typename>+    friend class co_composed_promise;+  template <typename, typename, typename, typename>+    friend class co_composed_state_return_overload;++  void cancellation_on_suspend_fn(void (*fn)(void*))+  {+    cancellation_on_suspend_fn_ = fn;+  }++  void check_for_cancellation_on_transform()+  {+    if (throw_if_cancelled_ && !!cancelled())+      throw_error(asio::error::operation_aborted, "co_await");+  }++  bool check_for_cancellation_on_suspend(+      co_composed_promise<Executors, Handler, Return>& promise) noexcept+  {+    if (complete_if_cancelled_ && !!cancelled() && cancellation_on_suspend_fn_)+    {+      promise.state().work_.reset();+      promise.state().on_suspend_->fn_ = cancellation_on_suspend_fn_;+      promise.state().on_suspend_->arg_ = &promise;+      return false;+    }+    return true;+  }++  cancellation_state cancellation_state_;+  void (*cancellation_on_suspend_fn_)(void*) =+    co_composed_state_default_cancellation_on_suspend<+      Executors, Handler, Return>::fn();+  bool throw_if_cancelled_ = false;+  bool complete_if_cancelled_ = true;+};++template <typename Executors, typename Handler, typename Return>+  requires is_same<+    typename associated_cancellation_slot<+      Handler, cancellation_slot+    >::asio_associated_cancellation_slot_is_unspecialised,+    void>::value+class co_composed_state_cancellation<Executors, Handler, Return>+{+public:+  void reset_cancellation_state()+  {+  }++  template <typename Filter>+  void reset_cancellation_state(Filter)+  {+  }++  template <typename InFilter, typename OutFilter>+  void reset_cancellation_state(InFilter&&, OutFilter&&)+  {+  }++  cancellation_type_t cancelled() const noexcept+  {+    return cancellation_type::none;+  }++  void clear_cancellation_slot() noexcept+  {+  }++  [[nodiscard]] bool throw_if_cancelled() const noexcept+  {+    return false;+  }++  void throw_if_cancelled(bool) noexcept+  {+  }++  [[nodiscard]] bool complete_if_cancelled() const noexcept+  {+    return false;+  }++  void complete_if_cancelled(bool) noexcept+  {+  }++private:+  template <typename, typename, typename>+    friend class co_composed_promise;+  template <typename, typename, typename, typename>+    friend class co_composed_state_return_overload;++  void cancellation_on_suspend_fn(void (*)(void*))+  {+  }++  void check_for_cancellation_on_transform() noexcept+  {+  }++  bool check_for_cancellation_on_suspend(+      co_composed_promise<Executors, Handler, Return>&) noexcept+  {+    return true;+  }+};++template <typename Executors, typename Handler, typename Return>+class co_composed_state+  : public co_composed_state_return<Executors, Handler, Return>,+    public co_composed_state_cancellation<Executors, Handler, Return>+{+public:+  using io_executor_type = typename composed_work_guard<+    typename composed_work<Executors>::head_type>::executor_type;++  template <typename H>+  co_composed_state(composed_io_executors<Executors>&& executors,+      H&& h, co_composed_on_suspend& on_suspend)+    : work_(std::move(executors)),+      handler_(std::forward<H>(h)),+      on_suspend_(&on_suspend)+  {+    this->reset_cancellation_state(enable_terminal_cancellation());+  }++  io_executor_type get_io_executor() const noexcept+  {+    return work_.head_.get_executor();+  }++  template <typename... Args>+  [[nodiscard]] co_composed_completion<Args...> complete(Args&&... args)+    requires requires { declval<Handler>()(std::forward<Args>(args)...); }+  {+    return co_composed_completion<Args...>(std::forward<Args>(args)...);+  }++  const Handler& handler() const noexcept+  {+    return handler_;+  }++private:+  template <typename, typename, typename>+    friend class co_composed_handler_base;+  template <typename, typename, typename>+    friend class co_composed_promise;+  template <typename, typename, typename, typename>+    friend class co_composed_promise_return_overload;+  template <typename, typename, typename>+    friend class co_composed_state_cancellation;+  template <typename, typename, typename, typename>+    friend class co_composed_state_return_overload;+  template <typename, typename, typename, typename...>+    friend struct co_composed_state_default_cancellation_on_suspend_impl;++  composed_work<Executors> work_;+  Handler handler_;+  co_composed_on_suspend* on_suspend_;+};++template <typename Executors, typename Handler, typename Return>+class co_composed_handler_cancellation+{+public:+  using cancellation_slot_type = cancellation_slot;++  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return static_cast<+      const co_composed_handler_base<Executors, Handler, Return>*>(+        this)->promise().state().get_cancellation_slot();+  }+};++template <typename Executors, typename Handler, typename Return>+  requires is_same<+    typename associated_cancellation_slot<+      Handler, cancellation_slot+    >::asio_associated_cancellation_slot_is_unspecialised,+    void>::value+class co_composed_handler_cancellation<Executors, Handler, Return>+{+};++template <typename Executors, typename Handler, typename Return>+class co_composed_handler_base :+  public co_composed_handler_cancellation<Executors, Handler, Return>+{+public:+  co_composed_handler_base(+      co_composed_promise<Executors, Handler, Return>& p) noexcept+    : p_(&p)+  {+  }++  co_composed_handler_base(co_composed_handler_base&& other) noexcept+    : p_(std::exchange(other.p_, nullptr))+  {+  }++  ~co_composed_handler_base()+  {+    if (p_) [[unlikely]]+      p_->destroy();+  }++  co_composed_promise<Executors, Handler, Return>& promise() const noexcept+  {+    return *p_;+  }++protected:+  void resume(void* result)+  {+    co_composed_on_suspend on_suspend{};+    std::exchange(p_, nullptr)->resume(p_, result, on_suspend);+    if (on_suspend.fn_)+      on_suspend.fn_(on_suspend.arg_);+  }++private:+  co_composed_promise<Executors, Handler, Return>* p_;+};++template <typename Executors, typename Handler,+    typename Return, typename Signature>+class co_composed_handler;++template <typename Executors, typename Handler,+    typename Return, typename R, typename... Args>+class co_composed_handler<Executors, Handler, Return, R(Args...)>+  : public co_composed_handler_base<Executors, Handler, Return>+{+public:+  using co_composed_handler_base<Executors,+    Handler, Return>::co_composed_handler_base;++  using result_type = std::tuple<typename decay<Args>::type...>;++  template <typename... T>+  void operator()(T&&... args)+  {+    result_type result(std::forward<T>(args)...);+    this->resume(&result);+  }++  static auto on_resume(void* result)+  {+    auto& args = *static_cast<result_type*>(result);+    if constexpr (sizeof...(Args) == 0)+      return;+    else if constexpr (sizeof...(Args) == 1)+      return std::move(std::get<0>(args));+    else+      return std::move(args);+  }+};++template <typename Executors, typename Handler,+    typename Return, typename R, typename... Args>+class co_composed_handler<Executors, Handler,+    Return, R(asio::error_code, Args...)>+  : public co_composed_handler_base<Executors, Handler, Return>+{+public:+  using co_composed_handler_base<Executors,+    Handler, Return>::co_composed_handler_base;++  using args_type = std::tuple<typename decay<Args>::type...>;+  using result_type = std::tuple<asio::error_code, args_type>;++  template <typename... T>+  void operator()(const asio::error_code& ec, T&&... args)+  {+    result_type result(ec, args_type(std::forward<T>(args)...));+    this->resume(&result);+  }++  static auto on_resume(void* result)+  {+    auto& [ec, args] = *static_cast<result_type*>(result);+    throw_error(ec);+    if constexpr (sizeof...(Args) == 0)+      return;+    else if constexpr (sizeof...(Args) == 1)+      return std::move(std::get<0>(args));+    else+      return std::move(args);+  }+};++template <typename Executors, typename Handler,+    typename Return, typename R, typename... Args>+class co_composed_handler<Executors, Handler,+    Return, R(std::exception_ptr, Args...)>+  : public co_composed_handler_base<Executors, Handler, Return>+{+public:+  using co_composed_handler_base<Executors,+    Handler, Return>::co_composed_handler_base;++  using args_type = std::tuple<typename decay<Args>::type...>;+  using result_type = std::tuple<std::exception_ptr, args_type>;++  template <typename... T>+  void operator()(std::exception_ptr ex, T&&... args)+  {+    result_type result(std::move(ex), args_type(std::forward<T>(args)...));+    this->resume(&result);+  }++  static auto on_resume(void* result)+  {+    auto& [ex, args] = *static_cast<result_type*>(result);+    if (ex)+      std::rethrow_exception(ex);+    if constexpr (sizeof...(Args) == 0)+      return;+    else if constexpr (sizeof...(Args) == 1)+      return std::move(std::get<0>(args));+    else+      return std::move(args);+  }+};++template <typename Executors, typename Handler, typename Return>+class co_composed_promise_return;++template <typename Executors, typename Handler>+class co_composed_promise_return<Executors, Handler, co_composed_returns<>>+{+public:+  auto final_suspend() noexcept+  {+    return suspend_never();+  }++  void return_void() noexcept+  {+  }+};++template <typename Executors, typename Handler,+    typename Return, typename Signature>+class co_composed_promise_return_overload;++template <typename Executors, typename Handler,+    typename Return, typename R, typename... Args>+class co_composed_promise_return_overload<+    Executors, Handler, Return, R(Args...)>+{+public:+  using derived_type = co_composed_promise<Executors, Handler, Return>;+  using return_type = std::tuple<Args...>;++  void return_value(std::tuple<Args...>&& value)+  {+    derived_type& promise = *static_cast<derived_type*>(this);+    promise.state().return_value_ = std::move(value);+    promise.state().work_.reset();+    promise.state().on_suspend_->arg_ = this;+    promise.state().on_suspend_->fn_ =+      [](void* p)+      {+        auto& promise = *static_cast<derived_type*>(p);++        co_composed_handler_base<Executors, Handler,+          Return> composed_handler(promise);++        Handler handler(std::move(promise.state().handler_));+        return_type result(+            std::move(std::get<return_type>(promise.state().return_value_)));++        co_composed_handler_base<Executors, Handler,+          Return>(std::move(composed_handler));++        std::apply(std::move(handler), std::move(result));+      };+  }+};++template <typename Executors, typename Handler, typename... Signatures>+class co_composed_promise_return<Executors,+    Handler, co_composed_returns<Signatures...>>+  : public co_composed_promise_return_overload<Executors,+      Handler, co_composed_returns<Signatures...>, Signatures>...+{+public:+  auto final_suspend() noexcept+  {+    return suspend_always();+  }++  using co_composed_promise_return_overload<Executors, Handler,+    co_composed_returns<Signatures...>, Signatures>::return_value...;++private:+  template <typename, typename, typename, typename>+    friend class co_composed_promise_return_overload;+};++template <typename Executors, typename Handler, typename Return>+class co_composed_promise+  : public co_composed_promise_return<Executors, Handler, Return>+{+public:+  template <typename... Args>+  void* operator new(std::size_t size,+      co_composed_state<Executors, Handler, Return>& state, Args&&...)+  {+    block_allocator_type allocator(+      (get_associated_allocator)(state.handler_,+        recycling_allocator<void>()));++    block* base_ptr = std::allocator_traits<block_allocator_type>::allocate(+        allocator, blocks(sizeof(allocator_type)) + blocks(size));++    new (static_cast<void*>(base_ptr)) allocator_type(std::move(allocator));++    return base_ptr + blocks(sizeof(allocator_type));+  }++  template <typename C, typename... Args>+  void* operator new(std::size_t size, C&&,+      co_composed_state<Executors, Handler, Return>& state, Args&&...)+  {+    return co_composed_promise::operator new(size, state);+  }++  void operator delete(void* ptr, std::size_t size)+  {+    block* base_ptr = static_cast<block*>(ptr) - blocks(sizeof(allocator_type));++    allocator_type* allocator_ptr = std::launder(+        static_cast<allocator_type*>(static_cast<void*>(base_ptr)));++    block_allocator_type block_allocator(std::move(*allocator_ptr));+    allocator_ptr->~allocator_type();++    std::allocator_traits<block_allocator_type>::deallocate(block_allocator,+        base_ptr, blocks(sizeof(allocator_type)) + blocks(size));+  }++  template <typename... Args>+  co_composed_promise(+      co_composed_state<Executors, Handler, Return>& state, Args&&...)+    : state_(state)+  {+  }++  template <typename C, typename... Args>+  co_composed_promise(C&&,+      co_composed_state<Executors, Handler, Return>& state, Args&&...)+    : state_(state)+  {+  }++  void destroy() noexcept+  {+    coroutine_handle<co_composed_promise>::from_promise(*this).destroy();+  }++  void resume(co_composed_promise*& owner, void* result,+      co_composed_on_suspend& on_suspend)+  {+    state_.on_suspend_ = &on_suspend;+    state_.clear_cancellation_slot();+    owner_ = &owner;+    result_ = result;+    coroutine_handle<co_composed_promise>::from_promise(*this).resume();+  }++  co_composed_state<Executors, Handler, Return>& state() noexcept+  {+    return state_;+  }++  void get_return_object() noexcept+  {+  }++  auto initial_suspend() noexcept+  {+    return suspend_never();+  }++  void unhandled_exception()+  {+    if (owner_)+      *owner_ = this;+    throw;+  }++  template <async_operation Op>+  auto await_transform(Op&& op+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+      , asio::detail::source_location location+        = asio::detail::source_location::current()+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+    )+  {+    class [[nodiscard]] awaitable+    {+    public:+      awaitable(Op&& op, co_composed_promise& promise+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+          , const asio::detail::source_location& location+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+        )+        : op_(std::forward<Op>(op)),+          promise_(promise)+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+        , location_(location)+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+      {+      }++      constexpr bool await_ready() const noexcept+      {+        return false;+      }++      void await_suspend(coroutine_handle<co_composed_promise>)+      {+        if (promise_.state_.check_for_cancellation_on_suspend(promise_))+        {+          promise_.state_.on_suspend_->arg_ = this;+          promise_.state_.on_suspend_->fn_ =+            [](void* p)+            {+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+              ASIO_HANDLER_LOCATION((+                  static_cast<awaitable*>(p)->location_.file_name(),+                  static_cast<awaitable*>(p)->location_.line(),+                  static_cast<awaitable*>(p)->location_.function_name()));+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+              std::forward<Op>(static_cast<awaitable*>(p)->op_)(+                  co_composed_handler<Executors, Handler,+                    Return, completion_signature_of_t<Op>>(+                      static_cast<awaitable*>(p)->promise_));+            };+        }+      }++      auto await_resume()+      {+        return co_composed_handler<Executors, Handler, Return,+          completion_signature_of_t<Op>>::on_resume(promise_.result_);+      }++    private:+      Op&& op_;+      co_composed_promise& promise_;+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+      asio::detail::source_location location_;+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+    };++    state_.check_for_cancellation_on_transform();+    return awaitable{std::forward<Op>(op), *this+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+        , location+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+      };+  }++  template <typename... Args>+  auto yield_value(co_composed_completion<Args...>&& result)+  {+    class [[nodiscard]] awaitable+    {+    public:+      awaitable(co_composed_completion<Args...>&& result,+          co_composed_promise& promise)+        : result_(std::move(result)),+          promise_(promise)+      {+      }++      constexpr bool await_ready() const noexcept+      {+        return false;+      }++      void await_suspend(coroutine_handle<co_composed_promise>)+      {+        promise_.state_.work_.reset();+        promise_.state_.on_suspend_->arg_ = this;+        promise_.state_.on_suspend_->fn_ =+          [](void* p)+          {+            awaitable& a = *static_cast<awaitable*>(p);++            co_composed_handler_base<Executors, Handler,+              Return> composed_handler(a.promise_);++            Handler handler(std::move(a.promise_.state_.handler_));+            std::tuple<typename decay<Args>::type...> result(+                std::move(static_cast<std::tuple<Args&&...>>(a.result_)));++            co_composed_handler_base<Executors, Handler,+              Return>(std::move(composed_handler));++            std::apply(std::move(handler), std::move(result));+          };+      }++      void await_resume() noexcept+      {+      }++    private:+      co_composed_completion<Args...> result_;+      co_composed_promise& promise_;+    };++    return awaitable{std::move(result), *this};+  }++private:+  using allocator_type =+    associated_allocator_t<Handler, recycling_allocator<void>>;++  union block+  {+    std::max_align_t max_align;+    alignas(allocator_type) char pad[alignof(allocator_type)];+  };++  using block_allocator_type =+    typename std::allocator_traits<allocator_type>+      ::template rebind_alloc<block>;++  static constexpr std::size_t blocks(std::size_t size)+  {+    return (size + sizeof(block) - 1) / sizeof(block);+  }++  co_composed_state<Executors, Handler, Return>& state_;+  co_composed_promise** owner_ = nullptr;+  void* result_ = nullptr;+};++template <typename Implementation, typename Executors, typename... Signatures>+class initiate_co_composed+{+public:+  using executor_type = typename composed_io_executors<Executors>::head_type;++  template <typename I>+  initiate_co_composed(I&& impl, composed_io_executors<Executors>&& executors)+    : implementation_(std::forward<I>(impl)),+      executors_(std::move(executors))+  {+  }++  executor_type get_executor() const noexcept+  {+    return executors_.head_;+  }++  template <typename Handler, typename... InitArgs>+  void operator()(Handler&& handler, InitArgs&&... init_args) const &+  {+    using handler_type = typename decay<Handler>::type;+    using returns_type = co_composed_returns<Signatures...>;+    co_composed_on_suspend on_suspend{};+    implementation_(+        co_composed_state<Executors, handler_type, returns_type>(+          executors_, std::forward<Handler>(handler), on_suspend),+        std::forward<InitArgs>(init_args)...);+    if (on_suspend.fn_)+      on_suspend.fn_(on_suspend.arg_);+  }++  template <typename Handler, typename... InitArgs>+  void operator()(Handler&& handler, InitArgs&&... init_args) &&+  {+    using handler_type = typename decay<Handler>::type;+    using returns_type = co_composed_returns<Signatures...>;+    co_composed_on_suspend on_suspend{};+    std::move(implementation_)(+        co_composed_state<Executors, handler_type, returns_type>(+          std::move(executors_), std::forward<Handler>(handler), on_suspend),+        std::forward<InitArgs>(init_args)...);+    if (on_suspend.fn_)+      on_suspend.fn_(on_suspend.arg_);+  }++private:+  Implementation implementation_;+  composed_io_executors<Executors> executors_;+};++template <typename... Signatures, typename Implementation, typename Executors>+inline initiate_co_composed<Implementation, Executors, Signatures...>+make_initiate_co_composed(Implementation&& implementation,+    composed_io_executors<Executors>&& executors)+{+  return initiate_co_composed<+    typename decay<Implementation>::type, Executors, Signatures...>(+        std::forward<Implementation>(implementation), std::move(executors));+}++} // namespace detail++template <completion_signature... Signatures,+    typename Implementation, typename... IoObjectsOrExecutors>+inline auto co_composed(Implementation&& implementation,+    IoObjectsOrExecutors&&... io_objects_or_executors)+{+  return detail::make_initiate_co_composed<Signatures...>(+      std::forward<Implementation>(implementation),+      detail::make_composed_io_executors(+        detail::get_composed_io_executor(+          std::forward<IoObjectsOrExecutors>(+            io_objects_or_executors))...));+}++} // namespace experimental++#if !defined(GENERATING_DOCUMENTATION)++template <template <typename, typename> class Associator,+    typename Executors, typename Handler, typename Return,+    typename Signature, typename DefaultCandidate>+struct associator<Associator,+    experimental::detail::co_composed_handler<+      Executors, Handler, Return, Signature>,+    DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const experimental::detail::co_composed_handler<+        Executors, Handler, Return, Signature>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(+        h.promise().state().handler());+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const experimental::detail::co_composed_handler<+        Executors, Handler, Return, Signature>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(+        h.promise().state().handler(), c)))+  {+    return Associator<Handler, DefaultCandidate>::get(+        h.promise().state().handler(), c);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#if !defined(GENERATING_DOCUMENTATION)+# if defined(ASIO_HAS_STD_COROUTINE)+namespace std {+# else // defined(ASIO_HAS_STD_COROUTINE)+namespace std { namespace experimental {+# endif // defined(ASIO_HAS_STD_COROUTINE)++template <typename C, typename Executors,+    typename Handler, typename Return, typename... Args>+struct coroutine_traits<void, C&,+    asio::experimental::detail::co_composed_state<+      Executors, Handler, Return>,+    Args...>+{+  using promise_type =+    asio::experimental::detail::co_composed_promise<+      Executors, Handler, Return>;+};++template <typename C, typename Executors,+    typename Handler, typename Return, typename... Args>+struct coroutine_traits<void, C&&,+    asio::experimental::detail::co_composed_state<+      Executors, Handler, Return>,+    Args...>+{+  using promise_type =+    asio::experimental::detail::co_composed_promise<+      Executors, Handler, Return>;+};++template <typename Executors, typename Handler,+    typename Return, typename... Args>+struct coroutine_traits<void,+    asio::experimental::detail::co_composed_state<+      Executors, Handler, Return>,+    Args...>+{+  using promise_type =+    asio::experimental::detail::co_composed_promise<+      Executors, Handler, Return>;+};++# if defined(ASIO_HAS_STD_COROUTINE)+} // namespace std+# else // defined(ASIO_HAS_STD_COROUTINE)+}} // namespace std::experimental+# endif // defined(ASIO_HAS_STD_COROUTINE)+#endif // !defined(GENERATING_DOCUMENTATION)++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_EXPERIMENTAL_CO_COMPOSED_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/coro.hpp view
@@ -0,0 +1,1222 @@+//+// experimental/impl/coro.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)++//+#ifndef ASIO_EXPERIMENTAL_IMPL_CORO_HPP+#define ASIO_EXPERIMENTAL_IMPL_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/append.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/bind_allocator.hpp"+#include "asio/deferred.hpp"+#include "asio/experimental/detail/coro_completion_handler.hpp"+#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++template <typename Yield, typename Return,+    typename Executor, typename Allocator>+struct coro;++namespace detail {++struct coro_cancellation_source+{+  cancellation_slot slot;+  cancellation_state state;+  bool throw_if_cancelled_ = true;++  void reset_cancellation_state()+  {+    state = cancellation_state(slot);+  }++  template <typename Filter>+  void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter)+  {+    state = cancellation_state(slot, ASIO_MOVE_CAST(Filter)(filter));+  }++  template <typename InFilter, typename OutFilter>+  void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter,+      ASIO_MOVE_ARG(OutFilter) out_filter)+  {+    state = cancellation_state(slot,+        ASIO_MOVE_CAST(InFilter)(in_filter),+        ASIO_MOVE_CAST(OutFilter)(out_filter));+  }++  bool throw_if_cancelled() const+  {+    return throw_if_cancelled_;+  }++  void throw_if_cancelled(bool value)+  {+    throw_if_cancelled_ = value;+  }+};++template <typename Signature, typename Return,+    typename Executor, typename Allocator>+struct coro_promise;++template <typename T>+struct is_noexcept : std::false_type+{+};++template <typename Return, typename... Args>+struct is_noexcept<Return(Args...)> : std::false_type+{+};++template <typename Return, typename... Args>+struct is_noexcept<Return(Args...) noexcept> : std::true_type+{+};++template <typename T>+constexpr bool is_noexcept_v = is_noexcept<T>::value;++template <typename T>+struct coro_error;++template <>+struct coro_error<asio::error_code>+{+  static asio::error_code invalid()+  {+    return asio::error::fault;+  }++  static asio::error_code cancelled()+  {+    return asio::error::operation_aborted;+  }++  static asio::error_code interrupted()+  {+    return asio::error::interrupted;+  }++  static asio::error_code done()+  {+    return asio::error::broken_pipe;+  }+};++template <>+struct coro_error<std::exception_ptr>+{+  static std::exception_ptr invalid()+  {+    return std::make_exception_ptr(+        asio::system_error(+          coro_error<asio::error_code>::invalid()));+  }++  static std::exception_ptr cancelled()+  {+    return std::make_exception_ptr(+        asio::system_error(+          coro_error<asio::error_code>::cancelled()));+  }++  static std::exception_ptr interrupted()+  {+    return std::make_exception_ptr(+        asio::system_error(+          coro_error<asio::error_code>::interrupted()));+  }++  static std::exception_ptr done()+  {+    return std::make_exception_ptr(+        asio::system_error(+          coro_error<asio::error_code>::done()));+  }+};++template <typename T, typename Coroutine >+struct coro_with_arg+{+  using coro_t = Coroutine;+  T value;+  coro_t& coro;++  struct awaitable_t+  {+    T value;+    coro_t& coro;++    constexpr static bool await_ready() { return false; }++    template <typename Y, typename R, typename E, typename A>+    auto await_suspend(coroutine_handle<coro_promise<Y, R, E, A>> h)+      -> coroutine_handle<>+    {+      auto& hp = h.promise();++      if constexpr (!coro_promise<Y, R, E, A>::is_noexcept)+      {+        if ((hp.cancel->state.cancelled() != cancellation_type::none)+            && hp.cancel->throw_if_cancelled_)+        {+          asio::detail::throw_error(+              asio::error::operation_aborted, "coro-cancelled");+        }+      }++      if (hp.get_executor() == coro.get_executor())+      {+        coro.coro_->awaited_from = h;+        coro.coro_->reset_error();+        coro.coro_->input_ = std::move(value);+        coro.coro_->cancel = hp.cancel;+        return coro.coro_->get_handle();+      }+      else+      {+        coro.coro_->awaited_from =+          dispatch_coroutine(+              asio::prefer(hp.get_executor(),+                execution::outstanding_work.tracked),+                [h]() mutable { h.resume(); }).handle;++        coro.coro_->reset_error();+        coro.coro_->input_ = std::move(value);++        struct cancel_handler+        {+          using src = std::pair<cancellation_signal,+                detail::coro_cancellation_source>;++          std::shared_ptr<src> st = std::make_shared<src>();++          cancel_handler(E e, coro_t& coro) : e(e), coro_(coro.coro_)+          {+            st->second.state =+              cancellation_state(st->second.slot = st->first.slot());+          }++          E e;+          typename coro_t::promise_type* coro_;++          void operator()(cancellation_type ct)+          {+            asio::dispatch(e, [ct, st = st]() mutable+            {+              auto & [sig, state] = *st;+              sig.emit(ct);+            });+          }+        };++        if (hp.cancel->state.slot().is_connected())+        {+          hp.cancel->state.slot().template emplace<cancel_handler>(+              coro.get_executor(), coro);+        }++        auto hh = detail::coroutine_handle<+          typename coro_t::promise_type>::from_promise(*coro.coro_);++        return dispatch_coroutine(+            coro.coro_->get_executor(), [hh]() mutable { hh.resume(); }).handle;+      }+    }++    auto await_resume() -> typename coro_t::result_type+    {+      coro.coro_->cancel = nullptr;+      coro.coro_->rethrow_if();+      return std::move(coro.coro_->result_);+    }+  };++  template <typename CompletionToken>+  auto async_resume(CompletionToken&& token) &&+  {+    return coro.async_resume(std::move(value),+        std::forward<CompletionToken>(token));+  }++  auto operator co_await() &&+  {+    return awaitable_t{std::move(value), coro};+  }+};++template <bool IsNoexcept>+struct coro_promise_error;++template <>+struct coro_promise_error<false>+{+  std::exception_ptr error_;++  void reset_error()+  {+    error_ = std::exception_ptr{};+  }++  void unhandled_exception()+  {+    error_ = std::current_exception();+  }++  void rethrow_if()+  {+    if (error_)+      std::rethrow_exception(error_);+  }+};++#if defined(__GNUC__)+# pragma GCC diagnostic push+# if defined(__clang__)+#  pragma GCC diagnostic ignored "-Wexceptions"+# else+#  pragma GCC diagnostic ignored "-Wterminate"+# endif+#elif defined(_MSC_VER)+# pragma warning(push)+# pragma warning (disable:4297)+#endif++template <>+struct coro_promise_error<true>+{+  void reset_error()+  {+  }++  void unhandled_exception() noexcept+  {+    throw;+  }++  void rethrow_if()+  {+  }+};++#if defined(__GNUC__)+# pragma GCC diagnostic pop+#elif defined(_MSC_VER)+# pragma warning(pop)+#endif++template <typename T = void>+struct yield_input+{+  T& value;+  coroutine_handle<> awaited_from{noop_coroutine()};++  bool await_ready() const noexcept+  {+    return false;+  }++  template <typename U>+  coroutine_handle<> await_suspend(coroutine_handle<U>) noexcept+  {+    return std::exchange(awaited_from, noop_coroutine());+  }++  T await_resume() const noexcept+  {+    return std::move(value);+  }+};++template <>+struct yield_input<void>+{+  coroutine_handle<> awaited_from{noop_coroutine()};++  bool await_ready() const noexcept+  {+    return false;+  }++  auto await_suspend(coroutine_handle<>) noexcept+  {+    return std::exchange(awaited_from, noop_coroutine());+  }++  constexpr void await_resume() const noexcept+  {+  }+};++struct coro_awaited_from+{+  coroutine_handle<> awaited_from{noop_coroutine()};++  auto final_suspend() noexcept+  {+    struct suspendor+    {+      coroutine_handle<> awaited_from;++      constexpr static bool await_ready() noexcept+      {+        return false;+      }++      auto await_suspend(coroutine_handle<>) noexcept+      {+        return std::exchange(awaited_from, noop_coroutine());+      }++      constexpr static void await_resume() noexcept+      {+      }+    };++    return suspendor{std::exchange(awaited_from, noop_coroutine())};+  }++  ~coro_awaited_from()+  {+    awaited_from.resume();+  }//must be on the right executor+};++template <typename Yield, typename Input, typename Return>+struct coro_promise_exchange : coro_awaited_from+{+  using result_type = coro_result_t<Yield, Return>;++  result_type result_;+  Input input_;++  auto yield_value(Yield&& y)+  {+    result_ = std::move(y);+    return yield_input<Input>{std::move(input_),+        std::exchange(awaited_from, noop_coroutine())};+  }++  auto yield_value(const Yield& y)+  {+    result_ = y;+    return yield_input<Input>{std::move(input_),+        std::exchange(awaited_from, noop_coroutine())};+  }++  void return_value(const Return& r)+  {+    result_ = r;+  }++  void return_value(Return&& r)+  {+    result_ = std::move(r);+  }+};++template <typename YieldReturn>+struct coro_promise_exchange<YieldReturn, void, YieldReturn> : coro_awaited_from+{+  using result_type = coro_result_t<YieldReturn, YieldReturn>;++  result_type result_;++  auto yield_value(const YieldReturn& y)+  {+    result_ = y;+    return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+  }++  auto yield_value(YieldReturn&& y)+  {+    result_ = std::move(y);+    return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+  }++  void return_value(const YieldReturn& r)+  {+    result_ = r;+  }++  void return_value(YieldReturn&& r)+  {+    result_ = std::move(r);+  }+};++template <typename Yield, typename Return>+struct coro_promise_exchange<Yield, void, Return> : coro_awaited_from+{+  using result_type = coro_result_t<Yield, Return>;++  result_type result_;++  auto yield_value(const Yield& y)+  {+    result_.template emplace<0>(y);+    return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+  }++  auto yield_value(Yield&& y)+  {+    result_.template emplace<0>(std::move(y));+    return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+  }++  void return_value(const Return& r)+  {+    result_.template emplace<1>(r);+  }++  void return_value(Return&& r)+  {+    result_.template emplace<1>(std::move(r));+  }+};++template <typename Yield, typename Input>+struct coro_promise_exchange<Yield, Input, void> : coro_awaited_from+{+  using result_type = coro_result_t<Yield, void>;++  result_type result_;+  Input input_;++  auto yield_value(Yield&& y)+  {+    result_ = std::move(y);+    return yield_input<Input>{input_,+                              std::exchange(awaited_from, noop_coroutine())};+  }++  auto yield_value(const Yield& y)+  {+    result_ = y;+    return yield_input<Input>{input_,+                              std::exchange(awaited_from, noop_coroutine())};+  }++  void return_void()+  {+    result_.reset();+  }+};++template <typename Return>+struct coro_promise_exchange<void, void, Return> : coro_awaited_from+{+  using result_type = coro_result_t<void, Return>;++  result_type result_;++  void yield_value();++  void return_value(const Return& r)+  {+    result_ = r;+  }++  void return_value(Return&& r)+  {+    result_ = std::move(r);+  }+};++template <>+struct coro_promise_exchange<void, void, void> : coro_awaited_from+{+  void return_void() {}++  void yield_value();+};++template <typename Yield>+struct coro_promise_exchange<Yield, void, void> : coro_awaited_from+{+  using result_type = coro_result_t<Yield, void>;++  result_type result_;++  auto yield_value(const Yield& y)+  {+    result_ = y;+    return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+  }++  auto yield_value(Yield&& y)+  {+    result_ = std::move(y);+    return yield_input<void>{std::exchange(awaited_from, noop_coroutine())};+  }++  void return_void()+  {+    result_.reset();+  }+};++template <typename Yield, typename Return,+    typename Executor, typename Allocator>+struct coro_promise final :+  coro_promise_allocator<Allocator>,+  coro_promise_error<coro_traits<Yield, Return, Executor>::is_noexcept>,+  coro_promise_exchange<+      typename coro_traits<Yield, Return, Executor>::yield_type,+      typename coro_traits<Yield, Return, Executor>::input_type,+      typename coro_traits<Yield, Return, Executor>::return_type>+{+  using coro_type = coro<Yield, Return, Executor, Allocator>;++  auto handle()+  {+    return coroutine_handle<coro_promise>::from_promise(this);+  }++  using executor_type = Executor;++  executor_type executor_;++  std::optional<coro_cancellation_source> cancel_source;+  coro_cancellation_source * cancel;++  using cancellation_slot_type = asio::cancellation_slot;++  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return cancel ? cancel->slot : cancellation_slot_type{};+  }++  using allocator_type =+    typename std::allocator_traits<associated_allocator_t<Executor>>::+      template rebind_alloc<std::byte>;+  using traits = coro_traits<Yield, Return, Executor>;++  using input_type = typename traits::input_type;+  using yield_type = typename traits::yield_type;+  using return_type = typename traits::return_type;+  using error_type = typename traits::error_type;+  using result_type = typename traits::result_type;+  constexpr static bool is_noexcept = traits::is_noexcept;++  auto get_executor() const -> Executor+  {+    return executor_;+  }++  auto get_handle()+  {+    return coroutine_handle<coro_promise>::from_promise(*this);+  }++  template <typename... Args>+  coro_promise(Executor executor, Args&&... args) noexcept+    : coro_promise_allocator<Allocator>(+        executor, std::forward<Args>(args)...),+      executor_(std::move(executor))+  {+  }++  template <typename First, typename... Args>+  coro_promise(First&& f, Executor executor, Args&&... args) noexcept+    : coro_promise_allocator<Allocator>(+        f, executor, std::forward<Args>(args)...),+      executor_(std::move(executor))+  {+  }++  template <typename First, detail::execution_context Context, typename... Args>+  coro_promise(First&& f, Context&& ctx, Args&&... args) noexcept+    : coro_promise_allocator<Allocator>(+        f, ctx, std::forward<Args>(args)...),+      executor_(ctx.get_executor())+  {+  }++  template <detail::execution_context Context, typename... Args>+  coro_promise(Context&& ctx, Args&&... args) noexcept+    : coro_promise_allocator<Allocator>(+        ctx, std::forward<Args>(args)...),+      executor_(ctx.get_executor())+  {+  }++  auto get_return_object()+  {+    return coro<Yield, Return, Executor, Allocator>{this};+  }++  auto initial_suspend() noexcept+  {+    return suspend_always{};+  }++  using coro_promise_exchange<+      typename coro_traits<Yield, Return, Executor>::yield_type,+      typename coro_traits<Yield, Return, Executor>::input_type,+      typename coro_traits<Yield, Return, Executor>::return_type>::yield_value;++  auto await_transform(this_coro::executor_t) const+  {+    struct exec_helper+    {+      const executor_type& value;++      constexpr static bool await_ready() noexcept+      {+        return true;+      }++      constexpr static void await_suspend(coroutine_handle<>) noexcept+      {+      }++      executor_type await_resume() const noexcept+      {+        return value;+      }+    };++    return exec_helper{executor_};+  }++  auto await_transform(this_coro::cancellation_state_t) const+  {+    struct exec_helper+    {+      const asio::cancellation_state& value;++      constexpr static bool await_ready() noexcept+      {+        return true;+      }++      constexpr static void await_suspend(coroutine_handle<>) noexcept+      {+      }++      asio::cancellation_state await_resume() const noexcept+      {+        return value;+      }+    };+    assert(cancel);+    return exec_helper{cancel->state};+  }++  // This await transformation resets the associated cancellation state.+  auto await_transform(this_coro::reset_cancellation_state_0_t) noexcept+  {+    struct result+    {+      detail::coro_cancellation_source * src_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      auto await_resume() const+      {+        return src_->reset_cancellation_state();+      }+    };++    return result{cancel};+  }++  // This await transformation resets the associated cancellation state.+  template <typename Filter>+  auto await_transform(+      this_coro::reset_cancellation_state_1_t<Filter> reset) noexcept+  {+    struct result+    {+      detail::coro_cancellation_source* src_;+      Filter filter_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      auto await_resume()+      {+        return src_->reset_cancellation_state(+            ASIO_MOVE_CAST(Filter)(filter_));+      }+    };++    return result{cancel, ASIO_MOVE_CAST(Filter)(reset.filter)};+  }++  // This await transformation resets the associated cancellation state.+  template <typename InFilter, typename OutFilter>+  auto await_transform(+      this_coro::reset_cancellation_state_2_t<InFilter, OutFilter> reset)+  noexcept+  {+    struct result+    {+      detail::coro_cancellation_source* src_;+      InFilter in_filter_;+      OutFilter out_filter_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      auto await_resume()+      {+        return src_->reset_cancellation_state(+            ASIO_MOVE_CAST(InFilter)(in_filter_),+            ASIO_MOVE_CAST(OutFilter)(out_filter_));+      }+    };++    return result{cancel,+        ASIO_MOVE_CAST(InFilter)(reset.in_filter),+        ASIO_MOVE_CAST(OutFilter)(reset.out_filter)};+  }++  // This await transformation determines whether cancellation is propagated as+  // an exception.+  auto await_transform(this_coro::throw_if_cancelled_0_t) noexcept+    requires (!is_noexcept)+  {+    struct result+    {+      detail::coro_cancellation_source* src_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      auto await_resume()+      {+        return src_->throw_if_cancelled();+      }+    };++    return result{cancel};+  }++  // This await transformation sets whether cancellation is propagated as an+  // exception.+  auto await_transform(+      this_coro::throw_if_cancelled_1_t throw_if_cancelled) noexcept+    requires (!is_noexcept)+  {+    struct result+    {+      detail::coro_cancellation_source* src_;+      bool value_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      auto await_resume()+      {+        src_->throw_if_cancelled(value_);+      }+    };++    return result{cancel, throw_if_cancelled.value};+  }++  template <typename Yield_, typename Return_,+      typename Executor_, typename Allocator_>+  auto await_transform(coro<Yield_, Return_, Executor_, Allocator_>& kr)+    -> decltype(auto)+  {+    return kr;+  }++  template <typename Yield_, typename Return_,+      typename Executor_, typename Allocator_>+  auto await_transform(coro<Yield_, Return_, Executor_, Allocator_>&& kr)+  {+    return std::move(kr);+  }++  template <typename T_, typename Coroutine >+  auto await_transform(coro_with_arg<T_, Coroutine>&& kr) -> decltype(auto)+  {+    return std::move(kr);+  }++  template <typename T_>+    requires requires(T_ t) {{ t.async_wait(deferred) }; }+  auto await_transform(T_& t) -> decltype(auto)+  {+    return await_transform(t.async_wait(deferred));+  }++  template <typename Op>+  auto await_transform(Op&& op,+      typename constraint<is_async_operation<Op>::value>::type = 0)+  {+    if ((cancel->state.cancelled() != cancellation_type::none)+        && cancel->throw_if_cancelled_)+    {+      asio::detail::throw_error(+          asio::error::operation_aborted, "coro-cancelled");+    }+    using signature = typename completion_signature_of<Op>::type;+    using result_type = detail::coro_completion_handler_type_t<signature>;+    using handler_type =+      typename detail::coro_completion_handler_type<signature>::template+        completion_handler<coro_promise>;++    struct aw_t+    {+      Op op;+      std::optional<result_type> result;++      constexpr static bool await_ready()+      {+        return false;+      }++      void await_suspend(coroutine_handle<coro_promise> h)+      {+        std::move(op)(handler_type{h, result});+      }++      auto await_resume()+      {+        if constexpr (is_noexcept)+        {+          if constexpr (std::tuple_size_v<result_type> == 0u)+            return;+          else if constexpr (std::tuple_size_v<result_type> == 1u)+            return std::get<0>(std::move(result).value());+          else+            return std::move(result).value();+        }+        else+          return detail::coro_interpret_result(std::move(result).value());+      }+    };++    return aw_t{std::move(op), {}};+  }+};++} // namespace detail++template <typename Yield, typename Return,+    typename Executor, typename Allocator>+struct coro<Yield, Return, Executor, Allocator>::awaitable_t+{+  coro& coro_;++  constexpr static bool await_ready() { return false; }++  template <typename Y, typename R, typename E, typename A>+  auto await_suspend(+      detail::coroutine_handle<detail::coro_promise<Y, R, E, A>> h)+    -> detail::coroutine_handle<>+  {+    auto& hp = h.promise();++    if constexpr (!detail::coro_promise<Y, R, E, A>::is_noexcept)+    {+      if ((hp.cancel->state.cancelled() != cancellation_type::none)+          && hp.cancel->throw_if_cancelled_)+      {+        asio::detail::throw_error(+            asio::error::operation_aborted, "coro-cancelled");+      }+    }++    if (hp.get_executor() == coro_.get_executor())+    {+      coro_.coro_->awaited_from  = h;+      coro_.coro_->cancel = hp.cancel;+      coro_.coro_->reset_error();++      return coro_.coro_->get_handle();+    }+    else+    {+      coro_.coro_->awaited_from = detail::dispatch_coroutine(+          asio::prefer(hp.get_executor(),+            execution::outstanding_work.tracked),+          [h]() mutable+          {+            h.resume();+          }).handle;++      coro_.coro_->reset_error();++      struct cancel_handler+      {+        std::shared_ptr<std::pair<cancellation_signal,+          detail::coro_cancellation_source>> st = std::make_shared<+            std::pair<cancellation_signal, detail::coro_cancellation_source>>();++        cancel_handler(E e, coro& coro) : e(e), coro_(coro.coro_)+        {+          st->second.state = cancellation_state(+              st->second.slot = st->first.slot());+        }++        E e;+        typename coro::promise_type* coro_;++        void operator()(cancellation_type ct)+        {+          asio::dispatch(e,+              [ct, st = st]() mutable+              {+                auto & [sig, state] = *st;+                sig.emit(ct);+              });+        }+      };++      if (hp.cancel->state.slot().is_connected())+      {+        hp.cancel->state.slot().template emplace<cancel_handler>(+            coro_.get_executor(), coro_);+      }++      auto hh = detail::coroutine_handle<+        detail::coro_promise<Yield, Return, Executor, Allocator>>::from_promise(+            *coro_.coro_);++      return detail::dispatch_coroutine(+          coro_.coro_->get_executor(),+          [hh]() mutable { hh.resume(); }).handle;+    }+  }++  auto await_resume() -> result_type+  {+    coro_.coro_->cancel = nullptr;+    coro_.coro_->rethrow_if();+    if constexpr (!std::is_void_v<result_type>)+      return std::move(coro_.coro_->result_);+  }+};++template <typename Yield, typename Return,+    typename Executor, typename Allocator>+struct coro<Yield, Return, Executor, Allocator>::initiate_async_resume+{+  typedef Executor executor_type;+  typedef Allocator allocator_type;+  typedef asio::cancellation_slot cancellation_slot_type;++  explicit initiate_async_resume(coro* self)+    : coro_(self->coro_)+  {+  }++  executor_type get_executor() const noexcept+  {+    return coro_->get_executor();+  }++  allocator_type get_allocator() const noexcept+  {+    return coro_->get_allocator();+  }++  template <typename E, typename WaitHandler>+  auto handle(E exec, WaitHandler&& handler,+      std::true_type /* error is noexcept */,+      std::true_type /* result is void */)  //noexcept+  {+    return [this, coro = coro_,+        h = std::forward<WaitHandler>(handler),+        exec = std::move(exec)]() mutable+    {+      assert(coro);++      auto ch = detail::coroutine_handle<promise_type>::from_promise(*coro);+      assert(ch && !ch.done());++      coro->awaited_from = post_coroutine(std::move(exec), std::move(h));+      coro->reset_error();+      ch.resume();+    };+  }++  template <typename E, typename WaitHandler>+  requires (!std::is_void_v<result_type>)+  auto handle(E exec, WaitHandler&& handler,+      std::true_type /* error is noexcept */,+      std::false_type  /* result is void */)  //noexcept+  {+    return [coro = coro_,+        h = std::forward<WaitHandler>(handler),+        exec = std::move(exec)]() mutable+    {+      assert(coro);++      auto ch = detail::coroutine_handle<promise_type>::from_promise(*coro);+      assert(ch && !ch.done());++      coro->awaited_from = detail::post_coroutine(+          exec, std::move(h), coro->result_).handle;+      coro->reset_error();+      ch.resume();+    };+  }++  template <typename E, typename WaitHandler>+  auto handle(E exec, WaitHandler&& handler,+      std::false_type /* error is noexcept */,+      std::true_type /* result is void */)+  {+    return [coro = coro_,+        h = std::forward<WaitHandler>(handler),+        exec = std::move(exec)]() mutable+    {+      if (!coro)+        return asio::post(exec,+            asio::append(std::move(h),+              detail::coro_error<error_type>::invalid()));++      auto ch = detail::coroutine_handle<promise_type>::from_promise(*coro);+      if (!ch)+        return asio::post(exec,+            asio::append(std::move(h),+              detail::coro_error<error_type>::invalid()));+      else if (ch.done())+        return asio::post(exec,+            asio::append(std::move(h),+              detail::coro_error<error_type>::done()));+      else+      {+        coro->awaited_from = detail::post_coroutine(+            exec, std::move(h), coro->error_).handle;+        coro->reset_error();+        ch.resume();+      }+    };+  }++  template <typename E, typename WaitHandler>+  auto handle(E exec, WaitHandler&& handler,+      std::false_type /* error is noexcept */,+      std::false_type  /* result is void */)+  {+    return [coro = coro_,+        h = std::forward<WaitHandler>(handler),+        exec = std::move(exec)]() mutable+    {+      if (!coro)+        return asio::post(exec,+            asio::append(std::move(h),+              detail::coro_error<error_type>::invalid(), result_type{}));++      auto ch =+        detail::coroutine_handle<promise_type>::from_promise(*coro);+      if (!ch)+        return asio::post(exec,+            asio::append(std::move(h),+              detail::coro_error<error_type>::invalid(), result_type{}));+      else if (ch.done())+        return asio::post(exec,+            asio::append(std::move(h),+              detail::coro_error<error_type>::done(), result_type{}));+      else+      {+        coro->awaited_from = detail::post_coroutine(+            exec, std::move(h), coro->error_, coro->result_).handle;+        coro->reset_error();+        ch.resume();+      }+    };+  }++  template <typename WaitHandler>+  void operator()(WaitHandler&& handler)+  {+    const auto exec = asio::prefer(+        get_associated_executor(handler, get_executor()),+        execution::outstanding_work.tracked);++    coro_->cancel = &coro_->cancel_source.emplace();+    coro_->cancel->state = cancellation_state(+        coro_->cancel->slot = get_associated_cancellation_slot(handler));+    asio::dispatch(get_executor(),+        handle(exec, std::forward<WaitHandler>(handler),+          std::integral_constant<bool, is_noexcept>{},+          std::is_void<result_type>{}));+  }++  template <typename WaitHandler, typename Input>+  void operator()(WaitHandler&& handler, Input&& input)+  {+    const auto exec = asio::prefer(+        get_associated_executor(handler, get_executor()),+        execution::outstanding_work.tracked);++    coro_->cancel = &coro_->cancel_source.emplace();+    coro_->cancel->state = cancellation_state(+        coro_->cancel->slot = get_associated_cancellation_slot(handler));+    asio::dispatch(get_executor(),+        [h = handle(exec, std::forward<WaitHandler>(handler),+            std::integral_constant<bool, is_noexcept>{},+            std::is_void<result_type>{}),+            in = std::forward<Input>(input), coro = coro_]() mutable+        {+          coro->input_ = std::move(in);+          std::move(h)();+        });+  }++private:+  typename coro::promise_type* coro_;+};++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/parallel_group.hpp view
@@ -0,0 +1,792 @@+//+// experimental/impl/parallel_group.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_EXPERIMENTAL_PARALLEL_GROUP_HPP+#define ASIO_IMPL_EXPERIMENTAL_PARALLEL_GROUP_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <atomic>+#include <deque>+#include <memory>+#include <new>+#include <tuple>+#include "asio/associated_cancellation_slot.hpp"+#include "asio/detail/recycling_allocator.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/dispatch.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++// Stores the result from an individual asynchronous operation.+template <typename T, typename = void>+struct parallel_group_op_result+{+public:+  parallel_group_op_result()+    : has_value_(false)+  {+  }++  parallel_group_op_result(parallel_group_op_result&& other)+    : has_value_(other.has_value_)+  {+    if (has_value_)+      new (&u_.value_) T(std::move(other.get()));+  }++  ~parallel_group_op_result()+  {+    if (has_value_)+      u_.value_.~T();+  }++  T& get() noexcept+  {+    return u_.value_;+  }++  template <typename... Args>+  void emplace(Args&&... args)+  {+    new (&u_.value_) T(std::forward<Args>(args)...);+    has_value_ = true;+  }++private:+  union u+  {+    u() {}+    ~u() {}+    char c_;+    T value_;+  } u_;+  bool has_value_;+};++// Proxy completion handler for the group of parallel operatations. Unpacks and+// concatenates the individual operations' results, and invokes the user's+// completion handler.+template <typename Handler, typename... Ops>+struct parallel_group_completion_handler+{+  typedef typename decay<+      typename prefer_result<+        typename associated_executor<Handler>::type,+        execution::outstanding_work_t::tracked_t+      >::type+    >::type executor_type;++  parallel_group_completion_handler(Handler&& h)+    : handler_(std::move(h)),+      executor_(+          asio::prefer(+            asio::get_associated_executor(handler_),+            execution::outstanding_work.tracked))+  {+  }++  executor_type get_executor() const noexcept+  {+    return executor_;+  }++  void operator()()+  {+    this->invoke(asio::detail::make_index_sequence<sizeof...(Ops)>());+  }++  template <std::size_t... I>+  void invoke(asio::detail::index_sequence<I...>)+  {+    this->invoke(std::tuple_cat(std::move(std::get<I>(args_).get())...));+  }++  template <typename... Args>+  void invoke(std::tuple<Args...>&& args)+  {+    this->invoke(std::move(args),+        asio::detail::index_sequence_for<Args...>());+  }++  template <typename... Args, std::size_t... I>+  void invoke(std::tuple<Args...>&& args,+      asio::detail::index_sequence<I...>)+  {+    std::move(handler_)(completion_order_, std::move(std::get<I>(args))...);+  }++  Handler handler_;+  executor_type executor_;+  std::array<std::size_t, sizeof...(Ops)> completion_order_{};+  std::tuple<+      parallel_group_op_result<+        typename parallel_op_signature_as_tuple<+          typename completion_signature_of<Ops>::type+        >::type+      >...+    > args_{};+};++// Shared state for the parallel group.+template <typename Condition, typename Handler, typename... Ops>+struct parallel_group_state+{+  parallel_group_state(Condition&& c, Handler&& h)+    : cancellation_condition_(std::move(c)),+      handler_(std::move(h))+  {+  }++  // The number of operations that have completed so far. Used to determine the+  // order of completion.+  std::atomic<unsigned int> completed_{0};++  // The non-none cancellation type that resulted from a cancellation condition.+  // Stored here for use by the group's initiating function.+  std::atomic<cancellation_type_t> cancel_type_{cancellation_type::none};++  // The number of cancellations that have been requested, either on completion+  // of the operations within the group, or via the cancellation slot for the+  // group operation. Initially set to the number of operations to prevent+  // cancellation signals from being emitted until after all of the group's+  // operations' initiating functions have completed.+  std::atomic<unsigned int> cancellations_requested_{sizeof...(Ops)};++  // The number of operations that are yet to complete. Used to determine when+  // it is safe to invoke the user's completion handler.+  std::atomic<unsigned int> outstanding_{sizeof...(Ops)};++  // The cancellation signals for each operation in the group.+  asio::cancellation_signal cancellation_signals_[sizeof...(Ops)];++  // The cancellation condition is used to determine whether the results from an+  // individual operation warrant a cancellation request for the whole group.+  Condition cancellation_condition_;++  // The proxy handler to be invoked once all operations in the group complete.+  parallel_group_completion_handler<Handler, Ops...> handler_;+};++// Handler for an individual operation within the parallel group.+template <std::size_t I, typename Condition, typename Handler, typename... Ops>+struct parallel_group_op_handler+{+  typedef asio::cancellation_slot cancellation_slot_type;++  parallel_group_op_handler(+    std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state)+    : state_(std::move(state))+  {+  }++  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return state_->cancellation_signals_[I].slot();+  }++  template <typename... Args>+  void operator()(Args... args)+  {+    // Capture this operation into the completion order.+    state_->handler_.completion_order_[state_->completed_++] = I;++    // Determine whether the results of this operation require cancellation of+    // the whole group.+    cancellation_type_t cancel_type = state_->cancellation_condition_(args...);++    // Capture the result of the operation into the proxy completion handler.+    std::get<I>(state_->handler_.args_).emplace(std::move(args)...);++    if (cancel_type != cancellation_type::none)+    {+      // Save the type for potential use by the group's initiating function.+      state_->cancel_type_ = cancel_type;++      // If we are the first operation to request cancellation, emit a signal+      // for each operation in the group.+      if (state_->cancellations_requested_++ == 0)+        for (std::size_t i = 0; i < sizeof...(Ops); ++i)+          if (i != I)+            state_->cancellation_signals_[i].emit(cancel_type);+    }++    // If this is the last outstanding operation, invoke the user's handler.+    if (--state_->outstanding_ == 0)+      asio::dispatch(std::move(state_->handler_));+  }++  std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state_;+};++// Handler for an individual operation within the parallel group that has an+// explicitly specified executor.+template <typename Executor, std::size_t I,+    typename Condition, typename Handler, typename... Ops>+struct parallel_group_op_handler_with_executor :+  parallel_group_op_handler<I, Condition, Handler, Ops...>+{+  typedef parallel_group_op_handler<I, Condition, Handler, Ops...> base_type;+  typedef asio::cancellation_slot cancellation_slot_type;+  typedef Executor executor_type;++  parallel_group_op_handler_with_executor(+      std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state,+      executor_type ex)+    : parallel_group_op_handler<I, Condition, Handler, Ops...>(std::move(state))+  {+    cancel_proxy_ =+      &this->state_->cancellation_signals_[I].slot().template+        emplace<cancel_proxy>(this->state_, std::move(ex));+  }++  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return cancel_proxy_->signal_.slot();+  }++  executor_type get_executor() const noexcept+  {+    return cancel_proxy_->executor_;+  }++  // Proxy handler that forwards the emitted signal to the correct executor.+  struct cancel_proxy+  {+    cancel_proxy(+        std::shared_ptr<parallel_group_state<+          Condition, Handler, Ops...> > state,+        executor_type ex)+      : state_(std::move(state)),+        executor_(std::move(ex))+    {+    }++    void operator()(cancellation_type_t type)+    {+      if (auto state = state_.lock())+      {+        asio::cancellation_signal* sig = &signal_;+        asio::dispatch(executor_,+            [state, sig, type]{ sig->emit(type); });+      }+    }++    std::weak_ptr<parallel_group_state<Condition, Handler, Ops...> > state_;+    asio::cancellation_signal signal_;+    executor_type executor_;+  };++  cancel_proxy* cancel_proxy_;+};++// Helper to launch an operation using the correct executor, if any.+template <std::size_t I, typename Op, typename = void>+struct parallel_group_op_launcher+{+  template <typename Condition, typename Handler, typename... Ops>+  static void launch(Op& op,+    const std::shared_ptr<parallel_group_state<+      Condition, Handler, Ops...> >& state)+  {+    typedef typename associated_executor<Op>::type ex_type;+    ex_type ex = asio::get_associated_executor(op);+    std::move(op)(+        parallel_group_op_handler_with_executor<ex_type, I,+          Condition, Handler, Ops...>(state, std::move(ex)));+  }+};++// Specialised launcher for operations that specify no executor.+template <std::size_t I, typename Op>+struct parallel_group_op_launcher<I, Op,+    typename enable_if<+      is_same<+        typename associated_executor<+          Op>::asio_associated_executor_is_unspecialised,+        void+      >::value+    >::type>+{+  template <typename Condition, typename Handler, typename... Ops>+  static void launch(Op& op,+    const std::shared_ptr<parallel_group_state<+      Condition, Handler, Ops...> >& state)+  {+    std::move(op)(+        parallel_group_op_handler<I, Condition, Handler, Ops...>(state));+  }+};++template <typename Condition, typename Handler, typename... Ops>+struct parallel_group_cancellation_handler+{+  parallel_group_cancellation_handler(+    std::shared_ptr<parallel_group_state<Condition, Handler, Ops...> > state)+    : state_(std::move(state))+  {+  }++  void operator()(cancellation_type_t cancel_type)+  {+    // If we are the first place to request cancellation, i.e. no operation has+    // yet completed and requested cancellation, emit a signal for each+    // operation in the group.+    if (cancel_type != cancellation_type::none)+      if (auto state = state_.lock())+        if (state->cancellations_requested_++ == 0)+          for (std::size_t i = 0; i < sizeof...(Ops); ++i)+            state->cancellation_signals_[i].emit(cancel_type);+  }++  std::weak_ptr<parallel_group_state<Condition, Handler, Ops...> > state_;+};++template <typename Condition, typename Handler,+    typename... Ops, std::size_t... I>+void parallel_group_launch(Condition cancellation_condition, Handler handler,+    std::tuple<Ops...>& ops, asio::detail::index_sequence<I...>)+{+  // Get the user's completion handler's cancellation slot, so that we can allow+  // cancellation of the entire group.+  typename associated_cancellation_slot<Handler>::type slot+    = asio::get_associated_cancellation_slot(handler);++  // Create the shared state for the operation.+  typedef parallel_group_state<Condition, Handler, Ops...> state_type;+  std::shared_ptr<state_type> state = std::allocate_shared<state_type>(+      asio::detail::recycling_allocator<state_type,+        asio::detail::thread_info_base::parallel_group_tag>(),+      std::move(cancellation_condition), std::move(handler));++  // Initiate each individual operation in the group.+  int fold[] = { 0,+    ( parallel_group_op_launcher<I, Ops>::launch(std::get<I>(ops), state),+      0 )...+  };+  (void)fold;++  // Check if any of the operations has already requested cancellation, and if+  // so, emit a signal for each operation in the group.+  if ((state->cancellations_requested_ -= sizeof...(Ops)) > 0)+    for (auto& signal : state->cancellation_signals_)+      signal.emit(state->cancel_type_);++  // Register a handler with the user's completion handler's cancellation slot.+  if (slot.is_connected())+    slot.template emplace<+      parallel_group_cancellation_handler<+        Condition, Handler, Ops...> >(state);+}++// Proxy completion handler for the ranged group of parallel operatations.+// Unpacks and recombines the individual operations' results, and invokes the+// user's completion handler.+template <typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_completion_handler+{+  typedef typename decay<+      typename prefer_result<+        typename associated_executor<Handler>::type,+        execution::outstanding_work_t::tracked_t+      >::type+    >::type executor_type;++  typedef typename parallel_op_signature_as_tuple<+      typename completion_signature_of<Op>::type+    >::type op_tuple_type;++  typedef parallel_group_op_result<op_tuple_type> op_result_type;++  ranged_parallel_group_completion_handler(Handler&& h,+      std::size_t size, const Allocator& allocator)+    : handler_(std::move(h)),+      executor_(+          asio::prefer(+            asio::get_associated_executor(handler_),+            execution::outstanding_work.tracked)),+      allocator_(allocator),+      completion_order_(size, 0,+          ASIO_REBIND_ALLOC(Allocator, std::size_t)(allocator)),+      args_(ASIO_REBIND_ALLOC(Allocator, op_result_type)(allocator))+  {+    for (std::size_t i = 0; i < size; ++i)+      args_.emplace_back();+  }++  executor_type get_executor() const noexcept+  {+    return executor_;+  }++  void operator()()+  {+    this->invoke(+        asio::detail::make_index_sequence<+          std::tuple_size<op_tuple_type>::value>());+  }++  template <std::size_t... I>+  void invoke(asio::detail::index_sequence<I...>)+  {+    typedef typename parallel_op_signature_as_tuple<+        typename ranged_parallel_group_signature<+          typename completion_signature_of<Op>::type,+          Allocator+        >::raw_type+      >::type vectors_type;++    // Construct all result vectors using the supplied allocator.+    vectors_type vectors{+        typename std::tuple_element<I, vectors_type>::type(+          ASIO_REBIND_ALLOC(Allocator, int)(allocator_))...};++    // Reserve sufficient space in each of the result vectors.+    int reserve_fold[] = { 0,+      ( std::get<I>(vectors).reserve(completion_order_.size()),+        0 )...+    };+    (void)reserve_fold;++    // Copy the results from all operations into the result vectors.+    for (std::size_t idx = 0; idx < completion_order_.size(); ++idx)+    {+      int pushback_fold[] = { 0,+        ( std::get<I>(vectors).push_back(+            std::move(std::get<I>(args_[idx].get()))),+          0 )...+      };+      (void)pushback_fold;+    }++    std::move(handler_)(completion_order_, std::move(std::get<I>(vectors))...);+  }++  Handler handler_;+  executor_type executor_;+  Allocator allocator_;+  std::vector<std::size_t,+    ASIO_REBIND_ALLOC(Allocator, std::size_t)> completion_order_;+  std::deque<op_result_type,+    ASIO_REBIND_ALLOC(Allocator, op_result_type)> args_;+};++// Shared state for the parallel group.+template <typename Condition, typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_state+{+  ranged_parallel_group_state(Condition&& c, Handler&& h,+      std::size_t size, const Allocator& allocator)+    : cancellations_requested_(size),+      outstanding_(size),+      cancellation_signals_(+          ASIO_REBIND_ALLOC(Allocator,+            asio::cancellation_signal)(allocator)),+      cancellation_condition_(std::move(c)),+      handler_(std::move(h), size, allocator)+  {+    for (std::size_t i = 0; i < size; ++i)+      cancellation_signals_.emplace_back();+  }++  // The number of operations that have completed so far. Used to determine the+  // order of completion.+  std::atomic<unsigned int> completed_{0};++  // The non-none cancellation type that resulted from a cancellation condition.+  // Stored here for use by the group's initiating function.+  std::atomic<cancellation_type_t> cancel_type_{cancellation_type::none};++  // The number of cancellations that have been requested, either on completion+  // of the operations within the group, or via the cancellation slot for the+  // group operation. Initially set to the number of operations to prevent+  // cancellation signals from being emitted until after all of the group's+  // operations' initiating functions have completed.+  std::atomic<unsigned int> cancellations_requested_;++  // The number of operations that are yet to complete. Used to determine when+  // it is safe to invoke the user's completion handler.+  std::atomic<unsigned int> outstanding_;++  // The cancellation signals for each operation in the group.+  std::deque<asio::cancellation_signal,+    ASIO_REBIND_ALLOC(Allocator, asio::cancellation_signal)>+      cancellation_signals_;++  // The cancellation condition is used to determine whether the results from an+  // individual operation warrant a cancellation request for the whole group.+  Condition cancellation_condition_;++  // The proxy handler to be invoked once all operations in the group complete.+  ranged_parallel_group_completion_handler<Handler, Op, Allocator> handler_;+};++// Handler for an individual operation within the parallel group.+template <typename Condition, typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_op_handler+{+  typedef asio::cancellation_slot cancellation_slot_type;++  ranged_parallel_group_op_handler(+      std::shared_ptr<ranged_parallel_group_state<+        Condition, Handler, Op, Allocator> > state,+      std::size_t idx)+    : state_(std::move(state)),+      idx_(idx)+  {+  }++  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return state_->cancellation_signals_[idx_].slot();+  }++  template <typename... Args>+  void operator()(Args... args)+  {+    // Capture this operation into the completion order.+    state_->handler_.completion_order_[state_->completed_++] = idx_;++    // Determine whether the results of this operation require cancellation of+    // the whole group.+    cancellation_type_t cancel_type = state_->cancellation_condition_(args...);++    // Capture the result of the operation into the proxy completion handler.+    state_->handler_.args_[idx_].emplace(std::move(args)...);++    if (cancel_type != cancellation_type::none)+    {+      // Save the type for potential use by the group's initiating function.+      state_->cancel_type_ = cancel_type;++      // If we are the first operation to request cancellation, emit a signal+      // for each operation in the group.+      if (state_->cancellations_requested_++ == 0)+        for (std::size_t i = 0; i < state_->cancellation_signals_.size(); ++i)+          if (i != idx_)+            state_->cancellation_signals_[i].emit(cancel_type);+    }++    // If this is the last outstanding operation, invoke the user's handler.+    if (--state_->outstanding_ == 0)+      asio::dispatch(std::move(state_->handler_));+  }++  std::shared_ptr<ranged_parallel_group_state<+    Condition, Handler, Op, Allocator> > state_;+  std::size_t idx_;+};++// Handler for an individual operation within the parallel group that has an+// explicitly specified executor.+template <typename Executor, typename Condition,+    typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_op_handler_with_executor :+  ranged_parallel_group_op_handler<Condition, Handler, Op, Allocator>+{+  typedef ranged_parallel_group_op_handler<+    Condition, Handler, Op, Allocator> base_type;+  typedef asio::cancellation_slot cancellation_slot_type;+  typedef Executor executor_type;++  ranged_parallel_group_op_handler_with_executor(+      std::shared_ptr<ranged_parallel_group_state<+        Condition, Handler, Op, Allocator> > state,+      executor_type ex, std::size_t idx)+    : ranged_parallel_group_op_handler<Condition, Handler, Op, Allocator>(+        std::move(state), idx)+  {+    cancel_proxy_ =+      &this->state_->cancellation_signals_[idx].slot().template+        emplace<cancel_proxy>(this->state_, std::move(ex));+  }++  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return cancel_proxy_->signal_.slot();+  }++  executor_type get_executor() const noexcept+  {+    return cancel_proxy_->executor_;+  }++  // Proxy handler that forwards the emitted signal to the correct executor.+  struct cancel_proxy+  {+    cancel_proxy(+        std::shared_ptr<ranged_parallel_group_state<+          Condition, Handler, Op, Allocator> > state,+        executor_type ex)+      : state_(std::move(state)),+        executor_(std::move(ex))+    {+    }++    void operator()(cancellation_type_t type)+    {+      if (auto state = state_.lock())+      {+        asio::cancellation_signal* sig = &signal_;+        asio::dispatch(executor_,+            [state, sig, type]{ sig->emit(type); });+      }+    }++    std::weak_ptr<ranged_parallel_group_state<+      Condition, Handler, Op, Allocator> > state_;+    asio::cancellation_signal signal_;+    executor_type executor_;+  };++  cancel_proxy* cancel_proxy_;+};++template <typename Condition, typename Handler, typename Op, typename Allocator>+struct ranged_parallel_group_cancellation_handler+{+  ranged_parallel_group_cancellation_handler(+      std::shared_ptr<ranged_parallel_group_state<+        Condition, Handler, Op, Allocator> > state)+    : state_(std::move(state))+  {+  }++  void operator()(cancellation_type_t cancel_type)+  {+    // If we are the first place to request cancellation, i.e. no operation has+    // yet completed and requested cancellation, emit a signal for each+    // operation in the group.+    if (cancel_type != cancellation_type::none)+      if (auto state = state_.lock())+        if (state->cancellations_requested_++ == 0)+          for (std::size_t i = 0; i < state->cancellation_signals_.size(); ++i)+            state->cancellation_signals_[i].emit(cancel_type);+  }++  std::weak_ptr<ranged_parallel_group_state<+    Condition, Handler, Op, Allocator> > state_;+};++template <typename Condition, typename Handler,+    typename Range, typename Allocator>+void ranged_parallel_group_launch(Condition cancellation_condition,+    Handler handler, Range&& range, const Allocator& allocator)+{+  // Get the user's completion handler's cancellation slot, so that we can allow+  // cancellation of the entire group.+  typename associated_cancellation_slot<Handler>::type slot+          = asio::get_associated_cancellation_slot(handler);++  // The type of the asynchronous operation.+  typedef typename std::decay<decltype(+      *std::declval<typename Range::iterator>())>::type op_type;++  // Create the shared state for the operation.+  typedef ranged_parallel_group_state<Condition,+    Handler, op_type, Allocator> state_type;+  std::shared_ptr<state_type> state = std::allocate_shared<state_type>(+      asio::detail::recycling_allocator<state_type,+        asio::detail::thread_info_base::parallel_group_tag>(),+      std::move(cancellation_condition),+      std::move(handler), range.size(), allocator);++  std::size_t idx = 0;+  for (auto&& op : std::forward<Range>(range))+  {+    typedef typename associated_executor<op_type>::type ex_type;+    ex_type ex = asio::get_associated_executor(op);+    std::move(op)(+        ranged_parallel_group_op_handler_with_executor<+          ex_type, Condition, Handler, op_type, Allocator>(+            state, std::move(ex), idx++));+  }++  // Check if any of the operations has already requested cancellation, and if+  // so, emit a signal for each operation in the group.+  if ((state->cancellations_requested_ -= range.size()) > 0)+    for (auto& signal : state->cancellation_signals_)+      signal.emit(state->cancel_type_);++  // Register a handler with the user's completion handler's cancellation slot.+  if (slot.is_connected())+    slot.template emplace<+      ranged_parallel_group_cancellation_handler<+        Condition, Handler, op_type, Allocator> >(state);+}++} // namespace detail+} // namespace experimental++template <template <typename, typename> class Associator,+    typename Handler, typename... Ops, typename DefaultCandidate>+struct associator<Associator,+    experimental::detail::parallel_group_completion_handler<Handler, Ops...>,+    DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const experimental::detail::parallel_group_completion_handler<+        Handler, Ops...>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const experimental::detail::parallel_group_completion_handler<+        Handler, Ops...>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++template <template <typename, typename> class Associator, typename Handler,+    typename Op, typename Allocator, typename DefaultCandidate>+struct associator<Associator,+    experimental::detail::ranged_parallel_group_completion_handler<+      Handler, Op, Allocator>,+    DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const experimental::detail::ranged_parallel_group_completion_handler<+        Handler, Op, Allocator>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const experimental::detail::ranged_parallel_group_completion_handler<+        Handler, Op, Allocator>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_EXPERIMENTAL_PARALLEL_GROUP_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/promise.hpp view
@@ -0,0 +1,254 @@+//+// experimental/impl/promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//+#ifndef ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP+#define ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/detail/utility.hpp"+#include <tuple>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++template<typename Signature = void(),+    typename Executor = asio::any_io_executor,+    typename Allocator = std::allocator<void>>+struct promise;++namespace detail {++template<typename Signature, typename Executor, typename Allocator>+struct promise_impl;++template<typename... Ts, typename Executor, typename Allocator>+struct promise_impl<void(Ts...), Executor, Allocator>+{+  using result_type = std::tuple<Ts...>;++  promise_impl(Allocator allocator, Executor executor)+    : allocator(std::move(allocator)), executor(std::move(executor))+  {+  }++  promise_impl(const promise_impl&) = delete;++  ~promise_impl()+  {+    if (completion)+      this->cancel_();++    if (done)+      reinterpret_cast<result_type*>(&result)->~result_type();+  }++  typename aligned_storage<sizeof(result_type),+    alignof(result_type)>::type result;+  std::atomic<bool> done{false};+  cancellation_signal cancel;+  Allocator allocator;+  Executor executor;++  template<typename Func, std::size_t... Idx>+  void apply_impl(Func f, asio::detail::index_sequence<Idx...>)+  {+    auto& result_type = *reinterpret_cast<promise_impl::result_type*>(&result);+    f(std::get<Idx>(std::move(result_type))...);+  }++  using allocator_type = Allocator;+  allocator_type get_allocator() {return allocator;}++  using executor_type = Executor;+  executor_type get_executor() {return executor;}++  template<typename Func>+  void apply(Func f)+  {+    apply_impl(std::forward<Func>(f),+        asio::detail::make_index_sequence<sizeof...(Ts)>{});+  }++  struct completion_base+  {+    virtual void invoke(Ts&&...ts) = 0;+  };++  template<typename Alloc, typename WaitHandler_>+  struct completion_impl final : completion_base+  {+    WaitHandler_ handler;+    Alloc allocator;+    void invoke(Ts&&... ts)+    {+      auto h = std::move(handler);++      using alloc_t = typename std::allocator_traits<+        typename asio::decay<Alloc>::type>::template+          rebind_alloc<completion_impl>;++      alloc_t alloc_{allocator};+      this->~completion_impl();+      std::allocator_traits<alloc_t>::deallocate(alloc_, this, 1u);+      std::move(h)(std::forward<Ts>(ts)...);+    }++    template<typename Alloc_, typename Handler_>+    completion_impl(Alloc_&& alloc, Handler_&& wh)+      : handler(std::forward<Handler_>(wh)),+        allocator(std::forward<Alloc_>(alloc))+    {+    }+  };++  completion_base* completion = nullptr;+  typename asio::aligned_storage<sizeof(void*) * 4,+    alignof(completion_base)>::type completion_opt;++  template<typename Alloc, typename Handler>+  void set_completion(Alloc&& alloc, Handler&& handler)+  {+    if (completion)+      cancel_();++    using impl_t = completion_impl<+      typename asio::decay<Alloc>::type, Handler>;+    using alloc_t = typename std::allocator_traits<+      typename asio::decay<Alloc>::type>::template rebind_alloc<impl_t>;++    alloc_t alloc_{alloc};+    auto p = std::allocator_traits<alloc_t>::allocate(alloc_, 1u);+    completion = new (p) impl_t(std::forward<Alloc>(alloc),+        std::forward<Handler>(handler));+  }++  template<typename... T_>+  void complete(T_&&... ts)+  {+    assert(completion);+    std::exchange(completion, nullptr)->invoke(std::forward<T_>(ts)...);+  }++  template<std::size_t... Idx>+  void complete_with_result_impl(asio::detail::index_sequence<Idx...>)+  {+    auto& result_type = *reinterpret_cast<promise_impl::result_type*>(&result);+    this->complete(std::get<Idx>(std::move(result_type))...);+  }++  void complete_with_result()+  {+    complete_with_result_impl(+        asio::detail::make_index_sequence<sizeof...(Ts)>{});+  }++  template<typename... T_>+  void cancel_impl_(std::exception_ptr*, T_*...)+  {+    complete(+        std::make_exception_ptr(+          asio::system_error(+            asio::error::operation_aborted)),+        T_{}...);+  }++  template<typename... T_>+  void cancel_impl_(asio::error_code*, T_*...)+  {+    complete(asio::error::operation_aborted, T_{}...);+  }++  template<typename... T_>+  void cancel_impl_(T_*...)+  {+    complete(T_{}...);+  }++  void cancel_()+  {+    cancel_impl_(static_cast<Ts*>(nullptr)...);+  }+};++template<typename Signature = void(),+    typename Executor = asio::any_io_executor,+    typename Allocator = any_io_executor>+struct promise_handler;++template<typename... Ts,  typename Executor, typename Allocator>+struct promise_handler<void(Ts...), Executor, Allocator>+{+  using promise_type = promise<void(Ts...), Executor, Allocator>;++  promise_handler(+      Allocator allocator, Executor executor) // get_associated_allocator(exec)+    : impl_(+        std::allocate_shared<promise_impl<void(Ts...), Executor, Allocator>>(+          allocator, allocator, executor))+  {+  }++  std::shared_ptr<promise_impl<void(Ts...), Executor, Allocator>> impl_;++  using cancellation_slot_type = cancellation_slot;++  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return impl_->cancel.slot();+  }++  using allocator_type = Allocator;++  allocator_type get_allocator() const noexcept+  {+    return impl_->get_allocator();+  }++  using executor_type = Executor;++  Executor get_executor() const noexcept+  {+    return impl_->get_executor();+  }++  auto make_promise() -> promise<void(Ts...), executor_type, allocator_type>+  {+    return promise<void(Ts...), executor_type, allocator_type>{impl_};+  }++  void operator()(std::remove_reference_t<Ts>... ts)+  {+    assert(impl_);++    using result_type = typename promise_impl<+      void(Ts...), allocator_type, executor_type>::result_type ;++    new (&impl_->result) result_type(std::move(ts)...);+    impl_->done = true;++    if (impl_->completion)+      impl_->complete_with_result();+  }+};++} // namespace detail+} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_PROMISE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/use_coro.hpp view
@@ -0,0 +1,214 @@+//+// experimental/impl/use_coro.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP+#define ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/deferred.hpp"+#include "asio/experimental/coro.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++#if !defined(GENERATING_DOCUMENTATION)++template <typename Allocator, typename R>+struct async_result<experimental::use_coro_t<Allocator>, R()>+{+  template <typename Initiation, typename... InitArgs>+  static auto initiate_impl(Initiation initiation,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void() noexcept, void,+      asio::associated_executor_t<Initiation>, Allocator>+  {+    co_await deferred_async_operation<R(), Initiation, InitArgs...>(+        deferred_init_tag{}, std::move(initiation), std::move(args)...);+  }++  template <typename... InitArgs>+  static auto initiate_impl(asio::detail::initiation_archetype<R()>,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void(), void,+      asio::any_io_executor, Allocator>;++  template <typename Initiation, typename... InitArgs>+  static auto initiate(Initiation initiation,+      experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+  {+    return initiate_impl(std::move(initiation), std::allocator_arg,+        tk.get_allocator(), std::forward<InitArgs>(args)...);+  }+};++template <typename Allocator, typename R>+struct async_result<+    experimental::use_coro_t<Allocator>, R(asio::error_code)>+{+  template <typename Initiation, typename... InitArgs>+  static auto initiate_impl(Initiation initiation,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void() noexcept, void,+      asio::associated_executor_t<Initiation>, Allocator>+  {+    co_await deferred_async_operation<+      R(asio::error_code), Initiation, InitArgs...>(+        deferred_init_tag{}, std::move(initiation), std::move(args)...);+  }++  template <typename... InitArgs>+  static auto initiate_impl(+      asio::detail::initiation_archetype<R(asio::error_code)>,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void(), void,+      asio::any_io_executor, Allocator>;++  template <typename Initiation, typename... InitArgs>+  static auto initiate(Initiation initiation,+      experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+  {+    return initiate_impl(std::move(initiation), std::allocator_arg,+        tk.get_allocator(), std::forward<InitArgs>(args)...);+  }+};++template <typename Allocator, typename R>+struct async_result<+    experimental::use_coro_t<Allocator>, R(std::exception_ptr)>+{+  template <typename Initiation, typename... InitArgs>+  static auto initiate_impl(Initiation initiation,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void(), void,+      asio::associated_executor_t<Initiation>, Allocator>+  {+    co_await deferred_async_operation<+      R(std::exception_ptr), Initiation, InitArgs...>(+        deferred_init_tag{}, std::move(initiation), std::move(args)...);+  }++  template <typename... InitArgs>+  static auto initiate_impl(+      asio::detail::initiation_archetype<R(std::exception_ptr)>,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void(), void,+      asio::any_io_executor, Allocator>;++  template <typename Initiation, typename... InitArgs>+  static auto initiate(Initiation initiation,+      experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+  {+    return initiate_impl(std::move(initiation), std::allocator_arg,+        tk.get_allocator(), std::forward<InitArgs>(args)...);+  }+};++template <typename Allocator, typename R, typename T>+struct async_result<experimental::use_coro_t<Allocator>, R(T)>+{++  template <typename Initiation, typename... InitArgs>+  static auto initiate_impl(Initiation initiation,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void() noexcept, T,+      asio::associated_executor_t<Initiation>, Allocator>+  {+    co_return co_await deferred_async_operation<R(T), Initiation, InitArgs...>(+        deferred_init_tag{}, std::move(initiation), std::move(args)...);+  }++  template <typename... InitArgs>+  static auto initiate_impl(asio::detail::initiation_archetype<R(T)>,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void() noexcept, T,+      asio::any_io_executor, Allocator>;++  template <typename Initiation, typename... InitArgs>+  static auto initiate(Initiation initiation,+      experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+  {+    return initiate_impl(std::move(initiation), std::allocator_arg,+        tk.get_allocator(), std::forward<InitArgs>(args)...);+  }+};++template <typename Allocator, typename R, typename T>+struct async_result<+    experimental::use_coro_t<Allocator>, R(asio::error_code, T)>+{+  template <typename Initiation, typename... InitArgs>+  static auto initiate_impl(Initiation initiation,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void(), T,+      asio::associated_executor_t<Initiation>, Allocator>+  {+    co_return co_await deferred_async_operation<+      R(asio::error_code, T), Initiation, InitArgs...>(+        deferred_init_tag{}, std::move(initiation), std::move(args)...);+  }++  template <typename... InitArgs>+  static auto initiate_impl(+      asio::detail::initiation_archetype<+        R(asio::error_code, T)>,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void(), T, asio::any_io_executor, Allocator>;++  template <typename Initiation, typename... InitArgs>+  static auto initiate(Initiation initiation,+      experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+  {+    return initiate_impl(std::move(initiation), std::allocator_arg,+        tk.get_allocator(), std::forward<InitArgs>(args)...);+  }+};++template <typename Allocator, typename R, typename T>+struct async_result<+    experimental::use_coro_t<Allocator>, R(std::exception_ptr, T)>+{+  template <typename Initiation, typename... InitArgs>+  static auto initiate_impl(Initiation initiation,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void(), T,+      asio::associated_executor_t<Initiation>, Allocator>+  {+    co_return co_await deferred_async_operation<+      R(std::exception_ptr, T), Initiation, InitArgs...>(+        deferred_init_tag{}, std::move(initiation), std::move(args)...);+  }++  template <typename... InitArgs>+  static auto initiate_impl(+      asio::detail::initiation_archetype<R(std::exception_ptr, T)>,+      std::allocator_arg_t, Allocator, InitArgs... args)+    -> experimental::coro<void(), T, asio::any_io_executor, Allocator>;++  template <typename Initiation, typename... InitArgs>+  static auto initiate(Initiation initiation,+      experimental::use_coro_t<Allocator> tk, InitArgs&&... args)+  {+    return initiate_impl(std::move(initiation), std::allocator_arg,+        tk.get_allocator(), std::forward<InitArgs>(args)...);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_USE_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/impl/use_promise.hpp view
@@ -0,0 +1,66 @@+//+// experimental/impl/use_promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_IMPL_USE_PROMISE_HPP+#define ASIO_EXPERIMENTAL_IMPL_USE_PROMISE_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/async_result.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++template <typename Allocator>+struct use_promise_t;++namespace detail {++template<typename Signature, typename Executor, typename Allocator>+struct promise_handler;++} // namespace detail+} // namespace experimental++#if !defined(GENERATING_DOCUMENTATION)++template <typename Allocator, typename R, typename... Args>+struct async_result<experimental::use_promise_t<Allocator>, R(Args...)>+{+  template <typename Initiation, typename... InitArgs>+  static auto initiate(Initiation initiation,+      experimental::use_promise_t<Allocator> up, InitArgs... args)+    -> experimental::promise<void(typename decay<Args>::type...),+      asio::associated_executor_t<Initiation>, Allocator>+  {+    using handler_type = experimental::detail::promise_handler<+      void(typename decay<Args>::type...),+      asio::associated_executor_t<Initiation>, Allocator>;++    handler_type ht{up.get_allocator(), get_associated_executor(initiation)};+    std::move(initiation)(ht, std::move(args)...);+    return ht.make_promise();+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_IMPL_USE_PROMISE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/parallel_group.hpp view
@@ -0,0 +1,461 @@+//+// experimental/parallel_group.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP+#define ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP++#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/array.hpp"+#include "asio/detail/memory.hpp"+#include "asio/detail/utility.hpp"+#include "asio/experimental/cancellation_condition.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {+namespace detail {++// Helper trait for getting a tuple from a completion signature.++template <typename Signature>+struct parallel_op_signature_as_tuple;++template <typename R, typename... Args>+struct parallel_op_signature_as_tuple<R(Args...)>+{+  typedef std::tuple<typename decay<Args>::type...> type;+};++// Helper trait for concatenating completion signatures.++template <std::size_t N, typename Offsets, typename... Signatures>+struct parallel_group_signature;++template <std::size_t N, typename R0, typename... Args0>+struct parallel_group_signature<N, R0(Args0...)>+{+  typedef asio::detail::array<std::size_t, N> order_type;+  typedef R0 raw_type(Args0...);+  typedef R0 type(order_type, Args0...);+};++template <std::size_t N,+    typename R0, typename... Args0,+    typename R1, typename... Args1>+struct parallel_group_signature<N, R0(Args0...), R1(Args1...)>+{+  typedef asio::detail::array<std::size_t, N> order_type;+  typedef R0 raw_type(Args0..., Args1...);+  typedef R0 type(order_type, Args0..., Args1...);+};++template <std::size_t N, typename Sig0,+    typename Sig1, typename... SigN>+struct parallel_group_signature<N, Sig0, Sig1, SigN...>+{+  typedef asio::detail::array<std::size_t, N> order_type;+  typedef typename parallel_group_signature<N,+    typename parallel_group_signature<N, Sig0, Sig1>::raw_type,+      SigN...>::raw_type raw_type;+  typedef typename parallel_group_signature<N,+    typename parallel_group_signature<N, Sig0, Sig1>::raw_type,+      SigN...>::type type;+};++template <typename Condition, typename Handler,+    typename... Ops, std::size_t... I>+void parallel_group_launch(Condition cancellation_condition, Handler handler,+    std::tuple<Ops...>& ops, asio::detail::index_sequence<I...>);++// Helper trait for determining ranged parallel group completion signatures.++template <typename Signature, typename Allocator>+struct ranged_parallel_group_signature;++template <typename R, typename... Args, typename Allocator>+struct ranged_parallel_group_signature<R(Args...), Allocator>+{+  typedef std::vector<std::size_t,+    ASIO_REBIND_ALLOC(Allocator, std::size_t)> order_type;+  typedef R raw_type(+      std::vector<Args, ASIO_REBIND_ALLOC(Allocator, Args)>...);+  typedef R type(order_type,+      std::vector<Args, ASIO_REBIND_ALLOC(Allocator, Args)>...);+};++template <typename Condition, typename Handler,+    typename Range, typename Allocator>+void ranged_parallel_group_launch(Condition cancellation_condition,+    Handler handler, Range&& range, const Allocator& allocator);++char (&parallel_group_has_iterator_helper(...))[2];++template <typename T>+char parallel_group_has_iterator_helper(T*, typename T::iterator* = 0);++template <typename T>+struct parallel_group_has_iterator_typedef+{+  enum { value = (sizeof((parallel_group_has_iterator_helper)((T*)(0))) == 1) };+};++} // namespace detail++/// Type trait used to determine whether a type is a range of asynchronous+/// operations that can be used with with @c make_parallel_group.+template <typename T>+struct is_async_operation_range+{+#if defined(GENERATING_DOCUMENTATION)+  /// The value member is true if the type may be used as a range of+  /// asynchronous operations.+  static const bool value;+#else+  enum+  {+    value = detail::parallel_group_has_iterator_typedef<T>::value+  };+#endif+};++/// A group of asynchronous operations that may be launched in parallel.+/**+ * See the documentation for asio::experimental::make_parallel_group for+ * a usage example.+ */+template <typename... Ops>+class parallel_group+{+private:+  struct initiate_async_wait+  {+    template <typename Handler, typename Condition>+    void operator()(Handler&& h, Condition&& c, std::tuple<Ops...>&& ops) const+    {+      detail::parallel_group_launch(+          std::forward<Condition>(c), std::forward<Handler>(h),+          ops, asio::detail::index_sequence_for<Ops...>());+    }+  };++  std::tuple<Ops...> ops_;++public:+  /// Constructor.+  explicit parallel_group(Ops... ops)+    : ops_(std::move(ops)...)+  {+  }++  /// The completion signature for the group of operations.+  typedef typename detail::parallel_group_signature<sizeof...(Ops),+      typename completion_signature_of<Ops>::type...>::type signature;++  /// Initiate an asynchronous wait for the group of operations.+  /**+   * Launches the group and asynchronously waits for completion.+   *+   * @param cancellation_condition A function object, called on completion of+   * an operation within the group, that is used to determine whether to cancel+   * the remaining operations. The function object is passed the arguments of+   * the completed operation's handler. To trigger cancellation of the remaining+   * operations, it must return a asio::cancellation_type value other+   * than <tt>asio::cancellation_type::none</tt>.+   *+   * @param token A @ref completion_token whose signature is comprised of+   * a @c std::array<std::size_t, N> indicating the completion order of the+   * operations, followed by all operations' completion handler arguments.+   *+   * The library provides the following @c cancellation_condition types:+   *+   * @li asio::experimental::wait_for_all+   * @li asio::experimental::wait_for_one+   * @li asio::experimental::wait_for_one_error+   * @li asio::experimental::wait_for_one_success+   */+  template <typename CancellationCondition,+      ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, signature)+  async_wait(CancellationCondition cancellation_condition,+      CompletionToken&& token)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      asio::async_initiate<CompletionToken, signature>(+          declval<initiate_async_wait>(), token,+          std::move(cancellation_condition), std::move(ops_))))+  {+    return asio::async_initiate<CompletionToken, signature>(+        initiate_async_wait(), token,+        std::move(cancellation_condition), std::move(ops_));+  }+};++/// Create a group of operations that may be launched in parallel.+/**+ * For example:+ * @code asio::experimental::make_parallel_group(+ *    [&](auto token)+ *    {+ *      return in.async_read_some(asio::buffer(data), token);+ *    },+ *    [&](auto token)+ *    {+ *      return timer.async_wait(token);+ *    }+ *  ).async_wait(+ *    asio::experimental::wait_for_all(),+ *    [](+ *        std::array<std::size_t, 2> completion_order,+ *        std::error_code ec1, std::size_t n1,+ *        std::error_code ec2+ *    )+ *    {+ *      switch (completion_order[0])+ *      {+ *      case 0:+ *        {+ *          std::cout << "descriptor finished: " << ec1 << ", " << n1 << "\n";+ *        }+ *        break;+ *      case 1:+ *        {+ *          std::cout << "timer finished: " << ec2 << "\n";+ *        }+ *        break;+ *      }+ *    }+ *  );+ * @endcode+ */+template <typename... Ops>+ASIO_NODISCARD inline parallel_group<Ops...>+make_parallel_group(Ops... ops)+{+  return parallel_group<Ops...>(std::move(ops)...);+}++/// A range-based group of asynchronous operations that may be launched in+/// parallel.+/**+ * See the documentation for asio::experimental::make_parallel_group for+ * a usage example.+ */+template <typename Range, typename Allocator = std::allocator<void> >+class ranged_parallel_group+{+private:+  struct initiate_async_wait+  {+    template <typename Handler, typename Condition>+    void operator()(Handler&& h, Condition&& c,+        Range&& range, const Allocator& allocator) const+    {+      detail::ranged_parallel_group_launch(std::move(c),+          std::move(h), std::forward<Range>(range), allocator);+    }+  };++  Range range_;+  Allocator allocator_;++public:+  /// Constructor.+  explicit ranged_parallel_group(Range range,+      const Allocator& allocator = Allocator())+    : range_(std::move(range)),+      allocator_(allocator)+  {+  }++  /// The completion signature for the group of operations.+  typedef typename detail::ranged_parallel_group_signature<+      typename completion_signature_of<+        typename std::decay<+          decltype(*std::declval<typename Range::iterator>())>::type>::type,+      Allocator>::type signature;++  /// Initiate an asynchronous wait for the group of operations.+  /**+   * Launches the group and asynchronously waits for completion.+   *+   * @param cancellation_condition A function object, called on completion of+   * an operation within the group, that is used to determine whether to cancel+   * the remaining operations. The function object is passed the arguments of+   * the completed operation's handler. To trigger cancellation of the remaining+   * operations, it must return a asio::cancellation_type value other+   * than <tt>asio::cancellation_type::none</tt>.+   *+   * @param token A @ref completion_token whose signature is comprised of+   * a @c std::vector<std::size_t, Allocator> indicating the completion order of+   * the operations, followed by a vector for each of the completion signature's+   * arguments.+   *+   * The library provides the following @c cancellation_condition types:+   *+   * @li asio::experimental::wait_for_all+   * @li asio::experimental::wait_for_one+   * @li asio::experimental::wait_for_one_error+   * @li asio::experimental::wait_for_one_success+   */+  template <typename CancellationCondition,+      ASIO_COMPLETION_TOKEN_FOR(signature) CompletionToken>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken, signature)+  async_wait(CancellationCondition cancellation_condition,+      CompletionToken&& token)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      asio::async_initiate<CompletionToken, signature>(+          declval<initiate_async_wait>(), token,+          std::move(cancellation_condition),+          std::move(range_), allocator_)))+  {+    return asio::async_initiate<CompletionToken, signature>(+        initiate_async_wait(), token,+        std::move(cancellation_condition),+        std::move(range_), allocator_);+  }+};++/// Create a group of operations that may be launched in parallel.+/**+ * @param range A range containing the operations to be launched.+ *+ * For example:+ * @code+ * using op_type = decltype(+ *     socket1.async_read_some(+ *       asio::buffer(data1),+ *       asio::deferred+ *     )+ *   );+ *+ * std::vector<op_type> ops;+ *+ * ops.push_back(+ *     socket1.async_read_some(+ *       asio::buffer(data1),+ *       asio::deferred+ *     )+ *   );+ *+ * ops.push_back(+ *     socket2.async_read_some(+ *       asio::buffer(data2),+ *       asio::deferred+ *     )+ *   );+ *+ * asio::experimental::make_parallel_group(ops).async_wait(+ *     asio::experimental::wait_for_all(),+ *     [](+ *         std::vector<std::size_t> completion_order,+ *         std::vector<std::error_code> e,+ *         std::vector<std::size_t> n+ *       )+ *     {+ *       for (std::size_t i = 0; i < completion_order.size(); ++i)+ *       {+ *         std::size_t idx = completion_order[i];+ *         std::cout << "socket " << idx << " finished: ";+ *         std::cout << e[idx] << ", " << n[idx] << "\n";+ *       }+ *     }+ *   );+ * @endcode+ */+template <typename Range>+ASIO_NODISCARD inline+ranged_parallel_group<typename std::decay<Range>::type>+make_parallel_group(Range&& range,+    typename constraint<+      is_async_operation_range<typename std::decay<Range>::type>::value+    >::type = 0)+{+  return ranged_parallel_group<typename std::decay<Range>::type>(+      std::forward<Range>(range));+}++/// Create a group of operations that may be launched in parallel.+/**+ * @param allocator Specifies the allocator to be used with the result vectors.+ *+ * @param range A range containing the operations to be launched.+ *+ * For example:+ * @code+ * using op_type = decltype(+ *     socket1.async_read_some(+ *       asio::buffer(data1),+ *       asio::deferred+ *     )+ *   );+ *+ * std::vector<op_type> ops;+ *+ * ops.push_back(+ *     socket1.async_read_some(+ *       asio::buffer(data1),+ *       asio::deferred+ *     )+ *   );+ *+ * ops.push_back(+ *     socket2.async_read_some(+ *       asio::buffer(data2),+ *       asio::deferred+ *     )+ *   );+ *+ * asio::experimental::make_parallel_group(+ *     std::allocator_arg_t,+ *     my_allocator,+ *     ops+ *   ).async_wait(+ *     asio::experimental::wait_for_all(),+ *     [](+ *         std::vector<std::size_t> completion_order,+ *         std::vector<std::error_code> e,+ *         std::vector<std::size_t> n+ *       )+ *     {+ *       for (std::size_t i = 0; i < completion_order.size(); ++i)+ *       {+ *         std::size_t idx = completion_order[i];+ *         std::cout << "socket " << idx << " finished: ";+ *         std::cout << e[idx] << ", " << n[idx] << "\n";+ *       }+ *     }+ *   );+ * @endcode+ */+template <typename Allocator, typename Range>+ASIO_NODISCARD inline+ranged_parallel_group<typename std::decay<Range>::type, Allocator>+make_parallel_group(allocator_arg_t, const Allocator& allocator, Range&& range,+    typename constraint<+      is_async_operation_range<typename std::decay<Range>::type>::value+    >::type = 0)+{+  return ranged_parallel_group<typename std::decay<Range>::type, Allocator>(+      std::forward<Range>(range), allocator);+}++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/parallel_group.hpp"++#endif // ASIO_EXPERIMENTAL_PARALLEL_GROUP_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/prepend.hpp view
@@ -0,0 +1,36 @@+//+// experimental/prepend.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_PREPEND_HPP+#define ASIO_EXPERIMENTAL_PREPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/prepend.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++#if !defined(ASIO_NO_DEPRECATED)+using asio::prepend_t;+using asio::prepend;+#endif // !defined(ASIO_NO_DEPRECATED)++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_PREPEND_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/promise.hpp view
@@ -0,0 +1,224 @@+//+// experimental/promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_PROMISE_HPP+#define ASIO_EXPERIMENTAL_PROMISE_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/any_io_executor.hpp"+#include "asio/associated_cancellation_slot.hpp"+#include "asio/associated_executor.hpp"+#include "asio/bind_executor.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/dispatch.hpp"+#include "asio/experimental/impl/promise.hpp"+#include "asio/post.hpp"++#include <algorithm>++#include "asio/detail/push_options.hpp"++namespace asio {+namespace experimental {++template <typename T>+struct is_promise : std::false_type {};++template <typename ... Ts>+struct is_promise<promise<Ts...>> : std::true_type {};++template <typename T>+constexpr bool is_promise_v = is_promise<T>::value;++template <typename ... Ts>+struct promise_value_type+{+  using type = std::tuple<Ts...>;+};++template <typename T>+struct promise_value_type<T>+{+  using type = T;+};++template <>+struct promise_value_type<>+{+  using type = std::tuple<>;+};++#if defined(GENERATING_DOCUMENTATION)+/// A disposable handle for an eager operation.+/**+ * @tparam Signature The signature of the operation.+ *+ * @tparam Executor The executor to be used by the promise (taken from the+ * operation).+ *+ * @tparam Allocator The allocator used for the promise. Can be set through+ * use_allocator.+ *+ * A promise can be used to initiate an asynchronous option that can be+ * completed later. If the promise gets destroyed before completion, the+ * operation gets a cancel signal and the result is ignored.+ *+ * A promise fulfills the requirements of async_operation.+ *+ * @par Examples+ * Reading and writing from one coroutine.+ * @code+ * awaitable<void> read_write_some(asio::ip::tcp::socket & sock,+ *     asio::mutable_buffer read_buf, asio::const_buffer to_write)+ * {+ *   auto p = asio::async_read(read_buf, asio::use_awaitable);+ *   co_await asio::async_write_some(to_write, asio::deferred);+ *   co_await p;+ * }+ * @endcode+ */+template<typename Signature = void(),+    typename Executor = asio::any_io_executor,+    typename Allocator = std::allocator<void>>+struct promise+#else+template <typename ... Ts, typename Executor, typename Allocator>+struct promise<void(Ts...), Executor,  Allocator>+#endif // defined(GENERATING_DOCUMENTATION)+{+  /// The value that's returned by the promise.+  using value_type = typename promise_value_type<Ts...>::type;++  /// Cancel the promise. Usually done through the destructor.+  void cancel(cancellation_type level = cancellation_type::all)+  {+    if (impl_ && !impl_->done)+    {+      asio::dispatch(impl_->executor,+          [level, impl = impl_]{ impl->cancel.emit(level); });+    }+  }++  /// Check if the promise is completed already.+  bool completed() const noexcept+  {+    return impl_ && impl_->done;+  }++  /// Wait for the promise to become ready.+  template <ASIO_COMPLETION_TOKEN_FOR(void(Ts...)) CompletionToken>+  inline ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void(Ts...))+  operator()(CompletionToken&& token)+  {+    assert(impl_);++    return async_initiate<CompletionToken, void(Ts...)>(+        initiate_async_wait{impl_}, token);+  }++  promise() = delete;+  promise(const promise& ) = delete;+  promise(promise&& ) noexcept = default;++  /// Destruct the promise and cancel the operation.+  /**+   * It is safe to destruct a promise of a promise that didn't complete.+   */+  ~promise() { cancel(); }+++private:+#if !defined(GENERATING_DOCUMENTATION)+  template <typename, typename, typename> friend struct promise;+  friend struct detail::promise_handler<void(Ts...), Executor, Allocator>;+#endif // !defined(GENERATING_DOCUMENTATION)++  std::shared_ptr<detail::promise_impl<+    void(Ts...), Executor, Allocator>> impl_;++  promise(+      std::shared_ptr<detail::promise_impl<+        void(Ts...), Executor, Allocator>> impl)+    : impl_(impl)+  {+  }++  struct initiate_async_wait+  {+    std::shared_ptr<detail::promise_impl<+      void(Ts...), Executor, Allocator>> self_;++    template <typename WaitHandler>+    void operator()(WaitHandler&& handler) const+    {+      const auto alloc = get_associated_allocator(+          handler, self_->get_allocator());++      auto cancel = get_associated_cancellation_slot(handler);++      if (self_->done)+      {+        auto exec = asio::get_associated_executor(+            handler, self_->get_executor());++        asio::post(exec,+            [self = std::move(self_),+              handler = std::forward<WaitHandler>(handler)]() mutable+            {+              self->apply(std::move(handler));+            });+      }+      else+      {+        if (cancel.is_connected())+        {+          struct cancel_handler+          {+            std::weak_ptr<detail::promise_impl<+              void(Ts...), Executor, Allocator>> self;++            cancel_handler(+                std::weak_ptr<detail::promise_impl<+                  void(Ts...), Executor, Allocator>> self)+              : self(std::move(self))+            {+            }++            void operator()(cancellation_type level) const+            {+              if (auto p = self.lock())+              {+                p->cancel.emit(level);+                p->cancel_();+              }+            }+          };+          cancel.template emplace<cancel_handler>(self_);+        }++        self_->set_completion(alloc, std::forward<WaitHandler>(handler));+      }+    }+  };+};++} // namespace experimental++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_EXPERIMENTAL_PROMISE_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/use_coro.hpp view
@@ -0,0 +1,195 @@+//+// experimental/use_coro.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_USE_CORO_HPP+#define ASIO_EXPERIMENTAL_USE_CORO_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/deferred.hpp"+#include "asio/detail/source_location.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++class any_io_executor;++namespace experimental {++/// A @ref completion_token that creates another coro for the task completion.+/**+ * The @c use_coro_t class, with its value @c use_coro, is used to represent an+ * operation that can be awaited by the current resumable coroutine. This+ * completion token may be passed as a handler to an asynchronous operation.+ * For example:+ *+ * @code coro<void> my_coroutine(tcp::socket my_socket)+ * {+ *   std::size_t n = co_await my_socket.async_read_some(buffer, use_coro);+ *   ...+ * } @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.+ *+ * Note that this token is not the most efficient (use @c asio::deferred+ * for that) but does provide type erasure, as it will always return a @c coro.+ */+template <typename Allocator = std::allocator<void>>+struct use_coro_t+{++  /// The allocator type. The allocator is used when constructing the+  /// @c std::promise object for a given asynchronous operation.+  typedef Allocator allocator_type;++  /// Default constructor.+  ASIO_CONSTEXPR use_coro_t(+      allocator_type allocator = allocator_type{}+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+      , asio::detail::source_location location =+        asio::detail::source_location::current()+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+    )+    : allocator_(allocator)+#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)+  {+  }+++  /// Specify an alternate allocator.+  template <typename OtherAllocator>+  use_coro_t<OtherAllocator> rebind(const OtherAllocator& allocator) const+  {+    return use_future_t<OtherAllocator>(allocator);+  }++  /// Obtain allocator.+  allocator_type get_allocator() const+  {+    return allocator_;+  }++  /// Constructor used to specify file name, line, and function name.+  ASIO_CONSTEXPR use_coro_t(const char* file_name,+      int line, const char* function_name,+      allocator_type allocator = allocator_type{}) :+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+      file_name_(file_name),+      line_(line),+      function_name_(function_name),+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+      allocator_(allocator)+  {+#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_coro_t completion token as the+  /// default.+  template <typename InnerExecutor>+  struct executor_with_default : InnerExecutor+  {+    /// Specify @c use_coro_t as the default completion token type.+    typedef use_coro_t default_completion_token_type;++    /// Construct the adapted executor from the inner executor type.+    template <typename InnerExecutor1>+    executor_with_default(const InnerExecutor1& ex,+        typename constraint<+          conditional<+            !is_same<InnerExecutor1, executor_with_default>::value,+            is_convertible<InnerExecutor1, InnerExecutor>,+            false_type+          >::type::value+        >::type = 0) ASIO_NOEXCEPT+      : InnerExecutor(ex)+    {+    }+  };++  /// Type alias to adapt an I/O object to use @c use_coro_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_coro_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)++private:+  Allocator allocator_;+};++/// A @ref completion_token object that represents the currently executing+/// resumable coroutine.+/**+ * See the documentation for asio::use_coro_t for a usage example.+ */+#if defined(GENERATING_DOCUMENTATION)+constexpr use_coro_t<> use_coro;+#elif defined(ASIO_HAS_CONSTEXPR)+constexpr use_coro_t<> use_coro(0, 0, 0);+#elif defined(ASIO_MSVC)+__declspec(selectany) use_coro_t<> use_coro(0, 0, 0);+#endif++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/use_coro.hpp"+#include "asio/experimental/coro.hpp"++#endif // ASIO_EXPERIMENTAL_USE_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/experimental/use_promise.hpp view
@@ -0,0 +1,111 @@+//+// experimental/use_promise.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2021-2023 Klemens D. Morgenstern+//                         (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_EXPERIMENTAL_USE_PROMISE_HPP+#define ASIO_EXPERIMENTAL_USE_PROMISE_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 experimental {++template <typename Allocator = std::allocator<void>>+struct use_promise_t+{+  /// The allocator type. The allocator is used when constructing the+  /// @c promise object for a given asynchronous operation.+  typedef Allocator allocator_type;++  /// Construct using default-constructed allocator.+  ASIO_CONSTEXPR use_promise_t()+  {+  }++  /// Construct using specified allocator.+  explicit use_promise_t(const Allocator& allocator)+    : allocator_(allocator)+  {+  }++  /// Obtain allocator.+  allocator_type get_allocator() const ASIO_NOEXCEPT+  {+    return allocator_;+  }++  /// Adapts an executor to add the @c use_promise_t completion token as the+  /// default.+  template <typename InnerExecutor>+  struct executor_with_default : InnerExecutor+  {+    /// Specify @c use_promise_t as the default completion token type.+    typedef use_promise_t<Allocator> default_completion_token_type;++    /// Construct the adapted executor from the inner executor type.+    executor_with_default(const InnerExecutor& ex) ASIO_NOEXCEPT+      : InnerExecutor(ex)+    {+    }++    /// Convert the specified executor to the inner executor type, then use+    /// that to construct the adapted executor.+    template <typename OtherExecutor>+    executor_with_default(const OtherExecutor& ex,+        typename constraint<+          is_convertible<OtherExecutor, InnerExecutor>::value+        >::type = 0) ASIO_NOEXCEPT+      : InnerExecutor(ex)+    {+    }+  };++  /// Function helper to adapt an I/O object to use @c use_promise_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));+  }++  /// Specify an alternate allocator.+  template <typename OtherAllocator>+  use_promise_t<OtherAllocator> rebind(const OtherAllocator& allocator) const+  {+    return use_promise_t<OtherAllocator>(allocator);+  }++private:+  Allocator allocator_;+};++constexpr use_promise_t<> use_promise;++} // namespace experimental+} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/experimental/impl/use_promise.hpp"++#endif // ASIO_EXPERIMENTAL_USE_CORO_HPP
+ link/modules/asio-standalone/asio/include/asio/file_base.hpp view
@@ -0,0 +1,166 @@+//+// file_base.hpp+// ~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_FILE_BASE_HPP+#define ASIO_FILE_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_FILE) \+  || defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_WINDOWS)+# include <fcntl.h>+#endif // !defined(ASIO_WINDOWS)++#include "asio/detail/push_options.hpp"++namespace asio {++/// The file_base class is used as a base for the basic_stream_file and+/// basic_random_access_file class templates so that we have a common place to+/// define flags.+class file_base+{+public:+#if defined(GENERATING_DOCUMENTATION)+  /// A bitmask type (C++ Std [lib.bitmask.types]).+  typedef unspecified flags;++  /// Open the file for reading.+  static const flags read_only = implementation_defined;++  /// Open the file for writing.+  static const flags write_only = implementation_defined;++  /// Open the file for reading and writing.+  static const flags read_write = implementation_defined;++  /// Open the file in append mode.+  static const flags append = implementation_defined;++  /// Create the file if it does not exist.+  static const flags create = implementation_defined;++  /// Ensure a new file is created. Must be combined with @c create.+  static const flags exclusive = implementation_defined;++  /// Open the file with any existing contents truncated.+  static const flags truncate = implementation_defined;++  /// Open the file so that write operations automatically synchronise the file+  /// data and metadata to disk.+  static const flags sync_all_on_write = implementation_defined;+#else+  enum flags+  {+#if defined(ASIO_WINDOWS)+    read_only = 1,+    write_only = 2,+    read_write = 4,+    append = 8,+    create = 16,+    exclusive = 32,+    truncate = 64,+    sync_all_on_write = 128+#else // defined(ASIO_WINDOWS)+    read_only = O_RDONLY,+    write_only = O_WRONLY,+    read_write = O_RDWR,+    append = O_APPEND,+    create = O_CREAT,+    exclusive = O_EXCL,+    truncate = O_TRUNC,+    sync_all_on_write = O_SYNC+#endif // defined(ASIO_WINDOWS)+  };++  // 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++  /// Basis for seeking in a file.+  enum seek_basis+  {+#if defined(GENERATING_DOCUMENTATION)+    /// Seek to an absolute position.+    seek_set = implementation_defined,++    /// Seek to an offset relative to the current file position.+    seek_cur = implementation_defined,++    /// Seek to an offset relative to the end of the file.+    seek_end = implementation_defined+#else+    seek_set = SEEK_SET,+    seek_cur = SEEK_CUR,+    seek_end = SEEK_END+#endif+  };++protected:+  /// Protected destructor to prevent deletion through this type.+  ~file_base()+  {+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_FILE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_FILE_BASE_HPP
link/modules/asio-standalone/asio/include/asio/generic/basic_endpoint.hpp view
@@ -2,7 +2,7 @@ // generic/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/datagram_protocol.hpp view
@@ -2,7 +2,7 @@ // generic/datagram_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/detail/endpoint.hpp view
@@ -2,7 +2,7 @@ // generic/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/detail/impl/endpoint.ipp view
@@ -2,7 +2,7 @@ // generic/detail/impl/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/raw_protocol.hpp view
@@ -2,7 +2,7 @@ // generic/raw_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/seq_packet_protocol.hpp view
@@ -2,7 +2,7 @@ // generic/seq_packet_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/generic/stream_protocol.hpp view
@@ -2,7 +2,7 @@ // generic/stream_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/handler_alloc_hook.hpp view
@@ -2,7 +2,7 @@ // handler_alloc_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/handler_continuation_hook.hpp view
@@ -2,7 +2,7 @@ // handler_continuation_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/handler_invoke_hook.hpp view
@@ -2,7 +2,7 @@ // handler_invoke_hook.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/high_resolution_timer.hpp view
@@ -2,7 +2,7 @@ // high_resolution_timer.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/impl/any_completion_executor.ipp view
@@ -0,0 +1,130 @@+//+// impl/any_completion_executor.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_ANY_COMPLETION_EXECUTOR_IPP+#define ASIO_IMPL_ANY_COMPLETION_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_USE_TS_EXECUTOR_AS_DEFAULT)++#include "asio/any_completion_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++any_completion_executor::any_completion_executor() ASIO_NOEXCEPT+  : base_type()+{+}++any_completion_executor::any_completion_executor(nullptr_t) ASIO_NOEXCEPT+  : base_type(nullptr_t())+{+}++any_completion_executor::any_completion_executor(+    const any_completion_executor& e) ASIO_NOEXCEPT+  : base_type(static_cast<const base_type&>(e))+{+}++any_completion_executor::any_completion_executor(std::nothrow_t,+    const any_completion_executor& e) ASIO_NOEXCEPT+  : base_type(static_cast<const base_type&>(e))+{+}++#if defined(ASIO_HAS_MOVE)+any_completion_executor::any_completion_executor(+    any_completion_executor&& e) ASIO_NOEXCEPT+  : base_type(static_cast<base_type&&>(e))+{+}++any_completion_executor::any_completion_executor(std::nothrow_t,+    any_completion_executor&& e) ASIO_NOEXCEPT+  : base_type(static_cast<base_type&&>(e))+{+}+#endif // defined(ASIO_HAS_MOVE)++any_completion_executor& any_completion_executor::operator=(+    const any_completion_executor& e) ASIO_NOEXCEPT+{+  base_type::operator=(static_cast<const base_type&>(e));+  return *this;+}++#if defined(ASIO_HAS_MOVE)+any_completion_executor& any_completion_executor::operator=(+    any_completion_executor&& e) ASIO_NOEXCEPT+{+  base_type::operator=(static_cast<base_type&&>(e));+  return *this;+}+#endif // defined(ASIO_HAS_MOVE)++any_completion_executor& any_completion_executor::operator=(nullptr_t)+{+  base_type::operator=(nullptr_t());+  return *this;+}++any_completion_executor::~any_completion_executor()+{+}++void any_completion_executor::swap(+    any_completion_executor& other) ASIO_NOEXCEPT+{+  static_cast<base_type&>(*this).swap(static_cast<base_type&>(other));+}++template <>+any_completion_executor any_completion_executor::prefer(+    const execution::outstanding_work_t::tracked_t& p, int) const+{+  return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_completion_executor any_completion_executor::prefer(+    const execution::outstanding_work_t::untracked_t& p, int) const+{+  return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_completion_executor any_completion_executor::prefer(+    const execution::relationship_t::fork_t& p, int) const+{+  return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_completion_executor any_completion_executor::prefer(+    const execution::relationship_t::continuation_t& p, int) const+{+  return static_cast<const base_type&>(*this).prefer(p);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#endif // ASIO_IMPL_ANY_COMPLETION_EXECUTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/any_io_executor.ipp view
@@ -0,0 +1,141 @@+//+// impl/any_io_executor.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_ANY_IO_EXECUTOR_IPP+#define ASIO_IMPL_ANY_IO_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_USE_TS_EXECUTOR_AS_DEFAULT)++#include "asio/any_io_executor.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++any_io_executor::any_io_executor() ASIO_NOEXCEPT+  : base_type()+{+}++any_io_executor::any_io_executor(nullptr_t) ASIO_NOEXCEPT+  : base_type(nullptr_t())+{+}++any_io_executor::any_io_executor(const any_io_executor& e) ASIO_NOEXCEPT+  : base_type(static_cast<const base_type&>(e))+{+}++any_io_executor::any_io_executor(std::nothrow_t,+    const any_io_executor& e) ASIO_NOEXCEPT+  : base_type(static_cast<const base_type&>(e))+{+}++#if defined(ASIO_HAS_MOVE)+any_io_executor::any_io_executor(any_io_executor&& e) ASIO_NOEXCEPT+  : base_type(static_cast<base_type&&>(e))+{+}++any_io_executor::any_io_executor(std::nothrow_t,+    any_io_executor&& e) ASIO_NOEXCEPT+  : base_type(static_cast<base_type&&>(e))+{+}+#endif // defined(ASIO_HAS_MOVE)++any_io_executor& any_io_executor::operator=(+    const any_io_executor& e) ASIO_NOEXCEPT+{+  base_type::operator=(static_cast<const base_type&>(e));+  return *this;+}++#if defined(ASIO_HAS_MOVE)+any_io_executor& any_io_executor::operator=(+    any_io_executor&& e) ASIO_NOEXCEPT+{+  base_type::operator=(static_cast<base_type&&>(e));+  return *this;+}+#endif // defined(ASIO_HAS_MOVE)++any_io_executor& any_io_executor::operator=(nullptr_t)+{+  base_type::operator=(nullptr_t());+  return *this;+}++any_io_executor::~any_io_executor()+{+}++void any_io_executor::swap(any_io_executor& other) ASIO_NOEXCEPT+{+  static_cast<base_type&>(*this).swap(static_cast<base_type&>(other));+}++template <>+any_io_executor any_io_executor::require(+    const execution::blocking_t::never_t& p, int) const+{+  return static_cast<const base_type&>(*this).require(p);+}++template <>+any_io_executor any_io_executor::prefer(+    const execution::blocking_t::possibly_t& p, int) const+{+  return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_io_executor any_io_executor::prefer(+    const execution::outstanding_work_t::tracked_t& p, int) const+{+  return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_io_executor any_io_executor::prefer(+    const execution::outstanding_work_t::untracked_t& p, int) const+{+  return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_io_executor any_io_executor::prefer(+    const execution::relationship_t::fork_t& p, int) const+{+  return static_cast<const base_type&>(*this).prefer(p);+}++template <>+any_io_executor any_io_executor::prefer(+    const execution::relationship_t::continuation_t& p, int) const+{+  return static_cast<const base_type&>(*this).prefer(p);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // !defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT)++#endif // ASIO_IMPL_ANY_IO_EXECUTOR_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/append.hpp view
@@ -0,0 +1,225 @@+//+// impl/append.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_APPEND_HPP+#define ASIO_IMPL_APPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/associator.hpp"+#include "asio/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/utility.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Class to adapt an append_t as a completion handler.+template <typename Handler, typename... Values>+class append_handler+{+public:+  typedef void result_type;++  template <typename H>+  append_handler(ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values)+    : handler_(ASIO_MOVE_CAST(H)(handler)),+      values_(ASIO_MOVE_CAST(std::tuple<Values...>)(values))+  {+  }++  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)... args)+  {+    this->invoke(+        index_sequence_for<Values...>{},+        ASIO_MOVE_CAST(Args)(args)...);+  }++  template <std::size_t... I, typename... Args>+  void invoke(index_sequence<I...>, ASIO_MOVE_ARG(Args)... args)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        ASIO_MOVE_CAST(Args)(args)...,+        ASIO_MOVE_CAST(Values)(std::get<I>(values_))...);+  }++//private:+  Handler handler_;+  std::tuple<Values...> values_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    append_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,+    append_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(+    append_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,+    append_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,+    append_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, typename... Values>+struct append_signature;++template <typename R, typename... Args, typename... Values>+struct append_signature<R(Args...), Values...>+{+  typedef R type(typename decay<Args>::type..., Values...);+};++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename... Values, typename Signature>+struct async_result<+    append_t<CompletionToken, Values...>, Signature>+  : async_result<CompletionToken,+      typename detail::append_signature<+        Signature, Values...>::type>+{+  typedef typename detail::append_signature<+      Signature, Values...>::type signature;++  template <typename Initiation>+  struct init_wrapper+  {+    init_wrapper(Initiation init)+      : initiation_(ASIO_MOVE_CAST(Initiation)(init))+    {+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        std::tuple<Values...> values,+        ASIO_MOVE_ARG(Args)... args)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          detail::append_handler<+            typename decay<Handler>::type, Values...>(+              ASIO_MOVE_CAST(Handler)(handler),+              ASIO_MOVE_CAST(std::tuple<Values...>)(values)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    Initiation initiation_;+  };++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature,+      (async_initiate<CompletionToken, signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<CompletionToken&>(),+        declval<std::tuple<Values...> >(),+        declval<ASIO_MOVE_ARG(Args)>()...)))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+  {+    return async_initiate<CompletionToken, signature>(+        init_wrapper<typename decay<Initiation>::type>(+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.token_,+        ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_),+        ASIO_MOVE_CAST(Args)(args)...);+  }+};++template <template <typename, typename> class Associator,+    typename Handler, typename... Values, typename DefaultCandidate>+struct associator<Associator,+    detail::append_handler<Handler, Values...>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::append_handler<Handler, Values...>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::append_handler<Handler, Values...>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_APPEND_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/as_tuple.hpp view
@@ -0,0 +1,320 @@+//+// impl/as_tuple.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_AS_TUPLE_HPP+#define ASIO_IMPL_AS_TUPLE_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/associator.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/detail/push_options.hpp"++namespace asio {+namespace detail {++// Class to adapt a as_tuple_t as a completion handler.+template <typename Handler>+class as_tuple_handler+{+public:+  typedef void result_type;++  template <typename CompletionToken>+  as_tuple_handler(as_tuple_t<CompletionToken> e)+    : handler_(ASIO_MOVE_CAST(CompletionToken)(e.token_))+  {+  }++  template <typename RedirectedHandler>+  as_tuple_handler(ASIO_MOVE_ARG(RedirectedHandler) h)+    : handler_(ASIO_MOVE_CAST(RedirectedHandler)(h))+  {+  }++  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)... args)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        std::make_tuple(ASIO_MOVE_CAST(Args)(args)...));+  }++//private:+  Handler handler_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    as_tuple_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,+    as_tuple_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(+    as_tuple_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,+    as_tuple_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,+    as_tuple_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 as_tuple_signature;++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...)>+{+  typedef R type(std::tuple<typename decay<Args>::type...>);+};++#if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) &>+{+  typedef R type(std::tuple<typename decay<Args>::type...>) &;+};++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) &&>+{+  typedef R type(std::tuple<typename decay<Args>::type...>) &&;+};++# if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) noexcept>+{+  typedef R type(std::tuple<typename decay<Args>::type...>) noexcept;+};++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) & noexcept>+{+  typedef R type(std::tuple<typename decay<Args>::type...>) & noexcept;+};++template <typename R, typename... Args>+struct as_tuple_signature<R(Args...) && noexcept>+{+  typedef R type(std::tuple<typename decay<Args>::type...>) && noexcept;+};++# endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+#endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename... Signatures>+struct async_result<as_tuple_t<CompletionToken>, Signatures...>+  : async_result<CompletionToken,+      typename detail::as_tuple_signature<Signatures>::type...>+{+  template <typename Initiation>+  struct init_wrapper+  {+    init_wrapper(Initiation init)+      : initiation_(ASIO_MOVE_CAST(Initiation)(init))+    {+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          detail::as_tuple_handler<+            typename decay<Handler>::type>(+              ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    Initiation initiation_;+  };++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+      typename detail::as_tuple_signature<Signatures>::type...)+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<+        typename conditional<+          is_const<typename remove_reference<RawCompletionToken>::type>::value,+            const CompletionToken, CompletionToken>::type,+        typename detail::as_tuple_signature<Signatures>::type...>(+          init_wrapper<typename decay<Initiation>::type>(+            ASIO_MOVE_CAST(Initiation)(initiation)),+          token.token_, ASIO_MOVE_CAST(Args)(args)...)))+  {+    return async_initiate<+      typename conditional<+        is_const<typename remove_reference<RawCompletionToken>::type>::value,+          const CompletionToken, CompletionToken>::type,+      typename detail::as_tuple_signature<Signatures>::type...>(+        init_wrapper<typename decay<Initiation>::type>(+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.token_, ASIO_MOVE_CAST(Args)(args)...);+  }+};++#if defined(ASIO_MSVC)++// Workaround for MSVC internal compiler error.++template <typename CompletionToken, typename Signature>+struct async_result<as_tuple_t<CompletionToken>, Signature>+  : async_result<CompletionToken,+      typename detail::as_tuple_signature<Signature>::type>+{+  template <typename Initiation>+  struct init_wrapper+  {+    init_wrapper(Initiation init)+      : initiation_(ASIO_MOVE_CAST(Initiation)(init))+    {+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Args)... args)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          detail::as_tuple_handler<+            typename decay<Handler>::type>(+              ASIO_MOVE_CAST(Handler)(handler)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    Initiation initiation_;+  };++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+      typename detail::as_tuple_signature<Signatures>::type...)+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<+        typename conditional<+          is_const<typename remove_reference<RawCompletionToken>::type>::value,+            const CompletionToken, CompletionToken>::type,+        typename detail::as_tuple_signature<Signature>::type>(+          init_wrapper<typename decay<Initiation>::type>(+            ASIO_MOVE_CAST(Initiation)(initiation)),+          token.token_, ASIO_MOVE_CAST(Args)(args)...)))+  {+    return async_initiate<+      typename conditional<+        is_const<typename remove_reference<RawCompletionToken>::type>::value,+          const CompletionToken, CompletionToken>::type,+      typename detail::as_tuple_signature<Signature>::type>(+        init_wrapper<typename decay<Initiation>::type>(+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.token_, ASIO_MOVE_CAST(Args)(args)...);+  }+};++#endif // defined(ASIO_MSVC)++template <template <typename, typename> class Associator,+    typename Handler, typename DefaultCandidate>+struct associator<Associator,+    detail::as_tuple_handler<Handler>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::as_tuple_handler<Handler>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::as_tuple_handler<Handler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_AS_TUPLE_HPP
link/modules/asio-standalone/asio/include/asio/impl/awaitable.hpp view
@@ -2,7 +2,7 @@ // impl/awaitable.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,19 +19,32 @@ #include <exception> #include <new> #include <tuple>-#include <utility>+#include "asio/cancellation_signal.hpp"+#include "asio/cancellation_state.hpp" #include "asio/detail/thread_context.hpp" #include "asio/detail/thread_info_base.hpp"+#include "asio/detail/throw_error.hpp" #include "asio/detail/type_traits.hpp"+#include "asio/error.hpp" #include "asio/post.hpp" #include "asio/system_error.hpp" #include "asio/this_coro.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 { namespace detail { +struct awaitable_thread_has_context_switched {};+template <typename, typename> class awaitable_async_op_handler;+template <typename, typename, typename> class awaitable_async_op;+ // 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@@ -77,7 +90,7 @@   {     return asio::detail::thread_info_base::allocate(         asio::detail::thread_info_base::awaitable_frame_tag(),-        asio::detail::thread_context::thread_call_stack::top(),+        asio::detail::thread_context::top_of_thread_call_stack(),         size);   } @@ -85,7 +98,7 @@   {     asio::detail::thread_info_base::deallocate(         asio::detail::thread_info_base::awaitable_frame_tag(),-        asio::detail::thread_context::thread_call_stack::top(),+        asio::detail::thread_context::top_of_thread_call_stack(),         pointer, size);   } #endif // !defined(ASIO_DISABLE_AWAITABLE_FRAME_RECYCLING)@@ -111,7 +124,7 @@        void await_suspend(coroutine_handle<void>) noexcept       {-        this_->pop_frame();+        this->this_->pop_frame();       }        void await_resume() const noexcept@@ -146,12 +159,45 @@     }   } +  void clear_cancellation_slot()+  {+    this->attached_thread_->entry_point()->cancellation_state_.slot().clear();+  }+   template <typename T>   auto await_transform(awaitable<T, Executor> a) const   {+    if (attached_thread_->entry_point()->throw_if_cancelled_)+      if (!!attached_thread_->get_cancellation_state().cancelled())+        throw_error(asio::error::operation_aborted, "co_await");     return a;   } +  template <typename Op>+  auto await_transform(Op&& op,+      typename constraint<is_async_operation<Op>::value>::type = 0+#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 (attached_thread_->entry_point()->throw_if_cancelled_)+      if (!!attached_thread_->get_cancellation_state().cancelled())+        throw_error(asio::error::operation_aborted, "co_await");++    return awaitable_async_op<typename completion_signature_of<Op>::type,+      typename decay<Op>::type, Executor>{+        std::forward<Op>(op), this+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+        , location+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+      };+  }+   // This await transformation obtains the associated executor of the thread of   // execution.   auto await_transform(this_coro::executor_t) noexcept@@ -178,6 +224,175 @@     return result{this};   } +  // This await transformation obtains the associated cancellation state of the+  // thread of execution.+  auto await_transform(this_coro::cancellation_state_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_cancellation_state();+      }+    };++    return result{this};+  }++  // This await transformation resets the associated cancellation state.+  auto await_transform(this_coro::reset_cancellation_state_0_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+      {+        return this_->attached_thread_->reset_cancellation_state();+      }+    };++    return result{this};+  }++  // This await transformation resets the associated cancellation state.+  template <typename Filter>+  auto await_transform(+      this_coro::reset_cancellation_state_1_t<Filter> reset) noexcept+  {+    struct result+    {+      awaitable_frame_base* this_;+      Filter filter_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      auto await_resume()+      {+        return this_->attached_thread_->reset_cancellation_state(+            ASIO_MOVE_CAST(Filter)(filter_));+      }+    };++    return result{this, ASIO_MOVE_CAST(Filter)(reset.filter)};+  }++  // This await transformation resets the associated cancellation state.+  template <typename InFilter, typename OutFilter>+  auto await_transform(+      this_coro::reset_cancellation_state_2_t<InFilter, OutFilter> reset)+    noexcept+  {+    struct result+    {+      awaitable_frame_base* this_;+      InFilter in_filter_;+      OutFilter out_filter_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      auto await_resume()+      {+        return this_->attached_thread_->reset_cancellation_state(+            ASIO_MOVE_CAST(InFilter)(in_filter_),+            ASIO_MOVE_CAST(OutFilter)(out_filter_));+      }+    };++    return result{this,+        ASIO_MOVE_CAST(InFilter)(reset.in_filter),+        ASIO_MOVE_CAST(OutFilter)(reset.out_filter)};+  }++  // This await transformation determines whether cancellation is propagated as+  // an exception.+  auto await_transform(this_coro::throw_if_cancelled_0_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()+      {+        return this_->attached_thread_->throw_if_cancelled();+      }+    };++    return result{this};+  }++  // This await transformation sets whether cancellation is propagated as an+  // exception.+  auto await_transform(this_coro::throw_if_cancelled_1_t throw_if_cancelled)+    noexcept+  {+    struct result+    {+      awaitable_frame_base* this_;+      bool value_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      auto await_resume()+      {+        this_->attached_thread_->throw_if_cancelled(value_);+      }+    };++    return result{this, throw_if_cancelled.value};+  }+   // 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@@ -189,7 +404,7 @@           typename result_of<Function(awaitable_frame_base*)>::type,           awaitable_thread<Executor>*         >::value-      >::type* = 0)+      >::type* = nullptr)   {     struct result     {@@ -203,7 +418,12 @@        void await_suspend(coroutine_handle<void>) noexcept       {-        function_(this_);+        this_->after_suspend(+            [](void* arg)+            {+              result* r = static_cast<result*>(arg);+              r->function_(r->this_);+            }, this);       }        void await_resume() const noexcept@@ -214,6 +434,31 @@     return result{std::move(f), this};   } +  // Access the awaitable thread's has_context_switched_ flag.+  auto await_transform(detail::awaitable_thread_has_context_switched) noexcept+  {+    struct result+    {+      awaitable_frame_base* this_;++      bool await_ready() const noexcept+      {+        return true;+      }++      void await_suspend(coroutine_handle<void>) noexcept+      {+      }++      bool& await_resume() const noexcept+      {+        return this_->attached_thread_->entry_point()->has_context_switched_;+      }+    };++    return result{this};+  }+   void attach_thread(awaitable_thread<Executor>* handler) noexcept   {     attached_thread_ = handler;@@ -221,6 +466,7 @@    awaitable_thread<Executor>* detach_thread() noexcept   {+    attached_thread_->entry_point()->has_context_switched_ = true;     return std::exchange(attached_thread_, nullptr);   } @@ -228,7 +474,7 @@   {     caller_ = caller;     attached_thread_ = caller_->attached_thread_;-    attached_thread_->top_of_stack_ = this;+    attached_thread_->entry_point()->top_of_stack_ = this;     caller_->attached_thread_ = nullptr;   } @@ -236,16 +482,32 @@   {     if (caller_)       caller_->attached_thread_ = attached_thread_;-    attached_thread_->top_of_stack_ = caller_;+    attached_thread_->entry_point()->top_of_stack_ = caller_;     attached_thread_ = nullptr;     caller_ = nullptr;   } +  struct resume_context+  {+    void (*after_suspend_fn_)(void*) = nullptr;+    void *after_suspend_arg_ = nullptr;+  };+   void resume()   {+    resume_context context;+    resume_context_ = &context;     coro_.resume();+    if (context.after_suspend_fn_)+      context.after_suspend_fn_(context.after_suspend_arg_);   } +  void after_suspend(void (*fn)(void*), void* arg)+  {+    resume_context_->after_suspend_fn_ = fn;+    resume_context_->after_suspend_arg_ = arg;+  }+   void destroy()   {     coro_.destroy();@@ -256,6 +518,7 @@   awaitable_thread<Executor>* attached_thread_ = nullptr;   awaitable_frame_base<Executor>* caller_ = nullptr;   std::exception_ptr pending_exception_ = nullptr;+  resume_context* resume_context_ = nullptr; };  template <typename T, typename Executor>@@ -331,25 +594,88 @@   } }; +struct awaitable_thread_entry_point {};+ template <typename Executor>+class awaitable_frame<awaitable_thread_entry_point, Executor>+  : public awaitable_frame_base<Executor>+{+public:+  awaitable_frame()+    : top_of_stack_(0),+      has_executor_(false),+      has_context_switched_(false),+      throw_if_cancelled_(true)+  {+  }++  ~awaitable_frame()+  {+    if (has_executor_)+      u_.executor_.~Executor();+  }++  awaitable<awaitable_thread_entry_point, Executor> get_return_object()+  {+    this->coro_ = coroutine_handle<awaitable_frame>::from_promise(*this);+    return awaitable<awaitable_thread_entry_point, Executor>(this);+  };++  void return_void()+  {+  }++  void get()+  {+    this->caller_ = nullptr;+    this->rethrow_exception();+  }++private:+  template <typename> friend class awaitable_frame_base;+  template <typename, typename> friend class awaitable_async_op_handler;+  template <typename, typename> friend class awaitable_handler_base;+  template <typename> friend class awaitable_thread;++  union u+  {+    u() {}+    ~u() {}+    char c_;+    Executor executor_;+  } u_;++  awaitable_frame_base<Executor>* top_of_stack_;+  asio::cancellation_slot parent_cancellation_slot_;+  asio::cancellation_state cancellation_state_;+  bool has_executor_;+  bool has_context_switched_;+  bool throw_if_cancelled_;+};++template <typename Executor> class awaitable_thread { public:   typedef Executor executor_type;+  typedef cancellation_slot cancellation_slot_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)+  awaitable_thread(awaitable<awaitable_thread_entry_point, Executor> p,+      const Executor& ex, cancellation_slot parent_cancel_slot,+      cancellation_state cancel_state)+    : bottom_of_stack_(std::move(p))   {+    bottom_of_stack_.frame_->top_of_stack_ = bottom_of_stack_.frame_;+    new (&bottom_of_stack_.frame_->u_.executor_) Executor(ex);+    bottom_of_stack_.frame_->has_executor_ = true;+    bottom_of_stack_.frame_->parent_cancellation_slot_ = parent_cancel_slot;+    bottom_of_stack_.frame_->cancellation_state_ = cancel_state;   }    // 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_))+    : bottom_of_stack_(std::move(other.bottom_of_stack_))   {   } @@ -360,23 +686,74 @@     if (bottom_of_stack_.valid())     {       // Coroutine "stack unwinding" must be performed through the executor.-      (post)(executor_,+      auto* bottom_frame = bottom_of_stack_.frame_;+      (post)(bottom_frame->u_.executor_,           [a = std::move(bottom_of_stack_)]() mutable           {-            awaitable<void, Executor>(std::move(a));+            (void)awaitable<awaitable_thread_entry_point, Executor>(+                std::move(a));           });     }   } +  awaitable_frame<awaitable_thread_entry_point, Executor>* entry_point()+  {+    return bottom_of_stack_.frame_;+  }+   executor_type get_executor() const noexcept   {-    return executor_;+    return bottom_of_stack_.frame_->u_.executor_;   } +  cancellation_state get_cancellation_state() const noexcept+  {+    return bottom_of_stack_.frame_->cancellation_state_;+  }++  void reset_cancellation_state()+  {+    bottom_of_stack_.frame_->cancellation_state_ =+      cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_);+  }++  template <typename Filter>+  void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter)+  {+    bottom_of_stack_.frame_->cancellation_state_ =+      cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_,+        ASIO_MOVE_CAST(Filter)(filter));+  }++  template <typename InFilter, typename OutFilter>+  void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter,+      ASIO_MOVE_ARG(OutFilter) out_filter)+  {+    bottom_of_stack_.frame_->cancellation_state_ =+      cancellation_state(bottom_of_stack_.frame_->parent_cancellation_slot_,+        ASIO_MOVE_CAST(InFilter)(in_filter),+        ASIO_MOVE_CAST(OutFilter)(out_filter));+  }++  bool throw_if_cancelled() const+  {+    return bottom_of_stack_.frame_->throw_if_cancelled_;+  }++  void throw_if_cancelled(bool value)+  {+    bottom_of_stack_.frame_->throw_if_cancelled_ = value;+  }++  cancellation_slot_type get_cancellation_slot() const noexcept+  {+    return bottom_of_stack_.frame_->cancellation_state_.slot();+  }+   // Launch a new thread of execution.   void launch()   {-    top_of_stack_->attach_thread(this);+    bottom_of_stack_.frame_->top_of_stack_->attach_thread(this);     pump();   } @@ -387,17 +764,399 @@   // has been transferred to another resumable_thread object.   void pump()   {-    do top_of_stack_->resume(); while (top_of_stack_);-    if (bottom_of_stack_.valid())+    do+      bottom_of_stack_.frame_->top_of_stack_->resume();+    while (bottom_of_stack_.frame_ && bottom_of_stack_.frame_->top_of_stack_);++    if (bottom_of_stack_.frame_)     {-      awaitable<void, Executor> a(std::move(bottom_of_stack_));+      awaitable<awaitable_thread_entry_point, 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_;+  awaitable<awaitable_thread_entry_point, Executor> bottom_of_stack_;+};++template <typename Signature, typename Executor>+class awaitable_async_op_handler;++template <typename R, typename Executor>+class awaitable_async_op_handler<R(), Executor>+  : public awaitable_thread<Executor>+{+public:+  struct result_type {};++  awaitable_async_op_handler(+      awaitable_thread<Executor>* h, result_type&)+    : awaitable_thread<Executor>(std::move(*h))+  {+  }++  void operator()()+  {+    this->entry_point()->top_of_stack_->attach_thread(this);+    this->entry_point()->top_of_stack_->clear_cancellation_slot();+    this->pump();+  }++  static void resume(result_type&)+  {+  }+};++template <typename R, typename Executor>+class awaitable_async_op_handler<R(asio::error_code), Executor>+  : public awaitable_thread<Executor>+{+public:+  typedef asio::error_code* result_type;++  awaitable_async_op_handler(+      awaitable_thread<Executor>* h, result_type& result)+    : awaitable_thread<Executor>(std::move(*h)),+      result_(result)+  {+  }++  void operator()(asio::error_code ec)+  {+    result_ = &ec;+    this->entry_point()->top_of_stack_->attach_thread(this);+    this->entry_point()->top_of_stack_->clear_cancellation_slot();+    this->pump();+  }++  static void resume(result_type& result)+  {+    throw_error(*result);+  }++private:+  result_type& result_;+};++template <typename R, typename Executor>+class awaitable_async_op_handler<R(std::exception_ptr), Executor>+  : public awaitable_thread<Executor>+{+public:+  typedef std::exception_ptr* result_type;++  awaitable_async_op_handler(+      awaitable_thread<Executor>* h, result_type& result)+    : awaitable_thread<Executor>(std::move(*h)),+      result_(result)+  {+  }++  void operator()(std::exception_ptr ex)+  {+    result_ = &ex;+    this->entry_point()->top_of_stack_->attach_thread(this);+    this->entry_point()->top_of_stack_->clear_cancellation_slot();+    this->pump();+  }++  static void resume(result_type& result)+  {+    if (*result)+    {+      std::exception_ptr ex = std::exchange(*result, nullptr);+      std::rethrow_exception(ex);+    }+  }++private:+  result_type& result_;+};++template <typename R, typename T, typename Executor>+class awaitable_async_op_handler<R(T), Executor>+  : public awaitable_thread<Executor>+{+public:+  typedef T* result_type;++  awaitable_async_op_handler(+      awaitable_thread<Executor>* h, result_type& result)+    : awaitable_thread<Executor>(std::move(*h)),+      result_(result)+  {+  }++  void operator()(T result)+  {+    result_ = &result;+    this->entry_point()->top_of_stack_->attach_thread(this);+    this->entry_point()->top_of_stack_->clear_cancellation_slot();+    this->pump();+  }++  static T resume(result_type& result)+  {+    return std::move(*result);+  }++private:+  result_type& result_;+};++template <typename R, typename T, typename Executor>+class awaitable_async_op_handler<R(asio::error_code, T), Executor>+  : public awaitable_thread<Executor>+{+public:+  struct result_type+  {+    asio::error_code* ec_;+    T* value_;+  };++  awaitable_async_op_handler(+      awaitable_thread<Executor>* h, result_type& result)+    : awaitable_thread<Executor>(std::move(*h)),+      result_(result)+  {+  }++  void operator()(asio::error_code ec, T value)+  {+    result_.ec_ = &ec;+    result_.value_ = &value;+    this->entry_point()->top_of_stack_->attach_thread(this);+    this->entry_point()->top_of_stack_->clear_cancellation_slot();+    this->pump();+  }++  static T resume(result_type& result)+  {+    throw_error(*result.ec_);+    return std::move(*result.value_);+  }++private:+  result_type& result_;+};++template <typename R, typename T, typename Executor>+class awaitable_async_op_handler<R(std::exception_ptr, T), Executor>+  : public awaitable_thread<Executor>+{+public:+  struct result_type+  {+    std::exception_ptr* ex_;+    T* value_;+  };++  awaitable_async_op_handler(+      awaitable_thread<Executor>* h, result_type& result)+    : awaitable_thread<Executor>(std::move(*h)),+      result_(result)+  {+  }++  void operator()(std::exception_ptr ex, T value)+  {+    result_.ex_ = &ex;+    result_.value_ = &value;+    this->entry_point()->top_of_stack_->attach_thread(this);+    this->entry_point()->top_of_stack_->clear_cancellation_slot();+    this->pump();+  }++  static T resume(result_type& result)+  {+    if (*result.ex_)+    {+      std::exception_ptr ex = std::exchange(*result.ex_, nullptr);+      std::rethrow_exception(ex);+    }+    return std::move(*result.value_);+  }++private:+  result_type& result_;+};++template <typename R, typename... Ts, typename Executor>+class awaitable_async_op_handler<R(Ts...), Executor>+  : public awaitable_thread<Executor>+{+public:+  typedef std::tuple<Ts...>* result_type;++  awaitable_async_op_handler(+      awaitable_thread<Executor>* h, result_type& result)+    : awaitable_thread<Executor>(std::move(*h)),+      result_(result)+  {+  }++  template <typename... Args>+  void operator()(Args&&... args)+  {+    std::tuple<Ts...> result(std::forward<Args>(args)...);+    result_ = &result;+    this->entry_point()->top_of_stack_->attach_thread(this);+    this->entry_point()->top_of_stack_->clear_cancellation_slot();+    this->pump();+  }++  static std::tuple<Ts...> resume(result_type& result)+  {+    return std::move(*result);+  }++private:+  result_type& result_;+};++template <typename R, typename... Ts, typename Executor>+class awaitable_async_op_handler<R(asio::error_code, Ts...), Executor>+  : public awaitable_thread<Executor>+{+public:+  struct result_type+  {+    asio::error_code* ec_;+    std::tuple<Ts...>* value_;+  };++  awaitable_async_op_handler(+      awaitable_thread<Executor>* h, result_type& result)+    : awaitable_thread<Executor>(std::move(*h)),+      result_(result)+  {+  }++  template <typename... Args>+  void operator()(asio::error_code ec, Args&&... args)+  {+    result_.ec_ = &ec;+    std::tuple<Ts...> value(std::forward<Args>(args)...);+    result_.value_ = &value;+    this->entry_point()->top_of_stack_->attach_thread(this);+    this->entry_point()->top_of_stack_->clear_cancellation_slot();+    this->pump();+  }++  static std::tuple<Ts...> resume(result_type& result)+  {+    throw_error(*result.ec_);+    return std::move(*result.value_);+  }++private:+  result_type& result_;+};++template <typename R, typename... Ts, typename Executor>+class awaitable_async_op_handler<R(std::exception_ptr, Ts...), Executor>+  : public awaitable_thread<Executor>+{+public:+  struct result_type+  {+    std::exception_ptr* ex_;+    std::tuple<Ts...>* value_;+  };++  awaitable_async_op_handler(+      awaitable_thread<Executor>* h, result_type& result)+    : awaitable_thread<Executor>(std::move(*h)),+      result_(result)+  {+  }++  template <typename... Args>+  void operator()(std::exception_ptr ex, Args&&... args)+  {+    result_.ex_ = &ex;+    std::tuple<Ts...> value(std::forward<Args>(args)...);+    result_.value_ = &value;+    this->entry_point()->top_of_stack_->attach_thread(this);+    this->entry_point()->top_of_stack_->clear_cancellation_slot();+    this->pump();+  }++  static std::tuple<Ts...> resume(result_type& result)+  {+    if (*result.ex_)+    {+      std::exception_ptr ex = std::exchange(*result.ex_, nullptr);+      std::rethrow_exception(ex);+    }+    return std::move(*result.value_);+  }++private:+  result_type& result_;+};++template <typename Signature, typename Op, typename Executor>+class awaitable_async_op+{+public:+  typedef awaitable_async_op_handler<Signature, Executor> handler_type;++  awaitable_async_op(Op&& o, awaitable_frame_base<Executor>* frame+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+      , const detail::source_location& location+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+    )+    : op_(std::forward<Op>(o)),+      frame_(frame),+      result_()+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+    , location_(location)+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+  {+  }++  bool await_ready() const noexcept+  {+    return false;+  }++  void await_suspend(coroutine_handle<void>)+  {+    frame_->after_suspend(+        [](void* arg)+        {+          awaitable_async_op* self = static_cast<awaitable_async_op*>(arg);+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+          ASIO_HANDLER_LOCATION((self->location_.file_name(),+              self->location_.line(), self->location_.function_name()));+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING)+          std::forward<Op&&>(self->op_)(+              handler_type(self->frame_->detach_thread(), self->result_));+        }, this);+  }++  auto await_resume()+  {+    return handler_type::resume(result_);+  }++private:+  Op&& op_;+  awaitable_frame_base<Executor>* frame_;+  typename handler_type::result_type result_;+#if defined(ASIO_ENABLE_HANDLER_TRACKING)+# if defined(ASIO_HAS_SOURCE_LOCATION)+  detail::source_location location_;+# endif // defined(ASIO_HAS_SOURCE_LOCATION)+#endif // defined(ASIO_ENABLE_HANDLER_TRACKING) };  } // namespace detail
link/modules/asio-standalone/asio/include/asio/impl/buffered_read_stream.hpp view
@@ -2,7 +2,7 @@ // impl/buffered_read_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,8 +15,7 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp"@@ -91,7 +90,7 @@         const std::size_t bytes_transferred)     {       storage_.resize(previous_size_ + bytes_transferred);-      handler_(ec, bytes_transferred);+      ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, bytes_transferred);     }    //private:@@ -202,29 +201,27 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename ReadHandler, typename Allocator>-struct associated_allocator<-    detail::buffered_fill_handler<ReadHandler>, Allocator>+template <template <typename, typename> class Associator,+    typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,+    detail::buffered_fill_handler<ReadHandler>,+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  typedef typename associated_allocator<ReadHandler, Allocator>::type type;--  static type get(const detail::buffered_fill_handler<ReadHandler>& h,-      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::buffered_fill_handler<ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::buffered_fill_handler<ReadHandler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -234,10 +231,15 @@ template <     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,       std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler,     void (asio::error_code, std::size_t)) buffered_read_stream<Stream>::async_fill(     ASIO_MOVE_ARG(ReadHandler) handler)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_buffered_fill<Stream> >(),+        handler, declval<detail::buffered_stream_storage*>()))) {   return async_initiate<ReadHandler,     void (asio::error_code, std::size_t)>(@@ -312,14 +314,14 @@       if (ec || storage_.empty())       {         const std::size_t length = 0;-        handler_(ec, length);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(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);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(ec, bytes_copied);       }     } @@ -447,37 +449,30 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename MutableBufferSequence,-    typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename MutableBufferSequence, typename ReadHandler,+    typename DefaultCandidate>+struct associator<Associator,     detail::buffered_read_some_handler<MutableBufferSequence, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::buffered_read_some_handler<+        MutableBufferSequence, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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<+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::buffered_read_some_handler<         MutableBufferSequence, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -487,11 +482,16 @@ template <typename MutableBufferSequence,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,       std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadHandler,     void (asio::error_code, std::size_t)) buffered_read_stream<Stream>::async_read_some(     const MutableBufferSequence& buffers,     ASIO_MOVE_ARG(ReadHandler) handler)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadHandler,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_buffered_read_some<Stream> >(),+        handler, declval<detail::buffered_stream_storage*>(), buffers))) {   return async_initiate<ReadHandler,     void (asio::error_code, std::size_t)>(
link/modules/asio-standalone/asio/include/asio/impl/buffered_write_stream.hpp view
@@ -2,7 +2,7 @@ // impl/buffered_write_stream.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,8 +15,7 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp" #include "asio/detail/handler_invoke_helpers.hpp"@@ -77,7 +76,7 @@         const std::size_t bytes_written)     {       storage_.consume(bytes_written);-      handler_(ec, bytes_written);+      ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_written);     }    //private:@@ -182,29 +181,27 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename WriteHandler, typename Allocator>-struct associated_allocator<-    detail::buffered_flush_handler<WriteHandler>, Allocator>+template <template <typename, typename> class Associator,+    typename WriteHandler, typename DefaultCandidate>+struct associator<Associator,+    detail::buffered_flush_handler<WriteHandler>,+    DefaultCandidate>+  : Associator<WriteHandler, DefaultCandidate> {-  typedef typename associated_allocator<WriteHandler, Allocator>::type type;--  static type get(const detail::buffered_flush_handler<WriteHandler>& h,-      const Allocator& a = Allocator()) ASIO_NOEXCEPT+  static typename Associator<WriteHandler, DefaultCandidate>::type+  get(const detail::buffered_flush_handler<WriteHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);   }-}; -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+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<WriteHandler, DefaultCandidate>::type)+  get(const detail::buffered_flush_handler<WriteHandler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -214,10 +211,15 @@ template <     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,       std::size_t)) WriteHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler,     void (asio::error_code, std::size_t)) buffered_write_stream<Stream>::async_flush(     ASIO_MOVE_ARG(WriteHandler) handler)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_buffered_flush<Stream> >(),+        handler, declval<detail::buffered_stream_storage*>()))) {   return async_initiate<WriteHandler,     void (asio::error_code, std::size_t)>(@@ -292,7 +294,7 @@       if (ec)       {         const std::size_t length = 0;-        handler_(ec, length);+        ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, length);       }       else       {@@ -305,7 +307,7 @@         storage_.resize(orig_size + length);         const std::size_t bytes_copied = asio::buffer_copy(             storage_.data() + orig_size, buffers_, length);-        handler_(ec, bytes_copied);+        ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_copied);       }     } @@ -433,37 +435,30 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename ConstBufferSequence,-    typename WriteHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename ConstBufferSequence, typename WriteHandler,+    typename DefaultCandidate>+struct associator<Associator,     detail::buffered_write_some_handler<ConstBufferSequence, WriteHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<WriteHandler, DefaultCandidate> {-  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+  static typename Associator<WriteHandler, DefaultCandidate>::type+  get(const detail::buffered_write_some_handler<+        ConstBufferSequence, WriteHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);   }-}; -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<+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<WriteHandler, DefaultCandidate>::type)+  get(const detail::buffered_write_some_handler<         ConstBufferSequence, WriteHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -473,11 +468,16 @@ template <typename ConstBufferSequence,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,       std::size_t)) WriteHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteHandler,     void (asio::error_code, std::size_t)) buffered_write_stream<Stream>::async_write_some(     const ConstBufferSequence& buffers,     ASIO_MOVE_ARG(WriteHandler) handler)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteHandler,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_buffered_write_some<Stream> >(),+        handler, declval<detail::buffered_stream_storage*>(), buffers))) {   return async_initiate<WriteHandler,     void (asio::error_code, std::size_t)>(
+ link/modules/asio-standalone/asio/include/asio/impl/cancellation_signal.ipp view
@@ -0,0 +1,96 @@+//+// impl/cancellation_signal.ipp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_CANCELLATION_SIGNAL_IPP+#define ASIO_IMPL_CANCELLATION_SIGNAL_IPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include "asio/cancellation_signal.hpp"+#include "asio/detail/thread_context.hpp"+#include "asio/detail/thread_info_base.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++cancellation_signal::~cancellation_signal()+{+  if (handler_)+  {+    std::pair<void*, std::size_t> mem = handler_->destroy();+    detail::thread_info_base::deallocate(+        detail::thread_info_base::cancellation_signal_tag(),+        detail::thread_context::top_of_thread_call_stack(),+        mem.first, mem.second);+  }+}++void cancellation_slot::clear()+{+  if (handler_ != 0 && *handler_ != 0)+  {+    std::pair<void*, std::size_t> mem = (*handler_)->destroy();+    detail::thread_info_base::deallocate(+        detail::thread_info_base::cancellation_signal_tag(),+        detail::thread_context::top_of_thread_call_stack(),+        mem.first, mem.second);+    *handler_ = 0;+  }+}++std::pair<void*, std::size_t> cancellation_slot::prepare_memory(+    std::size_t size, std::size_t align)+{+  assert(handler_);+  std::pair<void*, std::size_t> mem;+  if (*handler_)+  {+    mem = (*handler_)->destroy();+    *handler_ = 0;+  }+  if (size > mem.second+      || reinterpret_cast<std::size_t>(mem.first) % align != 0)+  {+    if (mem.first)+    {+      detail::thread_info_base::deallocate(+          detail::thread_info_base::cancellation_signal_tag(),+          detail::thread_context::top_of_thread_call_stack(),+          mem.first, mem.second);+    }+    mem.first = detail::thread_info_base::allocate(+        detail::thread_info_base::cancellation_signal_tag(),+        detail::thread_context::top_of_thread_call_stack(),+        size, align);+    mem.second = size;+  }+  return mem;+}++cancellation_slot::auto_delete_helper::~auto_delete_helper()+{+  if (mem.first)+  {+    detail::thread_info_base::deallocate(+        detail::thread_info_base::cancellation_signal_tag(),+        detail::thread_context::top_of_thread_call_stack(),+        mem.first, mem.second);+  }+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_CANCELLATION_SIGNAL_IPP
link/modules/asio-standalone/asio/include/asio/impl/co_spawn.hpp view
@@ -2,7 +2,7 @@ // impl/co_spawn.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"+#include "asio/associated_cancellation_slot.hpp" #include "asio/awaitable.hpp" #include "asio/dispatch.hpp" #include "asio/execution/outstanding_work.hpp"@@ -76,16 +77,18 @@ }  template <typename T, typename Executor, typename F, typename Handler>-awaitable<void, Executor> co_spawn_entry_point(+awaitable<awaitable_thread_entry_point, 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>{});+  (void) co_await (dispatch)(+      use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"}); +  (co_await awaitable_thread_has_context_switched{}) = false;+  std::exception_ptr e = nullptr;   bool done = false;   try   {@@ -93,36 +96,56 @@      done = true; +    bool switched = (co_await awaitable_thread_has_context_switched{});+    if (!switched)+    {+      (void) co_await (post)(+          use_awaitable_t<Executor>{__FILE__,+            __LINE__, "co_spawn_entry_point"});+    }+     (dispatch)(handler_work.get_executor(),         [handler = std::move(handler), t = std::move(t)]() mutable         {-          handler(std::exception_ptr(), std::move(t));+          std::move(handler)(std::exception_ptr(), std::move(t));         });++    co_return;   }   catch (...)   {     if (done)       throw; -    (dispatch)(handler_work.get_executor(),-        [handler = std::move(handler), e = std::current_exception()]() mutable-        {-          handler(e, T());-        });+    e = std::current_exception();   }++  bool switched = (co_await awaitable_thread_has_context_switched{});+  if (!switched)+  {+    (void) co_await (post)(+        use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"});+  }++  (dispatch)(handler_work.get_executor(),+      [handler = std::move(handler), e]() mutable+      {+        std::move(handler)(e, T());+      }); }  template <typename Executor, typename F, typename Handler>-awaitable<void, Executor> co_spawn_entry_point(+awaitable<awaitable_thread_entry_point, 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(),+  (void) co_await (dispatch)(       use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"}); +  (co_await awaitable_thread_has_context_switched{}) = false;   std::exception_ptr e = nullptr;   try   {@@ -133,10 +156,17 @@     e = std::current_exception();   } +  bool switched = (co_await awaitable_thread_has_context_switched{});+  if (!switched)+  {+    (void) co_await (post)(+        use_awaitable_t<Executor>{__FILE__, __LINE__, "co_spawn_entry_point"});+  }+   (dispatch)(handler_work.get_executor(),       [handler = std::move(handler), e]() mutable       {-        handler(e);+        std::move(handler)(e);       }); } @@ -158,6 +188,61 @@   awaitable<T, Executor> awaitable_; }; +template <typename Handler, typename Executor, typename = void>+class co_spawn_cancellation_handler+{+public:+  co_spawn_cancellation_handler(const Handler&, const Executor& ex)+    : ex_(ex)+  {+  }++  cancellation_slot slot()+  {+    return signal_.slot();+  }++  void operator()(cancellation_type_t type)+  {+    cancellation_signal* sig = &signal_;+    asio::dispatch(ex_, [sig, type]{ sig->emit(type); });+  }++private:+  cancellation_signal signal_;+  Executor ex_;+};+++template <typename Handler, typename Executor>+class co_spawn_cancellation_handler<Handler, Executor,+    typename enable_if<+      is_same<+        typename associated_executor<Handler,+          Executor>::asio_associated_executor_is_unspecialised,+        void+      >::value+    >::type>+{+public:+  co_spawn_cancellation_handler(const Handler&, const Executor&)+  {+  }++  cancellation_slot slot()+  {+    return signal_.slot();+  }++  void operator()(cancellation_type_t type)+  {+    signal_.emit(type);+  }++private:+  cancellation_signal signal_;+};+ template <typename Executor> class initiate_co_spawn {@@ -179,10 +264,26 @@   void operator()(Handler&& handler, F&& f) const   {     typedef typename result_of<F()>::type awaitable_type;+    typedef typename decay<Handler>::type handler_type;+    typedef co_spawn_cancellation_handler<+      handler_type, Executor> cancel_handler_type; +    auto slot = asio::get_associated_cancellation_slot(handler);+    cancel_handler_type* cancel_handler = slot.is_connected()+      ? &slot.template emplace<cancel_handler_type>(handler, ex_)+      : nullptr;++    cancellation_slot proxy_slot(+        cancel_handler+          ? cancel_handler->slot()+          : cancellation_slot());++    cancellation_state cancel_state(proxy_slot);+     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();+    awaitable_handler<executor_type, void>(std::move(a),+        ex_, proxy_slot, cancel_state).launch();   }  private:@@ -198,10 +299,10 @@     CompletionToken, void(std::exception_ptr, T)) co_spawn(const Executor& ex,     awaitable<T, AwaitableExecutor> a, CompletionToken&& token,-    typename enable_if<+    typename constraint<       (is_executor<Executor>::value || execution::is_executor<Executor>::value)         && is_convertible<Executor, AwaitableExecutor>::value-    >::type*)+    >::type) {   return async_initiate<CompletionToken, void(std::exception_ptr, T)>(       detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)),@@ -215,10 +316,10 @@     CompletionToken, void(std::exception_ptr)) co_spawn(const Executor& ex,     awaitable<void, AwaitableExecutor> a, CompletionToken&& token,-    typename enable_if<+    typename constraint<       (is_executor<Executor>::value || execution::is_executor<Executor>::value)         && is_convertible<Executor, AwaitableExecutor>::value-    >::type*)+    >::type) {   return async_initiate<CompletionToken, void(std::exception_ptr)>(       detail::initiate_co_spawn<AwaitableExecutor>(AwaitableExecutor(ex)),@@ -233,11 +334,11 @@     CompletionToken, void(std::exception_ptr, T)) co_spawn(ExecutionContext& ctx,     awaitable<T, AwaitableExecutor> a, CompletionToken&& token,-    typename enable_if<+    typename constraint<       is_convertible<ExecutionContext&, execution_context&>::value         && is_convertible<typename ExecutionContext::executor_type,           AwaitableExecutor>::value-    >::type*)+    >::type) {   return (co_spawn)(ctx.get_executor(), std::move(a),       std::forward<CompletionToken>(token));@@ -250,11 +351,11 @@     CompletionToken, void(std::exception_ptr)) co_spawn(ExecutionContext& ctx,     awaitable<void, AwaitableExecutor> a, CompletionToken&& token,-    typename enable_if<+    typename constraint<       is_convertible<ExecutionContext&, execution_context&>::value         && is_convertible<typename ExecutionContext::executor_type,           AwaitableExecutor>::value-    >::type*)+    >::type) {   return (co_spawn)(ctx.get_executor(), std::move(a),       std::forward<CompletionToken>(token));@@ -266,9 +367,9 @@ 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<+    typename constraint<       is_executor<Executor>::value || execution::is_executor<Executor>::value-    >::type*)+    >::type) {   return async_initiate<CompletionToken,     typename detail::awaitable_signature<typename result_of<F()>::type>::type>(@@ -283,9 +384,9 @@ 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<+    typename constraint<       is_convertible<ExecutionContext&, execution_context&>::value-    >::type*)+    >::type) {   return (co_spawn)(ctx.get_executor(), std::forward<F>(f),       std::forward<CompletionToken>(token));
− link/modules/asio-standalone/asio/include/asio/impl/compose.hpp
@@ -1,635 +0,0 @@-//-// 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
@@ -2,7 +2,7 @@ // impl/connect.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,8 +16,8 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include <algorithm>-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp"@@ -26,6 +26,7 @@ #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/post.hpp" @@ -73,9 +74,9 @@      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;+        (declval<legacy_connect_condition_helper<T, Iterator> >())(+          declval<const asio::error_code>(),+          declval<const Iterator>()))) != 1;   };    template <typename ConnectCondition, typename Iterator>@@ -105,8 +106,8 @@ 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*)+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type) {   asio::error_code ec;   typename Protocol::endpoint result = connect(s, endpoints, ec);@@ -117,8 +118,8 @@ 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*)+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type) {   return detail::deref_connect_result<Protocol>(       connect(s, endpoints.begin(), endpoints.end(),@@ -128,7 +129,7 @@ #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*)+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type) {   asio::error_code ec;   Iterator result = connect(s, begin, ec);@@ -139,7 +140,7 @@ 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*)+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type) {   return connect(s, begin, Iterator(), detail::default_connect_condition(), ec); }@@ -166,8 +167,8 @@     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*)+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type) {   asio::error_code ec;   typename Protocol::endpoint result = connect(@@ -181,8 +182,8 @@ 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*)+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type) {   return detail::deref_connect_result<Protocol>(       connect(s, endpoints.begin(), endpoints.end(),@@ -194,7 +195,7 @@     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*)+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type) {   asio::error_code ec;   Iterator result = connect(s, begin, connect_condition, ec);@@ -207,7 +208,7 @@ 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*)+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type) {   return connect(s, begin, Iterator(), connect_condition, ec); }@@ -294,14 +295,18 @@    template <typename Protocol, typename Executor, typename EndpointSequence,       typename ConnectCondition, typename RangeConnectHandler>-  class range_connect_op : base_from_connect_condition<ConnectCondition>+  class range_connect_op+    : public base_from_cancellation_state<RangeConnectHandler>,+      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),+      : base_from_cancellation_state<RangeConnectHandler>(+          handler, enable_partial_cancellation()),+        base_from_connect_condition<ConnectCondition>(connect_condition),         socket_(sock),         endpoints_(endpoints),         index_(0),@@ -312,7 +317,8 @@  #if defined(ASIO_HAS_MOVE)     range_connect_op(const range_connect_op& other)-      : base_from_connect_condition<ConnectCondition>(other),+      : base_from_cancellation_state<RangeConnectHandler>(other),+        base_from_connect_condition<ConnectCondition>(other),         socket_(other.socket_),         endpoints_(other.endpoints_),         index_(other.index_),@@ -322,7 +328,10 @@     }      range_connect_op(range_connect_op&& other)-      : base_from_connect_condition<ConnectCondition>(other),+      : base_from_cancellation_state<RangeConnectHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            RangeConnectHandler>)(other)),+        base_from_connect_condition<ConnectCondition>(other),         socket_(other.socket_),         endpoints_(other.endpoints_),         index_(other.index_),@@ -388,11 +397,18 @@           if (!ec)             break; +          if (this->cancelled() != cancellation_type::none)+          {+            ec = asio::error::operation_aborted;+            break;+          }+           ++iter;           ++index_;         } -        handler_(static_cast<const asio::error_code&>(ec),+        ASIO_MOVE_OR_LVALUE(RangeConnectHandler)(handler_)(+            static_cast<const asio::error_code&>(ec),             static_cast<const typename Protocol::endpoint&>(               ec || iter == end ? typename Protocol::endpoint() : *iter));       }@@ -515,14 +531,18 @@    template <typename Protocol, typename Executor, typename Iterator,       typename ConnectCondition, typename IteratorConnectHandler>-  class iterator_connect_op : base_from_connect_condition<ConnectCondition>+  class iterator_connect_op+    : public base_from_cancellation_state<IteratorConnectHandler>,+      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),+      : base_from_cancellation_state<IteratorConnectHandler>(+          handler, enable_partial_cancellation()),+        base_from_connect_condition<ConnectCondition>(connect_condition),         socket_(sock),         iter_(begin),         end_(end),@@ -533,7 +553,8 @@  #if defined(ASIO_HAS_MOVE)     iterator_connect_op(const iterator_connect_op& other)-      : base_from_connect_condition<ConnectCondition>(other),+      : base_from_cancellation_state<IteratorConnectHandler>(other),+        base_from_connect_condition<ConnectCondition>(other),         socket_(other.socket_),         iter_(other.iter_),         end_(other.end_),@@ -543,7 +564,10 @@     }      iterator_connect_op(iterator_connect_op&& other)-      : base_from_connect_condition<ConnectCondition>(other),+      : base_from_cancellation_state<IteratorConnectHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            IteratorConnectHandler>)(other)),+        base_from_connect_condition<ConnectCondition>(other),         socket_(other.socket_),         iter_(other.iter_),         end_(other.end_),@@ -595,10 +619,17 @@           if (!ec)             break; +          if (this->cancelled() != cancellation_type::none)+          {+            ec = asio::error::operation_aborted;+            break;+          }+           ++iter_;         } -        handler_(static_cast<const asio::error_code&>(ec),+        ASIO_MOVE_OR_LVALUE(IteratorConnectHandler)(handler_)(+            static_cast<const asio::error_code&>(ec),             static_cast<const Iterator&>(iter_));       }     }@@ -723,86 +754,66 @@  #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>+template <template <typename, typename> class Associator,+    typename Protocol, typename Executor, typename EndpointSequence,+    typename ConnectCondition, typename RangeConnectHandler,+    typename DefaultCandidate>+struct associator<Associator,+    detail::range_connect_op<Protocol, Executor,+      EndpointSequence, ConnectCondition, RangeConnectHandler>,+    DefaultCandidate>+  : Associator<RangeConnectHandler, DefaultCandidate> {-  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+  static typename Associator<RangeConnectHandler, DefaultCandidate>::type+  get(const detail::range_connect_op<Protocol, Executor, EndpointSequence,+        ConnectCondition, RangeConnectHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<RangeConnectHandler,-        Allocator>::get(h.handler_, a);+    return Associator<RangeConnectHandler, DefaultCandidate>::get(h.handler_);   }-}; -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+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<RangeConnectHandler, DefaultCandidate>::type)+  get(const detail::range_connect_op<Protocol, Executor,+        EndpointSequence, ConnectCondition, RangeConnectHandler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<RangeConnectHandler, DefaultCandidate>::get(+        h.handler_, c)))   {-    return associated_executor<RangeConnectHandler,-        Executor1>::get(h.handler_, ex);+    return Associator<RangeConnectHandler, DefaultCandidate>::get(+        h.handler_, c);   } }; -template <typename Protocol, typename Executor, typename Iterator,+template <template <typename, typename> class Associator,+    typename Protocol, typename Executor, typename Iterator,     typename ConnectCondition, typename IteratorConnectHandler,-    typename Allocator>-struct associated_allocator<+    typename DefaultCandidate>+struct associator<Associator,     detail::iterator_connect_op<Protocol, Executor,       Iterator, ConnectCondition, IteratorConnectHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<IteratorConnectHandler, DefaultCandidate> {-  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+  static typename Associator<IteratorConnectHandler, DefaultCandidate>::type+  get(const detail::iterator_connect_op<Protocol, Executor, Iterator,+        ConnectCondition, IteratorConnectHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<IteratorConnectHandler,-        Allocator>::get(h.handler_, a);+    return Associator<IteratorConnectHandler, DefaultCandidate>::get(+        h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<IteratorConnectHandler, DefaultCandidate>::type)+  get(const detail::iterator_connect_op<Protocol, Executor,         Iterator, ConnectCondition, IteratorConnectHandler>& h,-      const Executor1& ex = Executor1()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<IteratorConnectHandler, DefaultCandidate>::get(+        h.handler_, c)))   {-    return associated_executor<IteratorConnectHandler,-        Executor1>::get(h.handler_, ex);+    return Associator<IteratorConnectHandler, DefaultCandidate>::get(+        h.handler_, c);   } }; @@ -810,103 +821,135 @@  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,+      typename Protocol::endpoint)) RangeConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken,     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*)+    ASIO_MOVE_ARG(RangeConnectToken) token,+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<RangeConnectToken,+      void (asio::error_code, typename Protocol::endpoint)>(+        declval<detail::initiate_async_range_connect<Protocol, Executor> >(),+        token, endpoints, declval<detail::default_connect_condition>()))) {-  return async_initiate<RangeConnectHandler,+  return async_initiate<RangeConnectToken,     void (asio::error_code, typename Protocol::endpoint)>(       detail::initiate_async_range_connect<Protocol, Executor>(s),-      handler, endpoints, detail::default_connect_condition());+      token, 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,+      Iterator)) IteratorConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,     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*)+    ASIO_MOVE_ARG(IteratorConnectToken) token,+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<IteratorConnectToken,+      void (asio::error_code, Iterator)>(+        declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+        token, begin, Iterator(),+        declval<detail::default_connect_condition>()))) {-  return async_initiate<IteratorConnectHandler,+  return async_initiate<IteratorConnectToken,     void (asio::error_code, Iterator)>(       detail::initiate_async_iterator_connect<Protocol, Executor>(s),-      handler, begin, Iterator(), detail::default_connect_condition());+      token, 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,+      Iterator)) IteratorConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,     void (asio::error_code, Iterator)) async_connect(basic_socket<Protocol, Executor>& s, Iterator begin, Iterator end,-    ASIO_MOVE_ARG(IteratorConnectHandler) handler)+    ASIO_MOVE_ARG(IteratorConnectToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<IteratorConnectToken,+      void (asio::error_code, Iterator)>(+        declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+        token, begin, end, declval<detail::default_connect_condition>()))) {-  return async_initiate<IteratorConnectHandler,+  return async_initiate<IteratorConnectToken,     void (asio::error_code, Iterator)>(       detail::initiate_async_iterator_connect<Protocol, Executor>(s),-      handler, begin, end, detail::default_connect_condition());+      token, 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,+      typename Protocol::endpoint)) RangeConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(RangeConnectToken,     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*)+    ASIO_MOVE_ARG(RangeConnectToken) token,+    typename constraint<is_endpoint_sequence<+        EndpointSequence>::value>::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<RangeConnectToken,+      void (asio::error_code, typename Protocol::endpoint)>(+        declval<detail::initiate_async_range_connect<Protocol, Executor> >(),+        token, endpoints, connect_condition))) {-  return async_initiate<RangeConnectHandler,+  return async_initiate<RangeConnectToken,     void (asio::error_code, typename Protocol::endpoint)>(       detail::initiate_async_range_connect<Protocol, Executor>(s),-      handler, endpoints, connect_condition);+      token, 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,+      Iterator)) IteratorConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,     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*)+    ASIO_MOVE_ARG(IteratorConnectToken) token,+    typename constraint<!is_endpoint_sequence<Iterator>::value>::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<IteratorConnectToken,+      void (asio::error_code, Iterator)>(+        declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+        token, begin, Iterator(), connect_condition))) {-  return async_initiate<IteratorConnectHandler,+  return async_initiate<IteratorConnectToken,     void (asio::error_code, Iterator)>(       detail::initiate_async_iterator_connect<Protocol, Executor>(s),-      handler, begin, Iterator(), connect_condition);+      token, 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,+      Iterator)) IteratorConnectToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(IteratorConnectToken,     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_MOVE_ARG(IteratorConnectToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<IteratorConnectToken,+      void (asio::error_code, Iterator)>(+        declval<detail::initiate_async_iterator_connect<Protocol, Executor> >(),+        token, begin, end, connect_condition))) {-  return async_initiate<IteratorConnectHandler,+  return async_initiate<IteratorConnectToken,     void (asio::error_code, Iterator)>(       detail::initiate_async_iterator_connect<Protocol, Executor>(s),-      handler, begin, end, connect_condition);+      token, begin, end, connect_condition); }  } // namespace asio
+ link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.hpp view
@@ -0,0 +1,73 @@+//+// impl/connect_pipe.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_PIPE_HPP+#define ASIO_IMPL_CONNECT_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE)++#include "asio/connect_pipe.hpp"+#include "asio/detail/throw_error.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++template <typename Executor1, typename Executor2>+void connect_pipe(basic_readable_pipe<Executor1>& read_end,+    basic_writable_pipe<Executor2>& write_end)+{+  asio::error_code ec;+  asio::connect_pipe(read_end, write_end, ec);+  asio::detail::throw_error(ec, "connect_pipe");+}++template <typename Executor1, typename Executor2>+ASIO_SYNC_OP_VOID connect_pipe(basic_readable_pipe<Executor1>& read_end,+    basic_writable_pipe<Executor2>& write_end, asio::error_code& ec)+{+  detail::native_pipe_handle p[2];+  detail::create_pipe(p, ec);+  if (ec)+    ASIO_SYNC_OP_VOID_RETURN(ec);++  read_end.assign(p[0], ec);+  if (ec)+  {+    detail::close_pipe(p[0]);+    detail::close_pipe(p[1]);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  write_end.assign(p[1], ec);+  if (ec)+  {+    asio::error_code temp_ec;+    read_end.close(temp_ec);+    detail::close_pipe(p[1]);+    ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  ASIO_SYNC_OP_VOID_RETURN(ec);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PIPE)++#endif // ASIO_IMPL_CONNECT_PIPE_HPP
+ link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.ipp view
@@ -0,0 +1,149 @@+//+// impl/connect_pipe.ipp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2021 Klemens D. Morgenstern+//                    (klemens dot morgenstern at gmx dot net)+//+// Distributed under the Boost Software 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_PIPE_IPP+#define ASIO_IMPL_CONNECT_PIPE_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_PIPE)++#include "asio/connect_pipe.hpp"++#if defined(ASIO_HAS_IOCP)+# include <cstdio>+# if _WIN32_WINNT >= 0x601+#  include <bcrypt.h>+#  if !defined(ASIO_NO_DEFAULT_LINKED_LIBS)+#   if defined(_MSC_VER)+#    pragma comment(lib, "bcrypt.lib")+#   endif // defined(_MSC_VER)+#  endif // !defined(ASIO_NO_DEFAULT_LINKED_LIBS)+# endif // _WIN32_WINNT >= 0x601+#else // defined(ASIO_HAS_IOCP)+# include "asio/detail/descriptor_ops.hpp"+#endif // defined(ASIO_HAS_IOCP)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++void create_pipe(native_pipe_handle p[2], asio::error_code& ec)+{+#if defined(ASIO_HAS_IOCP)+  using namespace std; // For sprintf and memcmp.++  static long counter1 = 0;+  static long counter2 = 0;++  long n1 = ::InterlockedIncrement(&counter1);+  long n2 = (static_cast<unsigned long>(n1) % 0x10000000) == 0+    ? ::InterlockedIncrement(&counter2)+    : ::InterlockedExchangeAdd(&counter2, 0);++  wchar_t pipe_name[128];+#if defined(ASIO_HAS_SECURE_RTL)+  swprintf_s(+#else // defined(ASIO_HAS_SECURE_RTL)+  _snwprintf(+#endif // defined(ASIO_HAS_SECURE_RTL)+      pipe_name, 128,+      L"\\\\.\\pipe\\asio-A0812896-741A-484D-AF23-BE51BF620E22-%u-%ld-%ld",+      static_cast<unsigned int>(::GetCurrentProcessId()), n1, n2);++  p[0] = ::CreateNamedPipeW(pipe_name,+      PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,+      0, 1, 8192, 8192, 0, 0);++  if (p[0] == INVALID_HANDLE_VALUE)+  {+    DWORD last_error = ::GetLastError();+    ec.assign(last_error, asio::error::get_system_category());+    return;+  }++  p[1] = ::CreateFileW(pipe_name, GENERIC_WRITE, 0,+    0, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);++  if (p[1] == INVALID_HANDLE_VALUE)+  {+    DWORD last_error = ::GetLastError();+    ::CloseHandle(p[0]);+    ec.assign(last_error, asio::error::get_system_category());+    return;+  }++# if _WIN32_WINNT >= 0x601+  unsigned char nonce[16];+  if (::BCryptGenRandom(0, nonce, sizeof(nonce),+        BCRYPT_USE_SYSTEM_PREFERRED_RNG) != 0)+  {+    ec = asio::error::connection_aborted;+    ::CloseHandle(p[0]);+    ::CloseHandle(p[1]);+    return;+  }++  DWORD bytes_written = 0;+  BOOL ok = ::WriteFile(p[1], nonce, sizeof(nonce), &bytes_written, 0);+  if (!ok || bytes_written != sizeof(nonce))+  {+    ec = asio::error::connection_aborted;+    ::CloseHandle(p[0]);+    ::CloseHandle(p[1]);+    return;+  }++  unsigned char nonce_check[sizeof(nonce)];+  DWORD bytes_read = 0;+  ok = ::ReadFile(p[0], nonce_check, sizeof(nonce), &bytes_read, 0);+  if (!ok || bytes_read != sizeof(nonce)+      || memcmp(nonce, nonce_check, sizeof(nonce)) != 0)+  {+    ec = asio::error::connection_aborted;+    ::CloseHandle(p[0]);+    ::CloseHandle(p[1]);+    return;+  }+#endif // _WIN32_WINNT >= 0x601++  asio::error::clear(ec);+#else // defined(ASIO_HAS_IOCP)+  int result = ::pipe(p);+  detail::descriptor_ops::get_last_error(ec, result != 0);+#endif // defined(ASIO_HAS_IOCP)+}++void close_pipe(native_pipe_handle p)+{+#if defined(ASIO_HAS_IOCP)+  ::CloseHandle(p);+#else // defined(ASIO_HAS_IOCP)+  asio::error_code ignored_ec;+  detail::descriptor_ops::state_type state = 0;+  detail::descriptor_ops::close(p, state, ignored_ec);+#endif // defined(ASIO_HAS_IOCP)+}++} // namespace detail+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_PIPE)++#endif // ASIO_IMPL_CONNECT_PIPE_IPP
+ link/modules/asio-standalone/asio/include/asio/impl/consign.hpp view
@@ -0,0 +1,202 @@+//+// impl/consign.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_CONSIGN_HPP+#define ASIO_IMPL_CONSIGN_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/associator.hpp"+#include "asio/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/utility.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Class to adapt a consign_t as a completion handler.+template <typename Handler, typename... Values>+class consign_handler+{+public:+  typedef void result_type;++  template <typename H>+  consign_handler(ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values)+    : handler_(ASIO_MOVE_CAST(H)(handler)),+      values_(ASIO_MOVE_CAST(std::tuple<Values...>)(values))+  {+  }++  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)... args)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        ASIO_MOVE_CAST(Args)(args)...);+  }++//private:+  Handler handler_;+  std::tuple<Values...> values_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    consign_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,+    consign_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(+    consign_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,+    consign_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,+    consign_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)+}++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename... Values, typename... Signatures>+struct async_result<+    consign_t<CompletionToken, Values...>, Signatures...>+  : async_result<CompletionToken, Signatures...>+{+  template <typename Initiation>+  struct init_wrapper+  {+    init_wrapper(Initiation init)+      : initiation_(ASIO_MOVE_CAST(Initiation)(init))+    {+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        std::tuple<Values...> values,+        ASIO_MOVE_ARG(Args)... args)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          detail::consign_handler<+            typename decay<Handler>::type, Values...>(+              ASIO_MOVE_CAST(Handler)(handler),+              ASIO_MOVE_CAST(std::tuple<Values...>)(values)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    Initiation initiation_;+  };++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, Signatures...,+      (async_initiate<CompletionToken, Signatures...>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<CompletionToken&>(),+        declval<std::tuple<Values...> >(),+        declval<ASIO_MOVE_ARG(Args)>()...)))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+  {+    return async_initiate<CompletionToken, Signatures...>(+        init_wrapper<typename decay<Initiation>::type>(+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.token_,+        ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_),+        ASIO_MOVE_CAST(Args)(args)...);+  }+};++template <template <typename, typename> class Associator,+    typename Handler, typename... Values, typename DefaultCandidate>+struct associator<Associator,+    detail::consign_handler<Handler, Values...>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::consign_handler<Handler, Values...>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::consign_handler<Handler, Values...>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_CONSIGN_HPP
− link/modules/asio-standalone/asio/include/asio/impl/defer.hpp
@@ -1,248 +0,0 @@-//-// 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/deferred.hpp view
@@ -0,0 +1,156 @@+//+// impl/deferred.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_DEFERRED_HPP+#define ASIO_IMPL_DEFERRED_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 {++#if !defined(GENERATING_DOCUMENTATION)++template <typename Signature>+class async_result<deferred_t, Signature>+{+public:+  template <typename Initiation, typename... InitArgs>+  static deferred_async_operation<Signature, Initiation, InitArgs...>+  initiate(ASIO_MOVE_ARG(Initiation) initiation,+      deferred_t, ASIO_MOVE_ARG(InitArgs)... args)+  {+    return deferred_async_operation<+        Signature, Initiation, InitArgs...>(+          deferred_init_tag{},+          ASIO_MOVE_CAST(Initiation)(initiation),+          ASIO_MOVE_CAST(InitArgs)(args)...);+    }+};++template <typename... Signatures>+class async_result<deferred_t, Signatures...>+{+public:+  template <typename Initiation, typename... InitArgs>+  static deferred_async_operation<+      deferred_signatures<Signatures...>, Initiation, InitArgs...>+  initiate(ASIO_MOVE_ARG(Initiation) initiation,+      deferred_t, ASIO_MOVE_ARG(InitArgs)... args)+  {+    return deferred_async_operation<+        deferred_signatures<Signatures...>, Initiation, InitArgs...>(+          deferred_init_tag{},+          ASIO_MOVE_CAST(Initiation)(initiation),+          ASIO_MOVE_CAST(InitArgs)(args)...);+    }+};++template <typename Function, typename Signature>+class async_result<deferred_function<Function>, Signature>+{+public:+  template <typename Initiation, typename... InitArgs>+  static auto initiate(ASIO_MOVE_ARG(Initiation) initiation,+      deferred_function<Function> token,+      ASIO_MOVE_ARG(InitArgs)... init_args)+    -> decltype(+        deferred_sequence<+          deferred_async_operation<+            Signature, Initiation, InitArgs...>,+          Function>(deferred_init_tag{},+            deferred_async_operation<+              Signature, Initiation, InitArgs...>(+                deferred_init_tag{},+                ASIO_MOVE_CAST(Initiation)(initiation),+                ASIO_MOVE_CAST(InitArgs)(init_args)...),+            ASIO_MOVE_CAST(Function)(token.function_)))+  {+    return deferred_sequence<+        deferred_async_operation<+          Signature, Initiation, InitArgs...>,+        Function>(deferred_init_tag{},+          deferred_async_operation<+            Signature, Initiation, InitArgs...>(+              deferred_init_tag{},+              ASIO_MOVE_CAST(Initiation)(initiation),+              ASIO_MOVE_CAST(InitArgs)(init_args)...),+          ASIO_MOVE_CAST(Function)(token.function_));+  }+};++template <typename Function, typename... Signatures>+class async_result<deferred_function<Function>, Signatures...>+{+public:+  template <typename Initiation, typename... InitArgs>+  static auto initiate(ASIO_MOVE_ARG(Initiation) initiation,+      deferred_function<Function> token,+      ASIO_MOVE_ARG(InitArgs)... init_args)+    -> decltype(+        deferred_sequence<+          deferred_async_operation<+            deferred_signatures<Signatures...>, Initiation, InitArgs...>,+          Function>(deferred_init_tag{},+            deferred_async_operation<+              deferred_signatures<Signatures...>, Initiation, InitArgs...>(+                deferred_init_tag{},+                ASIO_MOVE_CAST(Initiation)(initiation),+                ASIO_MOVE_CAST(InitArgs)(init_args)...),+            ASIO_MOVE_CAST(Function)(token.function_)))+  {+    return deferred_sequence<+        deferred_async_operation<+          deferred_signatures<Signatures...>, Initiation, InitArgs...>,+        Function>(deferred_init_tag{},+          deferred_async_operation<+            deferred_signatures<Signatures...>, Initiation, InitArgs...>(+              deferred_init_tag{},+              ASIO_MOVE_CAST(Initiation)(initiation),+              ASIO_MOVE_CAST(InitArgs)(init_args)...),+          ASIO_MOVE_CAST(Function)(token.function_));+  }+};++template <template <typename, typename> class Associator,+    typename Handler, typename Tail, typename DefaultCandidate>+struct associator<Associator,+    detail::deferred_sequence_handler<Handler, Tail>,+    DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::deferred_sequence_handler<Handler, Tail>& h)+    ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::deferred_sequence_handler<Handler, Tail>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_DEFERRED_HPP
link/modules/asio-standalone/asio/include/asio/impl/detached.hpp view
@@ -2,7 +2,7 @@ // impl/detached.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
− link/modules/asio-standalone/asio/include/asio/impl/dispatch.hpp
@@ -1,243 +0,0 @@-//-// 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
@@ -2,7 +2,7 @@ // impl/error.ipp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/error_code.ipp view
@@ -2,7 +2,7 @@ // impl/error_code.ipp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/execution_context.hpp view
@@ -2,7 +2,7 @@ // impl/execution_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/execution_context.ipp view
@@ -2,7 +2,7 @@ // impl/execution_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/executor.hpp view
@@ -2,7 +2,7 @@ // impl/executor.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -22,7 +22,6 @@ #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" 
link/modules/asio-standalone/asio/include/asio/impl/executor.ipp view
@@ -2,7 +2,7 @@ // impl/executor.ipp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/handler_alloc_hook.ipp view
@@ -2,7 +2,7 @@ // impl/handler_alloc_hook.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #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/handler_alloc_hook.hpp"@@ -32,9 +33,9 @@   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);+      detail::thread_context::top_of_thread_call_stack(), size); #else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)-  return ::operator new(size);+  return aligned_new(ASIO_DEFAULT_ALIGN, size); #endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) } @@ -47,10 +48,10 @@   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);+      detail::thread_context::top_of_thread_call_stack(), pointer, size); #else // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING)   (void)size;-  ::operator delete(pointer);+  aligned_delete(pointer); #endif // !defined(ASIO_DISABLE_SMALL_BLOCK_RECYCLING) } 
link/modules/asio-standalone/asio/include/asio/impl/io_context.hpp view
@@ -2,7 +2,7 @@ // impl/io_context.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,7 +20,6 @@ #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"@@ -155,8 +154,11 @@ };  template <typename LegacyCompletionHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ()) io_context::dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<LegacyCompletionHandler, void ()>(+        declval<initiate_dispatch>(), handler, this))) {   return async_initiate<LegacyCompletionHandler, void ()>(       initiate_dispatch(), handler, this);@@ -194,8 +196,11 @@ };  template <typename LegacyCompletionHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ()) io_context::post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<LegacyCompletionHandler, void ()>(+        declval<initiate_post>(), handler, this))) {   return async_initiate<LegacyCompletionHandler, void ()>(       initiate_post(), handler, this);@@ -214,21 +219,20 @@  #endif // !defined(ASIO_NO_DEPRECATED) -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t 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_;+    static_cast<Allocator&>(*this) = static_cast<const Allocator&>(other);+    io_context* old_io_context = context_ptr();+    target_ = other.target_;     if (Bits & outstanding_work_tracked)     {-      if (io_context_)-        io_context_->impl_.work_started();+      if (context_ptr())+        context_ptr()->impl_.work_started();       if (old_io_context)         old_io_context->impl_.work_finished();     }@@ -237,31 +241,35 @@ }  #if defined(ASIO_HAS_MOVE)-template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t 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_;+    static_cast<Allocator&>(*this) = static_cast<Allocator&&>(other);+    io_context* old_io_context = context_ptr();+    target_ = other.target_;     if (Bits & outstanding_work_tracked)-      other.io_context_ = 0;+    {+      other.target_ = 0;+      if (old_io_context)+        old_io_context->impl_.work_finished();+    }   }   return *this; } #endif // defined(ASIO_HAS_MOVE) -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> inline bool io_context::basic_executor_type<Allocator,     Bits>::running_in_this_thread() const ASIO_NOEXCEPT {-  return io_context_->impl_.can_dispatch();+  return context_ptr()->impl_.can_dispatch(); } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> template <typename Function> void io_context::basic_executor_type<Allocator, Bits>::execute(     ASIO_MOVE_ARG(Function) f) const@@ -270,7 +278,7 @@    // 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())+  if ((bits() & blocking_never) == 0 && context_ptr()->impl_.can_dispatch())   {     // Make a local, non-const copy of the function.     function_type tmp(ASIO_MOVE_CAST(Function)(f));@@ -289,7 +297,7 @@     }     catch (...)     {-      io_context_->impl_.capture_current_exception();+      context_ptr()->impl_.capture_current_exception();       return;     } #endif // defined(ASIO_HAS_STD_EXCEPTION_PTR)@@ -298,41 +306,43 @@    // 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_);+  typename op::ptr p = {+      detail::addressof(static_cast<const Allocator&>(*this)),+      op::ptr::allocate(static_cast<const Allocator&>(*this)), 0 };+  p.p = new (p.v) op(ASIO_MOVE_CAST(Function)(f),+      static_cast<const Allocator&>(*this)); -  ASIO_HANDLER_CREATION((*io_context_, *p.p,-        "io_context", io_context_, 0, "execute"));+  ASIO_HANDLER_CREATION((*context_ptr(), *p.p,+        "io_context", context_ptr(), 0, "execute")); -  io_context_->impl_.post_immediate_completion(p.p,-      (bits_ & relationship_continuation) != 0);+  context_ptr()->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>+template <typename Allocator, uintptr_t Bits> inline io_context& io_context::basic_executor_type<     Allocator, Bits>::context() const ASIO_NOEXCEPT {-  return *io_context_;+  return *context_ptr(); } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> inline void io_context::basic_executor_type<Allocator,     Bits>::on_work_started() const ASIO_NOEXCEPT {-  io_context_->impl_.work_started();+  context_ptr()->impl_.work_started(); } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> inline void io_context::basic_executor_type<Allocator,     Bits>::on_work_finished() const ASIO_NOEXCEPT {-  io_context_->impl_.work_finished();+  context_ptr()->impl_.work_finished(); } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> template <typename Function, typename OtherAllocator> void io_context::basic_executor_type<Allocator, Bits>::dispatch(     ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const@@ -340,7 +350,7 @@   typedef typename decay<Function>::type function_type;    // Invoke immediately if we are already inside the thread pool.-  if (io_context_->impl_.can_dispatch())+  if (context_ptr()->impl_.can_dispatch())   {     // Make a local, non-const copy of the function.     function_type tmp(ASIO_MOVE_CAST(Function)(f));@@ -356,14 +366,14 @@   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"));+  ASIO_HANDLER_CREATION((*context_ptr(), *p.p,+        "io_context", context_ptr(), 0, "dispatch")); -  io_context_->impl_.post_immediate_completion(p.p, false);+  context_ptr()->impl_.post_immediate_completion(p.p, false);   p.v = p.p = 0; } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> template <typename Function, typename OtherAllocator> void io_context::basic_executor_type<Allocator, Bits>::post(     ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const@@ -376,14 +386,14 @@   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"));+  ASIO_HANDLER_CREATION((*context_ptr(), *p.p,+        "io_context", context_ptr(), 0, "post")); -  io_context_->impl_.post_immediate_completion(p.p, false);+  context_ptr()->impl_.post_immediate_completion(p.p, false);   p.v = p.p = 0; } -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> template <typename Function, typename OtherAllocator> void io_context::basic_executor_type<Allocator, Bits>::defer(     ASIO_MOVE_ARG(Function) f, const OtherAllocator& a) const@@ -396,10 +406,10 @@   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"));+  ASIO_HANDLER_CREATION((*context_ptr(), *p.p,+        "io_context", context_ptr(), 0, "defer")); -  io_context_->impl_.post_immediate_completion(p.p, true);+  context_ptr()->impl_.post_immediate_completion(p.p, true);   p.v = p.p = 0; } #endif // !defined(ASIO_NO_TS_EXECUTORS)
link/modules/asio-standalone/asio/include/asio/impl/io_context.ipp view
@@ -2,7 +2,7 @@ // impl/io_context.ipp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -54,6 +54,7 @@  io_context::~io_context() {+  shutdown(); }  io_context::count_type io_context::run()
link/modules/asio-standalone/asio/include/asio/impl/multiple_exceptions.ipp view
@@ -2,7 +2,7 @@ // impl/multiple_exceptions.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
− link/modules/asio-standalone/asio/include/asio/impl/post.hpp
@@ -1,248 +0,0 @@-//-// 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/prepend.hpp view
@@ -0,0 +1,225 @@+//+// impl/prepend.hpp+// ~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_PREPEND_HPP+#define ASIO_IMPL_PREPEND_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#include "asio/associator.hpp"+#include "asio/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/utility.hpp"+#include "asio/detail/variadic_templates.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++// Class to adapt a prepend_t as a completion handler.+template <typename Handler, typename... Values>+class prepend_handler+{+public:+  typedef void result_type;++  template <typename H>+  prepend_handler(ASIO_MOVE_ARG(H) handler, std::tuple<Values...> values)+    : handler_(ASIO_MOVE_CAST(H)(handler)),+      values_(ASIO_MOVE_CAST(std::tuple<Values...>)(values))+  {+  }++  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)... args)+  {+    this->invoke(+        index_sequence_for<Values...>{},+        ASIO_MOVE_CAST(Args)(args)...);+  }++  template <std::size_t... I, typename... Args>+  void invoke(index_sequence<I...>, ASIO_MOVE_ARG(Args)... args)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        ASIO_MOVE_CAST(Values)(std::get<I>(values_))...,+        ASIO_MOVE_CAST(Args)(args)...);+  }++//private:+  Handler handler_;+  std::tuple<Values...> values_;+};++template <typename Handler>+inline asio_handler_allocate_is_deprecated+asio_handler_allocate(std::size_t size,+    prepend_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,+    prepend_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(+    prepend_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,+    prepend_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,+    prepend_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, typename... Values>+struct prepend_signature;++template <typename R, typename... Args, typename... Values>+struct prepend_signature<R(Args...), Values...>+{+  typedef R type(Values..., typename decay<Args>::type...);+};++} // namespace detail++#if !defined(GENERATING_DOCUMENTATION)++template <typename CompletionToken, typename... Values, typename Signature>+struct async_result<+    prepend_t<CompletionToken, Values...>, Signature>+  : async_result<CompletionToken,+      typename detail::prepend_signature<+        Signature, Values...>::type>+{+  typedef typename detail::prepend_signature<+      Signature, Values...>::type signature;++  template <typename Initiation>+  struct init_wrapper+  {+    init_wrapper(Initiation init)+      : initiation_(ASIO_MOVE_CAST(Initiation)(init))+    {+    }++    template <typename Handler, typename... Args>+    void operator()(+        ASIO_MOVE_ARG(Handler) handler,+        std::tuple<Values...> values,+        ASIO_MOVE_ARG(Args)... args)+    {+      ASIO_MOVE_CAST(Initiation)(initiation_)(+          detail::prepend_handler<+            typename decay<Handler>::type, Values...>(+              ASIO_MOVE_CAST(Handler)(handler),+              ASIO_MOVE_CAST(std::tuple<Values...>)(values)),+          ASIO_MOVE_CAST(Args)(args)...);+    }++    Initiation initiation_;+  };++  template <typename Initiation, typename RawCompletionToken, typename... Args>+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, signature,+      (async_initiate<CompletionToken, signature>(+        declval<init_wrapper<typename decay<Initiation>::type> >(),+        declval<CompletionToken&>(),+        declval<std::tuple<Values...> >(),+        declval<ASIO_MOVE_ARG(Args)>()...)))+  initiate(+      ASIO_MOVE_ARG(Initiation) initiation,+      ASIO_MOVE_ARG(RawCompletionToken) token,+      ASIO_MOVE_ARG(Args)... args)+  {+    return async_initiate<CompletionToken, signature>(+        init_wrapper<typename decay<Initiation>::type>(+          ASIO_MOVE_CAST(Initiation)(initiation)),+        token.token_,+        ASIO_MOVE_CAST(std::tuple<Values...>)(token.values_),+        ASIO_MOVE_CAST(Args)(args)...);+  }+};++template <template <typename, typename> class Associator,+    typename Handler, typename... Values, typename DefaultCandidate>+struct associator<Associator,+    detail::prepend_handler<Handler, Values...>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate>+{+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::prepend_handler<Handler, Values...>& h) ASIO_NOEXCEPT+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_);+  }++  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::prepend_handler<Handler, Values...>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))+  {+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);+  }+};++#endif // !defined(GENERATING_DOCUMENTATION)++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IMPL_PREPEND_HPP
link/modules/asio-standalone/asio/include/asio/impl/read.hpp view
@@ -2,7 +2,7 @@ // impl/read.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,11 +16,10 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include <algorithm>-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp"-#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp"@@ -42,7 +41,7 @@ {   template <typename SyncReadStream, typename MutableBufferSequence,       typename MutableBufferIterator, typename CompletionCondition>-  std::size_t read_buffer_sequence(SyncReadStream& s,+  std::size_t read_buffer_seq(SyncReadStream& s,       const MutableBufferSequence& buffers, const MutableBufferIterator&,       CompletionCondition completion_condition, asio::error_code& ec)   {@@ -57,7 +56,7 @@       else         break;     }-    return tmp.total_consumed();;+    return tmp.total_consumed();   } } // namespace detail @@ -65,20 +64,20 @@     typename CompletionCondition> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type*)+    >::type) {-  return detail::read_buffer_sequence(s, buffers,+  return detail::read_buffer_seq(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<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read(s, buffers, transfer_all(), ec);@@ -89,9 +88,9 @@ template <typename SyncReadStream, typename MutableBufferSequence> inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type*)+    >::type) {   return read(s, buffers, transfer_all(), ec); }@@ -100,9 +99,9 @@     typename CompletionCondition> inline std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read(s, buffers,@@ -118,10 +117,12 @@ std::size_t read(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   typename decay<DynamicBuffer_v1>::type b(       ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -150,10 +151,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v1> inline std::size_t read(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read(s,@@ -166,10 +169,12 @@ inline std::size_t read(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   return read(s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),       transfer_all(), ec);@@ -180,10 +185,12 @@ inline std::size_t read(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read(s,@@ -239,9 +246,9 @@     typename CompletionCondition> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   DynamicBuffer_v2& b = buffers; @@ -271,9 +278,9 @@  template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read(s,@@ -285,9 +292,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   return read(s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),       transfer_all(), ec);@@ -297,9 +304,9 @@     typename CompletionCondition> inline std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read(s,@@ -315,13 +322,15 @@       typename MutableBufferIterator, typename CompletionCondition,       typename ReadHandler>   class read_op-    : detail::base_from_completion_cond<CompletionCondition>+    : public base_from_cancellation_state<ReadHandler>,+      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),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        base_from_completion_cond<CompletionCondition>(completion_condition),         stream_(stream),         buffers_(buffers),         start_(0),@@ -331,7 +340,8 @@  #if defined(ASIO_HAS_MOVE)     read_op(const read_op& other)-      : detail::base_from_completion_cond<CompletionCondition>(other),+      : base_from_cancellation_state<ReadHandler>(other),+        base_from_completion_cond<CompletionCondition>(other),         stream_(other.stream_),         buffers_(other.buffers_),         start_(other.start_),@@ -340,8 +350,11 @@     }      read_op(read_op&& other)-      : detail::base_from_completion_cond<CompletionCondition>(-          ASIO_MOVE_CAST(detail::base_from_completion_cond<+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(base_from_completion_cond<             CompletionCondition>)(other)),         stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)),@@ -351,7 +364,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(asio::error_code ec,         std::size_t bytes_transferred, int start = 0)     {       std::size_t max_size;@@ -359,7 +372,7 @@       {         case 1:         max_size = this->check_for_completion(ec, buffers_.total_consumed());-        do+        for (;;)         {           {             ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read"));@@ -371,9 +384,18 @@           if ((!ec && bytes_transferred == 0) || buffers_.empty())             break;           max_size = this->check_for_completion(ec, buffers_.total_consumed());-        } while (max_size > 0);+          if (max_size == 0)+            break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }+        } -        handler_(ec, buffers_.total_consumed());+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+            static_cast<const asio::error_code&>(ec),+            static_cast<const std::size_t&>(buffers_.total_consumed()));       }     } @@ -464,23 +486,23 @@   template <typename AsyncReadStream, typename MutableBufferSequence,       typename MutableBufferIterator, typename CompletionCondition,       typename ReadHandler>-  inline void start_read_buffer_sequence_op(AsyncReadStream& stream,+  inline void start_read_op(AsyncReadStream& stream,       const MutableBufferSequence& buffers, const MutableBufferIterator&,       CompletionCondition& completion_condition, ReadHandler& handler)   {-    detail::read_op<AsyncReadStream, MutableBufferSequence,+    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+  class initiate_async_read   {   public:     typedef typename AsyncReadStream::executor_type executor_type; -    explicit initiate_async_read_buffer_sequence(AsyncReadStream& stream)+    explicit initiate_async_read(AsyncReadStream& stream)       : stream_(stream)     {     }@@ -502,7 +524,7 @@        non_const_lvalue<ReadHandler> handler2(handler);       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);-      start_read_buffer_sequence_op(stream_, buffers,+      start_read_op(stream_, buffers,           asio::buffer_sequence_begin(buffers),           completion_cond2.value, handler2.value);     }@@ -514,42 +536,33 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename MutableBufferSequence,+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename MutableBufferSequence,     typename MutableBufferIterator, typename CompletionCondition,-    typename ReadHandler, typename Allocator>-struct associated_allocator<+    typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_op<AsyncReadStream, MutableBufferSequence,       MutableBufferIterator, CompletionCondition, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_op<AsyncReadStream, MutableBufferSequence,+        MutableBufferIterator, CompletionCondition, ReadHandler>& h)+    ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_op<AsyncReadStream, MutableBufferSequence,         MutableBufferIterator, CompletionCondition, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -558,37 +571,49 @@ 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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read<AsyncReadStream> >(),+        token, buffers,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(-      detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s), handler,-      buffers, ASIO_MOVE_CAST(CompletionCondition)(completion_condition));+      detail::initiate_async_read<AsyncReadStream>(s),+      token, 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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,-    ASIO_MOVE_ARG(ReadHandler) handler,-    typename enable_if<+    ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read<AsyncReadStream> >(),+        token, buffers, transfer_all()))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(-      detail::initiate_async_read_buffer_sequence<AsyncReadStream>(s),-      handler, buffers, transfer_all());+      detail::initiate_async_read<AsyncReadStream>(s),+      token, buffers, transfer_all()); }  #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)@@ -598,15 +623,17 @@   template <typename AsyncReadStream, typename DynamicBuffer_v1,       typename CompletionCondition, typename ReadHandler>   class read_dynbuf_v1_op-    : detail::base_from_completion_cond<CompletionCondition>+    : public base_from_cancellation_state<ReadHandler>,+      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),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        base_from_completion_cond<CompletionCondition>(completion_condition),         stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         start_(0),@@ -617,7 +644,8 @@  #if defined(ASIO_HAS_MOVE)     read_dynbuf_v1_op(const read_dynbuf_v1_op& other)-      : detail::base_from_completion_cond<CompletionCondition>(other),+      : base_from_cancellation_state<ReadHandler>(other),+        base_from_completion_cond<CompletionCondition>(other),         stream_(other.stream_),         buffers_(other.buffers_),         start_(other.start_),@@ -627,8 +655,11 @@     }      read_dynbuf_v1_op(read_dynbuf_v1_op&& other)-      : detail::base_from_completion_cond<CompletionCondition>(-          ASIO_MOVE_CAST(detail::base_from_completion_cond<+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(base_from_completion_cond<             CompletionCondition>)(other)),         stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),@@ -639,7 +670,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(asio::error_code ec,         std::size_t bytes_transferred, int start = 0)     {       std::size_t max_size, bytes_available;@@ -670,9 +701,16 @@                   buffers_.max_size() - buffers_.size()));           if ((!ec && bytes_transferred == 0) || bytes_available == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         } -        handler_(ec, static_cast<const std::size_t&>(total_transferred_));+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+            static_cast<const asio::error_code&>(ec),+            static_cast<const std::size_t&>(total_transferred_));       }     } @@ -797,40 +835,32 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,-    typename CompletionCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v1,+    typename CompletionCondition, typename ReadHandler,+    typename DefaultCandidate>+struct associator<Associator,     detail::read_dynbuf_v1_op<AsyncReadStream,       DynamicBuffer_v1, CompletionCondition, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_dynbuf_v1_op<AsyncReadStream, DynamicBuffer_v1,+        CompletionCondition, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_dynbuf_v1_op<AsyncReadStream,         DynamicBuffer_v1, CompletionCondition, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -838,41 +868,59 @@  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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        transfer_all()))) {-  return async_read(s,-      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),-      transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));+  return async_initiate<ReadToken,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),+      token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      transfer_all()); }  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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_dynbuf_v1<AsyncReadStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),       ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } @@ -881,29 +929,36 @@  template <typename AsyncReadStream, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,-    ASIO_MOVE_ARG(ReadHandler) handler)+    ASIO_MOVE_ARG(ReadToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read(s, basic_streambuf_ref<Allocator>(b),+        ASIO_MOVE_CAST(ReadToken)(token)))) {   return async_read(s, basic_streambuf_ref<Allocator>(b),-      ASIO_MOVE_CAST(ReadHandler)(handler));+      ASIO_MOVE_CAST(ReadToken)(token)); }  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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,     CompletionCondition completion_condition,-    ASIO_MOVE_ARG(ReadHandler) handler)+    ASIO_MOVE_ARG(ReadToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read(s, basic_streambuf_ref<Allocator>(b),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+        ASIO_MOVE_CAST(ReadToken)(token)))) {   return async_read(s, basic_streambuf_ref<Allocator>(b),       ASIO_MOVE_CAST(CompletionCondition)(completion_condition),-      ASIO_MOVE_CAST(ReadHandler)(handler));+      ASIO_MOVE_CAST(ReadToken)(token)); }  #endif // !defined(ASIO_NO_IOSTREAM)@@ -915,15 +970,17 @@   template <typename AsyncReadStream, typename DynamicBuffer_v2,       typename CompletionCondition, typename ReadHandler>   class read_dynbuf_v2_op-    : detail::base_from_completion_cond<CompletionCondition>+    : public base_from_cancellation_state<ReadHandler>,+      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),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        base_from_completion_cond<CompletionCondition>(completion_condition),         stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         start_(0),@@ -935,7 +992,8 @@  #if defined(ASIO_HAS_MOVE)     read_dynbuf_v2_op(const read_dynbuf_v2_op& other)-      : detail::base_from_completion_cond<CompletionCondition>(other),+      : base_from_cancellation_state<ReadHandler>(other),+        base_from_completion_cond<CompletionCondition>(other),         stream_(other.stream_),         buffers_(other.buffers_),         start_(other.start_),@@ -946,8 +1004,11 @@     }      read_dynbuf_v2_op(read_dynbuf_v2_op&& other)-      : detail::base_from_completion_cond<CompletionCondition>(-          ASIO_MOVE_CAST(detail::base_from_completion_cond<+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(base_from_completion_cond<             CompletionCondition>)(other)),         stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),@@ -959,7 +1020,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(asio::error_code ec,         std::size_t bytes_transferred, int start = 0)     {       std::size_t max_size, pos;@@ -992,9 +1053,16 @@                   buffers_.max_size() - buffers_.size()));           if ((!ec && bytes_transferred == 0) || bytes_available_ == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         } -        handler_(ec, static_cast<const std::size_t&>(total_transferred_));+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+            static_cast<const asio::error_code&>(ec),+            static_cast<const std::size_t&>(total_transferred_));       }     } @@ -1120,40 +1188,32 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,-    typename CompletionCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v2,+    typename CompletionCondition, typename ReadHandler,+    typename DefaultCandidate>+struct associator<Associator,     detail::read_dynbuf_v2_op<AsyncReadStream,       DynamicBuffer_v2, CompletionCondition, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_dynbuf_v2_op<AsyncReadStream, DynamicBuffer_v2,+        CompletionCondition, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_dynbuf_v2_op<AsyncReadStream,         DynamicBuffer_v2, CompletionCondition, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -1161,37 +1221,51 @@  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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,-    ASIO_MOVE_ARG(ReadHandler) handler,-    typename enable_if<+    ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        transfer_all()))) {-  return async_read(s,-      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),-      transfer_all(), ASIO_MOVE_CAST(ReadHandler)(handler));+  return async_initiate<ReadToken,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),+      token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      transfer_all()); }  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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_dynbuf_v2<AsyncReadStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),       ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } 
link/modules/asio-standalone/asio/include/asio/impl/read_at.hpp view
@@ -2,7 +2,7 @@ // impl/read_at.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,11 +16,10 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include <algorithm>-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp"-#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp"@@ -61,7 +60,7 @@       else         break;     }-    return tmp.total_consumed();;+    return tmp.total_consumed();   } } // namespace detail @@ -176,14 +175,16 @@       typename MutableBufferSequence, typename MutableBufferIterator,       typename CompletionCondition, typename ReadHandler>   class read_at_op-    : detail::base_from_completion_cond<CompletionCondition>+    : public base_from_cancellation_state<ReadHandler>,+      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),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        base_from_completion_cond<CompletionCondition>(completion_condition),         device_(device),         offset_(offset),         buffers_(buffers),@@ -194,7 +195,8 @@  #if defined(ASIO_HAS_MOVE)     read_at_op(const read_at_op& other)-      : detail::base_from_completion_cond<CompletionCondition>(other),+      : base_from_cancellation_state<ReadHandler>(other),+        base_from_completion_cond<CompletionCondition>(other),         device_(other.device_),         offset_(other.offset_),         buffers_(other.buffers_),@@ -204,8 +206,11 @@     }      read_at_op(read_at_op&& other)-      : detail::base_from_completion_cond<CompletionCondition>(-          ASIO_MOVE_CAST(detail::base_from_completion_cond<+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(base_from_completion_cond<             CompletionCondition>)(other)),         device_(other.device_),         offset_(other.offset_),@@ -216,7 +221,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(asio::error_code ec,         std::size_t bytes_transferred, int start = 0)     {       std::size_t max_size;@@ -224,7 +229,7 @@       {         case 1:         max_size = this->check_for_completion(ec, buffers_.total_consumed());-        do+        for (;;)         {           {             ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_read_at"));@@ -237,9 +242,18 @@           if ((!ec && bytes_transferred == 0) || buffers_.empty())             break;           max_size = this->check_for_completion(ec, buffers_.total_consumed());-        } while (max_size > 0);+          if (max_size == 0)+            break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = asio::error::operation_aborted;+            break;+          }+        } -        handler_(ec, buffers_.total_consumed());+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+            static_cast<const asio::error_code&>(ec),+            static_cast<const std::size_t&>(buffers_.total_consumed()));       }     } @@ -331,7 +345,7 @@   template <typename AsyncRandomAccessReadDevice,       typename MutableBufferSequence, typename MutableBufferIterator,       typename CompletionCondition, typename ReadHandler>-  inline void start_read_at_buffer_sequence_op(AsyncRandomAccessReadDevice& d,+  inline void start_read_at_op(AsyncRandomAccessReadDevice& d,       uint64_t offset, const MutableBufferSequence& buffers,       const MutableBufferIterator&, CompletionCondition& completion_condition,       ReadHandler& handler)@@ -343,13 +357,12 @@   }    template <typename AsyncRandomAccessReadDevice>-  class initiate_async_read_at_buffer_sequence+  class initiate_async_read_at   {   public:     typedef typename AsyncRandomAccessReadDevice::executor_type executor_type; -    explicit initiate_async_read_at_buffer_sequence(-        AsyncRandomAccessReadDevice& device)+    explicit initiate_async_read_at(AsyncRandomAccessReadDevice& device)       : device_(device)     {     }@@ -371,7 +384,7 @@        non_const_lvalue<ReadHandler> handler2(handler);       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);-      start_read_at_buffer_sequence_op(device_, offset, buffers,+      start_read_at_op(device_, offset, buffers,           asio::buffer_sequence_begin(buffers),           completion_cond2.value, handler2.value);     }@@ -383,44 +396,34 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncRandomAccessReadDevice,-    typename MutableBufferSequence, typename MutableBufferIterator,-    typename CompletionCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,+    typename MutableBufferIterator, typename CompletionCondition,+    typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_at_op<AsyncRandomAccessReadDevice, MutableBufferSequence,-    MutableBufferIterator, CompletionCondition, ReadHandler>,-    Allocator>+      MutableBufferIterator, CompletionCondition, ReadHandler>,+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_at_op<AsyncRandomAccessReadDevice,+        MutableBufferSequence, MutableBufferIterator,+        CompletionCondition, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_at_op<AsyncRandomAccessReadDevice,+        MutableBufferSequence, MutableBufferIterator,+        CompletionCondition, ReadHandler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -429,36 +432,45 @@ 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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),+        token, offset, buffers,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(-      detail::initiate_async_read_at_buffer_sequence<-        AsyncRandomAccessReadDevice>(d),-      handler, offset, buffers,+      detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),+      token, 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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d,     uint64_t offset, const MutableBufferSequence& buffers,-    ASIO_MOVE_ARG(ReadHandler) handler)+    ASIO_MOVE_ARG(ReadToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),+        token, offset, buffers, transfer_all()))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(-      detail::initiate_async_read_at_buffer_sequence<-        AsyncRandomAccessReadDevice>(d),-      handler, offset, buffers, transfer_all());+      detail::initiate_async_read_at<AsyncRandomAccessReadDevice>(d),+      token, offset, buffers, transfer_all()); }  #if !defined(ASIO_NO_EXTENSIONS)@@ -469,14 +481,16 @@   template <typename AsyncRandomAccessReadDevice, typename Allocator,       typename CompletionCondition, typename ReadHandler>   class read_at_streambuf_op-    : detail::base_from_completion_cond<CompletionCondition>+    : public base_from_cancellation_state<ReadHandler>,+      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),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        base_from_completion_cond<CompletionCondition>(completion_condition),         device_(device),         offset_(offset),         streambuf_(streambuf),@@ -488,7 +502,8 @@  #if defined(ASIO_HAS_MOVE)     read_at_streambuf_op(const read_at_streambuf_op& other)-      : detail::base_from_completion_cond<CompletionCondition>(other),+      : base_from_cancellation_state<ReadHandler>(other),+        base_from_completion_cond<CompletionCondition>(other),         device_(other.device_),         offset_(other.offset_),         streambuf_(other.streambuf_),@@ -499,8 +514,11 @@     }      read_at_streambuf_op(read_at_streambuf_op&& other)-      : detail::base_from_completion_cond<CompletionCondition>(-          ASIO_MOVE_CAST(detail::base_from_completion_cond<+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(base_from_completion_cond<             CompletionCondition>)(other)),         device_(other.device_),         offset_(other.offset_),@@ -512,7 +530,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(asio::error_code ec,         std::size_t bytes_transferred, int start = 0)     {       std::size_t max_size, bytes_available;@@ -536,9 +554,16 @@           bytes_available = read_size_helper(streambuf_, max_size);           if ((!ec && bytes_transferred == 0) || bytes_available == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = asio::error::operation_aborted;+            break;+          }         } -        handler_(ec, static_cast<const std::size_t&>(total_transferred_));+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(+            static_cast<const asio::error_code&>(ec),+            static_cast<const std::size_t&>(total_transferred_));       }     } @@ -662,40 +687,32 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncRandomAccessReadDevice, typename Allocator,-    typename CompletionCondition, typename ReadHandler, typename Allocator1>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncRandomAccessReadDevice, typename Executor,+    typename CompletionCondition, typename ReadHandler,+    typename DefaultCandidate>+struct associator<Associator,     detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,-      Allocator, CompletionCondition, ReadHandler>,-    Allocator1>+      Executor, CompletionCondition, ReadHandler>,+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,+        Executor, CompletionCondition, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator1>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_at_streambuf_op<AsyncRandomAccessReadDevice,         Executor, CompletionCondition, ReadHandler>& h,-      const Executor1& ex = Executor1()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor1>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -704,34 +721,47 @@ 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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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)+    ASIO_MOVE_ARG(ReadToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_at_streambuf<+          AsyncRandomAccessReadDevice> >(),+        token, offset, &b,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),-      handler, offset, &b,+      token, 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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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)+    ASIO_MOVE_ARG(ReadToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_at_streambuf<+          AsyncRandomAccessReadDevice> >(),+        token, offset, &b, transfer_all()))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_at_streambuf<AsyncRandomAccessReadDevice>(d),-      handler, offset, &b, transfer_all());+      token, offset, &b, transfer_all()); }  #endif // !defined(ASIO_NO_IOSTREAM)
link/modules/asio-standalone/asio/include/asio/impl/read_until.hpp view
@@ -2,7 +2,7 @@ // impl/read_until.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,10 +19,10 @@ #include <string> #include <vector> #include <utility>-#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp" #include "asio/buffers_iterator.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp"@@ -77,10 +77,12 @@ 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<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read_until(s,@@ -93,10 +95,12 @@ std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     char delim, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   typename decay<DynamicBuffer_v1>::type b(       ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -147,10 +151,12 @@ inline std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     ASIO_STRING_VIEW_PARAM delim,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read_until(s,@@ -163,10 +169,12 @@ 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<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   typename decay<DynamicBuffer_v1>::type b(       ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -229,10 +237,12 @@ inline std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     const boost::regex& expr,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read_until(s,@@ -245,10 +255,12 @@ std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     const boost::regex& expr, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   typename decay<DynamicBuffer_v1>::type b(       ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -313,11 +325,15 @@ inline std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     MatchCondition match_condition,-    typename enable_if<+    typename constraint<       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*)+    >::type,+    typename constraint<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read_until(s,@@ -332,11 +348,15 @@ std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     MatchCondition match_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       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*)+    >::type,+    typename constraint<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   typename decay<DynamicBuffer_v1>::type b(       ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -443,7 +463,7 @@ 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*)+    typename constraint<is_match_condition<MatchCondition>::value>::type) {   return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition); }@@ -452,7 +472,7 @@ 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*)+    typename constraint<is_match_condition<MatchCondition>::value>::type) {   return read_until(s, basic_streambuf_ref<Allocator>(b), match_condition, ec); }@@ -464,9 +484,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read_until(SyncReadStream& s,     DynamicBuffer_v2 buffers, char delim,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read_until(s,@@ -478,9 +498,9 @@ 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<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   DynamicBuffer_v2& b = buffers; @@ -533,9 +553,9 @@ 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<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read_until(s,@@ -547,9 +567,9 @@ 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<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   DynamicBuffer_v2& b = buffers; @@ -614,9 +634,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> inline std::size_t read_until(SyncReadStream& s,     DynamicBuffer_v2 buffers, const boost::regex& expr,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read_until(s,@@ -628,9 +648,9 @@ 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<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   DynamicBuffer_v2& b = buffers; @@ -697,10 +717,12 @@     typename DynamicBuffer_v2, typename MatchCondition> inline std::size_t read_until(SyncReadStream& s,     DynamicBuffer_v2 buffers, MatchCondition match_condition,-    typename enable_if<+    typename constraint<       is_match_condition<MatchCondition>::value-        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type,+    typename constraint<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = read_until(s,@@ -714,10 +736,12 @@     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<+    typename constraint<       is_match_condition<MatchCondition>::value-        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type,+    typename constraint<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type) {   DynamicBuffer_v2& b = buffers; @@ -781,13 +805,16 @@   template <typename AsyncReadStream,       typename DynamicBuffer_v1, typename ReadHandler>   class read_until_delim_op_v1+    : public base_from_cancellation_state<ReadHandler>   {   public:     template <typename BufferSequence>     read_until_delim_op_v1(AsyncReadStream& stream,         ASIO_MOVE_ARG(BufferSequence) buffers,         char delim, ReadHandler& handler)-      : stream_(stream),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         delim_(delim),         start_(0),@@ -798,7 +825,8 @@  #if defined(ASIO_HAS_MOVE)     read_until_delim_op_v1(const read_until_delim_op_v1& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(other),+        stream_(other.stream_),         buffers_(other.buffers_),         delim_(other.delim_),         start_(other.start_),@@ -808,7 +836,10 @@     }      read_until_delim_op_v1(read_until_delim_op_v1&& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),         delim_(other.delim_),         start_(other.start_),@@ -818,7 +849,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(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)();@@ -882,6 +913,11 @@           buffers_.commit(bytes_transferred);           if (ec || bytes_transferred == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         }          const asio::error_code result_ec =@@ -892,7 +928,7 @@           (ec || search_position_ == not_found)           ? 0 : search_position_; -        handler_(result_ec, result_n);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);       }     } @@ -1014,40 +1050,31 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,-    typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v1,+    typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_until_delim_op_v1<AsyncReadStream,       DynamicBuffer_v1, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_until_delim_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_until_delim_op_v1<AsyncReadStream,         DynamicBuffer_v1, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -1055,21 +1082,28 @@  template <typename AsyncReadStream, typename DynamicBuffer_v1,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+      std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    char delim, ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_until_delim_v1<AsyncReadStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim);+      token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim); }  namespace detail@@ -1077,13 +1111,16 @@   template <typename AsyncReadStream,       typename DynamicBuffer_v1, typename ReadHandler>   class read_until_delim_string_op_v1+    : public base_from_cancellation_state<ReadHandler>   {   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),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         delim_(delim),         start_(0),@@ -1094,7 +1131,8 @@  #if defined(ASIO_HAS_MOVE)     read_until_delim_string_op_v1(const read_until_delim_string_op_v1& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(other),+        stream_(other.stream_),         buffers_(other.buffers_),         delim_(other.delim_),         start_(other.start_),@@ -1104,7 +1142,10 @@     }      read_until_delim_string_op_v1(read_until_delim_string_op_v1&& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),         delim_(ASIO_MOVE_CAST(std::string)(other.delim_)),         start_(other.start_),@@ -1114,7 +1155,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(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)();@@ -1189,6 +1230,11 @@           buffers_.commit(bytes_transferred);           if (ec || bytes_transferred == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         }          const asio::error_code result_ec =@@ -1199,7 +1245,7 @@           (ec || search_position_ == not_found)           ? 0 : search_position_; -        handler_(result_ec, result_n);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);       }     } @@ -1321,40 +1367,31 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,-    typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v1,+    typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_until_delim_string_op_v1<AsyncReadStream,       DynamicBuffer_v1, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_until_delim_string_op_v1<AsyncReadStream,+        DynamicBuffer_v1, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_until_delim_string_op_v1<AsyncReadStream,         DynamicBuffer_v1, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -1362,22 +1399,31 @@  template <typename AsyncReadStream, typename DynamicBuffer_v1,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+      std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_delim_string_v1<+          AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        static_cast<std::string>(delim)))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_until_delim_string_v1<AsyncReadStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),       static_cast<std::string>(delim)); } @@ -1389,13 +1435,16 @@   template <typename AsyncReadStream, typename DynamicBuffer_v1,       typename RegEx, typename ReadHandler>   class read_until_expr_op_v1+    : public base_from_cancellation_state<ReadHandler>   {   public:     template <typename BufferSequence>     read_until_expr_op_v1(AsyncReadStream& stream,         ASIO_MOVE_ARG(BufferSequence) buffers,         const boost::regex& expr, ReadHandler& handler)-      : stream_(stream),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         expr_(expr),         start_(0),@@ -1406,7 +1455,8 @@  #if defined(ASIO_HAS_MOVE)     read_until_expr_op_v1(const read_until_expr_op_v1& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(other),+        stream_(other.stream_),         buffers_(other.buffers_),         expr_(other.expr_),         start_(other.start_),@@ -1416,7 +1466,10 @@     }      read_until_expr_op_v1(read_until_expr_op_v1&& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),         expr_(other.expr_),         start_(other.start_),@@ -1426,7 +1479,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(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)();@@ -1504,6 +1557,11 @@           buffers_.commit(bytes_transferred);           if (ec || bytes_transferred == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         }          const asio::error_code result_ec =@@ -1514,7 +1572,7 @@           (ec || search_position_ == not_found)           ? 0 : search_position_; -        handler_(result_ec, result_n);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);       }     } @@ -1635,40 +1693,31 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,-    typename RegEx, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v1,+    typename RegEx, typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_until_expr_op_v1<AsyncReadStream,       DynamicBuffer_v1, RegEx, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_until_expr_op_v1<AsyncReadStream,+        DynamicBuffer_v1, RegEx, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_until_expr_op_v1<AsyncReadStream,         DynamicBuffer_v1, RegEx, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -1676,22 +1725,29 @@  template <typename AsyncReadStream, typename DynamicBuffer_v1,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+      std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_until_expr_v1<AsyncReadStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr);+      token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr); }  #endif // defined(ASIO_HAS_BOOST_REGEX)@@ -1701,13 +1757,16 @@   template <typename AsyncReadStream, typename DynamicBuffer_v1,       typename MatchCondition, typename ReadHandler>   class read_until_match_op_v1+    : public base_from_cancellation_state<ReadHandler>   {   public:     template <typename BufferSequence>     read_until_match_op_v1(AsyncReadStream& stream,         ASIO_MOVE_ARG(BufferSequence) buffers,         MatchCondition match_condition, ReadHandler& handler)-      : stream_(stream),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         match_condition_(match_condition),         start_(0),@@ -1718,7 +1777,8 @@  #if defined(ASIO_HAS_MOVE)     read_until_match_op_v1(const read_until_match_op_v1& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(other),+        stream_(other.stream_),         buffers_(other.buffers_),         match_condition_(other.match_condition_),         start_(other.start_),@@ -1728,7 +1788,10 @@     }      read_until_match_op_v1(read_until_match_op_v1&& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v1)(other.buffers_)),         match_condition_(other.match_condition_),         start_(other.start_),@@ -1738,7 +1801,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(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)();@@ -1812,6 +1875,11 @@           buffers_.commit(bytes_transferred);           if (ec || bytes_transferred == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         }          const asio::error_code result_ec =@@ -1822,7 +1890,7 @@           (ec || search_position_ == not_found)           ? 0 : search_position_; -        handler_(result_ec, result_n);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);       }     } @@ -1947,40 +2015,31 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v1,-    typename MatchCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v1,+    typename MatchCondition, typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_until_match_op_v1<AsyncReadStream,       DynamicBuffer_v1, MatchCondition, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_until_match_op_v1<AsyncReadStream,+        DynamicBuffer_v1, MatchCondition, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_until_match_op_v1<AsyncReadStream,         DynamicBuffer_v1, MatchCondition, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -1989,82 +2048,105 @@ 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,+      std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    MatchCondition match_condition, ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       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*)+    >::type,+    typename constraint<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_match_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        match_condition))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     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);+      detail::initiate_async_read_until_match_v1<AsyncReadStream>(s),+      token, 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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s,     asio::basic_streambuf<Allocator>& b,-    char delim, ASIO_MOVE_ARG(ReadHandler) handler)+    char delim, ASIO_MOVE_ARG(ReadToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read_until(s, basic_streambuf_ref<Allocator>(b),+        delim, ASIO_MOVE_CAST(ReadToken)(token)))) {   return async_read_until(s, basic_streambuf_ref<Allocator>(b),-      delim, ASIO_MOVE_CAST(ReadHandler)(handler));+      delim, ASIO_MOVE_CAST(ReadToken)(token)); }  template <typename AsyncReadStream, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read_until(s, basic_streambuf_ref<Allocator>(b),+        delim, ASIO_MOVE_CAST(ReadToken)(token)))) {   return async_read_until(s, basic_streambuf_ref<Allocator>(b),-      delim, ASIO_MOVE_CAST(ReadHandler)(handler));+      delim, ASIO_MOVE_CAST(ReadToken)(token)); }  #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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read_until(s, basic_streambuf_ref<Allocator>(b),+        expr, ASIO_MOVE_CAST(ReadToken)(token)))) {   return async_read_until(s, basic_streambuf_ref<Allocator>(b),-      expr, ASIO_MOVE_CAST(ReadHandler)(handler));+      expr, ASIO_MOVE_CAST(ReadToken)(token)); }  #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,+      std::size_t)) ReadToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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*)+    MatchCondition match_condition, ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<is_match_condition<MatchCondition>::value>::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read_until(s, basic_streambuf_ref<Allocator>(b),+        match_condition, ASIO_MOVE_CAST(ReadToken)(token)))) {   return async_read_until(s, basic_streambuf_ref<Allocator>(b),-      match_condition, ASIO_MOVE_CAST(ReadHandler)(handler));+      match_condition, ASIO_MOVE_CAST(ReadToken)(token)); }  #endif // !defined(ASIO_NO_IOSTREAM)@@ -2076,13 +2158,16 @@   template <typename AsyncReadStream,       typename DynamicBuffer_v2, typename ReadHandler>   class read_until_delim_op_v2+    : public base_from_cancellation_state<ReadHandler>   {   public:     template <typename BufferSequence>     read_until_delim_op_v2(AsyncReadStream& stream,         ASIO_MOVE_ARG(BufferSequence) buffers,         char delim, ReadHandler& handler)-      : stream_(stream),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         delim_(delim),         start_(0),@@ -2094,7 +2179,8 @@  #if defined(ASIO_HAS_MOVE)     read_until_delim_op_v2(const read_until_delim_op_v2& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(other),+        stream_(other.stream_),         buffers_(other.buffers_),         delim_(other.delim_),         start_(other.start_),@@ -2105,7 +2191,10 @@     }      read_until_delim_op_v2(read_until_delim_op_v2&& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),         delim_(other.delim_),         start_(other.start_),@@ -2116,7 +2205,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(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)();@@ -2184,6 +2273,11 @@           buffers_.shrink(bytes_to_read_ - bytes_transferred);           if (ec || bytes_transferred == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         }          const asio::error_code result_ec =@@ -2194,7 +2288,7 @@           (ec || search_position_ == not_found)           ? 0 : search_position_; -        handler_(result_ec, result_n);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);       }     } @@ -2316,40 +2410,31 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,-    typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v2,+    typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_until_delim_op_v2<AsyncReadStream,       DynamicBuffer_v2, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_until_delim_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_until_delim_op_v2<AsyncReadStream,         DynamicBuffer_v2, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -2357,19 +2442,24 @@  template <typename AsyncReadStream, typename DynamicBuffer_v2,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+      std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    char delim, ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_delim_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_until_delim_v2<AsyncReadStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim);+      token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim); }  namespace detail@@ -2377,13 +2467,16 @@   template <typename AsyncReadStream,       typename DynamicBuffer_v2, typename ReadHandler>   class read_until_delim_string_op_v2+    : public base_from_cancellation_state<ReadHandler>   {   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),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         delim_(delim),         start_(0),@@ -2395,7 +2488,8 @@  #if defined(ASIO_HAS_MOVE)     read_until_delim_string_op_v2(const read_until_delim_string_op_v2& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(other),+        stream_(other.stream_),         buffers_(other.buffers_),         delim_(other.delim_),         start_(other.start_),@@ -2406,7 +2500,10 @@     }      read_until_delim_string_op_v2(read_until_delim_string_op_v2&& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),         delim_(ASIO_MOVE_CAST(std::string)(other.delim_)),         start_(other.start_),@@ -2417,7 +2514,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(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)();@@ -2496,6 +2593,11 @@           buffers_.shrink(bytes_to_read_ - bytes_transferred);           if (ec || bytes_transferred == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         }          const asio::error_code result_ec =@@ -2506,7 +2608,7 @@           (ec || search_position_ == not_found)           ? 0 : search_position_; -        handler_(result_ec, result_n);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);       }     } @@ -2629,40 +2731,31 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,-    typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v2,+    typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_until_delim_string_op_v2<AsyncReadStream,       DynamicBuffer_v2, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_until_delim_string_op_v2<AsyncReadStream,+        DynamicBuffer_v2, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_until_delim_string_op_v2<AsyncReadStream,         DynamicBuffer_v2, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -2671,20 +2764,27 @@ template <typename AsyncReadStream,     typename DynamicBuffer_v2,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+      std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_delim_string_v2<+          AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        static_cast<std::string>(delim)))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_until_delim_string_v2<AsyncReadStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),       static_cast<std::string>(delim)); } @@ -2696,13 +2796,16 @@   template <typename AsyncReadStream, typename DynamicBuffer_v2,       typename RegEx, typename ReadHandler>   class read_until_expr_op_v2+    : public base_from_cancellation_state<ReadHandler>   {   public:     template <typename BufferSequence>     read_until_expr_op_v2(AsyncReadStream& stream,         ASIO_MOVE_ARG(BufferSequence) buffers,         const boost::regex& expr, ReadHandler& handler)-      : stream_(stream),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         expr_(expr),         start_(0),@@ -2714,7 +2817,8 @@  #if defined(ASIO_HAS_MOVE)     read_until_expr_op_v2(const read_until_expr_op_v2& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(other),+        stream_(other.stream_),         buffers_(other.buffers_),         expr_(other.expr_),         start_(other.start_),@@ -2725,7 +2829,10 @@     }      read_until_expr_op_v2(read_until_expr_op_v2&& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),         expr_(other.expr_),         start_(other.start_),@@ -2736,7 +2843,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(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)();@@ -2818,6 +2925,11 @@           buffers_.shrink(bytes_to_read_ - bytes_transferred);           if (ec || bytes_transferred == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         }          const asio::error_code result_ec =@@ -2828,7 +2940,7 @@           (ec || search_position_ == not_found)           ? 0 : search_position_; -        handler_(result_ec, result_n);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);       }     } @@ -2951,40 +3063,31 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,-    typename RegEx, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v2,+    typename RegEx, typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_until_expr_op_v2<AsyncReadStream,       DynamicBuffer_v2, RegEx, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_until_expr_op_v2<AsyncReadStream,+        DynamicBuffer_v2, RegEx, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_until_expr_op_v2<AsyncReadStream,         DynamicBuffer_v2, RegEx, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -2992,19 +3095,24 @@  template <typename AsyncReadStream, typename DynamicBuffer_v2,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+      std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    const boost::regex& expr, ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_expr_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_read_until_expr_v2<AsyncReadStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr);+      token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr); }  #endif // defined(ASIO_HAS_BOOST_REGEX)@@ -3014,13 +3122,16 @@   template <typename AsyncReadStream, typename DynamicBuffer_v2,       typename MatchCondition, typename ReadHandler>   class read_until_match_op_v2+    : public base_from_cancellation_state<ReadHandler>   {   public:     template <typename BufferSequence>     read_until_match_op_v2(AsyncReadStream& stream,         ASIO_MOVE_ARG(BufferSequence) buffers,         MatchCondition match_condition, ReadHandler& handler)-      : stream_(stream),+      : base_from_cancellation_state<ReadHandler>(+          handler, enable_partial_cancellation()),+        stream_(stream),         buffers_(ASIO_MOVE_CAST(BufferSequence)(buffers)),         match_condition_(match_condition),         start_(0),@@ -3032,7 +3143,8 @@  #if defined(ASIO_HAS_MOVE)     read_until_match_op_v2(const read_until_match_op_v2& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(other),+        stream_(other.stream_),         buffers_(other.buffers_),         match_condition_(other.match_condition_),         start_(other.start_),@@ -3043,7 +3155,10 @@     }      read_until_match_op_v2(read_until_match_op_v2&& other)-      : stream_(other.stream_),+      : base_from_cancellation_state<ReadHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            ReadHandler>)(other)),+        stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(DynamicBuffer_v2)(other.buffers_)),         match_condition_(other.match_condition_),         start_(other.start_),@@ -3054,7 +3169,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(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)();@@ -3132,6 +3247,11 @@           buffers_.shrink(bytes_to_read_ - bytes_transferred);           if (ec || bytes_transferred == 0)             break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }         }          const asio::error_code result_ec =@@ -3142,7 +3262,7 @@           (ec || search_position_ == not_found)           ? 0 : search_position_; -        handler_(result_ec, result_n);+        ASIO_MOVE_OR_LVALUE(ReadHandler)(handler_)(result_ec, result_n);       }     } @@ -3268,40 +3388,31 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncReadStream, typename DynamicBuffer_v2,-    typename MatchCondition, typename ReadHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncReadStream, typename DynamicBuffer_v2,+    typename MatchCondition, typename ReadHandler, typename DefaultCandidate>+struct associator<Associator,     detail::read_until_match_op_v2<AsyncReadStream,       DynamicBuffer_v2, MatchCondition, ReadHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<ReadHandler, DefaultCandidate> {-  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+  static typename Associator<ReadHandler, DefaultCandidate>::type+  get(const detail::read_until_match_op_v2<AsyncReadStream,+        DynamicBuffer_v2, MatchCondition, ReadHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<ReadHandler, Allocator>::get(h.handler_, a);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<ReadHandler, DefaultCandidate>::type)+  get(const detail::read_until_match_op_v2<AsyncReadStream,         DynamicBuffer_v2, MatchCondition, ReadHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<ReadHandler, Executor>::get(h.handler_, ex);+    return Associator<ReadHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -3310,20 +3421,29 @@ 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,+      std::size_t)) ReadToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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<+    MatchCondition match_condition, ASIO_MOVE_ARG(ReadToken) token,+    typename constraint<       is_match_condition<MatchCondition>::value-        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type,+    typename constraint<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_match_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        match_condition))) {-  return async_initiate<ReadHandler,+  return async_initiate<ReadToken,     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);+      detail::initiate_async_read_until_match_v2<AsyncReadStream>(s),+      token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      match_condition); }  #endif // !defined(ASIO_NO_EXTENSIONS)
link/modules/asio-standalone/asio/include/asio/impl/redirect_error.hpp view
@@ -2,7 +2,7 @@ // impl/redirect_error.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,8 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"-#include "asio/associated_executor.hpp"-#include "asio/associated_allocator.hpp"+#include "asio/associator.hpp" #include "asio/async_result.hpp" #include "asio/detail/handler_alloc_helpers.hpp" #include "asio/detail/handler_cont_helpers.hpp"@@ -55,7 +54,7 @@    void operator()()   {-    handler_();+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)();   }  #if defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -66,7 +65,8 @@   >::type   operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_MOVE_ARG(Args)... args)   {-    handler_(ASIO_MOVE_CAST(Arg)(arg),+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        ASIO_MOVE_CAST(Arg)(arg),         ASIO_MOVE_CAST(Args)(args)...);   } @@ -75,7 +75,8 @@       ASIO_MOVE_ARG(Args)... args)   {     ec_ = ec;-    handler_(ASIO_MOVE_CAST(Args)(args)...);+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        ASIO_MOVE_CAST(Args)(args)...);   }  #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -86,13 +87,14 @@   >::type   operator()(ASIO_MOVE_ARG(Arg) arg)   {-    handler_(ASIO_MOVE_CAST(Arg)(arg));+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(+        ASIO_MOVE_CAST(Arg)(arg));   }    void operator()(const asio::error_code& ec)   {     ec_ = ec;-    handler_();+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)();   }  #define ASIO_PRIVATE_REDIRECT_ERROR_DEF(n) \@@ -102,7 +104,8 @@   >::type \   operator()(ASIO_MOVE_ARG(Arg) arg, ASIO_VARIADIC_MOVE_PARAMS(n)) \   { \-    handler_(ASIO_MOVE_CAST(Arg)(arg), \+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)( \+        ASIO_MOVE_CAST(Arg)(arg), \         ASIO_VARIADIC_MOVE_ARGS(n)); \   } \   \@@ -111,7 +114,8 @@       ASIO_VARIADIC_MOVE_PARAMS(n)) \   { \     ec_ = ec; \-    handler_(ASIO_VARIADIC_MOVE_ARGS(n)); \+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)( \+        ASIO_VARIADIC_MOVE_ARGS(n)); \   } \   /**/   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF)@@ -202,6 +206,78 @@   typedef R type(Args...); }; +# if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++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...) &;+};++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...) &&;+};++#  if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R, typename... Args>+struct redirect_error_signature<+  R(asio::error_code, Args...) noexcept>+{+  typedef R type(Args...) & noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+  R(const asio::error_code&, Args...) noexcept>+{+  typedef R type(Args...) & noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+  R(asio::error_code, Args...) & noexcept>+{+  typedef R type(Args...) & noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+  R(const asio::error_code&, Args...) & noexcept>+{+  typedef R type(Args...) & noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+  R(asio::error_code, Args...) && noexcept>+{+  typedef R type(Args...) && noexcept;+};++template <typename R, typename... Args>+struct redirect_error_signature<+  R(const asio::error_code&, Args...) && noexcept>+{+  typedef R type(Args...) && noexcept;+};++#  endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+# endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)  template <typename R>@@ -234,6 +310,161 @@   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF) #undef ASIO_PRIVATE_REDIRECT_ERROR_DEF +# if defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS)++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() &;+};++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)) &; \+  }; \+  \+  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++#  if defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)++template <typename R>+struct redirect_error_signature<+  R(asio::error_code) noexcept>+{+  typedef R type() noexcept;+};++template <typename R>+struct redirect_error_signature<+  R(const asio::error_code&) noexcept>+{+  typedef R type() noexcept;+};++template <typename R>+struct redirect_error_signature<+  R(asio::error_code) & noexcept>+{+  typedef R type() & noexcept;+};++template <typename R>+struct redirect_error_signature<+  R(const asio::error_code&) & noexcept>+{+  typedef R type() & noexcept;+};++template <typename R>+struct redirect_error_signature<+  R(asio::error_code) && noexcept>+{+  typedef R type() && noexcept;+};++template <typename R>+struct redirect_error_signature<+  R(const asio::error_code&) && noexcept>+{+  typedef R type() && noexcept;+};++#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)) noexcept> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)) noexcept; \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct redirect_error_signature< \+      R(const asio::error_code&, \+        ASIO_VARIADIC_TARGS(n)) noexcept> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)) noexcept; \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct redirect_error_signature< \+      R(asio::error_code, \+        ASIO_VARIADIC_TARGS(n)) & noexcept> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)) & noexcept; \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct redirect_error_signature< \+      R(const asio::error_code&, \+        ASIO_VARIADIC_TARGS(n)) & noexcept> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)) & noexcept; \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct redirect_error_signature< \+      R(asio::error_code, \+        ASIO_VARIADIC_TARGS(n)) && noexcept> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)) && noexcept; \+  }; \+  \+  template <typename R, ASIO_VARIADIC_TPARAMS(n)> \+  struct redirect_error_signature< \+      R(const asio::error_code&, \+        ASIO_VARIADIC_TARGS(n)) && noexcept> \+  { \+    typedef R type(ASIO_VARIADIC_TARGS(n)) && noexcept; \+  }; \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_REDIRECT_ERROR_DEF)+#undef ASIO_PRIVATE_REDIRECT_ERROR_DEF++#  endif // defined(ASIO_HAS_NOEXCEPT_FUNCTION_TYPE)+# endif // defined(ASIO_HAS_REF_QUALIFIED_FUNCTIONS) #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)  } // namespace detail@@ -242,29 +473,26 @@  template <typename CompletionToken, typename Signature> struct async_result<redirect_error_t<CompletionToken>, Signature>+  : async_result<CompletionToken,+      typename detail::redirect_error_signature<Signature>::type> {-  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))+    explicit init_wrapper(asio::error_code& ec)+      : ec_(ec)     {     }  #if defined(ASIO_HAS_VARIADIC_TEMPLATES) -    template <typename Handler, typename... Args>+    template <typename Handler, typename Initiation, typename... Args>     void operator()(         ASIO_MOVE_ARG(Handler) handler,-        ASIO_MOVE_ARG(Args)... args)+        ASIO_MOVE_ARG(Initiation) initiation,+        ASIO_MOVE_ARG(Args)... args) const     {-      ASIO_MOVE_CAST(Initiation)(initiation_)(+      ASIO_MOVE_CAST(Initiation)(initiation)(           detail::redirect_error_handler<             typename decay<Handler>::type>(               ec_, ASIO_MOVE_CAST(Handler)(handler)),@@ -273,23 +501,26 @@  #else // defined(ASIO_HAS_VARIADIC_TEMPLATES) -    template <typename Handler>+    template <typename Handler, typename Initiation>     void operator()(-        ASIO_MOVE_ARG(Handler) handler)+        ASIO_MOVE_ARG(Handler) handler,+        ASIO_MOVE_ARG(Initiation) initiation) const     {-      ASIO_MOVE_CAST(Initiation)(initiation_)(+      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)> \+    template <typename Handler, typename Initiation, \+        ASIO_VARIADIC_TPARAMS(n)> \     void operator()( \         ASIO_MOVE_ARG(Handler) handler, \-        ASIO_VARIADIC_MOVE_PARAMS(n)) \+        ASIO_MOVE_ARG(Initiation) initiation, \+        ASIO_VARIADIC_MOVE_PARAMS(n)) const \     { \-      ASIO_MOVE_CAST(Initiation)(initiation_)( \+      ASIO_MOVE_CAST(Initiation)(initiation)( \           detail::redirect_error_handler< \             typename decay<Handler>::type>( \               ec_, ASIO_MOVE_CAST(Handler)(handler)), \@@ -302,51 +533,67 @@ #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(+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken,+      typename detail::redirect_error_signature<Signature>::type,+      (async_initiate<CompletionToken,+        typename detail::redirect_error_signature<Signature>::type>(+          declval<init_wrapper>(), declval<CompletionToken&>(),+          declval<Initiation>(), declval<ASIO_MOVE_ARG(Args)>()...)))+  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)...);+        init_wrapper(token.ec_), token.token_,+        ASIO_MOVE_CAST(Initiation)(initiation),+        ASIO_MOVE_CAST(Args)(args)...);   }  #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)    template <typename Initiation, typename RawCompletionToken>-  static return_type initiate(+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken,+      typename detail::redirect_error_signature<Signature>::type,+      (async_initiate<CompletionToken,+        typename detail::redirect_error_signature<Signature>::type>(+          declval<init_wrapper>(), declval<CompletionToken&>(),+          declval<Initiation>())))+  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_);+        init_wrapper(token.ec_), token.token_,+        ASIO_MOVE_CAST(Initiation)(initiation));   }  #define ASIO_PRIVATE_INITIATE_DEF(n) \   template <typename Initiation, typename RawCompletionToken, \       ASIO_VARIADIC_TPARAMS(n)> \-  static return_type initiate( \+  static ASIO_INITFN_DEDUCED_RESULT_TYPE(CompletionToken, \+      typename detail::redirect_error_signature<Signature>::type, \+      (async_initiate<CompletionToken, \+        typename detail::redirect_error_signature<Signature>::type>( \+          declval<init_wrapper>(), declval<CompletionToken&>(), \+          declval<Initiation>(), ASIO_VARIADIC_DECLVAL(n)))) \+  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)); \+        init_wrapper(token.ec_), token.token_, \+        ASIO_MOVE_CAST(Initiation)(initiation), \+        ASIO_VARIADIC_MOVE_ARGS(n)); \   } \   /**/   ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)@@ -355,29 +602,26 @@ #endif // defined(ASIO_HAS_VARIADIC_TEMPLATES) }; -template <typename Handler, typename Executor>-struct associated_executor<detail::redirect_error_handler<Handler>, Executor>+template <template <typename, typename> class Associator,+    typename Handler, typename DefaultCandidate>+struct associator<Associator,+    detail::redirect_error_handler<Handler>, DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  typedef typename associated_executor<Handler, Executor>::type type;--  static type get(-      const detail::redirect_error_handler<Handler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+  static typename Associator<Handler, DefaultCandidate>::type+  get(const detail::redirect_error_handler<Handler>& h) ASIO_NOEXCEPT   {-    return associated_executor<Handler, Executor>::get(h.handler_, ex);+    return Associator<Handler, DefaultCandidate>::get(h.handler_);   }-}; -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+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const detail::redirect_error_handler<Handler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; 
link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.hpp view
@@ -2,7 +2,7 @@ // impl/serial_port_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.ipp view
@@ -2,7 +2,7 @@ // impl/serial_port_base.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/impl/spawn.hpp view
@@ -2,522 +2,1612 @@ // 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)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_cancellation_slot.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/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/memory.hpp"+#include "asio/detail/noncopyable.hpp"+#include "asio/detail/type_traits.hpp"+#include "asio/detail/utility.hpp"+#include "asio/detail/variadic_templates.hpp"+#include "asio/system_error.hpp"++#if defined(ASIO_HAS_STD_TUPLE)+# include <tuple>+#endif // defined(ASIO_HAS_STD_TUPLE)++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+# include <boost/context/fiber.hpp>+#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++#include "asio/detail/push_options.hpp"++namespace asio {+namespace detail {++#if !defined(ASIO_NO_EXCEPTIONS)+inline void spawned_thread_rethrow(void* ex)+{+  if (*static_cast<exception_ptr*>(ex))+    rethrow_exception(*static_cast<exception_ptr*>(ex));+}+#endif // !defined(ASIO_NO_EXCEPTIONS)++#if defined(ASIO_HAS_BOOST_COROUTINE)++// Spawned thread implementation using Boost.Coroutine.+class spawned_coroutine_thread : public spawned_thread_base+{+public:+#if defined(BOOST_COROUTINES_UNIDIRECT) || defined(BOOST_COROUTINES_V2)+  typedef boost::coroutines::pull_coroutine<void> callee_type;+  typedef boost::coroutines::push_coroutine<void> caller_type;+#else+  typedef boost::coroutines::coroutine<void()> callee_type;+  typedef boost::coroutines::coroutine<void()> caller_type;+#endif++  spawned_coroutine_thread(caller_type& caller)+    : caller_(caller),+      on_suspend_fn_(0),+      on_suspend_arg_(0)+  {+  }++  template <typename F>+  static spawned_thread_base* spawn(ASIO_MOVE_ARG(F) f,+      const boost::coroutines::attributes& attributes,+      cancellation_slot parent_cancel_slot = cancellation_slot(),+      cancellation_state cancel_state = cancellation_state())+  {+    spawned_coroutine_thread* spawned_thread = 0;+    callee_type callee(entry_point<typename decay<F>::type>(+          ASIO_MOVE_CAST(F)(f), &spawned_thread), attributes);+    spawned_thread->callee_.swap(callee);+    spawned_thread->parent_cancellation_slot_ = parent_cancel_slot;+    spawned_thread->cancellation_state_ = cancel_state;+    return spawned_thread;+  }++  template <typename F>+  static spawned_thread_base* spawn(ASIO_MOVE_ARG(F) f,+      cancellation_slot parent_cancel_slot = cancellation_slot(),+      cancellation_state cancel_state = cancellation_state())+  {+    return spawn(ASIO_MOVE_CAST(F)(f), boost::coroutines::attributes(),+        parent_cancel_slot, cancel_state);+  }++  void resume()+  {+    callee_();+    if (on_suspend_fn_)+    {+      void (*fn)(void*) = on_suspend_fn_;+      void* arg = on_suspend_arg_;+      on_suspend_fn_ = 0;+      fn(arg);+    }+  }++  void suspend_with(void (*fn)(void*), void* arg)+  {+    if (throw_if_cancelled_)+      if (!!cancellation_state_.cancelled())+        throw_error(asio::error::operation_aborted, "yield");+    has_context_switched_ = true;+    on_suspend_fn_ = fn;+    on_suspend_arg_ = arg;+    caller_();+  }++  void destroy()+  {+    callee_type callee;+    callee.swap(callee_);+    if (terminal_)+      callee();+  }++private:+  template <typename Function>+  class entry_point+  {+  public:+    template <typename F>+    entry_point(ASIO_MOVE_ARG(F) f,+        spawned_coroutine_thread** spawned_thread_out)+      : function_(ASIO_MOVE_CAST(F)(f)),+        spawned_thread_out_(spawned_thread_out)+    {+    }++    void operator()(caller_type& caller)+    {+      Function function(ASIO_MOVE_CAST(Function)(function_));+      spawned_coroutine_thread spawned_thread(caller);+      *spawned_thread_out_ = &spawned_thread;+      spawned_thread_out_ = 0;+      spawned_thread.suspend();+#if !defined(ASIO_NO_EXCEPTIONS)+      try+#endif // !defined(ASIO_NO_EXCEPTIONS)+      {+        function(&spawned_thread);+        spawned_thread.terminal_ = true;+        spawned_thread.suspend();+      }+#if !defined(ASIO_NO_EXCEPTIONS)+      catch (const boost::coroutines::detail::forced_unwind&)+      {+        throw;+      }+      catch (...)+      {+        exception_ptr ex = current_exception();+        spawned_thread.terminal_ = true;+        spawned_thread.suspend_with(spawned_thread_rethrow, &ex);+      }+#endif // !defined(ASIO_NO_EXCEPTIONS)+    }++  private:+    Function function_;+    spawned_coroutine_thread** spawned_thread_out_;+  };++  caller_type& caller_;+  callee_type callee_;+  void (*on_suspend_fn_)(void*);+  void* on_suspend_arg_;+};++#endif // defined(ASIO_HAS_BOOST_COROUTINE)++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++// Spawned thread implementation using Boost.Context's fiber.+class spawned_fiber_thread : public spawned_thread_base+{+public:+  typedef boost::context::fiber fiber_type;++  spawned_fiber_thread(ASIO_MOVE_ARG(fiber_type) caller)+    : caller_(ASIO_MOVE_CAST(fiber_type)(caller)),+      on_suspend_fn_(0),+      on_suspend_arg_(0)+  {+  }++  template <typename StackAllocator, typename F>+  static spawned_thread_base* spawn(allocator_arg_t,+      ASIO_MOVE_ARG(StackAllocator) stack_allocator,+      ASIO_MOVE_ARG(F) f,+      cancellation_slot parent_cancel_slot = cancellation_slot(),+      cancellation_state cancel_state = cancellation_state())+  {+    spawned_fiber_thread* spawned_thread = 0;+    fiber_type callee(allocator_arg_t(),+        ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+        entry_point<typename decay<F>::type>(+          ASIO_MOVE_CAST(F)(f), &spawned_thread));+    callee = fiber_type(ASIO_MOVE_CAST(fiber_type)(callee)).resume();+    spawned_thread->callee_ = ASIO_MOVE_CAST(fiber_type)(callee);+    spawned_thread->parent_cancellation_slot_ = parent_cancel_slot;+    spawned_thread->cancellation_state_ = cancel_state;+    return spawned_thread;+  }++  template <typename F>+  static spawned_thread_base* spawn(ASIO_MOVE_ARG(F) f,+      cancellation_slot parent_cancel_slot = cancellation_slot(),+      cancellation_state cancel_state = cancellation_state())+  {+    return spawn(allocator_arg_t(), boost::context::fixedsize_stack(),+        ASIO_MOVE_CAST(F)(f), parent_cancel_slot, cancel_state);+  }++  void resume()+  {+    callee_ = fiber_type(ASIO_MOVE_CAST(fiber_type)(callee_)).resume();+    if (on_suspend_fn_)+    {+      void (*fn)(void*) = on_suspend_fn_;+      void* arg = on_suspend_arg_;+      on_suspend_fn_ = 0;+      fn(arg);+    }+  }++  void suspend_with(void (*fn)(void*), void* arg)+  {+    if (throw_if_cancelled_)+      if (!!cancellation_state_.cancelled())+        throw_error(asio::error::operation_aborted, "yield");+    has_context_switched_ = true;+    on_suspend_fn_ = fn;+    on_suspend_arg_ = arg;+    caller_ = fiber_type(ASIO_MOVE_CAST(fiber_type)(caller_)).resume();+  }++  void destroy()+  {+    fiber_type callee = ASIO_MOVE_CAST(fiber_type)(callee_);+    if (terminal_)+      fiber_type(ASIO_MOVE_CAST(fiber_type)(callee)).resume();+  }++private:+  template <typename Function>+  class entry_point+  {+  public:+    template <typename F>+    entry_point(ASIO_MOVE_ARG(F) f,+        spawned_fiber_thread** spawned_thread_out)+      : function_(ASIO_MOVE_CAST(F)(f)),+        spawned_thread_out_(spawned_thread_out)+    {+    }++    fiber_type operator()(ASIO_MOVE_ARG(fiber_type) caller)+    {+      Function function(ASIO_MOVE_CAST(Function)(function_));+      spawned_fiber_thread spawned_thread(+          ASIO_MOVE_CAST(fiber_type)(caller));+      *spawned_thread_out_ = &spawned_thread;+      spawned_thread_out_ = 0;+      spawned_thread.suspend();+#if !defined(ASIO_NO_EXCEPTIONS)+      try+#endif // !defined(ASIO_NO_EXCEPTIONS)+      {+        function(&spawned_thread);+        spawned_thread.terminal_ = true;+        spawned_thread.suspend();+      }+#if !defined(ASIO_NO_EXCEPTIONS)+      catch (const boost::context::detail::forced_unwind&)+      {+        throw;+      }+      catch (...)+      {+        exception_ptr ex = current_exception();+        spawned_thread.terminal_ = true;+        spawned_thread.suspend_with(spawned_thread_rethrow, &ex);+      }+#endif // !defined(ASIO_NO_EXCEPTIONS)+      return ASIO_MOVE_CAST(fiber_type)(spawned_thread.caller_);+    }++  private:+    Function function_;+    spawned_fiber_thread** spawned_thread_out_;+  };++  fiber_type caller_;+  fiber_type callee_;+  void (*on_suspend_fn_)(void*);+  void* on_suspend_arg_;+};++#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+typedef spawned_fiber_thread default_spawned_thread_type;+#elif defined(ASIO_HAS_BOOST_COROUTINE)+typedef spawned_coroutine_thread default_spawned_thread_type;+#else+# error No spawn() implementation available+#endif++// Helper class to perform the initial resume on the correct executor.+class spawned_thread_resumer+{+public:+  explicit spawned_thread_resumer(spawned_thread_base* spawned_thread)+    : spawned_thread_(spawned_thread)+  {+#if !defined(ASIO_HAS_MOVE)+    spawned_thread->detach();+    spawned_thread->attach(&spawned_thread_);+#endif // !defined(ASIO_HAS_MOVE)+  }++#if defined(ASIO_HAS_MOVE)++  spawned_thread_resumer(spawned_thread_resumer&& other) ASIO_NOEXCEPT+    : spawned_thread_(other.spawned_thread_)+  {+    other.spawned_thread_ = 0;+  }++#else // defined(ASIO_HAS_MOVE)++  spawned_thread_resumer(+      const spawned_thread_resumer& other) ASIO_NOEXCEPT+    : spawned_thread_(other.spawned_thread_)+  {+    spawned_thread_->detach();+    spawned_thread_->attach(&spawned_thread_);+  }++#endif // defined(ASIO_HAS_MOVE)++  ~spawned_thread_resumer()+  {+    if (spawned_thread_)+      spawned_thread_->destroy();+  }++  void operator()()+  {+#if defined(ASIO_HAS_MOVE)+    spawned_thread_->attach(&spawned_thread_);+#endif // defined(ASIO_HAS_MOVE)+    spawned_thread_->resume();+  }++private:+  spawned_thread_base* spawned_thread_;+};++// Helper class to ensure spawned threads are destroyed on the correct executor.+class spawned_thread_destroyer+{+public:+  explicit spawned_thread_destroyer(spawned_thread_base* spawned_thread)+    : spawned_thread_(spawned_thread)+  {+    spawned_thread->detach();+#if !defined(ASIO_HAS_MOVE)+    spawned_thread->attach(&spawned_thread_);+#endif // !defined(ASIO_HAS_MOVE)+  }++#if defined(ASIO_HAS_MOVE)++  spawned_thread_destroyer(spawned_thread_destroyer&& other) ASIO_NOEXCEPT+    : spawned_thread_(other.spawned_thread_)+  {+    other.spawned_thread_ = 0;+  }++#else // defined(ASIO_HAS_MOVE)++  spawned_thread_destroyer(+      const spawned_thread_destroyer& other) ASIO_NOEXCEPT+    : spawned_thread_(other.spawned_thread_)+  {+    spawned_thread_->detach();+    spawned_thread_->attach(&spawned_thread_);+  }++#endif // defined(ASIO_HAS_MOVE)++  ~spawned_thread_destroyer()+  {+    if (spawned_thread_)+      spawned_thread_->destroy();+  }++  void operator()()+  {+    if (spawned_thread_)+    {+      spawned_thread_->destroy();+      spawned_thread_ = 0;+    }+  }++private:+  spawned_thread_base* spawned_thread_;+};++// Base class for all completion handlers associated with a spawned thread.+template <typename Executor>+class spawn_handler_base+{+public:+  typedef Executor executor_type;+  typedef cancellation_slot cancellation_slot_type;++  spawn_handler_base(const basic_yield_context<Executor>& yield)+    : yield_(yield),+      spawned_thread_(yield.spawned_thread_)+  {+    spawned_thread_->detach();+#if !defined(ASIO_HAS_MOVE)+    spawned_thread_->attach(&spawned_thread_);+#endif // !defined(ASIO_HAS_MOVE)+  }++#if defined(ASIO_HAS_MOVE)++  spawn_handler_base(spawn_handler_base&& other) ASIO_NOEXCEPT+    : yield_(other.yield_),+      spawned_thread_(other.spawned_thread_)++  {+    other.spawned_thread_ = 0;+  }++#else // defined(ASIO_HAS_MOVE)++  spawn_handler_base(const spawn_handler_base& other) ASIO_NOEXCEPT+    : yield_(other.yield_),+      spawned_thread_(other.spawned_thread_)+  {+    spawned_thread_->detach();+    spawned_thread_->attach(&spawned_thread_);+  }++#endif // defined(ASIO_HAS_MOVE)++  ~spawn_handler_base()+  {+    if (spawned_thread_)+      (post)(yield_.executor_, spawned_thread_destroyer(spawned_thread_));+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return yield_.executor_;+  }++  cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+  {+    return spawned_thread_->get_cancellation_slot();+  }++  void resume()+  {+    spawned_thread_resumer resumer(spawned_thread_);+    spawned_thread_ = 0;+    resumer();+  }++protected:+  const basic_yield_context<Executor>& yield_;+  spawned_thread_base* spawned_thread_;+};++// Completion handlers for when basic_yield_context is used as a token.+template <typename Executor, typename Signature>+class spawn_handler;++template <typename Executor, typename R>+class spawn_handler<Executor, R()>+  : public spawn_handler_base<Executor>+{+public:+  typedef void return_type;++  struct result_type {};++  spawn_handler(const basic_yield_context<Executor>& yield, result_type&)+    : spawn_handler_base<Executor>(yield)+  {+  }++  void operator()()+  {+    this->resume();+  }++  static return_type on_resume(result_type&)+  {+  }+};++template <typename Executor, typename R>+class spawn_handler<Executor, R(asio::error_code)>+  : public spawn_handler_base<Executor>+{+public:+  typedef void return_type;+  typedef asio::error_code* result_type;++  spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+    : spawn_handler_base<Executor>(yield),+      result_(result)+  {+  }++  void operator()(asio::error_code ec)+  {+    if (this->yield_.ec_)+    {+      *this->yield_.ec_ = ec;+      result_ = 0;+    }+    else+      result_ = &ec;+    this->resume();+  }++  static return_type on_resume(result_type& result)+  {+    if (result)+      throw_error(*result);+  }++private:+  result_type& result_;+};++template <typename Executor, typename R>+class spawn_handler<Executor, R(exception_ptr)>+  : public spawn_handler_base<Executor>+{+public:+  typedef void return_type;+  typedef exception_ptr* result_type;++  spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+    : spawn_handler_base<Executor>(yield),+      result_(result)+  {+  }++  void operator()(exception_ptr ex)+  {+    result_ = &ex;+    this->resume();+  }++  static return_type on_resume(result_type& result)+  {+    if (result)+      rethrow_exception(*result);+  }++private:+  result_type& result_;+};++template <typename Executor, typename R, typename T>+class spawn_handler<Executor, R(T)>+  : public spawn_handler_base<Executor>+{+public:+  typedef T return_type;+  typedef return_type* result_type;++  spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+    : spawn_handler_base<Executor>(yield),+      result_(result)+  {+  }++  void operator()(T value)+  {+    result_ = &value;+    this->resume();+  }++  static return_type on_resume(result_type& result)+  {+    return ASIO_MOVE_CAST(return_type)(*result);+  }++private:+  result_type& result_;+};++template <typename Executor, typename R, typename T>+class spawn_handler<Executor, R(asio::error_code, T)>+  : public spawn_handler_base<Executor>+{+public:+  typedef T return_type;++  struct result_type+  {+    asio::error_code* ec_;+    return_type* value_;+  };++  spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+    : spawn_handler_base<Executor>(yield),+      result_(result)+  {+  }++  void operator()(asio::error_code ec, T value)+  {+    if (this->yield_.ec_)+    {+      *this->yield_.ec_ = ec;+      result_.ec_ = 0;+    }+    else+      result_.ec_ = &ec;+    result_.value_ = &value;+    this->resume();+  }++  static return_type on_resume(result_type& result)+  {+    if (result.ec_)+      throw_error(*result.ec_);+    return ASIO_MOVE_CAST(return_type)(*result.value_);+  }++private:+  result_type& result_;+};++template <typename Executor, typename R, typename T>+class spawn_handler<Executor, R(exception_ptr, T)>+  : public spawn_handler_base<Executor>+{+public:+  typedef T return_type;++  struct result_type+  {+    exception_ptr ex_;+    return_type* value_;+  };++  spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+    : spawn_handler_base<Executor>(yield),+      result_(result)+  {+  }++  void operator()(exception_ptr ex, T value)+  {+    result_.ex_ = &ex;+    result_.value_ = &value;+    this->resume();+  }++  static return_type on_resume(result_type& result)+  {+    if (result.ex_)+      rethrow_exception(*result.ex_);+    return ASIO_MOVE_CAST(return_type)(*result.value_);+  }++private:+  result_type& result_;+};++#if defined(ASIO_HAS_VARIADIC_TEMPLATES) \+  && defined(ASIO_HAS_STD_TUPLE)++template <typename Executor, typename R, typename... Ts>+class spawn_handler<Executor, R(Ts...)>+  : public spawn_handler_base<Executor>+{+public:+  typedef std::tuple<Ts...> return_type;++  typedef return_type* result_type;++  spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+    : spawn_handler_base<Executor>(yield),+      result_(result)+  {+  }++  template <typename... Args>+  void operator()(ASIO_MOVE_ARG(Args)... args)+  {+    return_type value(ASIO_MOVE_CAST(Args)(args)...);+    result_ = &value;+    this->resume();+  }++  static return_type on_resume(result_type& result)+  {+    return ASIO_MOVE_CAST(return_type)(*result);+  }++private:+  result_type& result_;+};++template <typename Executor, typename R, typename... Ts>+class spawn_handler<Executor, R(asio::error_code, Ts...)>+  : public spawn_handler_base<Executor>+{+public:+  typedef std::tuple<Ts...> return_type;++  struct result_type+  {+    asio::error_code* ec_;+    return_type* value_;+  };++  spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+    : spawn_handler_base<Executor>(yield),+      result_(result)+  {+  }++  template <typename... Args>+  void operator()(asio::error_code ec,+      ASIO_MOVE_ARG(Args)... args)+  {+    return_type value(ASIO_MOVE_CAST(Args)(args)...);+    if (this->yield_.ec_)+    {+      *this->yield_.ec_ = ec;+      result_.ec_ = 0;+    }+    else+      result_.ec_ = &ec;+    result_.value_ = &value;+    this->resume();+  }++  static return_type on_resume(result_type& result)+  {+    if (result.ec_)+      throw_error(*result.ec_);+    return ASIO_MOVE_CAST(return_type)(*result.value_);+  }++private:+  result_type& result_;+};++template <typename Executor, typename R, typename... Ts>+class spawn_handler<Executor, R(exception_ptr, Ts...)>+  : public spawn_handler_base<Executor>+{+public:+  typedef std::tuple<Ts...> return_type;++  struct result_type+  {+    exception_ptr ex_;+    return_type* value_;+  };++  spawn_handler(const basic_yield_context<Executor>& yield, result_type& result)+    : spawn_handler_base<Executor>(yield),+      result_(result)+  {+  }++  template <typename... Args>+  void operator()(exception_ptr ex, ASIO_MOVE_ARG(Args)... args)+  {+    return_type value(ASIO_MOVE_CAST(Args)(args)...);+    result_.ex_ = &ex;+    result_.value_ = &value;+    this->resume();+  }++  static return_type on_resume(result_type& result)+  {+    if (result.ex_)+      rethrow_exception(*result.ex_);+    return ASIO_MOVE_CAST(return_type)(*result.value_);+  }++private:+  result_type& result_;+};++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+       //   && defined(ASIO_HAS_STD_TUPLE)++template <typename Executor, typename Signature>+inline bool asio_handler_is_continuation(spawn_handler<Executor, Signature>*)+{+  return true;+}++} // namespace detail++template <typename Executor, typename Signature>+class async_result<basic_yield_context<Executor>, Signature>+{+public:+  typedef typename detail::spawn_handler<Executor, Signature> handler_type;+  typedef typename handler_type::return_type return_type;++#if defined(ASIO_HAS_VARIADIC_TEMPLATES)+# if defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)++  template <typename Initiation, typename... InitArgs>+  static return_type initiate(ASIO_MOVE_ARG(Initiation) init,+      const basic_yield_context<Executor>& yield,+      ASIO_MOVE_ARG(InitArgs)... init_args)+  {+    typename handler_type::result_type result+      = typename handler_type::result_type();++    yield.spawned_thread_->suspend_with(+        [&]()+        {+          ASIO_MOVE_CAST(Initiation)(init)(+              handler_type(yield, result),+              ASIO_MOVE_CAST(InitArgs)(init_args)...);+        });++    return handler_type::on_resume(result);+  }++# else // defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)++  template <typename Initiation, typename... InitArgs>+  struct suspend_with_helper+  {+    typename handler_type::result_type& result_;+    ASIO_MOVE_ARG(Initiation) init_;+    const basic_yield_context<Executor>& yield_;+    std::tuple<ASIO_MOVE_ARG(InitArgs)...> init_args_;++    template <std::size_t... I>+    void do_invoke(detail::index_sequence<I...>)+    {+      ASIO_MOVE_CAST(Initiation)(init_)(+          handler_type(yield_, result_),+          ASIO_MOVE_CAST(InitArgs)(std::get<I>(init_args_))...);+    }++    void operator()()+    {+      this->do_invoke(detail::make_index_sequence<sizeof...(InitArgs)>());+    }+  };++  template <typename Initiation, typename... InitArgs>+  static return_type initiate(ASIO_MOVE_ARG(Initiation) init,+      const basic_yield_context<Executor>& yield,+      ASIO_MOVE_ARG(InitArgs)... init_args)+  {+    typename handler_type::result_type result+      = typename handler_type::result_type();++    yield.spawned_thread_->suspend_with(+      suspend_with_helper<Initiation, InitArgs...>{+          result, ASIO_MOVE_CAST(Initiation)(init), yield,+          std::tuple<ASIO_MOVE_ARG(InitArgs)...>(+            ASIO_MOVE_CAST(InitArgs)(init_args)...)});++    return handler_type::on_resume(result);+  }++# endif // defined(ASIO_HAS_VARIADIC_LAMBDA_CAPTURES)+#else // defined(ASIO_HAS_VARIADIC_TEMPLATES)++  template <typename Initiation>+  static return_type initiate(Initiation init,+      const basic_yield_context<Executor>& yield)+  {+    typename handler_type::result_type result+      = typename handler_type::result_type();++    struct on_suspend+    {+      Initiation& init_;+      const basic_yield_context<Executor>& yield_;+      typename handler_type::result_type& result_;++      void do_call()+      {+        ASIO_MOVE_CAST(Initiation)(init_)(+            handler_type(yield_, result_));+      }++      static void call(void* arg)+      {+        static_cast<on_suspend*>(arg)->do_call();+      }+    } o = { init, yield, result };++    yield.spawned_thread_->suspend_with(&on_suspend::call, &o);++    return handler_type::on_resume(result);+  }++#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS(n) \+  ASIO_PRIVATE_ON_SUSPEND_MEMBERS_##n+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_1 \+  T1& x1;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_2 \+  T1& x1; T2& x2;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_3 \+  T1& x1; T2& x2; T3& x3;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_4 \+  T1& x1; T2& x2; T3& x3; T4& x4;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_5 \+  T1& x1; T2& x2; T3& x3; T4& x4; T5& x5;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_6 \+  T1& x1; T2& x2; T3& x3; T4& x4; T5& x5; T6& x6;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_7 \+  T1& x1; T2& x2; T3& x3; T4& x4; T5& x5; T6& x6; T7& x7;+#define ASIO_PRIVATE_ON_SUSPEND_MEMBERS_8 \+  T1& x1; T2& x2; T3& x3; T4& x4; T5& x5; T6& x6; T7& x7; T8& x8;++#define ASIO_PRIVATE_INITIATE_DEF(n) \+  template <typename Initiation, ASIO_VARIADIC_TPARAMS(n)> \+  static return_type initiate(Initiation init, \+      const basic_yield_context<Executor>& yield, \+      ASIO_VARIADIC_BYVAL_PARAMS(n)) \+  { \+    typename handler_type::result_type result \+      = typename handler_type::result_type(); \+  \+    struct on_suspend \+    { \+      Initiation& init; \+      const basic_yield_context<Executor>& yield; \+      typename handler_type::result_type& result; \+      ASIO_PRIVATE_ON_SUSPEND_MEMBERS(n) \+  \+      void do_call() \+      { \+        ASIO_MOVE_CAST(Initiation)(init)( \+            handler_type(yield, result), \+            ASIO_VARIADIC_MOVE_ARGS(n)); \+      } \+  \+      static void call(void* arg) \+      { \+        static_cast<on_suspend*>(arg)->do_call(); \+      } \+    } o = { init, yield, result, ASIO_VARIADIC_BYVAL_ARGS(n) }; \+  \+    yield.spawned_thread_->suspend_with(&on_suspend::call, &o); \+  \+    return handler_type::on_resume(result); \+  } \+  /**/+  ASIO_VARIADIC_GENERATE(ASIO_PRIVATE_INITIATE_DEF)+#undef ASIO_PRIVATE_INITIATE_DEF+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_1+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_2+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_3+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_4+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_5+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_6+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_7+#undef ASIO_PRIVATE_ON_SUSPEND_MEMBERS_8++#endif // defined(ASIO_HAS_VARIADIC_TEMPLATES)+};++namespace detail {++template <typename Executor, typename Function, typename Handler>+class spawn_entry_point+{+public:+  template <typename F, typename H>+  spawn_entry_point(const Executor& ex,+      ASIO_MOVE_ARG(F) f, ASIO_MOVE_ARG(H) h)+    : executor_(ex),+      function_(ASIO_MOVE_CAST(F)(f)),+      handler_(ASIO_MOVE_CAST(H)(h)),+      work_(handler_, executor_)+  {+  }++  void operator()(spawned_thread_base* spawned_thread)+  {+    const basic_yield_context<Executor> yield(spawned_thread, executor_);+    this->call(yield,+        void_type<typename result_of<Function(+          basic_yield_context<Executor>)>::type>());+  }++private:+  void call(const basic_yield_context<Executor>& yield, void_type<void>)+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+#endif // !defined(ASIO_NO_EXCEPTIONS)+    {+      function_(yield);+      if (!yield.spawned_thread_->has_context_switched())+        (post)(yield);+      detail::binder1<Handler, exception_ptr>+        handler(handler_, exception_ptr());+      work_.complete(handler, handler.handler_);+    }+#if !defined(ASIO_NO_EXCEPTIONS)+# if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+    catch (const boost::context::detail::forced_unwind&)+    {+      throw;+    }+# endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+# if defined(ASIO_HAS_BOOST_COROUTINE)+    catch (const boost::coroutines::detail::forced_unwind&)+    {+      throw;+    }+# endif // defined(ASIO_HAS_BOOST_COROUTINE)+    catch (...)+    {+      exception_ptr ex = current_exception();+      if (!yield.spawned_thread_->has_context_switched())+        (post)(yield);+      detail::binder1<Handler, exception_ptr> handler(handler_, ex);+      work_.complete(handler, handler.handler_);+    }+#endif // !defined(ASIO_NO_EXCEPTIONS)+  }++  template <typename T>+  void call(const basic_yield_context<Executor>& yield, void_type<T>)+  {+#if !defined(ASIO_NO_EXCEPTIONS)+    try+#endif // !defined(ASIO_NO_EXCEPTIONS)+    {+      T result(function_(yield));+      if (!yield.spawned_thread_->has_context_switched())+        (post)(yield);+      detail::binder2<Handler, exception_ptr, T>+        handler(handler_, exception_ptr(), ASIO_MOVE_CAST(T)(result));+      work_.complete(handler, handler.handler_);+    }+#if !defined(ASIO_NO_EXCEPTIONS)+# if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+    catch (const boost::context::detail::forced_unwind&)+    {+      throw;+    }+# endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+# if defined(ASIO_HAS_BOOST_COROUTINE)+    catch (const boost::coroutines::detail::forced_unwind&)+    {+      throw;+    }+# endif // defined(ASIO_HAS_BOOST_COROUTINE)+    catch (...)+    {+      exception_ptr ex = current_exception();+      if (!yield.spawned_thread_->has_context_switched())+        (post)(yield);+      detail::binder2<Handler, exception_ptr, T> handler(handler_, ex, T());+      work_.complete(handler, handler.handler_);+    }+#endif // !defined(ASIO_NO_EXCEPTIONS)+  }++  Executor executor_;+  Function function_;+  Handler handler_;+  handler_work<Handler, Executor> work_;+};++struct spawn_cancellation_signal_emitter+{+  cancellation_signal* signal_;+  cancellation_type_t type_;++  void operator()()+  {+    signal_->emit(type_);+  }+};++template <typename Handler, typename Executor, typename = void>+class spawn_cancellation_handler+{+public:+  spawn_cancellation_handler(const Handler&, const Executor& ex)+    : ex_(ex)+  {+  }++  cancellation_slot slot()+  {+    return signal_.slot();+  }++  void operator()(cancellation_type_t type)+  {+    spawn_cancellation_signal_emitter emitter = { &signal_, type };+    (dispatch)(ex_, emitter);+  }++private:+  cancellation_signal signal_;+  Executor ex_;+};+++template <typename Handler, typename Executor>+class spawn_cancellation_handler<Handler, Executor,+    typename enable_if<+      is_same<+        typename associated_executor<Handler,+          Executor>::asio_associated_executor_is_unspecialised,+        void+      >::value+    >::type>+{+public:+  spawn_cancellation_handler(const Handler&, const Executor&)+  {+  }++  cancellation_slot slot()+  {+    return signal_.slot();+  }++  void operator()(cancellation_type_t type)+  {+    signal_.emit(type);+  }++private:+  cancellation_signal signal_;+};++template <typename Executor>+class initiate_spawn+{+public:+  typedef Executor executor_type;++  explicit initiate_spawn(const executor_type& ex)+    : executor_(ex)+  {+  }++  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return executor_;+  }++  template <typename Handler, typename F>+  void operator()(ASIO_MOVE_ARG(Handler) handler,+      ASIO_MOVE_ARG(F) f) const+  {+    typedef typename decay<Handler>::type handler_type;+    typedef typename decay<F>::type function_type;+    typedef spawn_cancellation_handler<+      handler_type, Executor> cancel_handler_type;++    typename associated_cancellation_slot<handler_type>::type slot+      = asio::get_associated_cancellation_slot(handler);++    cancel_handler_type* cancel_handler = slot.is_connected()+      ? &slot.template emplace<cancel_handler_type>(handler, executor_)+      : 0;++    cancellation_slot proxy_slot(+        cancel_handler+          ? cancel_handler->slot()+          : cancellation_slot());++    cancellation_state cancel_state(proxy_slot);++    (dispatch)(executor_,+        spawned_thread_resumer(+          default_spawned_thread_type::spawn(+            spawn_entry_point<Executor, function_type, handler_type>(+              executor_, ASIO_MOVE_CAST(F)(f),+              ASIO_MOVE_CAST(Handler)(handler)),+            proxy_slot, cancel_state)));+  }++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++  template <typename Handler, typename StackAllocator, typename F>+  void operator()(ASIO_MOVE_ARG(Handler) handler, allocator_arg_t,+      ASIO_MOVE_ARG(StackAllocator) stack_allocator,+      ASIO_MOVE_ARG(F) f) const+  {+    typedef typename decay<Handler>::type handler_type;+    typedef typename decay<F>::type function_type;+    typedef spawn_cancellation_handler<+      handler_type, Executor> cancel_handler_type;++    typename associated_cancellation_slot<handler_type>::type slot+      = asio::get_associated_cancellation_slot(handler);++    cancel_handler_type* cancel_handler = slot.is_connected()+      ? &slot.template emplace<cancel_handler_type>(handler, executor_)+      : 0;++    cancellation_slot proxy_slot(+        cancel_handler+          ? cancel_handler->slot()+          : cancellation_slot());++    cancellation_state cancel_state(proxy_slot);++    (dispatch)(executor_,+        spawned_thread_resumer(+          spawned_fiber_thread::spawn(allocator_arg_t(),+            ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+            spawn_entry_point<Executor, function_type, handler_type>(+              executor_, ASIO_MOVE_CAST(F)(f),+              ASIO_MOVE_CAST(Handler)(handler)),+            proxy_slot, cancel_state)));+  }++#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++private:+  executor_type executor_;+};++} // namespace detail++template <typename Executor, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+        CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const Executor& ex, ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token,+#if defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      !is_same<+        typename decay<CompletionToken>::type,+        boost::coroutines::attributes+      >::value+    >::type,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+          declval<detail::initiate_spawn<Executor> >(),+          token, ASIO_MOVE_CAST(F)(function))))+{+  return async_initiate<CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+        detail::initiate_spawn<Executor>(ex),+        token, ASIO_MOVE_CAST(F)(function));+}++template <typename ExecutionContext, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<+        typename ExecutionContext::executor_type>)>::type>::type)+          CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<+        typename ExecutionContext::executor_type>)>::type>::type)+spawn(ExecutionContext& ctx, ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token,+#if defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      !is_same<+        typename decay<CompletionToken>::type,+        boost::coroutines::attributes+      >::value+    >::type,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<+          typename ExecutionContext::executor_type>)>::type>::type>(+            declval<detail::initiate_spawn<+              typename ExecutionContext::executor_type> >(),+            token, ASIO_MOVE_CAST(F)(function))))+{+  return (spawn)(ctx.get_executor(), ASIO_MOVE_CAST(F)(function),+      ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename Executor, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+        CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const basic_yield_context<Executor>& ctx,+    ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token,+#if defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      !is_same<+        typename decay<CompletionToken>::type,+        boost::coroutines::attributes+      >::value+    >::type,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+          declval<detail::initiate_spawn<Executor> >(),+          token, ASIO_MOVE_CAST(F)(function))))+{+  return (spawn)(ctx.get_executor(), ASIO_MOVE_CAST(F)(function),+      ASIO_MOVE_CAST(CompletionToken)(token));+}++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++template <typename Executor, typename StackAllocator, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+        CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const Executor& ex, allocator_arg_t,+    ASIO_MOVE_ARG(StackAllocator) stack_allocator,+    ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token,+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+          declval<detail::initiate_spawn<Executor> >(),+          token, allocator_arg_t(),+          ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+          ASIO_MOVE_CAST(F)(function))))+{+  return async_initiate<CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+        detail::initiate_spawn<Executor>(ex), token, allocator_arg_t(),+        ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+        ASIO_MOVE_CAST(F)(function));+}++template <typename ExecutionContext, typename StackAllocator, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<+        typename ExecutionContext::executor_type>)>::type>::type)+          CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<+        typename ExecutionContext::executor_type>)>::type>::type)+spawn(ExecutionContext& ctx, allocator_arg_t,+    ASIO_MOVE_ARG(StackAllocator) stack_allocator,+    ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token,+    typename constraint<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<+          typename ExecutionContext::executor_type>)>::type>::type>(+            declval<detail::initiate_spawn<+              typename ExecutionContext::executor_type> >(),+            token, allocator_arg_t(),+            ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+            ASIO_MOVE_CAST(F)(function))))+{+  return (spawn)(ctx.get_executor(), allocator_arg_t(),+      ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+      ASIO_MOVE_CAST(F)(function),+      ASIO_MOVE_CAST(CompletionToken)(token));+}++template <typename Executor, typename StackAllocator, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+        CompletionToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const basic_yield_context<Executor>& ctx, allocator_arg_t,+    ASIO_MOVE_ARG(StackAllocator) stack_allocator,+    ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token,+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+          declval<detail::initiate_spawn<Executor> >(),+          token, allocator_arg_t(),+          ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+          ASIO_MOVE_CAST(F)(function))))+{+  return (spawn)(ctx.get_executor(), allocator_arg_t(),+      ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+      ASIO_MOVE_CAST(F)(function),+      ASIO_MOVE_CAST(CompletionToken)(token));+}++#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)++#if defined(ASIO_HAS_BOOST_COROUTINE)++namespace detail {++template <typename Executor, typename Function, typename Handler>+class old_spawn_entry_point+{+public:+  template <typename F, typename H>+  old_spawn_entry_point(const Executor& ex,+      ASIO_MOVE_ARG(F) f, ASIO_MOVE_ARG(H) h)+    : executor_(ex),+      function_(ASIO_MOVE_CAST(F)(f)),+      handler_(ASIO_MOVE_CAST(H)(h))+  {+  }++  void operator()(spawned_thread_base* spawned_thread)+  {+    const basic_yield_context<Executor> yield(spawned_thread, executor_);+    this->call(yield,+        void_type<typename result_of<Function(+          basic_yield_context<Executor>)>::type>());+  }++private:+  void call(const basic_yield_context<Executor>& yield, void_type<void>)+  {+    function_(yield);+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)();+  }++  template <typename T>+  void call(const basic_yield_context<Executor>& yield, void_type<T>)+  {+    ASIO_MOVE_OR_LVALUE(Handler)(handler_)(function_(yield));+  }++  Executor executor_;+  Function function_;+  Handler handler_;+};++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 constraint<+      !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;+  typedef typename associated_executor<handler_type>::type executor_type;++  executor_type ex((get_associated_executor)(handler));++  (dispatch)(ex,+      detail::spawned_thread_resumer(+        detail::spawned_coroutine_thread::spawn(+          detail::old_spawn_entry_point<executor_type,+            function_type, void (*)()>(+              ex, ASIO_MOVE_CAST(Function)(function),+              &detail::default_spawn_handler), attributes)));+}++template <typename Executor, typename Function>+void spawn(basic_yield_context<Executor> ctx,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes)+{+  typedef typename decay<Function>::type function_type;++  (dispatch)(ctx.get_executor(),+      detail::spawned_thread_resumer(+        detail::spawned_coroutine_thread::spawn(+          detail::old_spawn_entry_point<Executor,+            function_type, void (*)()>(ctx.get_executor(),+              ASIO_MOVE_CAST(Function)(function),+              &detail::default_spawn_handler), attributes)));+}++template <typename Function, typename Executor>+inline void spawn(const Executor& ex,+    ASIO_MOVE_ARG(Function) function,+    const boost::coroutines::attributes& attributes,+    typename constraint<+      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 constraint<is_convertible<+      ExecutionContext&, execution_context&>::value>::type)+{+  asio::spawn(ctx.get_executor(),+      ASIO_MOVE_CAST(Function)(function), attributes);+}++#endif // defined(ASIO_HAS_BOOST_COROUTINE)  } // namespace asio 
link/modules/asio-standalone/asio/include/asio/impl/src.hpp view
@@ -2,7 +2,7 @@ // impl/src.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,10 @@ # error Do not compile Asio library source with ASIO_HEADER_ONLY defined #endif +#include "asio/impl/any_completion_executor.ipp"+#include "asio/impl/any_io_executor.ipp"+#include "asio/impl/cancellation_signal.ipp"+#include "asio/impl/connect_pipe.ipp" #include "asio/impl/error.ipp" #include "asio/impl/error_code.ipp" #include "asio/impl/execution_context.ipp"@@ -35,15 +39,19 @@ #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/io_uring_descriptor_service.ipp"+#include "asio/detail/impl/io_uring_file_service.ipp"+#include "asio/detail/impl/io_uring_socket_service_base.ipp"+#include "asio/detail/impl/io_uring_service.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_serial_port_service.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"@@ -54,9 +62,11 @@ #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/thread_context.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_file_service.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"@@ -72,6 +82,7 @@ #include "asio/detail/impl/winsock_init.ipp" #include "asio/execution/impl/bad_executor.ipp" #include "asio/execution/impl/receiver_invocation_error.ipp"+#include "asio/experimental/impl/channel_error.ipp" #include "asio/generic/detail/impl/endpoint.ipp" #include "asio/ip/impl/address.ipp" #include "asio/ip/impl/address_v4.ipp"
link/modules/asio-standalone/asio/include/asio/impl/system_context.hpp view
@@ -2,7 +2,7 @@ // impl/system_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/system_context.ipp view
@@ -2,7 +2,7 @@ // impl/system_context.ipp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/impl/system_executor.hpp view
@@ -2,7 +2,7 @@ // impl/system_executor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,7 +17,6 @@  #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" 
link/modules/asio-standalone/asio/include/asio/impl/thread_pool.hpp view
@@ -2,7 +2,7 @@ // impl/thread_pool.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,7 +20,6 @@ #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" @@ -76,11 +75,16 @@ {   if (this != &other)   {+    thread_pool* old_thread_pool = pool_;     pool_ = other.pool_;     allocator_ = std::move(other.allocator_);     bits_ = other.bits_;     if (Bits & outstanding_work_tracked)+    {       other.pool_ = 0;+      if (old_thread_pool)+        old_thread_pool->scheduler_.work_finished();+    }   }   return *this; }
link/modules/asio-standalone/asio/include/asio/impl/thread_pool.ipp view
@@ -2,7 +2,7 @@ // impl/thread_pool.ipp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -98,6 +98,7 @@ {   stop();   join();+  shutdown(); }  void thread_pool::stop()@@ -114,11 +115,11 @@  void thread_pool::join() {-  if (!threads_.empty())-  {+  if (num_threads_)     scheduler_.work_finished();++  if (!threads_.empty())     threads_.join();-  } }  detail::scheduler& thread_pool::add_scheduler(detail::scheduler* s)
link/modules/asio-standalone/asio/include/asio/impl/use_awaitable.hpp view
@@ -2,7 +2,7 @@ // impl/use_awaitable.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,7 @@  #include "asio/detail/config.hpp" #include "asio/async_result.hpp"+#include "asio/cancellation_signal.hpp"  #include "asio/detail/push_options.hpp" @@ -32,8 +33,9 @@   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)+  awaitable_handler_base(awaitable<awaitable_thread_entry_point, Executor> a,+      const Executor& ex, cancellation_slot pcs, cancellation_state cs)+    : awaitable_thread<Executor>(std::move(a), ex, pcs, cs)   {   } @@ -46,7 +48,8 @@ protected:   awaitable_frame<T, Executor>* frame() noexcept   {-    return static_cast<awaitable_frame<T, Executor>*>(this->top_of_stack_);+    return static_cast<awaitable_frame<T, Executor>*>(+        this->entry_point()->top_of_stack_);   } }; @@ -64,6 +67,7 @@   {     this->frame()->attach_thread(this);     this->frame()->return_void();+    this->frame()->clear_cancellation_slot();     this->frame()->pop_frame();     this->pump();   }@@ -83,6 +87,7 @@       this->frame()->set_error(ec);     else       this->frame()->return_void();+    this->frame()->clear_cancellation_slot();     this->frame()->pop_frame();     this->pump();   }@@ -102,6 +107,7 @@       this->frame()->set_except(ex);     else       this->frame()->return_void();+    this->frame()->clear_cancellation_slot();     this->frame()->pop_frame();     this->pump();   }@@ -119,6 +125,7 @@   {     this->frame()->attach_thread(this);     this->frame()->return_value(std::forward<Arg>(arg));+    this->frame()->clear_cancellation_slot();     this->frame()->pop_frame();     this->pump();   }@@ -139,6 +146,7 @@       this->frame()->set_error(ec);     else       this->frame()->return_value(std::forward<Arg>(arg));+    this->frame()->clear_cancellation_slot();     this->frame()->pop_frame();     this->pump();   }@@ -159,6 +167,7 @@       this->frame()->set_except(ex);     else       this->frame()->return_value(std::forward<Arg>(arg));+    this->frame()->clear_cancellation_slot();     this->frame()->pop_frame();     this->pump();   }@@ -177,6 +186,7 @@   {     this->frame()->attach_thread(this);     this->frame()->return_values(std::forward<Args>(args)...);+    this->frame()->clear_cancellation_slot();     this->frame()->pop_frame();     this->pump();   }@@ -198,6 +208,7 @@       this->frame()->set_error(ec);     else       this->frame()->return_values(std::forward<Args>(args)...);+    this->frame()->clear_cancellation_slot();     this->frame()->pop_frame();     this->pump();   }@@ -219,6 +230,7 @@       this->frame()->set_except(ex);     else       this->frame()->return_values(std::forward<Args>(args)...);+    this->frame()->clear_cancellation_slot();     this->frame()->pop_frame();     this->pump();   }@@ -228,6 +240,19 @@  #if !defined(GENERATING_DOCUMENTATION) +#if defined(_MSC_VER)+template <typename T>+T dummy_return()+{+  return std::move(*static_cast<T*>(nullptr));+}++template <>+inline void dummy_return()+{+}+#endif // defined(_MSC_VER)+ template <typename Executor, typename R, typename... Args> class async_result<use_awaitable_t<Executor>, R(Args...)> {@@ -236,31 +261,28 @@       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()+  template <typename Initiation, typename... InitArgs>+#if defined(__APPLE_CC__) && (__clang_major__ == 13)+  __attribute__((noinline))+#endif // defined(__APPLE_CC__) && (__clang_major__ == 13)+  static handler_type* do_init(+      detail::awaitable_frame_base<Executor>* frame, Initiation& initiation,+      use_awaitable_t<Executor> u, InitArgs&... args)   {-    return std::move(*static_cast<T*>(nullptr));+    (void)u;+    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 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)+    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);+        return do_init(frame, initiation, u, args...);       };      for (;;) {} // Never reached.
link/modules/asio-standalone/asio/include/asio/impl/use_future.hpp view
@@ -2,7 +2,7 @@ // impl/use_future.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -211,6 +211,11 @@   {   } +  execution_context& query(execution::context_t) const ASIO_NOEXCEPT+  {+    return asio::query(system_executor(), execution::context);+  }+   static ASIO_CONSTEXPR Blocking query(execution::blocking_t)   {     return Blocking();@@ -231,9 +236,14 @@   template <typename F>   void execute(ASIO_MOVE_ARG(F) f) const   {+#if defined(ASIO_NO_DEPRECATED)+    asio::require(system_executor(), Blocking()).execute(+        promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)));+#else // defined(ASIO_NO_DEPRECATED)     execution::execute(         asio::require(system_executor(), Blocking()),         promise_invoker<T, F>(p_, ASIO_MOVE_CAST(F)(f)));+#endif // defined(ASIO_NO_DEPRECATED)   }  #if !defined(ASIO_NO_TS_EXECUTORS)@@ -963,7 +973,7 @@  #endif // !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) -#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)+#if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)  template <typename T, typename Blocking, typename Property> struct query_static_constexpr_member<@@ -987,7 +997,22 @@   } }; -#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_TRAIT)+#endif // !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT)++#if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)++template <typename T, typename Blocking>+struct query_member<+    asio::detail::promise_executor<T, Blocking>,+    execution::context_t+  >+{+  ASIO_STATIC_CONSTEXPR(bool, is_valid = true);+  ASIO_STATIC_CONSTEXPR(bool, is_noexcept = true);+  typedef asio::system_context& result_type;+};++#endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)  #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) 
link/modules/asio-standalone/asio/include/asio/impl/write.hpp view
@@ -2,7 +2,7 @@ // impl/write.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,11 +15,10 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp"-#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp"@@ -40,7 +39,7 @@ {   template <typename SyncWriteStream, typename ConstBufferSequence,       typename ConstBufferIterator, typename CompletionCondition>-  std::size_t write_buffer_sequence(SyncWriteStream& s,+  std::size_t write(SyncWriteStream& s,       const ConstBufferSequence& buffers, const ConstBufferIterator&,       CompletionCondition completion_condition, asio::error_code& ec)   {@@ -55,7 +54,7 @@       else         break;     }-    return tmp.total_consumed();;+    return tmp.total_consumed();   } } // namespace detail @@ -63,20 +62,20 @@     typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type*)+    >::type) {-  return detail::write_buffer_sequence(s, buffers,+  return detail::write(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<+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = write(s, buffers, transfer_all(), ec);@@ -87,9 +86,9 @@ template <typename SyncWriteStream, typename ConstBufferSequence> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type*)+    >::type) {   return write(s, buffers, transfer_all(), ec); }@@ -98,9 +97,9 @@     typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = write(s, buffers,@@ -116,10 +115,12 @@ std::size_t write(SyncWriteStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   typename decay<DynamicBuffer_v1>::type b(       ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers));@@ -133,10 +134,12 @@ template <typename SyncWriteStream, typename DynamicBuffer_v1> inline std::size_t write(SyncWriteStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = write(s,@@ -150,10 +153,12 @@ inline std::size_t write(SyncWriteStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   return write(s, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),       transfer_all(), ec);@@ -164,10 +169,12 @@ inline std::size_t write(SyncWriteStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = write(s,@@ -223,9 +230,9 @@     typename CompletionCondition> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   std::size_t bytes_transferred = write(s, buffers.data(0, buffers.size()),       ASIO_MOVE_CAST(CompletionCondition)(completion_condition), ec);@@ -235,9 +242,9 @@  template <typename SyncWriteStream, typename DynamicBuffer_v2> inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = write(s,@@ -250,9 +257,9 @@ template <typename SyncWriteStream, typename DynamicBuffer_v2> inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   return write(s, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),       transfer_all(), ec);@@ -262,9 +269,9 @@     typename CompletionCondition> inline std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type) {   asio::error_code ec;   std::size_t bytes_transferred = write(s,@@ -280,13 +287,15 @@       typename ConstBufferIterator, typename CompletionCondition,       typename WriteHandler>   class write_op-    : detail::base_from_completion_cond<CompletionCondition>+    : public base_from_cancellation_state<WriteHandler>,+      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),+      : base_from_cancellation_state<WriteHandler>(+          handler, enable_partial_cancellation()),+        base_from_completion_cond<CompletionCondition>(completion_condition),         stream_(stream),         buffers_(buffers),         start_(0),@@ -296,7 +305,8 @@  #if defined(ASIO_HAS_MOVE)     write_op(const write_op& other)-      : detail::base_from_completion_cond<CompletionCondition>(other),+      : base_from_cancellation_state<WriteHandler>(other),+        base_from_completion_cond<CompletionCondition>(other),         stream_(other.stream_),         buffers_(other.buffers_),         start_(other.start_),@@ -305,8 +315,11 @@     }      write_op(write_op&& other)-      : detail::base_from_completion_cond<CompletionCondition>(-          ASIO_MOVE_CAST(detail::base_from_completion_cond<+      : base_from_cancellation_state<WriteHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            WriteHandler>)(other)),+        base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(base_from_completion_cond<             CompletionCondition>)(other)),         stream_(other.stream_),         buffers_(ASIO_MOVE_CAST(buffers_type)(other.buffers_)),@@ -316,7 +329,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(asio::error_code ec,         std::size_t bytes_transferred, int start = 0)     {       std::size_t max_size;@@ -324,7 +337,7 @@       {         case 1:         max_size = this->check_for_completion(ec, buffers_.total_consumed());-        do+        for (;;)         {           {             ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write"));@@ -336,9 +349,18 @@           if ((!ec && bytes_transferred == 0) || buffers_.empty())             break;           max_size = this->check_for_completion(ec, buffers_.total_consumed());-        } while (max_size > 0);+          if (max_size == 0)+            break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = error::operation_aborted;+            break;+          }+        } -        handler_(ec, buffers_.total_consumed());+        ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(+            static_cast<const asio::error_code&>(ec),+            static_cast<const std::size_t&>(buffers_.total_consumed()));       }     } @@ -429,7 +451,7 @@   template <typename AsyncWriteStream, typename ConstBufferSequence,       typename ConstBufferIterator, typename CompletionCondition,       typename WriteHandler>-  inline void start_write_buffer_sequence_op(AsyncWriteStream& stream,+  inline void start_write_op(AsyncWriteStream& stream,       const ConstBufferSequence& buffers, const ConstBufferIterator&,       CompletionCondition& completion_condition, WriteHandler& handler)   {@@ -440,12 +462,12 @@   }    template <typename AsyncWriteStream>-  class initiate_async_write_buffer_sequence+  class initiate_async_write   {   public:     typedef typename AsyncWriteStream::executor_type executor_type; -    explicit initiate_async_write_buffer_sequence(AsyncWriteStream& stream)+    explicit initiate_async_write(AsyncWriteStream& stream)       : stream_(stream)     {     }@@ -467,7 +489,7 @@        non_const_lvalue<WriteHandler> handler2(handler);       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);-      start_write_buffer_sequence_op(stream_, buffers,+      start_write_op(stream_, buffers,           asio::buffer_sequence_begin(buffers),           completion_cond2.value, handler2.value);     }@@ -479,42 +501,33 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncWriteStream, typename ConstBufferSequence,+template <template <typename, typename> class Associator,+    typename AsyncWriteStream, typename ConstBufferSequence,     typename ConstBufferIterator, typename CompletionCondition,-    typename WriteHandler, typename Allocator>-struct associated_allocator<+    typename WriteHandler, typename DefaultCandidate>+struct associator<Associator,     detail::write_op<AsyncWriteStream, ConstBufferSequence,       ConstBufferIterator, CompletionCondition, WriteHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<WriteHandler, DefaultCandidate> {-  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+  static typename Associator<WriteHandler, DefaultCandidate>::type+  get(const detail::write_op<AsyncWriteStream, ConstBufferSequence,+        ConstBufferIterator, CompletionCondition, WriteHandler>& h)+    ASIO_NOEXCEPT   {-    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<WriteHandler, DefaultCandidate>::type)+  get(const detail::write_op<AsyncWriteStream, ConstBufferSequence,         ConstBufferIterator, CompletionCondition, WriteHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -523,38 +536,49 @@ 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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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<+    ASIO_MOVE_ARG(WriteToken) token,+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write<AsyncWriteStream> >(),+        token, buffers,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<WriteHandler,+  return async_initiate<WriteToken,     void (asio::error_code, std::size_t)>(-      detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),-      handler, buffers,+      detail::initiate_async_write<AsyncWriteStream>(s),+      token, 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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,-    ASIO_MOVE_ARG(WriteHandler) handler,-    typename enable_if<+    ASIO_MOVE_ARG(WriteToken) token,+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write<AsyncWriteStream> >(),+        token, buffers, transfer_all()))) {-  return async_initiate<WriteHandler,+  return async_initiate<WriteToken,     void (asio::error_code, std::size_t)>(-      detail::initiate_async_write_buffer_sequence<AsyncWriteStream>(s),-      handler, buffers, transfer_all());+      detail::initiate_async_write<AsyncWriteStream>(s),+      token, buffers, transfer_all()); }  #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)@@ -609,7 +633,8 @@             ASIO_MOVE_CAST(write_dynbuf_v1_op)(*this));         return; default:         buffers_.consume(bytes_transferred);-        handler_(ec, static_cast<const std::size_t&>(bytes_transferred));+        ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec,+            static_cast<const std::size_t&>(bytes_transferred));       }     } @@ -733,40 +758,32 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncWriteStream, typename DynamicBuffer_v1,-    typename CompletionCondition, typename WriteHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncWriteStream, typename DynamicBuffer_v1,+    typename CompletionCondition, typename WriteHandler,+    typename DefaultCandidate>+struct associator<Associator,     detail::write_dynbuf_v1_op<AsyncWriteStream,       DynamicBuffer_v1, CompletionCondition, WriteHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<WriteHandler, DefaultCandidate> {-  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+  static typename Associator<WriteHandler, DefaultCandidate>::type+  get(const detail::write_dynbuf_v1_op<AsyncWriteStream, DynamicBuffer_v1,+        CompletionCondition, WriteHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<WriteHandler, DefaultCandidate>::type)+  get(const detail::write_dynbuf_v1_op<AsyncWriteStream,         DynamicBuffer_v1, CompletionCondition, WriteHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -774,41 +791,59 @@  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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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<+    ASIO_MOVE_ARG(WriteToken) token,+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        transfer_all()))) {-  return async_write(s,-      ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),-      transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler));+  return async_initiate<WriteToken,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),+      token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      transfer_all()); }  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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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<+    ASIO_MOVE_ARG(WriteToken) token,+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type*)+    >::type,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<WriteHandler,+  return async_initiate<WriteToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_write_dynbuf_v1<AsyncWriteStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+      token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),       ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } @@ -817,31 +852,38 @@  template <typename AsyncWriteStream, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) WriteHandler>-inline ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s,     asio::basic_streambuf<Allocator>& b,-    ASIO_MOVE_ARG(WriteHandler) handler)+    ASIO_MOVE_ARG(WriteToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_write(s, basic_streambuf_ref<Allocator>(b),+        ASIO_MOVE_CAST(WriteToken)(token)))) {   return async_write(s, basic_streambuf_ref<Allocator>(b),-      ASIO_MOVE_CAST(WriteHandler)(handler));+      ASIO_MOVE_CAST(WriteToken)(token)); }  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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s,     asio::basic_streambuf<Allocator>& b,     CompletionCondition completion_condition,-    ASIO_MOVE_ARG(WriteHandler) handler)+    ASIO_MOVE_ARG(WriteToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_write(s, basic_streambuf_ref<Allocator>(b),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+        ASIO_MOVE_CAST(WriteToken)(token)))) {   return async_write(s, basic_streambuf_ref<Allocator>(b),       ASIO_MOVE_CAST(CompletionCondition)(completion_condition),-      ASIO_MOVE_CAST(WriteHandler)(handler));+      ASIO_MOVE_CAST(WriteToken)(token)); }  #endif // !defined(ASIO_NO_IOSTREAM)@@ -898,7 +940,8 @@             ASIO_MOVE_CAST(write_dynbuf_v2_op)(*this));         return; default:         buffers_.consume(bytes_transferred);-        handler_(ec, static_cast<const std::size_t&>(bytes_transferred));+        ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec,+            static_cast<const std::size_t&>(bytes_transferred));       }     } @@ -1022,40 +1065,32 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncWriteStream, typename DynamicBuffer_v2,-    typename CompletionCondition, typename WriteHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncWriteStream, typename DynamicBuffer_v2,+    typename CompletionCondition, typename WriteHandler,+    typename DefaultCandidate>+struct associator<Associator,     detail::write_dynbuf_v2_op<AsyncWriteStream,       DynamicBuffer_v2, CompletionCondition, WriteHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<WriteHandler, DefaultCandidate> {-  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+  static typename Associator<WriteHandler, DefaultCandidate>::type+  get(const detail::write_dynbuf_v2_op<AsyncWriteStream, DynamicBuffer_v2,+        CompletionCondition, WriteHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<WriteHandler, DefaultCandidate>::type)+  get(const detail::write_dynbuf_v2_op<AsyncWriteStream,         DynamicBuffer_v2, CompletionCondition, WriteHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -1063,37 +1098,51 @@  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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,-    ASIO_MOVE_ARG(WriteHandler) handler,-    typename enable_if<+    ASIO_MOVE_ARG(WriteToken) token,+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        transfer_all()))) {-  return async_write(s,-      ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),-      transfer_all(), ASIO_MOVE_CAST(WriteHandler)(handler));+  return async_initiate<WriteToken,+    void (asio::error_code, std::size_t)>(+      detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),+      token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      transfer_all()); }  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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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<+    ASIO_MOVE_ARG(WriteToken) token,+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type*)+    >::type)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<WriteHandler,+  return async_initiate<WriteToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_write_dynbuf_v2<AsyncWriteStream>(s),-      handler, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+      token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),       ASIO_MOVE_CAST(CompletionCondition)(completion_condition)); } 
link/modules/asio-standalone/asio/include/asio/impl/write_at.hpp view
@@ -2,7 +2,7 @@ // impl/write_at.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -15,11 +15,10 @@ # pragma once #endif // defined(_MSC_VER) && (_MSC_VER >= 1200) -#include "asio/associated_allocator.hpp"-#include "asio/associated_executor.hpp"+#include "asio/associator.hpp" #include "asio/buffer.hpp"-#include "asio/completion_condition.hpp" #include "asio/detail/array_fwd.hpp"+#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/base_from_completion_cond.hpp" #include "asio/detail/bind_handler.hpp" #include "asio/detail/consuming_buffers.hpp"@@ -59,7 +58,7 @@       else         break;     }-    return tmp.total_consumed();;+    return tmp.total_consumed();   } } // namespace detail @@ -161,14 +160,16 @@       typename ConstBufferSequence, typename ConstBufferIterator,       typename CompletionCondition, typename WriteHandler>   class write_at_op-    : detail::base_from_completion_cond<CompletionCondition>+    : public base_from_cancellation_state<WriteHandler>,+      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),+      : base_from_cancellation_state<WriteHandler>(+          handler, enable_partial_cancellation()),+        base_from_completion_cond<CompletionCondition>(completion_condition),         device_(device),         offset_(offset),         buffers_(buffers),@@ -179,7 +180,8 @@  #if defined(ASIO_HAS_MOVE)     write_at_op(const write_at_op& other)-      : detail::base_from_completion_cond<CompletionCondition>(other),+      : base_from_cancellation_state<WriteHandler>(other),+        base_from_completion_cond<CompletionCondition>(other),         device_(other.device_),         offset_(other.offset_),         buffers_(other.buffers_),@@ -189,8 +191,11 @@     }      write_at_op(write_at_op&& other)-      : detail::base_from_completion_cond<CompletionCondition>(-          ASIO_MOVE_CAST(detail::base_from_completion_cond<+      : base_from_cancellation_state<WriteHandler>(+          ASIO_MOVE_CAST(base_from_cancellation_state<+            WriteHandler>)(other)),+        base_from_completion_cond<CompletionCondition>(+          ASIO_MOVE_CAST(base_from_completion_cond<             CompletionCondition>)(other)),         device_(other.device_),         offset_(other.offset_),@@ -201,7 +206,7 @@     } #endif // defined(ASIO_HAS_MOVE) -    void operator()(const asio::error_code& ec,+    void operator()(asio::error_code ec,         std::size_t bytes_transferred, int start = 0)     {       std::size_t max_size;@@ -209,7 +214,7 @@       {         case 1:         max_size = this->check_for_completion(ec, buffers_.total_consumed());-        do+        for (;;)         {           {             ASIO_HANDLER_LOCATION((__FILE__, __LINE__, "async_write_at"));@@ -222,9 +227,18 @@           if ((!ec && bytes_transferred == 0) || buffers_.empty())             break;           max_size = this->check_for_completion(ec, buffers_.total_consumed());-        } while (max_size > 0);+          if (max_size == 0)+            break;+          if (this->cancelled() != cancellation_type::none)+          {+            ec = asio::error::operation_aborted;+            break;+          }+        } -        handler_(ec, buffers_.total_consumed());+        ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(+            static_cast<const asio::error_code&>(ec),+            static_cast<const std::size_t&>(buffers_.total_consumed()));       }     } @@ -316,7 +330,7 @@   template <typename AsyncRandomAccessWriteDevice,       typename ConstBufferSequence, typename ConstBufferIterator,       typename CompletionCondition, typename WriteHandler>-  inline void start_write_at_buffer_sequence_op(AsyncRandomAccessWriteDevice& d,+  inline void start_write_at_op(AsyncRandomAccessWriteDevice& d,       uint64_t offset, const ConstBufferSequence& buffers,       const ConstBufferIterator&, CompletionCondition& completion_condition,       WriteHandler& handler)@@ -328,13 +342,12 @@   }    template <typename AsyncRandomAccessWriteDevice>-  class initiate_async_write_at_buffer_sequence+  class initiate_async_write_at   {   public:     typedef typename AsyncRandomAccessWriteDevice::executor_type executor_type; -    explicit initiate_async_write_at_buffer_sequence(-        AsyncRandomAccessWriteDevice& device)+    explicit initiate_async_write_at(AsyncRandomAccessWriteDevice& device)       : device_(device)     {     }@@ -356,7 +369,7 @@        non_const_lvalue<WriteHandler> handler2(handler);       non_const_lvalue<CompletionCondition> completion_cond2(completion_cond);-      start_write_at_buffer_sequence_op(device_, offset, buffers,+      start_write_at_op(device_, offset, buffers,           asio::buffer_sequence_begin(buffers),           completion_cond2.value, handler2.value);     }@@ -368,44 +381,34 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename AsyncRandomAccessWriteDevice,-    typename ConstBufferSequence, typename ConstBufferIterator,-    typename CompletionCondition, typename WriteHandler, typename Allocator>-struct associated_allocator<+template <template <typename, typename> class Associator,+    typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,+    typename ConstBufferIterator, typename CompletionCondition,+    typename WriteHandler, typename DefaultCandidate>+struct associator<Associator,     detail::write_at_op<AsyncRandomAccessWriteDevice, ConstBufferSequence,       ConstBufferIterator, CompletionCondition, WriteHandler>,-    Allocator>+    DefaultCandidate>+  : Associator<WriteHandler, DefaultCandidate> {-  typedef typename associated_allocator<WriteHandler, Allocator>::type type;--  static type get(-      const detail::write_at_op<AsyncRandomAccessWriteDevice,+  static typename Associator<WriteHandler, DefaultCandidate>::type+  get(const detail::write_at_op<AsyncRandomAccessWriteDevice,         ConstBufferSequence, ConstBufferIterator,-        CompletionCondition, WriteHandler>& h,-      const Allocator& a = Allocator()) ASIO_NOEXCEPT+        CompletionCondition, WriteHandler>& h) ASIO_NOEXCEPT   {-    return associated_allocator<WriteHandler, Allocator>::get(h.handler_, a);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);   }-}; -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,+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<WriteHandler, DefaultCandidate>::type)+  get(const detail::write_at_op<AsyncRandomAccessWriteDevice,         ConstBufferSequence, ConstBufferIterator,         CompletionCondition, WriteHandler>& h,-      const Executor& ex = Executor()) ASIO_NOEXCEPT+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<WriteHandler, Executor>::get(h.handler_, ex);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -414,36 +417,47 @@ 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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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_MOVE_ARG(WriteToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_at<+          AsyncRandomAccessWriteDevice> >(),+        token, offset, buffers,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<WriteHandler,+  return async_initiate<WriteToken,     void (asio::error_code, std::size_t)>(-      detail::initiate_async_write_at_buffer_sequence<-        AsyncRandomAccessWriteDevice>(d),-      handler, offset, buffers,+      detail::initiate_async_write_at<AsyncRandomAccessWriteDevice>(d),+      token, 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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d,     uint64_t offset, const ConstBufferSequence& buffers,-    ASIO_MOVE_ARG(WriteHandler) handler)+    ASIO_MOVE_ARG(WriteToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_at<+          AsyncRandomAccessWriteDevice> >(),+        token, offset, buffers, transfer_all()))) {-  return async_initiate<WriteHandler,+  return async_initiate<WriteToken,     void (asio::error_code, std::size_t)>(-      detail::initiate_async_write_at_buffer_sequence<-        AsyncRandomAccessWriteDevice>(d),-      handler, offset, buffers, transfer_all());+      detail::initiate_async_write_at<AsyncRandomAccessWriteDevice>(d),+      token, offset, buffers, transfer_all()); }  #if !defined(ASIO_NO_EXTENSIONS)@@ -481,7 +495,7 @@         const std::size_t bytes_transferred)     {       streambuf_.consume(bytes_transferred);-      handler_(ec, bytes_transferred);+      ASIO_MOVE_OR_LVALUE(WriteHandler)(handler_)(ec, bytes_transferred);     }    //private:@@ -588,34 +602,28 @@  #if !defined(GENERATING_DOCUMENTATION) -template <typename Allocator, typename WriteHandler, typename Allocator1>-struct associated_allocator<-    detail::write_at_streambuf_op<Allocator, WriteHandler>,-    Allocator1>+template <template <typename, typename> class Associator,+    typename Executor, typename WriteHandler, typename DefaultCandidate>+struct associator<Associator,+    detail::write_at_streambuf_op<Executor, WriteHandler>,+    DefaultCandidate>+  : Associator<WriteHandler, DefaultCandidate> {-  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+  static typename Associator<WriteHandler, DefaultCandidate>::type+  get(const detail::write_at_streambuf_op<Executor, WriteHandler>& h)+    ASIO_NOEXCEPT   {-    return associated_allocator<WriteHandler, Allocator1>::get(h.handler_, a);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_);   }-}; -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+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<WriteHandler, DefaultCandidate>::type)+  get(const detail::write_at_streambuf_op<Executor, WriteHandler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<WriteHandler, Executor1>::get(h.handler_, ex);+    return Associator<WriteHandler, DefaultCandidate>::get(h.handler_, c);   } }; @@ -624,36 +632,49 @@ 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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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)+    ASIO_MOVE_ARG(WriteToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_at_streambuf<+          AsyncRandomAccessWriteDevice> >(),+        token, offset, &b,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition)))) {-  return async_initiate<WriteHandler,+  return async_initiate<WriteToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_write_at_streambuf<         AsyncRandomAccessWriteDevice>(d),-      handler, offset, &b,+      token, 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,+      std::size_t)) WriteToken>+inline ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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)+    ASIO_MOVE_ARG(WriteToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_at_streambuf<+          AsyncRandomAccessWriteDevice> >(),+        token, offset, &b, transfer_all()))) {-  return async_initiate<WriteHandler,+  return async_initiate<WriteToken,     void (asio::error_code, std::size_t)>(       detail::initiate_async_write_at_streambuf<         AsyncRandomAccessWriteDevice>(d),-      handler, offset, &b, transfer_all());+      token, offset, &b, transfer_all()); }  #endif // !defined(ASIO_NO_IOSTREAM)
link/modules/asio-standalone/asio/include/asio/io_context.hpp view
@@ -2,7 +2,7 @@ // io_context.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -20,6 +20,8 @@ #include <stdexcept> #include <typeinfo> #include "asio/async_result.hpp"+#include "asio/detail/concurrency_hint.hpp"+#include "asio/detail/cstdint.hpp" #include "asio/detail/wrapped_handler.hpp" #include "asio/error_code.hpp" #include "asio/execution.hpp"@@ -56,9 +58,10 @@    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);+    ASIO_STATIC_CONSTEXPR(uintptr_t, blocking_never = 1);+    ASIO_STATIC_CONSTEXPR(uintptr_t, relationship_continuation = 2);+    ASIO_STATIC_CONSTEXPR(uintptr_t, outstanding_work_tracked = 4);+    ASIO_STATIC_CONSTEXPR(uintptr_t, runtime_bits = 3);   }; } // namespace detail @@ -166,30 +169,12 @@  * 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:+ * using the @ref make_work_guard function to create an object of type+ * asio::executor_work_guard<io_context::executor_type>:  *  * @code asio::io_context io_context;- * asio::any_io_executor work- *   = asio::require(io_context.get_executor(),- *       asio::execution::outstanding_work.tracked);+ * asio::executor_work_guard<asio::io_context::executor_type>+ *   = asio::make_work_guard(io_context);  * ... @endcode  *  * To effect a shutdown, the application will then need to call the io_context@@ -198,15 +183,13 @@  * 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.+ * be allowed to finish normally, the work object 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);+ * asio::executor_work_guard<asio::io_context::executor_type>+ *   = asio::make_work_guard(io_context);  * ...- * work = asio::any_io_executor(); // Allow run() to exit. @endcode+ * work.reset(); // Allow run() to exit. @endcode  */ class io_context   : public execution_context@@ -217,11 +200,16 @@   friend class detail::win_iocp_overlapped_ptr; #endif +#if !defined(ASIO_NO_DEPRECATED)+  struct initiate_dispatch;+  struct initiate_post;+#endif // !defined(ASIO_NO_DEPRECATED)+ public:-  template <typename Allocator, unsigned int Bits>+  template <typename Allocator, uintptr_t Bits>   class basic_executor_type; -  template <typename Allocator, unsigned int Bits>+  template <typename Allocator, uintptr_t Bits>   friend class basic_executor_type;    /// Executor used to submit functions to an io_context.@@ -400,7 +388,7 @@   ASIO_DECL count_type run_one();  #if !defined(ASIO_NO_DEPRECATED)-  /// (Deprecated: Use non-error_code overlaod.) Run the io_context object's+  /// (Deprecated: Use non-error_code overload.) 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@@ -573,8 +561,11 @@    * throws an exception.    */   template <typename LegacyCompletionHandler>-  ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())-  dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler);+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ())+  dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<LegacyCompletionHandler, void ()>(+          declval<initiate_dispatch>(), handler, this)));    /// (Deprecated: Use asio::post().) Request the io_context to invoke   /// the given handler and return immediately.@@ -600,8 +591,11 @@    * throws an exception.    */   template <typename LegacyCompletionHandler>-  ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())-  post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler);+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ())+  post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<LegacyCompletionHandler, void ()>(+          declval<initiate_post>(), handler, this)));    /// (Deprecated: Use asio::bind_executor().) Create a new handler that   /// automatically dispatches the wrapped handler on the io_context.@@ -638,11 +632,6 @@   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); @@ -667,31 +656,30 @@ } // 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+template <typename Allocator, uintptr_t Bits>+class io_context::basic_executor_type :+  detail::io_context_bits, Allocator { public:   /// Copy constructor.   basic_executor_type(       const basic_executor_type& other) ASIO_NOEXCEPT-    : io_context_(other.io_context_),-      allocator_(other.allocator_),-      bits_(other.bits_)+    : Allocator(static_cast<const Allocator&>(other)),+      target_(other.target_)   {     if (Bits & outstanding_work_tracked)-      if (io_context_)-        io_context_->impl_.work_started();+      if (context_ptr())+        context_ptr()->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_)+    : Allocator(ASIO_MOVE_CAST(Allocator)(other)),+      target_(other.target_)   {     if (Bits & outstanding_work_tracked)-      other.io_context_ = 0;+      other.target_ = 0;   } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) @@ -699,8 +687,8 @@   ~basic_executor_type() ASIO_NOEXCEPT   {     if (Bits & outstanding_work_tracked)-      if (io_context_)-        io_context_->impl_.work_finished();+      if (context_ptr())+        context_ptr()->impl_.work_finished();   }    /// Assignment operator.@@ -713,6 +701,12 @@       basic_executor_type&& other) ASIO_NOEXCEPT; #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) +#if !defined(GENERATING_DOCUMENTATION)+private:+  friend struct asio_require_fn::impl;+  friend struct asio_prefer_fn::impl;+#endif // !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@@ -726,8 +720,8 @@   ASIO_CONSTEXPR basic_executor_type require(       execution::blocking_t::possibly_t) const   {-    return basic_executor_type(io_context_,-        allocator_, bits_ & ~blocking_never);+    return basic_executor_type(context_ptr(),+        *this, bits() & ~blocking_never);   }    /// Obtain an executor with the @c blocking.never property.@@ -743,8 +737,8 @@   ASIO_CONSTEXPR basic_executor_type require(       execution::blocking_t::never_t) const   {-    return basic_executor_type(io_context_,-        allocator_, bits_ | blocking_never);+    return basic_executor_type(context_ptr(),+        *this, bits() | blocking_never);   }    /// Obtain an executor with the @c relationship.fork property.@@ -760,8 +754,8 @@   ASIO_CONSTEXPR basic_executor_type require(       execution::relationship_t::fork_t) const   {-    return basic_executor_type(io_context_,-        allocator_, bits_ & ~relationship_continuation);+    return basic_executor_type(context_ptr(),+        *this, bits() & ~relationship_continuation);   }    /// Obtain an executor with the @c relationship.continuation property.@@ -777,8 +771,8 @@   ASIO_CONSTEXPR basic_executor_type require(       execution::relationship_t::continuation_t) const   {-    return basic_executor_type(io_context_,-        allocator_, bits_ | relationship_continuation);+    return basic_executor_type(context_ptr(),+        *this, bits() | relationship_continuation);   }    /// Obtain an executor with the @c outstanding_work.tracked property.@@ -796,7 +790,7 @@   require(execution::outstanding_work_t::tracked_t) const   {     return basic_executor_type<Allocator, Bits | outstanding_work_tracked>(-        io_context_, allocator_, bits_);+        context_ptr(), *this, bits());   }    /// Obtain an executor with the @c outstanding_work.untracked property.@@ -814,7 +808,7 @@   require(execution::outstanding_work_t::untracked_t) const   {     return basic_executor_type<Allocator, Bits & ~outstanding_work_tracked>(-        io_context_, allocator_, bits_);+        context_ptr(), *this, bits());   }    /// Obtain an executor with the specified @c allocator property.@@ -832,7 +826,7 @@   require(execution::allocator_t<OtherAllocator> a) const   {     return basic_executor_type<OtherAllocator, Bits>(-        io_context_, a.value(), bits_);+        context_ptr(), a.value(), bits());   }    /// Obtain an executor with the default @c allocator property.@@ -849,9 +843,16 @@   require(execution::allocator_t<void>) const   {     return basic_executor_type<std::allocator<void>, Bits>(-        io_context_, std::allocator<void>(), bits_);+        context_ptr(), std::allocator<void>(), bits());   } +#if !defined(GENERATING_DOCUMENTATION)+private:+  friend struct asio_query_fn::impl;+  friend struct asio::execution::detail::mapping_t<0>;+  friend struct asio::execution::detail::outstanding_work_t<0>;+#endif // !defined(GENERATING_DOCUMENTATION)+   /// Query the current value of the @c mapping property.   /**    * Do not call this function directly. It is intended for use with the@@ -881,7 +882,7 @@    */   io_context& query(execution::context_t) const ASIO_NOEXCEPT   {-    return *io_context_;+    return *context_ptr();   }    /// Query the current value of the @c blocking property.@@ -898,7 +899,7 @@   ASIO_CONSTEXPR execution::blocking_t query(       execution::blocking_t) const ASIO_NOEXCEPT   {-    return (bits_ & blocking_never)+    return (bits() & blocking_never)       ? execution::blocking_t(execution::blocking.never)       : execution::blocking_t(execution::blocking.possibly);   }@@ -917,7 +918,7 @@   ASIO_CONSTEXPR execution::relationship_t query(       execution::relationship_t) const ASIO_NOEXCEPT   {-    return (bits_ & relationship_continuation)+    return (bits() & relationship_continuation)       ? execution::relationship_t(execution::relationship.continuation)       : execution::relationship_t(execution::relationship.fork);   }@@ -955,7 +956,7 @@   ASIO_CONSTEXPR Allocator query(       execution::allocator_t<OtherAllocator>) const ASIO_NOEXCEPT   {-    return allocator_;+    return static_cast<const Allocator&>(*this);   }    /// Query the current value of the @c allocator property.@@ -971,9 +972,10 @@   ASIO_CONSTEXPR Allocator query(       execution::allocator_t<void>) const ASIO_NOEXCEPT   {-    return allocator_;+    return static_cast<const Allocator&>(*this);   } +public:   /// Determine whether the io_context is running in the current thread.   /**    * @return @c true if the current thread is running the io_context. Otherwise@@ -988,9 +990,8 @@   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_;+    return a.target_ == b.target_+      && static_cast<const Allocator&>(a) == static_cast<const Allocator&>(b);   }    /// Compare two executors for inequality.@@ -1000,24 +1001,16 @@   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_;+    return a.target_ != b.target_+      || static_cast<const Allocator&>(a) != static_cast<const Allocator&>(b);   }    /// 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)+public:   /// Obtain the underlying execution context.   io_context& context() const ASIO_NOEXCEPT; @@ -1096,38 +1089,40 @@  private:   friend class io_context;-  template <typename, unsigned int> friend class basic_executor_type;+  template <typename, uintptr_t> 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)+    : Allocator(),+      target_(reinterpret_cast<uintptr_t>(&i))   {     if (Bits & outstanding_work_tracked)-      io_context_->impl_.work_started();+      context_ptr()->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)+      const Allocator& a, uintptr_t bits) ASIO_NOEXCEPT+    : Allocator(a),+      target_(reinterpret_cast<uintptr_t>(i) | bits)   {     if (Bits & outstanding_work_tracked)-      if (io_context_)-        io_context_->impl_.work_started();+      if (context_ptr())+        context_ptr()->impl_.work_started();   } -  // The underlying io_context.-  io_context* io_context_;+  io_context* context_ptr() const ASIO_NOEXCEPT+  {+    return reinterpret_cast<io_context*>(target_ & ~runtime_bits);+  } -  // The allocator used for execution functions.-  Allocator allocator_;+  uintptr_t bits() const ASIO_NOEXCEPT+  {+    return target_ & runtime_bits;+  } -  // The runtime-switched properties of the io_context executor.-  unsigned int bits_;+  // The underlying io_context and runtime bits.+  uintptr_t target_; };  #if !defined(ASIO_NO_DEPRECATED)@@ -1258,7 +1253,7 @@  #if !defined(ASIO_HAS_DEDUCED_EQUALITY_COMPARABLE_TRAIT) -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct equality_comparable<     asio::io_context::basic_executor_type<Allocator, Bits>   >@@ -1271,7 +1266,7 @@  #if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits, typename Function>+template <typename Allocator, uintptr_t Bits, typename Function> struct execute_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     Function@@ -1286,7 +1281,7 @@  #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::blocking_t::possibly_t@@ -1298,7 +1293,7 @@       Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::blocking_t::never_t@@ -1310,7 +1305,7 @@       Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::relationship_t::fork_t@@ -1322,7 +1317,7 @@       Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::relationship_t::continuation_t@@ -1334,7 +1329,7 @@       Allocator, Bits> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::outstanding_work_t::tracked_t@@ -1346,7 +1341,7 @@       Allocator, Bits | outstanding_work_tracked> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::outstanding_work_t::untracked_t@@ -1358,7 +1353,7 @@       Allocator, Bits & ~outstanding_work_tracked> result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct require_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::allocator_t<void>@@ -1370,7 +1365,7 @@       std::allocator<void>, Bits> result_type; }; -template <unsigned int Bits,+template <uintptr_t Bits,     typename Allocator, typename OtherAllocator> struct require_member<     asio::io_context::basic_executor_type<Allocator, Bits>,@@ -1387,7 +1382,7 @@  #if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits, typename Property>+template <typename Allocator, uintptr_t Bits, typename Property> struct query_static_constexpr_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     Property,@@ -1411,7 +1406,7 @@   } }; -template <typename Allocator, unsigned int Bits, typename Property>+template <typename Allocator, uintptr_t Bits, typename Property> struct query_static_constexpr_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     Property,@@ -1437,7 +1432,7 @@  #if !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT) -template <typename Allocator, unsigned int Bits, typename Property>+template <typename Allocator, uintptr_t Bits, typename Property> struct query_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     Property,@@ -1454,7 +1449,7 @@   typedef asio::execution::blocking_t result_type; }; -template <typename Allocator, unsigned int Bits, typename Property>+template <typename Allocator, uintptr_t Bits, typename Property> struct query_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     Property,@@ -1471,7 +1466,7 @@   typedef asio::execution::relationship_t result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct query_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::context_t@@ -1482,7 +1477,7 @@   typedef asio::io_context& result_type; }; -template <typename Allocator, unsigned int Bits>+template <typename Allocator, uintptr_t Bits> struct query_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::allocator_t<void>@@ -1493,7 +1488,7 @@   typedef Allocator result_type; }; -template <typename Allocator, unsigned int Bits, typename OtherAllocator>+template <typename Allocator, uintptr_t Bits, typename OtherAllocator> struct query_member<     asio::io_context::basic_executor_type<Allocator, Bits>,     asio::execution::allocator_t<OtherAllocator>@@ -1507,6 +1502,15 @@ #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)  } // namespace traits++namespace execution {++template <>+struct is_executor<io_context> : false_type+{+};++} // namespace execution  #endif // !defined(GENERATING_DOCUMENTATION) 
link/modules/asio-standalone/asio/include/asio/io_context_strand.hpp view
@@ -2,7 +2,7 @@ // io_context_strand.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -88,6 +88,12 @@  */ class io_context::strand {+private:+#if !defined(ASIO_NO_DEPRECATED)+  struct initiate_dispatch;+  struct initiate_post;+#endif // !defined(ASIO_NO_DEPRECATED)+ public:   /// Constructor.   /**@@ -183,8 +189,11 @@    * @code void handler(); @endcode    */   template <typename LegacyCompletionHandler>-  ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ())   dispatch(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<LegacyCompletionHandler, void ()>(+          declval<initiate_dispatch>(), handler, this)))   {     return async_initiate<LegacyCompletionHandler, void ()>(         initiate_dispatch(), handler, this);@@ -230,8 +239,11 @@    * @code void handler(); @endcode    */   template <typename LegacyCompletionHandler>-  ASIO_INITFN_AUTO_RESULT_TYPE(LegacyCompletionHandler, void ())+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(LegacyCompletionHandler, void ())   post(ASIO_MOVE_ARG(LegacyCompletionHandler) handler)+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<LegacyCompletionHandler, void ()>(+          declval<initiate_post>(), handler, this)))   {     return async_initiate<LegacyCompletionHandler, void ()>(         initiate_post(), handler, this);
link/modules/asio-standalone/asio/include/asio/io_service.hpp view
@@ -2,7 +2,7 @@ // io_service.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/io_service_strand.hpp view
@@ -2,7 +2,7 @@ // io_service_strand.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/address.hpp view
@@ -2,7 +2,7 @@ // ip/address.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,6 +25,10 @@ #include "asio/ip/address_v6.hpp" #include "asio/ip/bad_address_cast.hpp" +#if defined(ASIO_HAS_STD_HASH)+# include <functional>+#endif // defined(ASIO_HAS_STD_HASH)+ #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM)@@ -257,6 +261,24 @@  } // namespace ip } // namespace asio++#if defined(ASIO_HAS_STD_HASH)+namespace std {++template <>+struct hash<asio::ip::address>+{+  std::size_t operator()(const asio::ip::address& addr)+    const ASIO_NOEXCEPT+  {+    return addr.is_v4()+      ? std::hash<asio::ip::address_v4>()(addr.to_v4())+      : std::hash<asio::ip::address_v6>()(addr.to_v6());+  }+};++} // namespace std+#endif // defined(ASIO_HAS_STD_HASH)  #include "asio/detail/pop_options.hpp" 
link/modules/asio-standalone/asio/include/asio/ip/address_v4.hpp view
@@ -2,7 +2,7 @@ // ip/address_v4.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -24,6 +24,10 @@ #include "asio/detail/winsock_init.hpp" #include "asio/error_code.hpp" +#if defined(ASIO_HAS_STD_HASH)+# include <functional>+#endif // defined(ASIO_HAS_STD_HASH)+ #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM)@@ -60,15 +64,31 @@ #endif    /// Default constructor.+  /**+   * Initialises the @c address_v4 object such that:+   * @li <tt>to_bytes()</tt> yields <tt>{0, 0, 0, 0}</tt>; and+   * @li <tt>to_uint() == 0</tt>.+   */   address_v4() ASIO_NOEXCEPT   {     addr_.s_addr = 0;   }    /// Construct an address from raw bytes.+  /**+   * Initialises the @c address_v4 object such that <tt>to_bytes() ==+   * bytes</tt>.+   *+   * @throws out_of_range Thrown if any element in @c bytes is not in the range+   * <tt>0 - 0xFF</tt>. Note that no range checking is required for platforms+   * where <tt>std::numeric_limits<unsigned char>::max()</tt> is <tt>0xFF</tt>.+   */   ASIO_DECL explicit address_v4(const bytes_type& bytes);    /// Construct an address from an unsigned integer in host byte order.+  /**+   * Initialises the @c address_v4 object such that <tt>to_uint() == addr</tt>.+   */   ASIO_DECL explicit address_v4(uint_type addr);    /// Copy constructor.@@ -104,11 +124,12 @@   /// 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+  /// 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+  /// (Deprecated: Use to_uint().) Get the address as an unsigned long in host+  /// byte order.   ASIO_DECL unsigned long to_ulong() const; #endif // !defined(ASIO_NO_DEPRECATED) @@ -140,9 +161,22 @@ #endif // !defined(ASIO_NO_DEPRECATED)    /// Determine whether the address is a loopback address.+  /**+   * This function tests whether the address is in the address block+   * <tt>127.0.0.0/8</tt>, which corresponds to the address range+   * <tt>127.0.0.0 - 127.255.255.255</tt>.+   *+   * @returns <tt>(to_uint() & 0xFF000000) == 0x7F000000</tt>.+   */   ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT;    /// Determine whether the address is unspecified.+  /**+   * This function tests whether the address is the unspecified address+   * <tt>0.0.0.0</tt>.+   *+   * @returns <tt>to_uint() == 0</tt>.+   */   ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT;  #if !defined(ASIO_NO_DEPRECATED)@@ -160,6 +194,13 @@ #endif // !defined(ASIO_NO_DEPRECATED)    /// Determine whether the address is a multicast address.+  /**+   * This function tests whether the address is in the multicast address block+   * <tt>224.0.0.0/4</tt>, which corresponds to the address range+   * <tt>224.0.0.0 - 239.255.255.255</tt>.+   *+   * @returns <tt>(to_uint() & 0xF0000000) == 0xE0000000</tt>.+   */   ASIO_DECL bool is_multicast() const ASIO_NOEXCEPT;    /// Compare two addresses for equality.@@ -177,6 +218,11 @@   }    /// Compare addresses for ordering.+  /**+   * Compares two addresses in host byte order.+   *+   * @returns <tt>a1.to_uint() < a2.to_uint()</tt>.+   */   friend bool operator<(const address_v4& a1,       const address_v4& a2) ASIO_NOEXCEPT   {@@ -184,6 +230,11 @@   }    /// Compare addresses for ordering.+  /**+   * Compares two addresses in host byte order.+   *+   * @returns <tt>a1.to_uint() > a2.to_uint()</tt>.+   */   friend bool operator>(const address_v4& a1,       const address_v4& a2) ASIO_NOEXCEPT   {@@ -191,6 +242,11 @@   }    /// Compare addresses for ordering.+  /**+   * Compares two addresses in host byte order.+   *+   * @returns <tt>a1.to_uint() <= a2.to_uint()</tt>.+   */   friend bool operator<=(const address_v4& a1,       const address_v4& a2) ASIO_NOEXCEPT   {@@ -198,6 +254,11 @@   }    /// Compare addresses for ordering.+  /**+   * Compares two addresses in host byte order.+   *+   * @returns <tt>a1.to_uint() >= a2.to_uint()</tt>.+   */   friend bool operator>=(const address_v4& a1,       const address_v4& a2) ASIO_NOEXCEPT   {@@ -205,18 +266,36 @@   }    /// Obtain an address object that represents any address.+  /**+   * This functions returns an address that represents the "any" address+   * <tt>0.0.0.0</tt>.+   *+   * @returns A default-constructed @c address_v4 object.+   */   static address_v4 any() ASIO_NOEXCEPT   {     return address_v4();   }    /// Obtain an address object that represents the loopback address.+  /**+   * This function returns an address that represents the well-known loopback+   * address <tt>127.0.0.1</tt>.+   *+   * @returns <tt>address_v4(0x7F000001)</tt>.+   */   static address_v4 loopback() ASIO_NOEXCEPT   {     return address_v4(0x7F000001);   }    /// Obtain an address object that represents the broadcast address.+  /**+   * This function returns an address that represents the broadcast address+   * <tt>255.255.255.255</tt>.+   *+   * @returns <tt>address_v4(0xFFFFFFFF)</tt>.+   */   static address_v4 broadcast() ASIO_NOEXCEPT   {     return address_v4(0xFFFFFFFF);@@ -324,6 +403,22 @@  } // namespace ip } // namespace asio++#if defined(ASIO_HAS_STD_HASH)+namespace std {++template <>+struct hash<asio::ip::address_v4>+{+  std::size_t operator()(const asio::ip::address_v4& addr)+    const ASIO_NOEXCEPT+  {+    return std::hash<unsigned int>()(addr.to_uint());+  }+};++} // namespace std+#endif // defined(ASIO_HAS_STD_HASH)  #include "asio/detail/pop_options.hpp" 
link/modules/asio-standalone/asio/include/asio/ip/address_v4_iterator.hpp view
@@ -2,7 +2,7 @@ // ip/address_v4_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/address_v4_range.hpp view
@@ -2,7 +2,7 @@ // ip/address_v4_range.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/address_v6.hpp view
@@ -2,7 +2,7 @@ // ip/address_v6.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,12 +18,17 @@ #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" #include "asio/ip/address_v4.hpp" +#if defined(ASIO_HAS_STD_HASH)+# include <functional>+#endif // defined(ASIO_HAS_STD_HASH)+ #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM)@@ -35,6 +40,9 @@  template <typename> class basic_address_iterator; +/// Type used for storing IPv6 scope IDs.+typedef uint_least32_t scope_id_type;+ /// Implements IP version 6 style addresses. /**  * The asio::ip::address_v6 class provides the ability to use and@@ -59,11 +67,25 @@ #endif    /// Default constructor.+  /**+   * Initialises the @c address_v6 object such that:+   * @li <tt>to_bytes()</tt> yields <tt>{0, 0, ..., 0}</tt>; and+   * @li <tt>scope_id() == 0</tt>.+   */   ASIO_DECL address_v6() ASIO_NOEXCEPT;    /// Construct an address from raw bytes and scope ID.+  /**+   * Initialises the @c address_v6 object such that:+   * @li <tt>to_bytes() == bytes</tt>; and+   * @li <tt>this->scope_id() == scope_id</tt>.+   *+   * @throws out_of_range Thrown if any element in @c bytes is not in the range+   * <tt>0 - 0xFF</tt>. Note that no range checking is required for platforms+   * where <tt>std::numeric_limits<unsigned char>::max()</tt> is <tt>0xFF</tt>.+   */   ASIO_DECL explicit address_v6(const bytes_type& bytes,-      unsigned long scope_id = 0);+      scope_id_type scope_id = 0);    /// Copy constructor.   ASIO_DECL address_v6(const address_v6& other) ASIO_NOEXCEPT;@@ -86,7 +108,7 @@   /**    * Returns the scope ID associated with the IPv6 address.    */-  unsigned long scope_id() const ASIO_NOEXCEPT+  scope_id_type scope_id() const ASIO_NOEXCEPT   {     return scope_id_;   }@@ -94,8 +116,10 @@   /// The scope ID of the address.   /**    * Modifies the scope ID associated with the IPv6 address.+   *+   * @param id The new scope ID.    */-  void scope_id(unsigned long id) ASIO_NOEXCEPT+  void scope_id(scope_id_type id) ASIO_NOEXCEPT   {     scope_id_ = id;   }@@ -134,9 +158,17 @@ #endif // !defined(ASIO_NO_DEPRECATED)    /// Determine whether the address is a loopback address.+  /**+   * This function tests whether the address is the loopback address+   * <tt>::1</tt>.+   */   ASIO_DECL bool is_loopback() const ASIO_NOEXCEPT;    /// Determine whether the address is unspecified.+  /**+   * This function tests whether the address is the loopback address+   * <tt>::</tt>.+   */   ASIO_DECL bool is_unspecified() const ASIO_NOEXCEPT;    /// Determine whether the address is link local.@@ -209,12 +241,22 @@   }    /// Obtain an address object that represents any address.+  /**+   * This functions returns an address that represents the "any" address+   * <tt>::</tt>.+   *+   * @returns A default-constructed @c address_v6 object.+   */   static address_v6 any() ASIO_NOEXCEPT   {     return address_v6();   }    /// Obtain an address object that represents the loopback address.+  /**+   * This function returns an address that represents the well-known loopback+   * address <tt>::1</tt>.+   */   ASIO_DECL static address_v6 loopback() ASIO_NOEXCEPT;  #if !defined(ASIO_NO_DEPRECATED)@@ -232,7 +274,7 @@   asio::detail::in6_addr_type addr_;    // The scope ID associated with the address.-  unsigned long scope_id_;+  scope_id_type scope_id_; };  /// Create an IPv6 address from raw bytes and scope ID.@@ -240,7 +282,7 @@  * @relates address_v6  */ inline address_v6 make_address_v6(const address_v6::bytes_type& bytes,-    unsigned long scope_id = 0)+    scope_id_type scope_id = 0) {   return address_v6(bytes, scope_id); }@@ -330,6 +372,39 @@  } // namespace ip } // namespace asio++#if defined(ASIO_HAS_STD_HASH)+namespace std {++template <>+struct hash<asio::ip::address_v6>+{+  std::size_t operator()(const asio::ip::address_v6& addr)+    const ASIO_NOEXCEPT+  {+    const asio::ip::address_v6::bytes_type bytes = addr.to_bytes();+    std::size_t result = static_cast<std::size_t>(addr.scope_id());+    combine_4_bytes(result, &bytes[0]);+    combine_4_bytes(result, &bytes[4]);+    combine_4_bytes(result, &bytes[8]);+    combine_4_bytes(result, &bytes[12]);+    return result;+  }++private:+  static void combine_4_bytes(std::size_t& seed, const unsigned char* bytes)+  {+    const std::size_t bytes_hash =+      (static_cast<std::size_t>(bytes[0]) << 24) |+      (static_cast<std::size_t>(bytes[1]) << 16) |+      (static_cast<std::size_t>(bytes[2]) << 8) |+      (static_cast<std::size_t>(bytes[3]));+    seed ^= bytes_hash + 0x9e3779b9 + (seed << 6) + (seed >> 2);+  }+};++} // namespace std+#endif // defined(ASIO_HAS_STD_HASH)  #include "asio/detail/pop_options.hpp" 
link/modules/asio-standalone/asio/include/asio/ip/address_v6_iterator.hpp view
@@ -2,7 +2,7 @@ // ip/address_v6_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/ip/address_v6_range.hpp view
@@ -2,7 +2,7 @@ // ip/address_v6_range.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/ip/bad_address_cast.hpp view
@@ -2,7 +2,7 @@ // ip/bad_address_cast.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/basic_endpoint.hpp view
@@ -2,7 +2,7 @@ // ip/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,9 +16,14 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"+#include "asio/detail/cstdint.hpp" #include "asio/ip/address.hpp" #include "asio/ip/detail/endpoint.hpp" +#if defined(ASIO_HAS_STD_HASH)+# include <functional>+#endif // defined(ASIO_HAS_STD_HASH)+ #if !defined(ASIO_NO_IOSTREAM) # include <iosfwd> #endif // !defined(ASIO_NO_IOSTREAM)@@ -28,6 +33,9 @@ namespace asio { namespace ip { +/// Type used for storing port numbers.+typedef uint_least16_t port_type;+ /// Describes an endpoint for a version-independent IP socket. /**  * The asio::ip::basic_endpoint class template describes an endpoint that@@ -78,7 +86,7 @@    * @endcode    */   basic_endpoint(const InternetProtocol& internet_protocol,-      unsigned short port_num) ASIO_NOEXCEPT+      port_type port_num) ASIO_NOEXCEPT     : impl_(internet_protocol.family(), port_num)   {   }@@ -87,7 +95,7 @@   /// 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+      port_type port_num) ASIO_NOEXCEPT     : impl_(addr, port_num)   {   }@@ -162,14 +170,14 @@    /// Get the port associated with the endpoint. The port number is always in   /// the host's byte order.-  unsigned short port() const ASIO_NOEXCEPT+  port_type 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+  void port(port_type port_num) ASIO_NOEXCEPT   {     impl_.port(port_num);   }@@ -256,6 +264,25 @@  } // namespace ip } // namespace asio++#if defined(ASIO_HAS_STD_HASH)+namespace std {++template <typename InternetProtocol>+struct hash<asio::ip::basic_endpoint<InternetProtocol> >+{+  std::size_t operator()(+      const asio::ip::basic_endpoint<InternetProtocol>& ep)+    const ASIO_NOEXCEPT+  {+    std::size_t hash1 = std::hash<asio::ip::address>()(ep.address());+    std::size_t hash2 = std::hash<unsigned short>()(ep.port());+    return hash1 ^ (hash2 + 0x9e3779b9 + (hash1 << 6) + (hash1 >> 2));+  }+};++} // namespace std+#endif // defined(ASIO_HAS_STD_HASH)  #include "asio/detail/pop_options.hpp" 
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -67,6 +67,9 @@ class basic_resolver   : public resolver_base {+private:+  class initiate_async_resolve;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -105,7 +108,7 @@    * resolver.    */   explicit basic_resolver(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -119,10 +122,10 @@    */   template <typename ExecutionContext>   explicit basic_resolver(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {   } @@ -142,6 +145,29 @@   {   } +  // All resolvers have access to each other's implementations.+  template <typename InternetProtocol1, typename Executor1>+  friend class basic_resolver;++  /// 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.+   */+  template <typename Executor1>+  basic_resolver(basic_resolver<InternetProtocol, Executor1>&& other,+      typename constraint<+          is_convertible<Executor1, Executor>::value+      >::type = 0)+    : impl_(std::move(other.impl_))+  {+  }+   /// Move-assign a basic_resolver from another.   /**    * This assignment operator moves a resolver from one object to another.@@ -159,6 +185,29 @@     impl_ = std::move(other.impl_);     return *this;   }++  /// 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.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_resolver&+  >::type operator=(basic_resolver<InternetProtocol, Executor1>&& other)+  {+    basic_resolver tmp(std::move(other));+    impl_ = std::move(tmp.impl_);+    return *this;+  } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)    /// Destroys the resolver.@@ -601,38 +650,48 @@   /// 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.+   * endpoint entries. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *    * @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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the resolve completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.    *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *    * A successful resolve operation is guaranteed to pass a non-empty range to    * the handler.+   *+   * @par Completion Signature+   * @code void(asio::error_code, results_type) @endcode    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        results_type)) ResolveHandler+        results_type)) ResolveToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken,       void (asio::error_code, results_type))   async_resolve(const query& q,-      ASIO_MOVE_ARG(ResolveHandler) handler+      ASIO_MOVE_ARG(ResolveToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      asio::async_initiate<ResolveToken,+        void (asio::error_code, results_type)>(+          declval<initiate_async_resolve>(), token, q)))   {-    return asio::async_initiate<ResolveHandler,+    return asio::async_initiate<ResolveToken,       void (asio::error_code, results_type)>(-        initiate_async_resolve(this), handler, q);+        initiate_async_resolve(this), token, q);   } #endif // !defined(ASIO_NO_DEPRECATED) @@ -652,21 +711,26 @@    * 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the resolve completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.    *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *    * A successful resolve operation is guaranteed to pass a non-empty range to    * the handler.    *+   * @par Completion Signature+   * @code void(asio::error_code, results_type) @endcode+   *    * @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@@ -680,23 +744,29 @@    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        results_type)) ResolveHandler+        results_type)) ResolveToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken,       void (asio::error_code, results_type))   async_resolve(ASIO_STRING_VIEW_PARAM host,       ASIO_STRING_VIEW_PARAM service,-      ASIO_MOVE_ARG(ResolveHandler) handler+      ASIO_MOVE_ARG(ResolveToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      asio::async_initiate<ResolveToken,+        void (asio::error_code, results_type)>(+          declval<initiate_async_resolve>(), token,+          declval<basic_resolver_query<protocol_type>&>())))   {     return async_resolve(host, service, resolver_base::flags(),-        ASIO_MOVE_CAST(ResolveHandler)(handler));+        ASIO_MOVE_CAST(ResolveToken)(token));   }    /// 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.+   * endpoint entries. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *    * @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@@ -714,21 +784,26 @@    * 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the resolve completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.    *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *    * A successful resolve operation is guaranteed to pass a non-empty range to    * the handler.    *+   * @par Completion Signature+   * @code void(asio::error_code, results_type) @endcode+   *    * @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@@ -742,28 +817,34 @@    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        results_type)) ResolveHandler+        results_type)) ResolveToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken,       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_MOVE_ARG(ResolveToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      asio::async_initiate<ResolveToken,+        void (asio::error_code, results_type)>(+          declval<initiate_async_resolve>(), token,+          declval<basic_resolver_query<protocol_type>&>())))   {     basic_resolver_query<protocol_type> q(static_cast<std::string>(host),         static_cast<std::string>(service), resolve_flags); -    return asio::async_initiate<ResolveHandler,+    return asio::async_initiate<ResolveToken,       void (asio::error_code, results_type)>(-        initiate_async_resolve(this), handler, q);+        initiate_async_resolve(this), token, 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.+   * endpoint entries. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *    * @param protocol A protocol object, normally representing either the IPv4 or    * IPv6 version of an internet protocol.@@ -779,21 +860,26 @@    * 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the resolve completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.    *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *    * A successful resolve operation is guaranteed to pass a non-empty range to    * the handler.    *+   * @par Completion Signature+   * @code void(asio::error_code, results_type) @endcode+   *    * @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@@ -807,23 +893,29 @@    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        results_type)) ResolveHandler+        results_type)) ResolveToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken,       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_MOVE_ARG(ResolveToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      asio::async_initiate<ResolveToken,+        void (asio::error_code, results_type)>(+          declval<initiate_async_resolve>(), token,+          declval<basic_resolver_query<protocol_type>&>())))   {     return async_resolve(protocol, host, service, resolver_base::flags(),-        ASIO_MOVE_CAST(ResolveHandler)(handler));+        ASIO_MOVE_CAST(ResolveToken)(token));   }    /// 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.+   * endpoint entries. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *    * @param protocol A protocol object, normally representing either the IPv4 or    * IPv6 version of an internet protocol.@@ -844,21 +936,26 @@    * 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the resolve completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.    *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *    * A successful resolve operation is guaranteed to pass a non-empty range to    * the handler.    *+   * @par Completion Signature+   * @code void(asio::error_code, results_type) @endcode+   *    * @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@@ -872,23 +969,28 @@    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        results_type)) ResolveHandler+        results_type)) ResolveToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken,       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_MOVE_ARG(ResolveToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      asio::async_initiate<ResolveToken,+        void (asio::error_code, results_type)>(+          declval<initiate_async_resolve>(), token,+          declval<basic_resolver_query<protocol_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,+    return asio::async_initiate<ResolveToken,       void (asio::error_code, results_type)>(-        initiate_async_resolve(this), handler, q);+        initiate_async_resolve(this), token, q);   }    /// Perform reverse resolution of an endpoint to a list of entries.@@ -937,39 +1039,49 @@   /// entries.   /**    * This function is used to asynchronously resolve an endpoint into a list of-   * endpoint entries.+   * endpoint entries. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *    * @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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the resolve completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.    *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *    * A successful resolve operation is guaranteed to pass a non-empty range to    * the handler.+   *+   * @par Completion Signature+   * @code void(asio::error_code, results_type) @endcode    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        results_type)) ResolveHandler+        results_type)) ResolveToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ResolveHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ResolveToken,       void (asio::error_code, results_type))   async_resolve(const endpoint_type& e,-      ASIO_MOVE_ARG(ResolveHandler) handler+      ASIO_MOVE_ARG(ResolveToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      asio::async_initiate<ResolveToken,+        void (asio::error_code, results_type)>(+          declval<initiate_async_resolve>(), token, e)))   {-    return asio::async_initiate<ResolveHandler,+    return asio::async_initiate<ResolveToken,       void (asio::error_code, results_type)>(-        initiate_async_resolve(this), handler, e);+        initiate_async_resolve(this), token, e);   }  private:
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_entry.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver_entry.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_iterator.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver_iterator.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_query.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver_query.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_results.hpp view
@@ -2,7 +2,7 @@ // ip/basic_resolver_results.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/detail/endpoint.hpp view
@@ -2,7 +2,7 @@ // ip/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/detail/impl/endpoint.ipp view
@@ -2,7 +2,7 @@ // ip/detail/impl/endpoint.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/detail/socket_option.hpp view
@@ -2,7 +2,7 @@ // detail/socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/host_name.hpp view
@@ -2,7 +2,7 @@ // ip/host_name.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/icmp.hpp view
@@ -2,7 +2,7 @@ // ip/icmp.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address.hpp view
@@ -2,7 +2,7 @@ // ip/impl/address.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address.ipp view
@@ -2,7 +2,7 @@ // ip/impl/address.ipp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.hpp view
@@ -2,7 +2,7 @@ // ip/impl/address_v4.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.ipp view
@@ -2,7 +2,7 @@ // ip/impl/address_v4.ipp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.hpp view
@@ -2,7 +2,7 @@ // ip/impl/address_v6.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.ipp view
@@ -2,7 +2,7 @@ // ip/impl/address_v6.ipp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -38,7 +38,7 @@ }  address_v6::address_v6(const address_v6::bytes_type& bytes,-    unsigned long scope)+    scope_id_type scope)   : scope_id_(scope) { #if UCHAR_MAX > 0xFF
link/modules/asio-standalone/asio/include/asio/ip/impl/basic_endpoint.hpp view
@@ -2,7 +2,7 @@ // ip/impl/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/host_name.ipp view
@@ -2,7 +2,7 @@ // ip/impl/host_name.ipp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.hpp view
@@ -2,7 +2,7 @@ // ip/impl/network_v4.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.ipp view
@@ -2,7 +2,7 @@ // ip/impl/network_v4.ipp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -129,7 +129,9 @@   using namespace std; // For sprintf.   ec = asio::error_code();   char prefix_len[16];-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+  snprintf(prefix_len, sizeof(prefix_len), "/%u", prefix_length_);+#elif 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_);
link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.hpp view
@@ -2,7 +2,7 @@ // ip/impl/network_v6.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.ipp view
@@ -2,7 +2,7 @@ // ip/impl/network_v6.ipp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -98,7 +98,9 @@   using namespace std; // For sprintf.   ec = asio::error_code();   char prefix_len[16];-#if defined(ASIO_HAS_SECURE_RTL)+#if defined(ASIO_HAS_SNPRINTF)+  snprintf(prefix_len, sizeof(prefix_len), "/%u", prefix_length_);+#elif 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_);
link/modules/asio-standalone/asio/include/asio/ip/multicast.hpp view
@@ -2,7 +2,7 @@ // ip/multicast.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/network_v4.hpp view
@@ -2,7 +2,7 @@ // ip/network_v4.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -122,7 +122,7 @@   /// Obtain the true network address, omitting any host bits.   network_v4 canonical() const ASIO_NOEXCEPT   {-    return network_v4(network(), netmask());+    return network_v4(network(), prefix_length());   }    /// Test if network is a valid host address.
link/modules/asio-standalone/asio/include/asio/ip/network_v6.hpp view
@@ -2,7 +2,7 @@ // ip/network_v6.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/ip/resolver_base.hpp view
@@ -2,7 +2,7 @@ // ip/resolver_base.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/resolver_query_base.hpp view
@@ -2,7 +2,7 @@ // ip/resolver_query_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/tcp.hpp view
@@ -2,7 +2,7 @@ // ip/tcp.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/udp.hpp view
@@ -2,7 +2,7 @@ // ip/udp.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/unicast.hpp view
@@ -2,7 +2,7 @@ // ip/unicast.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ip/v6_only.hpp view
@@ -2,7 +2,7 @@ // ip/v6_only.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -26,7 +26,7 @@ /// Socket option for determining whether an IPv6 socket supports IPv6 /// communication only. /**- * Implements the IPPROTO_IPV6/IP_V6ONLY socket option.+ * Implements the IPPROTO_IPV6/IPV6_V6ONLY socket option.  *  * @par Examples  * Setting the option:
link/modules/asio-standalone/asio/include/asio/is_applicable_property.hpp view
@@ -2,7 +2,7 @@ // is_applicable_property.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/is_contiguous_iterator.hpp view
@@ -0,0 +1,45 @@+//+// is_contiguous_iterator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_CONTIGUOUS_ITERATOR_HPP+#define ASIO_IS_CONTIGUOUS_ITERATOR_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"+#include <iterator>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// The is_contiguous_iterator class is a traits class that may be used to+/// determine whether a type is a contiguous iterator.+template <typename T>+struct is_contiguous_iterator :+#if defined(ASIO_HAS_STD_CONCEPTS) \+  || defined(GENERATING_DOCUMENTATION)+  integral_constant<bool, std::contiguous_iterator<T> >+#else // defined(ASIO_HAS_STD_CONCEPTS)+      //   || defined(GENERATING_DOCUMENTATION)+  is_pointer<T>+#endif // defined(ASIO_HAS_STD_CONCEPTS)+       //   || defined(GENERATING_DOCUMENTATION)+{+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_IS_CONTIGUOUS_ITERATOR_HPP
link/modules/asio-standalone/asio/include/asio/is_executor.hpp view
@@ -2,7 +2,7 @@ // is_executor.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/is_read_buffered.hpp view
@@ -2,7 +2,7 @@ // is_read_buffered.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/is_write_buffered.hpp view
@@ -2,7 +2,7 @@ // is_write_buffered.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/local/basic_endpoint.hpp view
@@ -2,7 +2,7 @@ // local/basic_endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/local/connect_pair.hpp view
@@ -2,7 +2,7 @@ // local/connect_pair.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/local/datagram_protocol.hpp view
@@ -2,7 +2,7 @@ // local/datagram_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/local/detail/endpoint.hpp view
@@ -2,7 +2,7 @@ // local/detail/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/local/detail/impl/endpoint.ipp view
@@ -2,7 +2,7 @@ // local/detail/impl/endpoint.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -112,17 +112,12 @@     asio::detail::throw_error(ec);   } -  using namespace std; // For memcpy.-  data_.local = asio::detail::sockaddr_un_type();+  using namespace std; // For memset and memcpy.+  memset(&data_.local, 0, sizeof(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
+ link/modules/asio-standalone/asio/include/asio/local/seq_packet_protocol.hpp view
@@ -0,0 +1,84 @@+//+// local/seq_packet_protocol.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_SEQ_PACKET_PROTOCOL_HPP+#define ASIO_LOCAL_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"++#if defined(ASIO_HAS_LOCAL_SOCKETS) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_socket_acceptor.hpp"+#include "asio/basic_seq_packet_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 seq_packet UNIX sockets.+/**+ * The asio::local::seq_packet_protocol class contains flags necessary+ * for sequenced packet UNIX domain sockets.+ *+ * @par Thread Safety+ * @e Distinct @e objects: Safe.@n+ * @e Shared @e objects: Safe.+ *+ * @par Concepts:+ * Protocol.+ */+class seq_packet_protocol+{+public:+  /// Obtain an identifier for the type of the protocol.+  int type() const ASIO_NOEXCEPT+  {+    return SOCK_SEQPACKET;+  }++  /// 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<seq_packet_protocol> endpoint;++  /// The UNIX domain socket type.+  typedef basic_seq_packet_socket<seq_packet_protocol> socket;++  /// The UNIX domain acceptor type.+  typedef basic_socket_acceptor<seq_packet_protocol> acceptor;+};++} // namespace local+} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // defined(ASIO_HAS_LOCAL_SOCKETS)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_LOCAL_SEQ_PACKET_PROTOCOL_HPP
link/modules/asio-standalone/asio/include/asio/local/stream_protocol.hpp view
@@ -2,7 +2,7 @@ // local/stream_protocol.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/multiple_exceptions.hpp view
@@ -2,7 +2,7 @@ // multiple_exceptions.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/packaged_task.hpp view
@@ -2,7 +2,7 @@ // packaged_task.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/placeholders.hpp view
@@ -2,7 +2,7 @@ // placeholders.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/posix/basic_descriptor.hpp view
@@ -2,7 +2,7 @@ // posix/basic_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -25,12 +25,17 @@ #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_IO_URING_AS_DEFAULT)+# include "asio/detail/io_uring_descriptor_service.hpp"+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+# include "asio/detail/reactive_descriptor_service.hpp"+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)+ #if defined(ASIO_HAS_MOVE) # include <utility> #endif // defined(ASIO_HAS_MOVE)@@ -53,6 +58,9 @@ class basic_descriptor   : public descriptor_base {+private:+  class initiate_async_wait;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -68,10 +76,13 @@   /// The native representation of a descriptor. #if defined(GENERATING_DOCUMENTATION)   typedef implementation_defined native_handle_type;-#else+#elif defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  typedef detail::io_uring_descriptor_service::native_handle_type+    native_handle_type;+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)   typedef detail::reactive_descriptor_service::native_handle_type     native_handle_type;-#endif+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)    /// A descriptor is always the lowest layer.   typedef basic_descriptor lowest_layer_type;@@ -85,7 +96,7 @@    * descriptor.    */   explicit basic_descriptor(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -99,10 +110,11 @@    */   template <typename ExecutionContext>   explicit basic_descriptor(ExecutionContext& context,-      typename enable_if<-        is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {   } @@ -121,7 +133,7 @@    */   basic_descriptor(const executor_type& ex,       const native_handle_type& native_descriptor)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(),@@ -145,10 +157,10 @@   template <typename ExecutionContext>   basic_descriptor(ExecutionContext& context,       const native_handle_type& native_descriptor,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(),@@ -189,10 +201,58 @@     impl_ = std::move(other.impl_);     return *this;   }++  // All descriptors have access to each other's implementations.+  template <typename Executor1>+  friend class basic_descriptor;++  /// Move-construct a basic_descriptor from a descriptor of another executor+  /// type.+  /**+   * This constructor moves a descriptor from one object to another.+   *+   * @param other The other basic_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.+   */+  template <typename Executor1>+  basic_descriptor(basic_descriptor<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign a basic_descriptor from a descriptor of another executor type.+  /**+   * This assignment operator moves a descriptor from one object to another.+   *+   * @param other The other basic_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.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_descriptor&+  >::type operator=(basic_descriptor<Executor1> && other)+  {+    basic_descriptor 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+  const executor_type& get_executor() ASIO_NOEXCEPT   {     return impl_.get_executor();   }@@ -588,21 +648,28 @@   /// 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.+   * enter a ready to read, write or error condition state. It is an initiating+   * function for an @ref asynchronous_operation, and always returns+   * immediately.    *    * @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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the wait completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(-   *   const asio::error_code& error // Result of operation+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *    * @par Example    * @code    * void wait_handler(const asio::error_code& error)@@ -621,18 +688,31 @@    *     asio::posix::stream_descriptor::wait_read,    *     wait_handler);    * @endcode+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+        WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken,       void (asio::error_code))   async_wait(wait_type w,-      ASIO_MOVE_ARG(WaitHandler) handler+      ASIO_MOVE_ARG(WaitToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WaitToken, void (asio::error_code)>(+          declval<initiate_async_wait>(), token, w)))   {-    return async_initiate<WaitHandler, void (asio::error_code)>(-        initiate_async_wait(this), handler, w);+    return async_initiate<WaitToken, void (asio::error_code)>(+        initiate_async_wait(this), token, w);   }  protected:@@ -646,7 +726,11 @@   {   } +#if defined(ASIO_HAS_IO_URING_AS_DEFAULT)+  detail::io_object_impl<detail::io_uring_descriptor_service, Executor> impl_;+#else // defined(ASIO_HAS_IO_URING_AS_DEFAULT)   detail::io_object_impl<detail::reactive_descriptor_service, Executor> impl_;+#endif // defined(ASIO_HAS_IO_URING_AS_DEFAULT)  private:   // Disallow copying and assignment.@@ -663,7 +747,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
link/modules/asio-standalone/asio/include/asio/posix/basic_stream_descriptor.hpp view
@@ -2,7 +2,7 @@ // posix/basic_stream_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,11 +16,13 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"-#include "asio/posix/descriptor.hpp"+#include "asio/posix/basic_descriptor.hpp"  #if defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR) \   || defined(GENERATING_DOCUMENTATION) +#include "asio/detail/push_options.hpp"+ namespace asio { namespace posix { @@ -33,6 +35,12 @@  * @e Distinct @e objects: Safe.@n  * @e Shared @e objects: Unsafe.  *+ * Synchronous @c read_some and @c write_some operations are thread safe with+ * respect to each other, if the underlying operating system calls are also+ * thread safe. This means that it is permitted to perform concurrent calls to+ * these synchronous operations on a single descriptor object. Other synchronous+ * operations, such as @c close, are not thread safe.+ *  * @par Concepts:  * AsyncReadStream, AsyncWriteStream, Stream, SyncReadStream, SyncWriteStream.  */@@ -40,6 +48,10 @@ class basic_stream_descriptor   : public basic_descriptor<Executor> {+private:+  class initiate_async_write_some;+  class initiate_async_read_some;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -83,9 +95,10 @@    */   template <typename ExecutionContext>   explicit basic_stream_descriptor(ExecutionContext& context,-      typename enable_if<-        is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      typename constraint<+        is_convertible<ExecutionContext&, execution_context&>::value,+        defaulted_constraint+      >::type = defaulted_constraint())     : basic_descriptor<Executor>(context)   {   }@@ -125,9 +138,9 @@   template <typename ExecutionContext>   basic_stream_descriptor(ExecutionContext& context,       const native_handle_type& native_descriptor,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_descriptor<Executor>(context, native_descriptor)   {   }@@ -145,7 +158,7 @@    * constructor.    */   basic_stream_descriptor(basic_stream_descriptor&& other) ASIO_NOEXCEPT-    : descriptor(std::move(other))+    : basic_descriptor<Executor>(std::move(other))   {   } @@ -163,9 +176,53 @@    */   basic_stream_descriptor& operator=(basic_stream_descriptor&& other)   {-    descriptor::operator=(std::move(other));+    basic_descriptor<Executor>::operator=(std::move(other));     return *this;   }++  /// Move-construct a basic_stream_descriptor from a descriptor of another+  /// executor type.+  /**+   * This constructor moves a descriptor from one object to another.+   *+   * @param other The other basic_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.+   */+  template <typename Executor1>+  basic_stream_descriptor(basic_stream_descriptor<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_descriptor<Executor>(std::move(other))+  {+  }++  /// Move-assign a basic_stream_descriptor from a descriptor of another+  /// executor type.+  /**+   * This assignment operator moves a descriptor from one object to another.+   *+   * @param other The other basic_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.+   */+  template <typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_stream_descriptor&+  >::type operator=(basic_stream_descriptor<Executor1> && other)+  {+    basic_descriptor<Executor>::operator=(std::move(other));+    return *this;+  } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)    /// Write some data to the descriptor.@@ -232,25 +289,31 @@   /// Start an asynchronous write.   /**    * This function is used to asynchronously write data to the stream-   * descriptor. The function call always returns immediately.+   * descriptor. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *    * @param buffers One or more data buffers to be written to the 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.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the write completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes written.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The write operation may not transmit all of the data to the peer.    * Consider using the @ref async_write function if you need to ensure that all    * data is written before the asynchronous operation completes.@@ -263,20 +326,34 @@    * See the @ref buffer documentation for information on writing multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_write_some(const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          initiate_async_write_some(this), token, buffers)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_write_some(this), handler, buffers);+        initiate_async_write_some(this), token, buffers);   }    /// Read some data from the descriptor.@@ -345,25 +422,31 @@   /// Start an asynchronous read.   /**    * This function is used to asynchronously read data from the stream-   * descriptor. The function call always returns immediately.+   * descriptor. It is an initiating function for an @ref+   * asynchronous_operation, and always returns immediately.    *    * @param buffers One or more buffers into which the data will be read.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the read completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes read.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The read operation may not read all of the requested number of bytes.    * Consider using the @ref async_read function if you need to ensure that the    * requested amount of data is read before the asynchronous operation@@ -377,20 +460,34 @@    * See the @ref buffer documentation for information on reading into multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_read_some(const MutableBufferSequence& buffers,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_read_some>(), token, buffers)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_read_some(this), handler, buffers);+        initiate_async_read_some(this), token, buffers);   }  private:@@ -404,7 +501,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -437,7 +534,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -463,6 +560,8 @@  } // namespace posix } // namespace asio++#include "asio/detail/pop_options.hpp"  #endif // defined(ASIO_HAS_POSIX_STREAM_DESCRIPTOR)        //   || defined(GENERATING_DOCUMENTATION)
link/modules/asio-standalone/asio/include/asio/posix/descriptor.hpp view
@@ -2,7 +2,7 @@ // posix/descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/posix/descriptor_base.hpp view
@@ -2,7 +2,7 @@ // posix/descriptor_base.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/posix/stream_descriptor.hpp view
@@ -2,7 +2,7 @@ // posix/stream_descriptor.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/post.hpp view
@@ -2,7 +2,7 @@ // post.hpp // ~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,10 +17,13 @@  #include "asio/detail/config.hpp" #include "asio/async_result.hpp"+#include "asio/detail/initiate_post.hpp" #include "asio/detail/type_traits.hpp" #include "asio/execution_context.hpp"+#include "asio/execution/blocking.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp"+#include "asio/require.hpp"  #include "asio/detail/push_options.hpp" @@ -35,27 +38,54 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode  *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{}, token)</tt>, where @c Init is a function object type defined+ * as:  *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @code class Init+ * {+ * public:+ *   template <typename CompletionHandler>+ *     void operator()(CompletionHandler&& completion_handler) const;+ * }; @endcode  *- * @li Obtains the handler's associated executor object @c ex by performing- * <tt>get_associated_executor(handler)</tt>.+ * The function call operator of @c Init:  *+ * @li Obtains the handler's associated executor object @c ex of type @c Ex by+ * performing @code auto ex = get_associated_executor(handler); @endcode+ *  * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode  *- * @li Performs <tt>ex.post(std::move(handler), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(+ *     require(ex, execution::blocking.never),+ *     execution::relationship.fork,+ *     execution::allocator(alloc)+ *   ).execute(std::forward<CompletionHandler>(completion_handler)); @endcode  *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.post(+ *     std::forward<CompletionHandler>(completion_handler),+ *     alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode  */-template <ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(-    ASIO_MOVE_ARG(CompletionToken) token);+template <ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) post(+    ASIO_MOVE_ARG(NullaryToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<NullaryToken, void()>(+        declval<detail::initiate_post>(), token)))+{+  return async_initiate<NullaryToken, void()>(+      detail::initiate_post(), token);+}  /// Submits a completion token or function object for execution. /**@@ -66,61 +96,123 @@  * 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:+ * @param ex The target executor.  *- * @li Constructs a function object handler of type @c Handler, initialized- * with <tt>handler(forward<CompletionToken>(token))</tt>.+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode  *- * @li Constructs an object @c result of type <tt>async_result<Handler></tt>,- * initializing the object as <tt>result(handler)</tt>.+ * @returns This function returns <tt>async_initiate<NullaryToken,+ * void()>(Init{ex}, token)</tt>, where @c Init is a function object type+ * defined as:  *- * @li Obtains the handler's associated executor object @c ex1 by performing- * <tt>get_associated_executor(handler)</tt>.+ * @code class Init+ * {+ * public:+ *   using executor_type = Executor;+ *   explicit Init(const Executor& ex) : ex_(ex) {}+ *   executor_type get_executor() const noexcept { return ex_; }+ *   template <typename CompletionHandler>+ *     void operator()(CompletionHandler&& completion_handler) const;+ * private:+ *   Executor ex_; // exposition only+ * }; @endcode  *- * @li Creates a work object @c w by performing <tt>make_work(ex1)</tt>.+ * The function call operator of @c Init:  *+ * @li Obtains the handler's associated executor object @c ex1 of type @c Ex1 by+ * performing @code auto ex1 = get_associated_executor(handler, ex); @endcode+ *  * @li Obtains the handler's associated allocator object @c alloc by performing- * <tt>get_associated_allocator(handler)</tt>.+ * @code auto alloc = get_associated_allocator(handler); @endcode  *- * @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 If <tt>execution::is_executor<Ex1>::value</tt> is true, constructs a+ * function object @c f with a member @c executor_ that is initialised with+ * <tt>prefer(ex1, execution::outstanding_work.tracked)</tt>, a member @c+ * handler_ that is a decay-copy of @c completion_handler, and a function call+ * operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * prefer(executor_, execution::allocator(a)).execute(std::move(handler_));+ * @endcode  *- * @li Performs <tt>Executor(ex).post(std::move(f), alloc)</tt>.+ * @li If <tt>execution::is_executor<Ex1>::value</tt> is false, constructs a+ * function object @c f with a member @c work_ that is initialised with+ * <tt>make_work_guard(ex1)</tt>, a member @c handler_ that is a decay-copy of+ * @c completion_handler, and a function call operator that performs:+ * @code auto a = get_associated_allocator(handler_);+ * work_.get_executor().dispatch(std::move(handler_), a);+ * work_.reset(); @endcode  *- * @li Returns <tt>result.get()</tt>.+ * @li If <tt>execution::is_executor<Ex>::value</tt> is true, performs+ * @code prefer(+ *     require(ex, execution::blocking.never),+ *     execution::relationship.fork,+ *     execution::allocator(alloc)+ *   ).execute(std::move(f)); @endcode+ *+ * @li If <tt>execution::is_executor<Ex>::value</tt> is false, performs+ * @code ex.post(std::move(f), alloc); @endcode+ *+ * @par Completion Signature+ * @code void() @endcode  */ template <typename Executor,-    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+    ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken       ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) post(     const Executor& ex,-    ASIO_MOVE_ARG(CompletionToken) token+    ASIO_MOVE_ARG(NullaryToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(Executor),-    typename enable_if<-      execution::is_executor<Executor>::value || is_executor<Executor>::value-    >::type* = 0);+    typename constraint<+      (execution::is_executor<Executor>::value+          && can_require<Executor, execution::blocking_t::never_t>::value)+        || is_executor<Executor>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<NullaryToken, void()>(+        declval<detail::initiate_post_with_executor<Executor> >(), token)))+{+  return async_initiate<NullaryToken, void()>(+      detail::initiate_post_with_executor<Executor>(ex), token);+}  /// Submits a completion token or function object for execution. /**- * @returns <tt>post(ctx.get_executor(), forward<CompletionToken>(token))</tt>.+ * @param ctx An execution context, from which the target executor is obtained.+ *+ * @param token The @ref completion_token that will be used to produce a+ * completion handler. The function signature of the completion handler must be:+ * @code void handler(); @endcode+ *+ * @returns <tt>post(ctx.get_executor(), forward<NullaryToken>(token))</tt>.+ *+ * @par Completion Signature+ * @code void() @endcode  */ template <typename ExecutionContext,-    ASIO_COMPLETION_TOKEN_FOR(void()) CompletionToken+    ASIO_COMPLETION_TOKEN_FOR(void()) NullaryToken       ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(         typename ExecutionContext::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(CompletionToken, void()) post(+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(NullaryToken, void()) post(     ExecutionContext& ctx,-    ASIO_MOVE_ARG(CompletionToken) token+    ASIO_MOVE_ARG(NullaryToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename ExecutionContext::executor_type),-    typename enable_if<is_convertible<-      ExecutionContext&, execution_context&>::value>::type* = 0);+    typename constraint<is_convertible<+      ExecutionContext&, execution_context&>::value>::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<NullaryToken, void()>(+        declval<detail::initiate_post_with_executor<+          typename ExecutionContext::executor_type> >(), token)))+{+  return async_initiate<NullaryToken, void()>(+      detail::initiate_post_with_executor<+        typename ExecutionContext::executor_type>(+          ctx.get_executor()), token);+}  } // 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
@@ -2,7 +2,7 @@ // prefer.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -118,6 +118,7 @@  namespace asio_prefer_fn { +using asio::conditional; using asio::decay; using asio::declval; using asio::enable_if;@@ -143,7 +144,9 @@   ill_formed }; -template <typename T, typename Properties, typename = void>+template <typename Impl, typename T, typename Properties,+    typename = void, typename = void, typename = void, typename = void,+    typename = void, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -151,19 +154,19 @@   typedef void result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_preferable+  >::type,+  typename enable_if<+    static_require<T, Property>::is_valid   >::type> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -176,123 +179,137 @@ #endif // defined(ASIO_HAS_MOVE) }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_preferable+  >::type,+  typename enable_if<+    !static_require<T, Property>::is_valid+  >::type,+  typename enable_if<+    require_member<typename Impl::template proxy<T>::type, Property>::is_valid   >::type> :-  require_member<T, Property>+  require_member<typename Impl::template proxy<T>::type, Property> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = call_require_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_preferable+  >::type,+  typename enable_if<+    !static_require<T, Property>::is_valid+  >::type,+  typename enable_if<+    !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+  >::type,+  typename enable_if<+    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),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_preferable+  >::type,+  typename enable_if<+    !static_require<T, Property>::is_valid+  >::type,+  typename enable_if<+    !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+  >::type,+  typename enable_if<+    !require_free<T, Property>::is_valid+  >::type,+  typename enable_if<+    prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid   >::type> :-  prefer_member<T, Property>+  prefer_member<typename Impl::template proxy<T>::type, Property> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = call_prefer_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_preferable+  >::type,+  typename enable_if<+    !static_require<T, Property>::is_valid+  >::type,+  typename enable_if<+    !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+  >::type,+  typename enable_if<+    !require_free<T, Property>::is_valid+  >::type,+  typename enable_if<+    !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid+  >::type,+  typename enable_if<+    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),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_preferable+  >::type,+  typename enable_if<+    !static_require<T, Property>::is_valid+  >::type,+  typename enable_if<+    !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+  >::type,+  typename enable_if<+    !require_free<T, Property>::is_valid+  >::type,+  typename enable_if<+    !prefer_member<typename Impl::template proxy<T>::type, Property>::is_valid+  >::type,+  typename enable_if<+    !prefer_free<T, Property>::is_valid   >::type> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -305,13 +322,15 @@ #endif // defined(ASIO_HAS_MOVE) }; -template <typename T, typename P0, typename P1>-struct call_traits<T, void(P0, P1),+template <typename Impl, typename T, typename P0, typename P1>+struct call_traits<Impl, T, void(P0, P1),   typename enable_if<-    call_traits<T, void(P0)>::overload != ill_formed-    &&+    call_traits<Impl, T, void(P0)>::overload != ill_formed+  >::type,+  typename enable_if<     call_traits<-      typename call_traits<T, void(P0)>::result_type,+      Impl,+      typename call_traits<Impl, T, void(P0)>::result_type,       void(P1)     >::overload != ill_formed   >::type>@@ -320,29 +339,34 @@    ASIO_STATIC_CONSTEXPR(bool, is_noexcept =     (-      call_traits<T, void(P0)>::is_noexcept+      call_traits<Impl, T, void(P0)>::is_noexcept       &&       call_traits<-        typename call_traits<T, void(P0)>::result_type,+        Impl,+        typename call_traits<Impl, T, void(P0)>::result_type,         void(P1)       >::is_noexcept     ));    typedef typename decay<     typename call_traits<-      typename call_traits<T, void(P0)>::result_type,+      Impl,+      typename call_traits<Impl, 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),+template <typename Impl, typename T, typename P0,+    typename P1, typename ASIO_ELLIPSIS PN>+struct call_traits<Impl, T, void(P0, P1, PN ASIO_ELLIPSIS),   typename enable_if<-    call_traits<T, void(P0)>::overload != ill_formed-    &&+    call_traits<Impl, T, void(P0)>::overload != ill_formed+  >::type,+  typename enable_if<     call_traits<-      typename call_traits<T, void(P0)>::result_type,+      Impl,+      typename call_traits<Impl, T, void(P0)>::result_type,       void(P1, PN ASIO_ELLIPSIS)     >::overload != ill_formed   >::type>@@ -351,17 +375,19 @@    ASIO_STATIC_CONSTEXPR(bool, is_noexcept =     (-      call_traits<T, void(P0)>::is_noexcept+      call_traits<Impl, T, void(P0)>::is_noexcept       &&       call_traits<-        typename call_traits<T, void(P0)>::result_type,+        Impl,+        typename call_traits<Impl, 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,+      Impl,+      typename call_traits<Impl, T, void(P0)>::result_type,       void(P1, PN ASIO_ELLIPSIS)     >::result_type   >::type result_type;@@ -369,30 +395,70 @@  struct impl {+  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT) \+  && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto require(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().require(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().require(+            ASIO_MOVE_CAST(P)(p))+        );++      template <typename P>+      auto prefer(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().prefer(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().prefer(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+      //   && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+       //   && defined(ASIO_HAS_DEDUCED_PREFER_MEMBER_TRAIT)+  };+   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+    call_traits<impl, T, void(Property)>::overload == identity,+    typename call_traits<impl, 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))+      call_traits<impl, 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+    call_traits<impl, T, void(Property)>::overload == call_require_member,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return ASIO_MOVE_CAST(T)(t).require(         ASIO_MOVE_CAST(Property)(p));@@ -400,14 +466,14 @@    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+    call_traits<impl, T, void(Property)>::overload == call_require_free,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return require(         ASIO_MOVE_CAST(T)(t),@@ -416,14 +482,14 @@    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+    call_traits<impl, T, void(Property)>::overload == call_prefer_member,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return ASIO_MOVE_CAST(T)(t).prefer(         ASIO_MOVE_CAST(Property)(p));@@ -431,14 +497,14 @@    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+    call_traits<impl, T, void(Property)>::overload == call_prefer_free,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return prefer(         ASIO_MOVE_CAST(T)(t),@@ -447,15 +513,15 @@    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+    call_traits<impl, T, void(P0, P1)>::overload == two_props,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(P0, P1)>::is_noexcept))   {     return (*this)(         (*this)(@@ -467,8 +533,10 @@   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+    call_traits<impl, T,+      void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,+    typename call_traits<impl, T,+      void(P0, P1, PN ASIO_ELLIPSIS)>::result_type   >::type   operator()(       ASIO_MOVE_ARG(T) t,@@ -476,7 +544,7 @@       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))+      call_traits<impl, T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept))   {     return (*this)(         (*this)(@@ -505,13 +573,16 @@  } // namespace +typedef asio_prefer_fn::impl prefer_t;+ #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>+    asio_prefer_fn::call_traits<+      prefer_t, T, void(Properties...)>::overload+        != asio_prefer_fn::ill_formed> { }; @@ -521,24 +592,27 @@     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>+    asio_prefer_fn::call_traits<+      prefer_t, 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>+    asio_prefer_fn::call_traits<+      prefer_t, 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>+    asio_prefer_fn::call_traits<+      prefer_t, T, void(P0)>::overload+        != asio_prefer_fn::ill_formed> { }; @@ -563,7 +637,8 @@ template <typename T, typename... Properties> struct is_nothrow_prefer :   integral_constant<bool,-    asio_prefer_fn::call_traits<T, void(Properties...)>::is_noexcept>+    asio_prefer_fn::call_traits<+      prefer_t, T, void(Properties...)>::is_noexcept> { }; @@ -573,21 +648,24 @@     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>+    asio_prefer_fn::call_traits<+      prefer_t, 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>+    asio_prefer_fn::call_traits<+      prefer_t, 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>+    asio_prefer_fn::call_traits<+      prefer_t, T, void(P0)>::is_noexcept> { }; @@ -613,7 +691,7 @@ struct prefer_result {   typedef typename asio_prefer_fn::call_traits<-      T, void(Properties...)>::result_type type;+      prefer_t, T, void(Properties...)>::result_type type; };  #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -623,21 +701,21 @@ struct prefer_result {   typedef typename asio_prefer_fn::call_traits<-      T, void(P0, P1, P2)>::result_type type;+      prefer_t, 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;+      prefer_t, 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;+      prefer_t, T, void(P0)>::result_type type; };  template <typename T>
+ link/modules/asio-standalone/asio/include/asio/prepend.hpp view
@@ -0,0 +1,78 @@+//+// prepend.hpp+// ~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_PREPEND_HPP+#define ASIO_PREPEND_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_TUPLE) \+    && defined(ASIO_HAS_VARIADIC_TEMPLATES)) \+  || defined(GENERATING_DOCUMENTATION)++#include <tuple>+#include "asio/detail/type_traits.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// Completion token type used to specify that the completion handler+/// arguments should be passed additional values before the results of the+/// operation.+template <typename CompletionToken, typename... Values>+class prepend_t+{+public:+  /// Constructor.+  template <typename T, typename... V>+  ASIO_CONSTEXPR explicit prepend_t(+      ASIO_MOVE_ARG(T) completion_token,+      ASIO_MOVE_ARG(V)... values)+    : token_(ASIO_MOVE_CAST(T)(completion_token)),+      values_(ASIO_MOVE_CAST(V)(values)...)+  {+  }++//private:+  CompletionToken token_;+  std::tuple<Values...> values_;+};++/// Completion token type used to specify that the completion handler+/// arguments should be passed additional values before the results of the+/// operation.+template <typename CompletionToken, typename... Values>+ASIO_NODISCARD inline ASIO_CONSTEXPR prepend_t<+  typename decay<CompletionToken>::type, typename decay<Values>::type...>+prepend(ASIO_MOVE_ARG(CompletionToken) completion_token,+    ASIO_MOVE_ARG(Values)... values)+{+  return prepend_t<+    typename decay<CompletionToken>::type, typename decay<Values>::type...>(+      ASIO_MOVE_CAST(CompletionToken)(completion_token),+      ASIO_MOVE_CAST(Values)(values)...);+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#include "asio/impl/prepend.hpp"++#endif // (defined(ASIO_HAS_STD_TUPLE)+       //     && defined(ASIO_HAS_VARIADIC_TEMPLATES))+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_PREPEND_HPP
link/modules/asio-standalone/asio/include/asio/query.hpp view
@@ -2,7 +2,7 @@ // query.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -100,6 +100,7 @@  namespace asio_query_fn { +using asio::conditional; using asio::decay; using asio::declval; using asio::enable_if;@@ -118,7 +119,8 @@   ill_formed }; -template <typename T, typename Properties, typename = void>+template <typename Impl, typename T, typename Properties,+    typename = void, typename = void, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -126,57 +128,57 @@   typedef void result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, T, void(Property),   typename enable_if<-    (-      is_applicable_property<-        typename decay<T>::type,-        typename decay<Property>::type-      >::value-      &&-      static_query<T, Property>::is_valid-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    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),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    !static_query<T, Property>::is_valid+  >::type,+  typename enable_if<+    query_member<typename Impl::template proxy<T>::type, Property>::is_valid   >::type> :-  query_member<T, Property>+  query_member<typename Impl::template proxy<T>::type, Property> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    !static_query<T, Property>::is_valid+  >::type,+  typename enable_if<+    !query_member<typename Impl::template proxy<T>::type, Property>::is_valid+  >::type,+  typename enable_if<+    query_free<T, Property>::is_valid   >::type> :   query_free<T, Property> {@@ -185,16 +187,40 @@  struct impl {+  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto query(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().query(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().query(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)+  };+   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+    call_traits<impl, T, void(Property)>::overload == static_value,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return static_query<       typename decay<T>::type,@@ -204,28 +230,28 @@    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+    call_traits<impl, T, void(Property)>::overload == call_member,+    typename call_traits<impl, 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))+      call_traits<impl, 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+    call_traits<impl, T, void(Property)>::overload == call_free,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return query(ASIO_MOVE_CAST(T)(t), ASIO_MOVE_CAST(Property)(p));   }@@ -249,10 +275,12 @@  } // namespace +typedef asio_query_fn::impl query_t;+ template <typename T, typename Property> struct can_query :   integral_constant<bool,-    asio_query_fn::call_traits<T, void(Property)>::overload !=+    asio_query_fn::call_traits<query_t, T, void(Property)>::overload !=       asio_query_fn::ill_formed> { };@@ -268,7 +296,7 @@ template <typename T, typename Property> struct is_nothrow_query :   integral_constant<bool,-    asio_query_fn::call_traits<T, void(Property)>::is_noexcept>+    asio_query_fn::call_traits<query_t, T, void(Property)>::is_noexcept> { }; @@ -284,7 +312,7 @@ struct query_result {   typedef typename asio_query_fn::call_traits<-      T, void(Property)>::result_type type;+      query_t, T, void(Property)>::result_type type; };  } // namespace asio
+ link/modules/asio-standalone/asio/include/asio/random_access_file.hpp view
@@ -0,0 +1,35 @@+//+// random_access_file.hpp+// ~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_RANDOM_ACCESS_FILE_HPP+#define ASIO_RANDOM_ACCESS_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_random_access_file.hpp"++namespace asio {++/// Typedef for the typical usage of a random-access file.+typedef basic_random_access_file<> random_access_file;++} // namespace asio++#endif // defined(ASIO_HAS_FILE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_RANDOM_ACCESS_FILE_HPP
link/modules/asio-standalone/asio/include/asio/read.hpp view
@@ -2,7 +2,7 @@ // read.hpp // ~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@ #include <cstddef> #include "asio/async_result.hpp" #include "asio/buffer.hpp"+#include "asio/completion_condition.hpp" #include "asio/error.hpp"  #if !defined(ASIO_NO_EXTENSIONS)@@ -28,7 +29,16 @@ #include "asio/detail/push_options.hpp"  namespace asio {+namespace detail { +template <typename> class initiate_async_read;+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_read_dynbuf_v1;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_read_dynbuf_v2;++} // namespace detail+ /**  * @defgroup read asio::read  *@@ -75,9 +85,9 @@  */ template <typename SyncReadStream, typename MutableBufferSequence> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,-    typename enable_if<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type* = 0);+    >::type = 0);  /// Attempt to read a certain amount of data from a stream before returning. /**@@ -118,9 +128,9 @@ template <typename SyncReadStream, typename MutableBufferSequence> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type* = 0);+    >::type = 0);  /// Attempt to read a certain amount of data from a stream before returning. /**@@ -172,9 +182,9 @@   typename CompletionCondition> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type* = 0);+    >::type = 0);  /// Attempt to read a certain amount of data from a stream before returning. /**@@ -219,9 +229,9 @@     typename CompletionCondition> std::size_t read(SyncReadStream& s, const MutableBufferSequence& buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type* = 0);+    >::type = 0);  #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -255,10 +265,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !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. /**@@ -290,10 +302,12 @@ std::size_t read(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !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. /**@@ -336,10 +350,12 @@ std::size_t read(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !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. /**@@ -383,10 +399,12 @@ std::size_t read(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0);  #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -564,9 +582,9 @@  */ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Attempt to read a certain amount of data from a stream before returning. /**@@ -597,9 +615,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Attempt to read a certain amount of data from a stream before returning. /**@@ -641,9 +659,9 @@     typename CompletionCondition> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Attempt to read a certain amount of data from a stream before returning. /**@@ -686,9 +704,9 @@     typename CompletionCondition> std::size_t read(SyncReadStream& s, DynamicBuffer_v2 buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /*@}*/ /**@@ -703,9 +721,9 @@ /// 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:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -725,25 +743,30 @@  * 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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @par Example  * To read into a single data buffer use the @ref buffer function as follows:  * @code@@ -758,29 +781,45 @@  *     s, buffers,  *     asio::transfer_all(),  *     handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename MutableBufferSequence,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read<AsyncReadStream> >(),+        token, buffers, transfer_all())));  /// 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:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -794,7 +833,7 @@  * 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.+ * that they remain valid until the completion 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@@ -810,23 +849,28 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @par Example  * To read into a single data buffer use the @ref buffer function as follows:  * @code asio::async_read(s,@@ -836,23 +880,40 @@  * See the @ref buffer documentation for information on reading into multiple  * buffers in one go, and how to use it with arrays, boost::array or  * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream,     typename MutableBufferSequence, typename CompletionCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, const MutableBufferSequence& buffers,     CompletionCondition completion_condition,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_mutable_buffer_sequence<MutableBufferSequence>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read<AsyncReadStream> >(),+        token, buffers,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -860,9 +921,9 @@ /// 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:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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).@@ -881,55 +942,79 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note This overload is equivalent to calling:  * @code asio::async_read(  *     s, buffers,  *     asio::transfer_all(),  *     handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename DynamicBuffer_v1,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        transfer_all())));  /// 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:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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).@@ -948,7 +1033,7 @@  * @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.+ * that they remain valid until the completion 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@@ -964,41 +1049,65 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream,     typename DynamicBuffer_v1, typename CompletionCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_dynbuf_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -1007,9 +1116,9 @@ /// 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:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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).  *@@ -1026,50 +1135,69 @@  *  * @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.+ * remains valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note This overload is equivalent to calling:  * @code asio::async_read(  *     s, b,  *     asio::transfer_all(),  *     handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncReadStream::executor_type));+        typename AsyncReadStream::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read(s, basic_streambuf_ref<Allocator>(b),+        ASIO_MOVE_CAST(ReadToken)(token))));  /// 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:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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).  *@@ -1086,7 +1214,7 @@  *  * @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.+ * remains valid until the completion 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@@ -1102,36 +1230,56 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream,     typename Allocator, typename CompletionCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, basic_streambuf<Allocator>& b,     CompletionCondition completion_condition,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncReadStream::executor_type));+        typename AsyncReadStream::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read(s, basic_streambuf_ref<Allocator>(b),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+        ASIO_MOVE_CAST(ReadToken)(token))));  #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)@@ -1141,9 +1289,9 @@ /// 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:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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).@@ -1162,53 +1310,75 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note This overload is equivalent to calling:  * @code asio::async_read(  *     s, buffers,  *     asio::transfer_all(),  *     handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename DynamicBuffer_v2,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        transfer_all())));  /// 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:+ * data from a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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).@@ -1227,7 +1397,7 @@  * @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.+ * that they remain valid until the completion 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@@ -1243,39 +1413,61 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream,     typename DynamicBuffer_v2, typename CompletionCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read(AsyncReadStream& s, DynamicBuffer_v2 buffers,     CompletionCondition completion_condition,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_dynbuf_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  /*@}*/ 
link/modules/asio-standalone/asio/include/asio/read_at.hpp view
@@ -2,7 +2,7 @@ // read_at.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include <cstddef> #include "asio/async_result.hpp"+#include "asio/completion_condition.hpp" #include "asio/detail/cstdint.hpp" #include "asio/error.hpp" @@ -28,7 +29,15 @@ #include "asio/detail/push_options.hpp"  namespace asio {+namespace detail { +template <typename> class initiate_async_read_at;+#if !defined(ASIO_NO_IOSTREAM)+template <typename> class initiate_async_read_at_streambuf;+#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace detail+ /**  * @defgroup read_at asio::read_at  *@@ -403,9 +412,10 @@ /// 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:+ * data from a random access device at the specified offset. It is an+ * initiating function for an @ref asynchronous_operation, and 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.@@ -424,11 +434,13 @@  * 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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -439,10 +451,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @par Example  * To read into a single data buffer use the @ref buffer function as follows:  * @code@@ -457,27 +472,44 @@  *     d, 42, buffers,  *     asio::transfer_all(),  *     handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessReadDevice type's+ * async_read_some_at operation.  */ template <typename AsyncRandomAccessReadDevice, typename MutableBufferSequence,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncRandomAccessReadDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read_at(AsyncRandomAccessReadDevice& d, uint64_t offset,     const MutableBufferSequence& buffers,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncRandomAccessReadDevice::executor_type));+        typename AsyncRandomAccessReadDevice::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),+        token, offset, buffers, transfer_all())));  /// 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:+ * data from a random access device at the specified offset. It is an+ * initiating function for an @ref asynchronous_operation, and 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.@@ -493,7 +525,7 @@  * 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.+ * that they remain valid until the completion 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@@ -509,9 +541,11 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -522,10 +556,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @par Example  * To read into a single data buffer use the @ref buffer function as follows:  * @code asio::async_read_at(d, 42,@@ -535,21 +572,38 @@  * See the @ref buffer documentation for information on reading into multiple  * buffers in one go, and how to use it with arrays, boost::array or  * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessReadDevice type's+ * async_read_some_at operation.  */ template <typename AsyncRandomAccessReadDevice,     typename MutableBufferSequence, typename CompletionCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncRandomAccessReadDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncRandomAccessReadDevice::executor_type));+        typename AsyncRandomAccessReadDevice::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_at<AsyncRandomAccessReadDevice> >(),+        token, offset, buffers,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -558,9 +612,10 @@ /// 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:+ * data from a random access device at the specified offset. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. The asynchronous operation will continue until one of the+ * following conditions is true:  *  * @li An error occurred.  *@@ -574,11 +629,13 @@  *  * @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.+ * remains valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -589,36 +646,57 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note This overload is equivalent to calling:  * @code asio::async_read_at(  *     d, 42, b,  *     asio::transfer_all(),  *     handler); @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessReadDevice type's+ * async_read_some_at operation.  */ template <typename AsyncRandomAccessReadDevice, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncRandomAccessReadDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncRandomAccessReadDevice::executor_type));+        typename AsyncRandomAccessReadDevice::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_at_streambuf<+          AsyncRandomAccessReadDevice> >(),+        token, offset, &b, transfer_all())));  /// 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:+ * data from a random access device at the specified offset. It is an+ * initiating function for an @ref asynchronous_operation, and always returns+ * immediately. The asynchronous operation will continue until one of the+ * following conditions is true:  *  * @li The completion_condition function object returns 0.  *@@ -632,7 +710,7 @@  *  * @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.+ * remains valid until the completion 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@@ -648,9 +726,11 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -661,24 +741,45 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessReadDevice type's+ * async_read_some_at operation.  */ template <typename AsyncRandomAccessReadDevice,     typename Allocator, typename CompletionCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncRandomAccessReadDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncRandomAccessReadDevice::executor_type));+        typename AsyncRandomAccessReadDevice::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_at_streambuf<+          AsyncRandomAccessReadDevice> >(),+        token, offset, &b,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)
link/modules/asio-standalone/asio/include/asio/read_until.hpp view
@@ -2,7 +2,7 @@ // read_until.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -32,19 +32,34 @@ #include "asio/detail/push_options.hpp"  namespace asio {+namespace detail { -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 {-  char (&has_result_type_helper(...))[2];+  enum { value = (sizeof((has_result_type_helper)((T*)(0))) == 1) };+}; -  template <typename T>-  char has_result_type_helper(T*, typename T::result_type* = 0);+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_read_until_delim_v1;+template <typename> class initiate_async_read_until_delim_string_v1;+#if defined(ASIO_HAS_BOOST_REGEX)+template <typename> class initiate_async_read_until_expr_v1;+#endif // defined(ASIO_HAS_BOOST_REGEX)+template <typename> class initiate_async_read_until_match_v1;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_read_until_delim_v2;+template <typename> class initiate_async_read_until_delim_string_v2;+#if defined(ASIO_HAS_BOOST_REGEX)+template <typename> class initiate_async_read_until_expr_v2;+#endif // defined(ASIO_HAS_BOOST_REGEX)+template <typename> class initiate_async_read_until_match_v2; -  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@@ -133,10 +148,12 @@ template <typename SyncReadStream, typename DynamicBuffer_v1> std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers, char delim,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !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.@@ -176,10 +193,12 @@ std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     char delim, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !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.@@ -236,10 +255,12 @@ std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     ASIO_STRING_VIEW_PARAM delim,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !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.@@ -280,10 +301,12 @@     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     ASIO_STRING_VIEW_PARAM delim,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0);  #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \@@ -347,10 +370,12 @@ std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     const boost::regex& expr,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !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.@@ -392,10 +417,12 @@ std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     const boost::regex& expr, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0);  #endif // defined(ASIO_HAS_BOOST_REGEX)        // || defined(GENERATING_DOCUMENTATION)@@ -507,11 +534,15 @@ std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     MatchCondition match_condition,-    typename enable_if<+    typename constraint<       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);+    >::type = 0,+    typename constraint<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0,+    typename constraint<+      !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.@@ -571,11 +602,15 @@ std::size_t read_until(SyncReadStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     MatchCondition match_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       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);+    >::type = 0,+    typename constraint<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0);  #if !defined(ASIO_NO_IOSTREAM) @@ -955,7 +990,7 @@ 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);+    typename constraint<is_match_condition<MatchCondition>::value>::type = 0);  /// Read data into a streambuf until a function object indicates a match. /**@@ -1012,7 +1047,7 @@ 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);+    typename constraint<is_match_condition<MatchCondition>::value>::type = 0);  #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)@@ -1073,9 +1108,9 @@  */ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers, char delim,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter.@@ -1114,9 +1149,9 @@ 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<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter.@@ -1172,9 +1207,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,     ASIO_STRING_VIEW_PARAM delim,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Read data into a dynamic buffer sequence until it contains a specified /// delimiter.@@ -1213,9 +1248,9 @@ 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<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \@@ -1278,9 +1313,9 @@ template <typename SyncReadStream, typename DynamicBuffer_v2> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,     const boost::regex& expr,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Read data into a dynamic buffer sequence until some part of the data it /// contains matches a regular expression.@@ -1321,9 +1356,9 @@ 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<+    typename constraint<         is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  #endif // defined(ASIO_HAS_BOOST_REGEX)        // || defined(GENERATING_DOCUMENTATION)@@ -1434,10 +1469,12 @@     typename DynamicBuffer_v2, typename MatchCondition> std::size_t read_until(SyncReadStream& s, DynamicBuffer_v2 buffers,     MatchCondition match_condition,-    typename enable_if<+    typename constraint<       is_match_condition<MatchCondition>::value-        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type = 0);  /// Read data into a dynamic buffer sequence until a function object indicates a /// match.@@ -1496,10 +1533,12 @@     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<+    typename constraint<       is_match_condition<MatchCondition>::value-        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type = 0);  #endif // !defined(ASIO_NO_EXTENSIONS) @@ -1521,9 +1560,9 @@ /**  * 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:+ * specified delimiter. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -1544,27 +1583,31 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note 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@@ -1597,32 +1640,50 @@  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename DynamicBuffer_v1,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_delim_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), delim)));  /// 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:+ * specified delimiter. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -1643,27 +1704,31 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note 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@@ -1696,24 +1761,44 @@  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename DynamicBuffer_v1,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_delim_string_v1<+          AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        static_cast<std::string>(delim))));  #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \@@ -1724,9 +1809,10 @@ /**  * 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:+ * data that matches a regular expression. It is an initiating function for an+ * @ref asynchronous_operation, and 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.@@ -1748,13 +1834,15 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -1766,10 +1854,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note 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@@ -1803,24 +1894,42 @@  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename DynamicBuffer_v1,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_expr_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers), expr)));  #endif // defined(ASIO_HAS_BOOST_REGEX)        // || defined(GENERATING_DOCUMENTATION)@@ -1831,9 +1940,9 @@  * 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:+ * successful match. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -1854,7 +1963,7 @@  * @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.+ * that they remain valid until the completion 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:@@ -1871,9 +1980,11 @@  * @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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -1884,8 +1995,8 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *  * @note After a successful async_read_until operation, the dynamic buffer@@ -1893,6 +2004,9 @@  * object. An application will typically leave that data in the dynamic buffer  * sequence for a subsequent async_read_until operation to examine.  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @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@@ -1952,26 +2066,47 @@  * std::string data;  * asio::async_read_until(s, data, match_char('a'), handler);  * @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream,     typename DynamicBuffer_v1, typename MatchCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       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);+    >::type = 0,+    typename constraint<+      is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_match_v1<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        match_condition)));  #if !defined(ASIO_NO_IOSTREAM) @@ -1980,8 +2115,9 @@ /**  * 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:+ * It is an initiating function for an @ref asynchronous_operation, and 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.  *@@ -2000,13 +2136,15 @@  *  * @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.+ * valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -2017,10 +2155,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note 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@@ -2052,27 +2193,42 @@  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncReadStream::executor_type));+        typename AsyncReadStream::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read_until(s, basic_streambuf_ref<Allocator>(b),+        delim, ASIO_MOVE_CAST(ReadToken)(token))));  /// 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:+ * It is an initiating function for an @ref asynchronous_operation, and 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.  *@@ -2091,13 +2247,15 @@  *  * @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.+ * valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -2108,10 +2266,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note 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@@ -2143,20 +2304,34 @@  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncReadStream::executor_type));+        typename AsyncReadStream::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read_until(s, basic_streambuf_ref<Allocator>(b),+        delim, ASIO_MOVE_CAST(ReadToken)(token))));  #if defined(ASIO_HAS_BOOST_REGEX) \   || defined(GENERATING_DOCUMENTATION)@@ -2166,9 +2341,9 @@ /**  * 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:+ * regular expression. It is an initiating function for an @ref+ * asynchronous_operation, and 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.  *@@ -2188,13 +2363,15 @@  *  * @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.+ * valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -2206,10 +2383,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note 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@@ -2242,19 +2422,33 @@  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncReadStream::executor_type));+        typename AsyncReadStream::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read_until(s, basic_streambuf_ref<Allocator>(b),+        expr, ASIO_MOVE_CAST(ReadToken)(token))));  #endif // defined(ASIO_HAS_BOOST_REGEX)        // || defined(GENERATING_DOCUMENTATION)@@ -2264,9 +2458,10 @@ /**  * 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:+ * to the data contained in the streambuf, indicates a successful match. It is+ * an initiating function for an @ref asynchronous_operation, and 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.@@ -2301,9 +2496,11 @@  * @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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -2314,8 +2511,8 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *  * @note After a successful async_read_until operation, the streambuf may@@ -2323,6 +2520,9 @@  * application will typically leave that data in the streambuf for a subsequent  * async_read_until operation to examine.  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @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@@ -2381,21 +2581,35 @@  * asio::streambuf b;  * asio::async_read_until(s, b, match_char('a'), handler);  * @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename Allocator, typename MatchCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<is_match_condition<MatchCondition>::value>::type* = 0);+    typename constraint<is_match_condition<MatchCondition>::value>::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_read_until(s, basic_streambuf_ref<Allocator>(b),+        match_condition, ASIO_MOVE_CAST(ReadToken)(token))));  #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)@@ -2406,9 +2620,9 @@ /**  * 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:+ * specified delimiter. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -2429,13 +2643,15 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -2446,10 +2662,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note 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@@ -2482,30 +2701,46 @@  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename DynamicBuffer_v2,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers, char delim,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_delim_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), delim)));  /// 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:+ * specified delimiter. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -2526,27 +2761,31 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note 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@@ -2579,22 +2818,40 @@  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename DynamicBuffer_v2,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_delim_string_v2<+          AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        static_cast<std::string>(delim))));  #if !defined(ASIO_NO_EXTENSIONS) #if defined(ASIO_HAS_BOOST_REGEX) \@@ -2605,9 +2862,10 @@ /**  * 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:+ * data that matches a regular expression. It is an initiating function for an+ * @ref asynchronous_operation, and 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.@@ -2629,13 +2887,15 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -2647,10 +2907,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @note 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@@ -2684,22 +2947,38 @@  * @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.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream, typename DynamicBuffer_v2,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     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_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_expr_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers), expr)));  #endif // defined(ASIO_HAS_BOOST_REGEX)        // || defined(GENERATING_DOCUMENTATION)@@ -2710,9 +2989,9 @@  * 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:+ * successful match. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -2733,7 +3012,7 @@  * @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.+ * that they remain valid until the completion 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:@@ -2750,9 +3029,11 @@  * @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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the read completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -2763,8 +3044,8 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *  * @note After a successful async_read_until operation, the dynamic buffer@@ -2772,6 +3053,9 @@  * object. An application will typically leave that data in the dynamic buffer  * sequence for a subsequent async_read_until operation to examine.  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @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@@ -2831,24 +3115,43 @@  * std::string data;  * asio::async_read_until(s, data, match_char('a'), handler);  * @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncReadStream type's+ * @c async_read_some operation.  */ template <typename AsyncReadStream,     typename DynamicBuffer_v2, typename MatchCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) ReadHandler+      std::size_t)) ReadToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncReadStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,     void (asio::error_code, std::size_t)) async_read_until(AsyncReadStream& s, DynamicBuffer_v2 buffers,     MatchCondition match_condition,-    ASIO_MOVE_ARG(ReadHandler) handler+    ASIO_MOVE_ARG(ReadToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncReadStream::executor_type),-    typename enable_if<+    typename constraint<       is_match_condition<MatchCondition>::value-        && is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      is_dynamic_buffer_v2<DynamicBuffer_v2>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<ReadToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_read_until_match_v2<AsyncReadStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        match_condition)));  #endif // !defined(ASIO_NO_EXTENSIONS) 
+ link/modules/asio-standalone/asio/include/asio/readable_pipe.hpp view
@@ -0,0 +1,35 @@+//+// readable_pipe.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_READABLE_PIPE_HPP+#define ASIO_READABLE_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_readable_pipe.hpp"++namespace asio {++/// Typedef for the typical usage of a readable pipe.+typedef basic_readable_pipe<> readable_pipe;++} // namespace asio++#endif // defined(ASIO_HAS_PIPE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_READABLE_PIPE_HPP
+ link/modules/asio-standalone/asio/include/asio/recycling_allocator.hpp view
@@ -0,0 +1,138 @@+//+// recycling_allocator.hpp+// ~~~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_RECYCLING_ALLOCATOR_HPP+#define ASIO_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/recycling_allocator.hpp"++#include "asio/detail/push_options.hpp"++namespace asio {++/// An allocator that caches memory blocks in thread-local storage for reuse.+/**+ * The @recycling_allocator uses a simple strategy where a limited number of+ * small memory blocks are cached in thread-local storage, if the current+ * thread is running an @c io_context or is part of a @c thread_pool.+ */+template <typename T>+class recycling_allocator+{+public:+  /// The type of object allocated by the recycling allocator.+  typedef T value_type;++  /// Rebind the allocator to another value_type.+  template <typename U>+  struct rebind+  {+    /// The rebound @c allocator type.+    typedef recycling_allocator<U> other;+  };++  /// Default constructor.+  ASIO_CONSTEXPR recycling_allocator() ASIO_NOEXCEPT+  {+  }++  /// Converting constructor.+  template <typename U>+  ASIO_CONSTEXPR recycling_allocator(+      const recycling_allocator<U>&) ASIO_NOEXCEPT+  {+  }++  /// Equality operator. Always returns true.+  ASIO_CONSTEXPR bool operator==(+      const recycling_allocator&) const ASIO_NOEXCEPT+  {+    return true;+  }++  /// Inequality operator. Always returns false.+  ASIO_CONSTEXPR bool operator!=(+      const recycling_allocator&) const ASIO_NOEXCEPT+  {+    return false;+  }++  /// Allocate memory for the specified number of values.+  T* allocate(std::size_t n)+  {+    return detail::recycling_allocator<T>().allocate(n);+  }++  /// Deallocate memory for the specified number of values.+  void deallocate(T* p, std::size_t n)+  {+    detail::recycling_allocator<T>().deallocate(p, n);+  }+};++/// A proto-allocator that caches memory blocks in thread-local storage for+/// reuse.+/**+ * The @recycling_allocator uses a simple strategy where a limited number of+ * small memory blocks are cached in thread-local storage, if the current+ * thread is running an @c io_context or is part of a @c thread_pool.+ */+template <>+class recycling_allocator<void>+{+public:+  /// No values are allocated by a proto-allocator.+  typedef void value_type;++  /// Rebind the allocator to another value_type.+  template <typename U>+  struct rebind+  {+    /// The rebound @c allocator type.+    typedef recycling_allocator<U> other;+  };++  /// Default constructor.+  ASIO_CONSTEXPR recycling_allocator() ASIO_NOEXCEPT+  {+  }++  /// Converting constructor.+  template <typename U>+  ASIO_CONSTEXPR recycling_allocator(+      const recycling_allocator<U>&) ASIO_NOEXCEPT+  {+  }++  /// Equality operator. Always returns true.+  ASIO_CONSTEXPR bool operator==(+      const recycling_allocator&) const ASIO_NOEXCEPT+  {+    return true;+  }++  /// Inequality operator. Always returns false.+  ASIO_CONSTEXPR bool operator!=(+      const recycling_allocator&) const ASIO_NOEXCEPT+  {+    return false;+  }+};++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_RECYCLING_ALLOCATOR_HPP
link/modules/asio-standalone/asio/include/asio/redirect_error.hpp view
@@ -2,7 +2,7 @@ // redirect_error.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -23,7 +23,7 @@  namespace asio { -/// Completion token type used to specify that an error produced by an+/// A @ref completion_token adapter 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@@ -47,7 +47,7 @@   asio::error_code& ec_; }; -/// Create a completion token to capture error_code values to a variable.+/// Adapt a @ref 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,
+ link/modules/asio-standalone/asio/include/asio/registered_buffer.hpp view
@@ -0,0 +1,356 @@+//+// registered_buffer.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_REGISTERED_BUFFER_HPP+#define ASIO_REGISTERED_BUFFER_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/push_options.hpp"++namespace asio {+namespace detail {++class buffer_registration_base;++} // namespace detail++class const_registered_buffer;++/// Type used to identify a registered buffer.+class registered_buffer_id+{+public:+  /// The native buffer identifier type.+  typedef int native_handle_type;++  /// Default constructor creates an invalid registered buffer identifier.+  registered_buffer_id() ASIO_NOEXCEPT+    : scope_(0),+      index_(-1)+  {+  }++  /// Get the native buffer identifier type.+  native_handle_type native_handle() const ASIO_NOEXCEPT+  {+    return index_;+  }++  /// Compare two IDs for equality.+  friend bool operator==(const registered_buffer_id& lhs,+      const registered_buffer_id& rhs) ASIO_NOEXCEPT+  {+    return lhs.scope_ == rhs.scope_ && lhs.index_ == rhs.index_;+  }++  /// Compare two IDs for equality.+  friend bool operator!=(const registered_buffer_id& lhs,+      const registered_buffer_id& rhs) ASIO_NOEXCEPT+  {+    return lhs.scope_ != rhs.scope_ || lhs.index_ != rhs.index_;+  }++private:+  friend class detail::buffer_registration_base;++  // Hidden constructor used by buffer registration.+  registered_buffer_id(const void* scope, int index) ASIO_NOEXCEPT+    : scope_(scope),+      index_(index)+  {+  }++  const void* scope_;+  int index_;+};++/// Holds a registered buffer over modifiable data.+/** + * Satisfies the @c MutableBufferSequence type requirements.+ */+class mutable_registered_buffer+{+public:+#if !defined(ASIO_HAS_DECLTYPE) \+  && !defined(GENERATING_DOCUMENTATION)+  typedef mutable_buffer value_type;+#endif // !defined(ASIO_HAS_DECLTYPE)+       //   && !defined(GENERATING_DOCUMENTATION)++  /// Default constructor creates an invalid registered buffer.+  mutable_registered_buffer() ASIO_NOEXCEPT+    : buffer_(),+      id_()+  {+  }++  /// Get the underlying mutable buffer.+  const mutable_buffer& buffer() const ASIO_NOEXCEPT+  {+    return buffer_;+  }++  /// Get a pointer to the beginning of the memory range.+  /**+   * @returns <tt>buffer().data()</tt>.+   */+  void* data() const ASIO_NOEXCEPT+  {+    return buffer_.data();+  }++  /// Get the size of the memory range.+  /**+   * @returns <tt>buffer().size()</tt>.+   */+  std::size_t size() const ASIO_NOEXCEPT+  {+    return buffer_.size();+  }++  /// Get the registered buffer identifier.+  const registered_buffer_id& id() const ASIO_NOEXCEPT+  {+    return id_;+  }++  /// Move the start of the buffer by the specified number of bytes.+  mutable_registered_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT+  {+    buffer_ += n;+    return *this;+  }++private:+  friend class detail::buffer_registration_base;++  // Hidden constructor used by buffer registration and operators.+  mutable_registered_buffer(const mutable_buffer& b,+      const registered_buffer_id& i) ASIO_NOEXCEPT+    : buffer_(b),+      id_(i)+  {+  }++#if !defined(GENERATING_DOCUMENTATION)+  friend mutable_registered_buffer buffer(+      const mutable_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT;+#endif // !defined(GENERATING_DOCUMENTATION)++  mutable_buffer buffer_;+  registered_buffer_id id_;+};++/// Holds a registered buffer over non-modifiable data.+/** + * Satisfies the @c ConstBufferSequence type requirements.+ */+class const_registered_buffer+{+public:+#if !defined(ASIO_HAS_DECLTYPE) \+  && !defined(GENERATING_DOCUMENTATION)+  typedef const_buffer value_type;+#endif // !defined(ASIO_HAS_DECLTYPE)+       //   && !defined(GENERATING_DOCUMENTATION)++  /// Default constructor creates an invalid registered buffer.+  const_registered_buffer() ASIO_NOEXCEPT+    : buffer_(),+      id_()+  {+  }++  /// Construct a non-modifiable buffer from a modifiable one.+  const_registered_buffer(+      const mutable_registered_buffer& b) ASIO_NOEXCEPT+    : buffer_(b.buffer()),+      id_(b.id())+  {+  }++  /// Get the underlying constant buffer.+  const const_buffer& buffer() const ASIO_NOEXCEPT+  {+    return buffer_;+  }++  /// Get a pointer to the beginning of the memory range.+  /**+   * @returns <tt>buffer().data()</tt>.+   */+  const void* data() const ASIO_NOEXCEPT+  {+    return buffer_.data();+  }++  /// Get the size of the memory range.+  /**+   * @returns <tt>buffer().size()</tt>.+   */+  std::size_t size() const ASIO_NOEXCEPT+  {+    return buffer_.size();+  }++  /// Get the registered buffer identifier.+  const registered_buffer_id& id() const ASIO_NOEXCEPT+  {+    return id_;+  }++  /// Move the start of the buffer by the specified number of bytes.+  const_registered_buffer& operator+=(std::size_t n) ASIO_NOEXCEPT+  {+    buffer_ += n;+    return *this;+  }++private:+  // Hidden constructor used by operators.+  const_registered_buffer(const const_buffer& b,+      const registered_buffer_id& i) ASIO_NOEXCEPT+    : buffer_(b),+      id_(i)+  {+  }++#if !defined(GENERATING_DOCUMENTATION)+  friend const_registered_buffer buffer(+      const const_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT;+#endif // !defined(GENERATING_DOCUMENTATION)++  const_buffer buffer_;+  registered_buffer_id id_;+};++/** @addtogroup buffer_sequence_begin */++/// Get an iterator to the first element in a buffer sequence.+inline const mutable_buffer* buffer_sequence_begin(+    const mutable_registered_buffer& b) ASIO_NOEXCEPT+{+  return &b.buffer();+}++/// Get an iterator to the first element in a buffer sequence.+inline const const_buffer* buffer_sequence_begin(+    const const_registered_buffer& b) ASIO_NOEXCEPT+{+  return &b.buffer();+}++/** @} */+/** @addtogroup buffer_sequence_end */++/// Get an iterator to one past the end element in a buffer sequence.+inline const mutable_buffer* buffer_sequence_end(+    const mutable_registered_buffer& b) ASIO_NOEXCEPT+{+  return &b.buffer() + 1;+}++/// Get an iterator to one past the end element in a buffer sequence.+inline const const_buffer* buffer_sequence_end(+    const const_registered_buffer& b) ASIO_NOEXCEPT+{+  return &b.buffer() + 1;+}++/** @} */+/** @addtogroup buffer */++/// Obtain a buffer representing the entire registered buffer.+inline mutable_registered_buffer buffer(+    const mutable_registered_buffer& b) ASIO_NOEXCEPT+{+  return b;+}++/// Obtain a buffer representing the entire registered buffer.+inline const_registered_buffer buffer(+    const const_registered_buffer& b) ASIO_NOEXCEPT+{+  return b;+}++/// Obtain a buffer representing part of a registered buffer.+inline mutable_registered_buffer buffer(+    const mutable_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT+{+  return mutable_registered_buffer(buffer(b.buffer_, n), b.id_);+}++/// Obtain a buffer representing part of a registered buffer.+inline const_registered_buffer buffer(+    const const_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT+{+  return const_registered_buffer(buffer(b.buffer_, n), b.id_);+}++/** @} */++/// Create a new modifiable registered buffer that is offset from the start of+/// another.+/**+ * @relates mutable_registered_buffer+ */+inline mutable_registered_buffer operator+(+    const mutable_registered_buffer& b, std::size_t n) ASIO_NOEXCEPT+{+  mutable_registered_buffer tmp(b);+  tmp += n;+  return tmp;+}++/// Create a new modifiable buffer that is offset from the start of another.+/**+ * @relates mutable_registered_buffer+ */+inline mutable_registered_buffer operator+(std::size_t n,+    const mutable_registered_buffer& b) ASIO_NOEXCEPT+{+  return b + n;+}++/// Create a new non-modifiable registered buffer that is offset from the start+/// of another.+/**+ * @relates const_registered_buffer+ */+inline const_registered_buffer operator+(const const_registered_buffer& b,+    std::size_t n) ASIO_NOEXCEPT+{+  const_registered_buffer tmp(b);+  tmp += n;+  return tmp;+}++/// Create a new non-modifiable buffer that is offset from the start of another.+/**+ * @relates const_registered_buffer+ */+inline const_registered_buffer operator+(std::size_t n,+    const const_registered_buffer& b) ASIO_NOEXCEPT+{+  return b + n;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_REGISTERED_BUFFER_HPP
link/modules/asio-standalone/asio/include/asio/require.hpp view
@@ -2,7 +2,7 @@ // require.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -107,6 +107,7 @@  namespace asio_require_fn { +using asio::conditional; using asio::decay; using asio::declval; using asio::enable_if;@@ -127,7 +128,8 @@   ill_formed }; -template <typename T, typename Properties, typename = void>+template <typename Impl, typename T, typename Properties, typename = void,+    typename = void, typename = void, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -135,19 +137,19 @@   typedef void result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_requirable+  >::type,+  typename enable_if<+    static_require<T, Property>::is_valid   >::type> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -160,57 +162,62 @@ #endif // defined(ASIO_HAS_MOVE) }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_requirable+  >::type,+  typename enable_if<+    !static_require<T, Property>::is_valid+  >::type,+  typename enable_if<+    require_member<typename Impl::template proxy<T>::type, Property>::is_valid   >::type> :-  require_member<T, Property>+  require_member<typename Impl::template proxy<T>::type, Property> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_requirable+  >::type,+  typename enable_if<+    !static_require<T, Property>::is_valid+  >::type,+  typename enable_if<+    !require_member<typename Impl::template proxy<T>::type, Property>::is_valid+  >::type,+  typename enable_if<+    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),+template <typename Impl, typename T, typename P0, typename P1>+struct call_traits<Impl, T, void(P0, P1),   typename enable_if<-    call_traits<T, void(P0)>::overload != ill_formed-    &&+    call_traits<Impl, T, void(P0)>::overload != ill_formed+  >::type,+  typename enable_if<     call_traits<-      typename call_traits<T, void(P0)>::result_type,+      Impl,+      typename call_traits<Impl, T, void(P0)>::result_type,       void(P1)     >::overload != ill_formed   >::type>@@ -219,29 +226,34 @@    ASIO_STATIC_CONSTEXPR(bool, is_noexcept =     (-      call_traits<T, void(P0)>::is_noexcept+      call_traits<Impl, T, void(P0)>::is_noexcept       &&       call_traits<-        typename call_traits<T, void(P0)>::result_type,+        Impl,+        typename call_traits<Impl, T, void(P0)>::result_type,         void(P1)       >::is_noexcept     ));    typedef typename decay<     typename call_traits<-      typename call_traits<T, void(P0)>::result_type,+      Impl,+      typename call_traits<Impl, 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),+template <typename Impl, typename T, typename P0,+    typename P1, typename ASIO_ELLIPSIS PN>+struct call_traits<Impl, T, void(P0, P1, PN ASIO_ELLIPSIS),   typename enable_if<-    call_traits<T, void(P0)>::overload != ill_formed-    &&+    call_traits<Impl, T, void(P0)>::overload != ill_formed+  >::type,+  typename enable_if<     call_traits<-      typename call_traits<T, void(P0)>::result_type,+      Impl,+      typename call_traits<Impl, T, void(P0)>::result_type,       void(P1, PN ASIO_ELLIPSIS)     >::overload != ill_formed   >::type>@@ -250,17 +262,19 @@    ASIO_STATIC_CONSTEXPR(bool, is_noexcept =     (-      call_traits<T, void(P0)>::is_noexcept+      call_traits<Impl, T, void(P0)>::is_noexcept       &&       call_traits<-        typename call_traits<T, void(P0)>::result_type,+        Impl,+        typename call_traits<Impl, 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,+      Impl,+      typename call_traits<Impl, T, void(P0)>::result_type,       void(P1, PN ASIO_ELLIPSIS)     >::result_type   >::type result_type;@@ -268,30 +282,54 @@  struct impl {+  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto require(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().require(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().require(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)+  };+   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+    call_traits<impl, T, void(Property)>::overload == identity,+    typename call_traits<impl, 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))+      call_traits<impl, 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+    call_traits<impl, T, void(Property)>::overload == call_member,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return ASIO_MOVE_CAST(T)(t).require(         ASIO_MOVE_CAST(Property)(p));@@ -299,14 +337,14 @@    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+    call_traits<impl, T, void(Property)>::overload == call_free,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return require(         ASIO_MOVE_CAST(T)(t),@@ -315,15 +353,15 @@    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+    call_traits<impl, T, void(P0, P1)>::overload == two_props,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(P0, P1)>::is_noexcept))   {     return (*this)(         (*this)(@@ -335,8 +373,10 @@   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+    call_traits<impl, T,+      void(P0, P1, PN ASIO_ELLIPSIS)>::overload == n_props,+    typename call_traits<impl, T,+      void(P0, P1, PN ASIO_ELLIPSIS)>::result_type   >::type   operator()(       ASIO_MOVE_ARG(T) t,@@ -344,7 +384,7 @@       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))+      call_traits<impl, T, void(P0, P1, PN ASIO_ELLIPSIS)>::is_noexcept))   {     return (*this)(         (*this)(@@ -373,13 +413,16 @@  } // namespace +typedef asio_require_fn::impl require_t;+ #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>+    asio_require_fn::call_traits<+      require_t, T, void(Properties...)>::overload+        != asio_require_fn::ill_formed> { }; @@ -389,7 +432,7 @@     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::call_traits<require_t, T, void(P0, P1, P2)>::overload       != asio_require_fn::ill_formed> { };@@ -397,7 +440,7 @@ 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::call_traits<require_t, T, void(P0, P1)>::overload       != asio_require_fn::ill_formed> { };@@ -405,7 +448,7 @@ 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::call_traits<require_t, T, void(P0)>::overload       != asio_require_fn::ill_formed> { };@@ -431,7 +474,8 @@ template <typename T, typename... Properties> struct is_nothrow_require :   integral_constant<bool,-    asio_require_fn::call_traits<T, void(Properties...)>::is_noexcept>+    asio_require_fn::call_traits<+      require_t, T, void(Properties...)>::is_noexcept> { }; @@ -441,21 +485,24 @@     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>+    asio_require_fn::call_traits<+      require_t, 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>+    asio_require_fn::call_traits<+      require_t, 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>+    asio_require_fn::call_traits<+      require_t, T, void(P0)>::is_noexcept> { }; @@ -481,7 +528,7 @@ struct require_result {   typedef typename asio_require_fn::call_traits<-      T, void(Properties...)>::result_type type;+      require_t, T, void(Properties...)>::result_type type; };  #else // defined(ASIO_HAS_VARIADIC_TEMPLATES)@@ -491,21 +538,21 @@ struct require_result {   typedef typename asio_require_fn::call_traits<-      T, void(P0, P1, P2)>::result_type type;+      require_t, 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;+      require_t, 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;+      require_t, T, void(P0)>::result_type type; };  template <typename T>
link/modules/asio-standalone/asio/include/asio/require_concept.hpp view
@@ -2,7 +2,7 @@ // require_concept.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -107,6 +107,7 @@  namespace asio_require_concept_fn { +using asio::conditional; using asio::decay; using asio::declval; using asio::enable_if;@@ -125,7 +126,8 @@   ill_formed }; -template <typename T, typename Properties, typename = void>+template <typename Impl, typename T, typename Properties, typename = void,+    typename = void, typename = void, typename = void, typename = void> struct call_traits {   ASIO_STATIC_CONSTEXPR(overload_type, overload = ill_formed);@@ -133,19 +135,19 @@   typedef void result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_requirable_concept+  >::type,+  typename enable_if<+    static_require_concept<T, Property>::is_valid   >::type> {   ASIO_STATIC_CONSTEXPR(overload_type, overload = identity);@@ -153,44 +155,56 @@   typedef ASIO_MOVE_ARG(T) result_type; }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_requirable_concept+  >::type,+  typename enable_if<+    !static_require_concept<T, Property>::is_valid+  >::type,+  typename enable_if<+    require_concept_member<+      typename Impl::template proxy<T>::type,+      Property+    >::is_valid   >::type> :-  require_concept_member<T, Property>+  require_concept_member<+    typename Impl::template proxy<T>::type,+    Property+  > {   ASIO_STATIC_CONSTEXPR(overload_type, overload = call_member); }; -template <typename T, typename Property>-struct call_traits<T, void(Property),+template <typename Impl, typename T, typename Property>+struct call_traits<Impl, 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-    )+    is_applicable_property<+      typename decay<T>::type,+      typename decay<Property>::type+    >::value+  >::type,+  typename enable_if<+    decay<Property>::type::is_requirable_concept+  >::type,+  typename enable_if<+    !static_require_concept<T, Property>::is_valid+  >::type,+  typename enable_if<+    !require_concept_member<+      typename Impl::template proxy<T>::type,+      Property+    >::is_valid+  >::type,+  typename enable_if<+    require_concept_free<T, Property>::is_valid   >::type> :   require_concept_free<T, Property> {@@ -199,30 +213,54 @@  struct impl {+  template <typename T>+  struct proxy+  {+#if defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)+    struct type+    {+      template <typename P>+      auto require_concept(ASIO_MOVE_ARG(P) p)+        noexcept(+          noexcept(+            declval<typename conditional<true, T, P>::type>().require_concept(+              ASIO_MOVE_CAST(P)(p))+          )+        )+        -> decltype(+          declval<typename conditional<true, T, P>::type>().require_concept(+            ASIO_MOVE_CAST(P)(p))+        );+    };+#else // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)+    typedef T type;+#endif // defined(ASIO_HAS_DEDUCED_REQUIRE_CONCEPT_MEMBER_TRAIT)+  };+   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+    call_traits<impl, T, void(Property)>::overload == identity,+    typename call_traits<impl, 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))+      call_traits<impl, 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+    call_traits<impl, T, void(Property)>::overload == call_member,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return ASIO_MOVE_CAST(T)(t).require_concept(         ASIO_MOVE_CAST(Property)(p));@@ -230,14 +268,14 @@    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+    call_traits<impl, T, void(Property)>::overload == call_free,+    typename call_traits<impl, 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))+      call_traits<impl, T, void(Property)>::is_noexcept))   {     return require_concept(         ASIO_MOVE_CAST(T)(t),@@ -263,11 +301,14 @@  } // namespace +typedef asio_require_concept_fn::impl require_concept_t;+ 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>+    asio_require_concept_fn::call_traits<+      require_concept_t, T, void(Property)>::overload !=+        asio_require_concept_fn::ill_formed> { }; @@ -282,7 +323,8 @@ template <typename T, typename Property> struct is_nothrow_require_concept :   integral_constant<bool,-    asio_require_concept_fn::call_traits<T, void(Property)>::is_noexcept>+    asio_require_concept_fn::call_traits<+      require_concept_t, T, void(Property)>::is_noexcept> { }; @@ -298,7 +340,7 @@ struct require_concept_result {   typedef typename asio_require_concept_fn::call_traits<-      T, void(Property)>::result_type type;+      require_concept_t, T, void(Property)>::result_type type; };  } // namespace asio
link/modules/asio-standalone/asio/include/asio/serial_port.hpp view
@@ -2,7 +2,7 @@ // serial_port.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/serial_port_base.hpp view
@@ -2,7 +2,7 @@ // serial_port_base.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/signal_set.hpp view
@@ -2,7 +2,7 @@ // signal_set.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/signal_set_base.hpp view
@@ -0,0 +1,182 @@+//+// signal_set_base.hpp+// ~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software 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_BASE_HPP+#define ASIO_SIGNAL_SET_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 {++/// The signal_set_base class is used as a base for the basic_signal_set class+/// templates so that we have a common place to define the flags enum.+class signal_set_base+{+public:+# if defined(GENERATING_DOCUMENTATION)+  /// Enumeration representing the different types of flags that may specified+  /// when adding a signal to a set.+  enum flags+  {+    /// Bitmask representing no flags.+    none = 0,++    /// Affects the behaviour of interruptible functions such that, if the+    /// function would have failed with error::interrupted when interrupted by+    /// the specified signal, the function shall instead be restarted and not+    /// fail with error::interrupted.+    restart = implementation_defined,++    /// Do not generate SIGCHLD when child processes stop or stopped child+    /// processes continue.+    no_child_stop = implementation_defined,++    /// Do not transform child processes into zombies when they terminate.+    no_child_wait = implementation_defined,++    /// Special value to indicate that the signal registration does not care+    /// which flags are set, and so will not conflict with any prior+    /// registrations of the same signal.+    dont_care = -1+  };++  /// Portability typedef.+  typedef flags flags_t;+#elif defined(ASIO_HAS_ENUM_CLASS)+  enum class flags : int+  {+    none = 0,+    restart = ASIO_OS_DEF(SA_RESTART),+    no_child_stop = ASIO_OS_DEF(SA_NOCLDSTOP),+    no_child_wait = ASIO_OS_DEF(SA_NOCLDWAIT),+    dont_care = -1+  };++  typedef flags flags_t;+#else // defined(ASIO_HAS_ENUM_CLASS)+  struct flags+  {+    enum flags_t+    {+      none = 0,+      restart = ASIO_OS_DEF(SA_RESTART),+      no_child_stop = ASIO_OS_DEF(SA_NOCLDSTOP),+      no_child_wait = ASIO_OS_DEF(SA_NOCLDWAIT),+      dont_care = -1+    };+  };++  typedef flags::flags_t flags_t;+#endif // defined(ASIO_HAS_ENUM_CLASS)++protected:+  /// Protected destructor to prevent deletion through this type.+  ~signal_set_base()+  {+  }+};++/// Negation operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR bool operator!(signal_set_base::flags_t x)+{+  return static_cast<int>(x) == 0;+}++/// Bitwise and operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR signal_set_base::flags_t operator&(+    signal_set_base::flags_t x, signal_set_base::flags_t y)+{+  return static_cast<signal_set_base::flags_t>(+      static_cast<int>(x) & static_cast<int>(y));+}++/// Bitwise or operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR signal_set_base::flags_t operator|(+    signal_set_base::flags_t x, signal_set_base::flags_t y)+{+  return static_cast<signal_set_base::flags_t>(+      static_cast<int>(x) | static_cast<int>(y));+}++/// Bitwise xor operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR signal_set_base::flags_t operator^(+    signal_set_base::flags_t x, signal_set_base::flags_t y)+{+  return static_cast<signal_set_base::flags_t>(+      static_cast<int>(x) ^ static_cast<int>(y));+}++/// Bitwise negation operator.+/**+ * @relates signal_set_base::flags+ */+inline ASIO_CONSTEXPR signal_set_base::flags_t operator~(+    signal_set_base::flags_t x)+{+  return static_cast<signal_set_base::flags_t>(~static_cast<int>(x));+}++/// Bitwise and-assignment operator.+/**+ * @relates signal_set_base::flags+ */+inline signal_set_base::flags_t& operator&=(+    signal_set_base::flags_t& x, signal_set_base::flags_t y)+{+  x = x & y;+  return x;+}++/// Bitwise or-assignment operator.+/**+ * @relates signal_set_base::flags+ */+inline signal_set_base::flags_t& operator|=(+    signal_set_base::flags_t& x, signal_set_base::flags_t y)+{+  x = x | y;+  return x;+}++/// Bitwise xor-assignment operator.+/**+ * @relates signal_set_base::flags+ */+inline signal_set_base::flags_t& operator^=(+    signal_set_base::flags_t& x, signal_set_base::flags_t y)+{+  x = x ^ y;+  return x;+}++} // namespace asio++#include "asio/detail/pop_options.hpp"++#endif // ASIO_SIGNAL_SET_BASE_HPP
link/modules/asio-standalone/asio/include/asio/socket_base.hpp view
@@ -2,7 +2,7 @@ // socket_base.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/spawn.hpp view
@@ -2,7 +2,7 @@ // spawn.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,28 +16,162 @@ #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/cancellation_signal.hpp"+#include "asio/cancellation_state.hpp"+#include "asio/detail/exception.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" +#if defined(ASIO_HAS_BOOST_COROUTINE)+# include <boost/coroutine/all.hpp>+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+ #include "asio/detail/push_options.hpp"  namespace asio {+namespace detail { -/// Context object the represents the currently executing coroutine.+// Base class for all spawn()-ed thread implementations.+class spawned_thread_base+{+public:+  spawned_thread_base()+    : owner_(0),+      has_context_switched_(false),+      throw_if_cancelled_(false),+      terminal_(false)+  {+  }++  virtual ~spawned_thread_base() {}+  virtual void resume() = 0;+  virtual void suspend_with(void (*fn)(void*), void* arg) = 0;+  virtual void destroy() = 0;++  void attach(spawned_thread_base** owner)+  {+    owner_ = owner;+    *owner_ = this;+  }++  void detach()+  {+    if (owner_)+      *owner_ = 0;+    owner_ = 0;+  }++  void suspend()+  {+    suspend_with(0, 0);+  }++  template <typename F>+  void suspend_with(F f)+  {+    suspend_with(&spawned_thread_base::call<F>, &f);+  }++  cancellation_slot get_cancellation_slot() const ASIO_NOEXCEPT+  {+    return cancellation_state_.slot();+  }++  cancellation_state get_cancellation_state() const ASIO_NOEXCEPT+  {+    return cancellation_state_;+  }++  void reset_cancellation_state()+  {+    cancellation_state_ = cancellation_state(parent_cancellation_slot_);+  }++  template <typename Filter>+  void reset_cancellation_state(Filter filter)+  {+    cancellation_state_ = cancellation_state(+        parent_cancellation_slot_, filter, filter);+  }++  template <typename InFilter, typename OutFilter>+  void reset_cancellation_state(InFilter in_filter, OutFilter out_filter)+  {+    cancellation_state_ = cancellation_state(+        parent_cancellation_slot_, in_filter, out_filter);+  }++  cancellation_type_t cancelled() const ASIO_NOEXCEPT+  {+    return cancellation_state_.cancelled();+  }++  bool has_context_switched() const ASIO_NOEXCEPT+  {+    return has_context_switched_;+  }++  bool throw_if_cancelled() const ASIO_NOEXCEPT+  {+    return throw_if_cancelled_;+  }++  void throw_if_cancelled(bool value) ASIO_NOEXCEPT+  {+    throw_if_cancelled_ = value;+  }++protected:+  spawned_thread_base** owner_; // Points to data member in active handler.+  asio::cancellation_slot parent_cancellation_slot_;+  asio::cancellation_state cancellation_state_;+  bool has_context_switched_;+  bool throw_if_cancelled_;+  bool terminal_;++private:+  // Disallow copying and assignment.+  spawned_thread_base(const spawned_thread_base&) ASIO_DELETED;+  spawned_thread_base& operator=(const spawned_thread_base&) ASIO_DELETED;++  template <typename F>+  static void call(void* f)+  {+    (*static_cast<F*>(f))();+  }+};+++template <typename T>+struct spawn_signature+{+  typedef void type(exception_ptr, T);+};++template <>+struct spawn_signature<void>+{+  typedef void type(exception_ptr);+};++template <typename Executor>+class initiate_spawn;++} // namespace detail++/// A @ref completion_token that 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:+ * The basic_yield_context class is a completion token type that is used to+ * represent the currently executing stackful coroutine. A basic_yield_context+ * object may be passed as a completion token to an asynchronous operation. For+ * example:  *- * @code template <typename Handler>- * void my_coroutine(basic_yield_context<Handler> yield)+ * @code template <typename Executor>+ * void my_coroutine(basic_yield_context<Executor> yield)  * {  *   ...  *   std::size_t n = my_socket.async_read_some(buffer, yield);@@ -48,69 +182,114 @@  * current coroutine. The coroutine is resumed when the asynchronous operation  * completes, and the result of the operation is returned.  */-template <typename Handler>+template <typename Executor> class basic_yield_context { public:-  /// The coroutine callee type, used by the implementation.+  /// The executor type associated with the yield context.+  typedef Executor executor_type;++  /// The cancellation slot type associated with the yield context.+  typedef cancellation_slot cancellation_slot_type;++  /// Construct a yield context from another yield context type.   /**-   * 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+   * Requires that OtherExecutor be convertible to Executor.    */-#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.+  template <typename OtherExecutor>+  basic_yield_context(const basic_yield_context<OtherExecutor>& other,+      typename constraint<+        is_convertible<OtherExecutor, Executor>::value+      >::type = 0)+    : spawned_thread_(other.spawned_thread_),+      executor_(other.executor_),+      ec_(other.ec_)+  {+  }++  /// Get the executor associated with the yield context.+  executor_type get_executor() const ASIO_NOEXCEPT+  {+    return executor_;+  }++  /// Get the cancellation slot associated with the coroutine.+  cancellation_slot_type get_cancellation_slot() const ASIO_NOEXCEPT+  {+    return spawned_thread_->get_cancellation_slot();+  }++  /// Get the cancellation state associated with the coroutine.+  cancellation_state get_cancellation_state() const ASIO_NOEXCEPT+  {+    return spawned_thread_->get_cancellation_state();+  }++  /// Reset the cancellation state associated with the coroutine.   /**-   * 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+   * Let <tt>P</tt> be the cancellation slot associated with the current+   * coroutine's @ref spawn completion handler. Assigns a new+   * asio::cancellation_state object <tt>S</tt>, constructed as+   * <tt>S(P)</tt>, into the current coroutine's cancellation state object.    */-#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+  void reset_cancellation_state() const+  {+    spawned_thread_->reset_cancellation_state();+  } -  /// Construct a yield context to represent the specified coroutine.+  /// Reset the cancellation state associated with the 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.+   * Let <tt>P</tt> be the cancellation slot associated with the current+   * coroutine's @ref spawn completion handler. Assigns a new+   * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P,+   * std::forward<Filter>(filter))</tt>, into the current coroutine's+   * cancellation state object.    */-  basic_yield_context(-      const detail::weak_ptr<callee_type>& coro,-      caller_type& ca, Handler& handler)-    : coro_(coro),-      ca_(ca),-      handler_(handler),-      ec_(0)+  template <typename Filter>+  void reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter) const   {+    spawned_thread_->reset_cancellation_state(+        ASIO_MOVE_CAST(Filter)(filter));   } -  /// Construct a yield context from another yield context type.+  /// Reset the cancellation state associated with the coroutine.   /**-   * Requires that OtherHandler be convertible to Handler.+   * Let <tt>P</tt> be the cancellation slot associated with the current+   * coroutine's @ref spawn completion handler. Assigns a new+   * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P,+   * std::forward<InFilter>(in_filter),+   * std::forward<OutFilter>(out_filter))</tt>, into the current coroutine's+   * cancellation state object.    */-  template <typename OtherHandler>-  basic_yield_context(const basic_yield_context<OtherHandler>& other)-    : coro_(other.coro_),-      ca_(other.ca_),-      handler_(other.handler_),-      ec_(other.ec_)+  template <typename InFilter, typename OutFilter>+  void reset_cancellation_state(ASIO_MOVE_ARG(InFilter) in_filter,+      ASIO_MOVE_ARG(OutFilter) out_filter) const   {+    spawned_thread_->reset_cancellation_state(+        ASIO_MOVE_CAST(InFilter)(in_filter),+        ASIO_MOVE_CAST(OutFilter)(out_filter));   } +  /// Determine whether the current coroutine has been cancelled.+  cancellation_type_t cancelled() const ASIO_NOEXCEPT+  {+    return spawned_thread_->cancelled();+  }++  /// Determine whether the coroutine throws if trying to suspend when it has+  /// been cancelled.+  bool throw_if_cancelled() const ASIO_NOEXCEPT+  {+    return spawned_thread_->throw_if_cancelled();+  }++  /// Set whether the coroutine throws if trying to suspend when it has been+  /// cancelled.+  void throw_if_cancelled(bool value) const ASIO_NOEXCEPT+  {+    spawned_thread_->throw_if_cancelled(value);+  }+   /// Return a yield context that sets the specified error_code.   /**    * By default, when a yield context is used with an asynchronous operation, a@@ -118,8 +297,8 @@    * 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)+   * @code template <typename Executor>+   * void my_coroutine(basic_yield_context<Executor> yield)    * {    *   ...    *   std::size_t n = my_socket.async_read_some(buffer, yield[ec]);@@ -137,22 +316,25 @@     return tmp;   } -#if defined(GENERATING_DOCUMENTATION)-private:-#endif // defined(GENERATING_DOCUMENTATION)-  detail::weak_ptr<callee_type> coro_;-  caller_type& ca_;-  Handler handler_;+#if !defined(GENERATING_DOCUMENTATION)+//private:+  basic_yield_context(detail::spawned_thread_base* spawned_thread,+      const Executor& ex)+    : spawned_thread_(spawned_thread),+      executor_(ex),+      ec_(0)+  {+  }++  detail::spawned_thread_base* spawned_thread_;+  Executor executor_;   asio::error_code* ec_;+#endif // !defined(GENERATING_DOCUMENTATION) }; -#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)+/// A @ref completion_token object that represents the currently executing+/// coroutine.+typedef basic_yield_context<any_io_executor> yield_context;  /**  * @defgroup spawn asio::spawn@@ -163,7 +345,7 @@  * 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);+ * @code asio::spawn(my_strand, do_echo, asio::detached);  *  * // ...  *@@ -190,13 +372,383 @@  */ /*@{*/ -/// Start a new stackful coroutine, calling the specified handler when it-/// completes.+/// Start a new stackful coroutine that executes on a given executor. /**+ * This function is used to launch a new stackful coroutine.+ *+ * @param ex Identifies the executor that will run the stackful coroutine.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename Executor, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+        CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const Executor& ex, ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+#if defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      !is_same<+        typename decay<CompletionToken>::type,+        boost::coroutines::attributes+      >::value+    >::type = 0,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+          declval<detail::initiate_spawn<Executor> >(),+          token, ASIO_MOVE_CAST(F)(function))));++/// Start a new stackful coroutine that executes on a given execution context.+/**+ * This function is used to launch a new stackful coroutine.+ *+ * @param ctx Identifies the execution context that will run the stackful+ * coroutine.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename ExecutionContext, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<+        typename ExecutionContext::executor_type>)>::type>::type)+          CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+            typename ExecutionContext::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<+        typename ExecutionContext::executor_type>)>::type>::type)+spawn(ExecutionContext& ctx, ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename ExecutionContext::executor_type),+#if defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      !is_same<+        typename decay<CompletionToken>::type,+        boost::coroutines::attributes+      >::value+    >::type = 0,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<+          typename ExecutionContext::executor_type>)>::type>::type>(+            declval<detail::initiate_spawn<+              typename ExecutionContext::executor_type> >(),+            token, ASIO_MOVE_CAST(F)(function))));++/// Start a new stackful coroutine, inheriting the executor of another.+/**+ * This function is used to launch a new stackful coroutine.+ *+ * @param ctx Identifies the current coroutine as a parent of the new+ * coroutine. This specifies that the new coroutine should inherit the executor+ * 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 be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename Executor, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+        CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const basic_yield_context<Executor>& ctx,+    ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+#if defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      !is_same<+        typename decay<CompletionToken>::type,+        boost::coroutines::attributes+      >::value+    >::type = 0,+#endif // defined(ASIO_HAS_BOOST_COROUTINE)+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+          declval<detail::initiate_spawn<Executor> >(),+          token, ASIO_MOVE_CAST(F)(function))));++#if defined(ASIO_HAS_BOOST_CONTEXT_FIBER) \+  || defined(GENERATING_DOCUMENTATION)++/// Start a new stackful coroutine that executes on a given executor.+/**+ * This function is used to launch a new stackful coroutine using the+ * specified stack allocator.+ *+ * @param ex Identifies the executor that will run the stackful coroutine.+ *+ * @param stack_allocator Denotes the allocator to be used to allocate the+ * underlying coroutine's stack. The type must satisfy the stack-allocator+ * concept defined by the Boost.Context library.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename Executor, typename StackAllocator, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+        CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const Executor& ex, allocator_arg_t,+    ASIO_MOVE_ARG(StackAllocator) stack_allocator,+    ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+    typename constraint<+      is_executor<Executor>::value || execution::is_executor<Executor>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+          declval<detail::initiate_spawn<Executor> >(),+          token, allocator_arg_t(),+          ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+          ASIO_MOVE_CAST(F)(function))));++/// Start a new stackful coroutine that executes on a given execution context.+/**+ * This function is used to launch a new stackful coroutine.+ *+ * @param ctx Identifies the execution context that will run the stackful+ * coroutine.+ *+ * @param stack_allocator Denotes the allocator to be used to allocate the+ * underlying coroutine's stack. The type must satisfy the stack-allocator+ * concept defined by the Boost.Context library.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename ExecutionContext, typename StackAllocator, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<+        typename ExecutionContext::executor_type>)>::type>::type)+          CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(+            typename ExecutionContext::executor_type)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<+        typename ExecutionContext::executor_type>)>::type>::type)+spawn(ExecutionContext& ctx, allocator_arg_t,+    ASIO_MOVE_ARG(StackAllocator) stack_allocator,+    ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token+      ASIO_DEFAULT_COMPLETION_TOKEN(+        typename ExecutionContext::executor_type),+    typename constraint<+      is_convertible<ExecutionContext&, execution_context&>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<CompletionToken,+      typename detail::spawn_signature<+        typename result_of<F(basic_yield_context<+          typename ExecutionContext::executor_type>)>::type>::type>(+            declval<detail::initiate_spawn<+              typename ExecutionContext::executor_type> >(),+            token, allocator_arg_t(),+            ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+            ASIO_MOVE_CAST(F)(function))));++/// Start a new stackful coroutine, inheriting the executor of another.+/**+ * This function is used to launch a new stackful coroutine using the+ * specified stack allocator.+ *+ * @param ctx Identifies the current coroutine as a parent of the new+ * coroutine. This specifies that the new coroutine should inherit the+ * executor 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 stack_allocator Denotes the allocator to be used to allocate the+ * underlying coroutine's stack. The type must satisfy the stack-allocator+ * concept defined by the Boost.Context library.+ *+ * @param function The coroutine function. The function must be callable the+ * signature:+ * @code void function(basic_yield_context<Executor> yield); @endcode+ *+ * @param token The @ref completion_token that will handle the notification+ * that the coroutine has completed. If the return type @c R of @c function is+ * @c void, the function signature of the completion handler must be:+ *+ * @code void handler(std::exception_ptr); @endcode+ * Otherwise, the function signature of the completion handler must be:+ * @code void handler(std::exception_ptr, R); @endcode+ *+ * @par Completion Signature+ * @code void(std::exception_ptr, R) @endcode+ * where @c R is the return type of the function object.+ *+ * @par Per-Operation Cancellation+ * The new thread of execution is created with a cancellation state that+ * supports @c cancellation_type::terminal values only. To change the+ * cancellation state, call the basic_yield_context member function+ * @c reset_cancellation_state.+ */+template <typename Executor, typename StackAllocator, typename F,+    ASIO_COMPLETION_TOKEN_FOR(typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+        CompletionToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(Executor)>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type)+spawn(const basic_yield_context<Executor>& ctx, allocator_arg_t,+    ASIO_MOVE_ARG(StackAllocator) stack_allocator,+    ASIO_MOVE_ARG(F) function,+    ASIO_MOVE_ARG(CompletionToken) token+    ASIO_DEFAULT_COMPLETION_TOKEN(Executor),+  typename constraint<+    is_executor<Executor>::value || execution::is_executor<Executor>::value+  >::type = 0)+ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+  async_initiate<CompletionToken,+    typename detail::spawn_signature<+      typename result_of<F(basic_yield_context<Executor>)>::type>::type>(+        declval<detail::initiate_spawn<Executor> >(),+        token, allocator_arg_t(),+        ASIO_MOVE_CAST(StackAllocator)(stack_allocator),+        ASIO_MOVE_CAST(F)(function))));++#endif // defined(ASIO_HAS_BOOST_CONTEXT_FIBER)+       //   || defined(GENERATING_DOCUMENTATION)++#if defined(ASIO_HAS_BOOST_COROUTINE) \+  || defined(GENERATING_DOCUMENTATION)++/// (Deprecated: Use overloads with a completion token.) 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+ * @code void function(basic_yield_context<Executor> yield); @endcode+ * where Executor is the associated executor type of @c Function.  *  * @param attributes Boost.Coroutine attributes used to customise the coroutine.  */@@ -205,8 +757,8 @@     const boost::coroutines::attributes& attributes       = boost::coroutines::attributes()); -/// Start a new stackful coroutine, calling the specified handler when it-/// completes.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine, calling the specified handler when it completes. /**  * This function is used to launch a new coroutine.  *@@ -216,7 +768,8 @@  * @code void handler(); @endcode  *  * @param function The coroutine function. The function must have the signature:- * @code void function(basic_yield_context<Handler> yield); @endcode+ * @code void function(basic_yield_context<Executor> yield); @endcode+ * where Executor is the associated executor type of @c Handler.  *  * @param attributes Boost.Coroutine attributes used to customise the coroutine.  */@@ -225,12 +778,13 @@     ASIO_MOVE_ARG(Function) function,     const boost::coroutines::attributes& attributes       = boost::coroutines::attributes(),-    typename enable_if<+    typename constraint<       !is_executor<typename decay<Handler>::type>::value &&       !execution::is_executor<typename decay<Handler>::type>::value &&-      !is_convertible<Handler&, execution_context&>::value>::type* = 0);+      !is_convertible<Handler&, execution_context&>::value>::type = 0); -/// Start a new stackful coroutine, inheriting the execution context of another.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine, inheriting the execution context of another. /**  * This function is used to launch a new coroutine.  *@@ -241,22 +795,24 @@  * same strand.  *  * @param function The coroutine function. The function must have the signature:- * @code void function(basic_yield_context<Handler> yield); @endcode+ * @code void function(basic_yield_context<Executor> yield); @endcode  *  * @param attributes Boost.Coroutine attributes used to customise the coroutine.  */-template <typename Handler, typename Function>-void spawn(basic_yield_context<Handler> ctx,+template <typename Executor, typename Function>+void spawn(basic_yield_context<Executor> 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.+/// (Deprecated: Use overloads with a completion token.) 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.+ * coroutine is automatically given its own explicit strand within this+ * executor.  *  * @param function The coroutine function. The function must have the signature:  * @code void function(yield_context yield); @endcode@@ -268,11 +824,12 @@     ASIO_MOVE_ARG(Function) function,     const boost::coroutines::attributes& attributes       = boost::coroutines::attributes(),-    typename enable_if<+    typename constraint<       is_executor<Executor>::value || execution::is_executor<Executor>::value-    >::type* = 0);+    >::type = 0); -/// Start a new stackful coroutine that executes on a given strand.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine that executes on a given strand. /**  * This function is used to launch a new coroutine.  *@@ -291,7 +848,8 @@  #if !defined(ASIO_NO_TS_EXECUTORS) -/// Start a new stackful coroutine that executes in the context of a strand.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine that executes in the context of a strand. /**  * This function is used to launch a new coroutine.  *@@ -312,7 +870,8 @@  #endif // !defined(ASIO_NO_TS_EXECUTORS) -/// Start a new stackful coroutine that executes on a given execution context.+/// (Deprecated: Use overloads with a completion token.) Start a new stackful+/// coroutine that executes on a given execution context. /**  * This function is used to launch a new coroutine.  *@@ -330,8 +889,11 @@     ASIO_MOVE_ARG(Function) function,     const boost::coroutines::attributes& attributes       = boost::coroutines::attributes(),-    typename enable_if<is_convertible<-      ExecutionContext&, execution_context&>::value>::type* = 0);+    typename constraint<is_convertible<+      ExecutionContext&, execution_context&>::value>::type = 0);++#endif // defined(ASIO_HAS_BOOST_COROUTINE)+       //   || defined(GENERATING_DOCUMENTATION)  /*@}*/ 
link/modules/asio-standalone/asio/include/asio/ssl.hpp view
@@ -2,7 +2,7 @@ // ssl.hpp // ~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/context.hpp view
@@ -2,7 +2,7 @@ // ssl/context.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -740,6 +740,9 @@    // Helper function to make a BIO from a memory buffer.   ASIO_DECL BIO* make_buffer_bio(const const_buffer& b);++  // Translate an SSL error into an error code.+  ASIO_DECL static asio::error_code translate_error(long error);    // The underlying native implementation.   native_handle_type handle_;
link/modules/asio-standalone/asio/include/asio/ssl/context_base.hpp view
@@ -2,7 +2,7 @@ // ssl/context_base.hpp // ~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -105,60 +105,60 @@   };    /// Bitmask type for SSL options.-  typedef long options;+  typedef uint64_t options;  #if defined(GENERATING_DOCUMENTATION)   /// Implement various bug workarounds.-  static const long default_workarounds = implementation_defined;+  static const uint64_t default_workarounds = implementation_defined;    /// Always create a new key when using tmp_dh parameters.-  static const long single_dh_use = implementation_defined;+  static const uint64_t single_dh_use = implementation_defined;    /// Disable SSL v2.-  static const long no_sslv2 = implementation_defined;+  static const uint64_t no_sslv2 = implementation_defined;    /// Disable SSL v3.-  static const long no_sslv3 = implementation_defined;+  static const uint64_t no_sslv3 = implementation_defined;    /// Disable TLS v1.-  static const long no_tlsv1 = implementation_defined;+  static const uint64_t no_tlsv1 = implementation_defined;    /// Disable TLS v1.1.-  static const long no_tlsv1_1 = implementation_defined;+  static const uint64_t no_tlsv1_1 = implementation_defined;    /// Disable TLS v1.2.-  static const long no_tlsv1_2 = implementation_defined;+  static const uint64_t no_tlsv1_2 = implementation_defined;    /// Disable TLS v1.3.-  static const long no_tlsv1_3 = implementation_defined;+  static const uint64_t no_tlsv1_3 = implementation_defined;    /// Disable compression. Compression is disabled by default.-  static const long no_compression = implementation_defined;+  static const uint64_t 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);+  ASIO_STATIC_CONSTANT(uint64_t, default_workarounds = SSL_OP_ALL);+  ASIO_STATIC_CONSTANT(uint64_t, single_dh_use = SSL_OP_SINGLE_DH_USE);+  ASIO_STATIC_CONSTANT(uint64_t, no_sslv2 = SSL_OP_NO_SSLv2);+  ASIO_STATIC_CONSTANT(uint64_t, no_sslv3 = SSL_OP_NO_SSLv3);+  ASIO_STATIC_CONSTANT(uint64_t, 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);+  ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_1 = SSL_OP_NO_TLSv1_1); # else // defined(SSL_OP_NO_TLSv1_1)-  ASIO_STATIC_CONSTANT(long, no_tlsv1_1 = 0x10000000L);+  ASIO_STATIC_CONSTANT(uint64_t, 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);+  ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_2 = SSL_OP_NO_TLSv1_2); # else // defined(SSL_OP_NO_TLSv1_2)-  ASIO_STATIC_CONSTANT(long, no_tlsv1_2 = 0x08000000L);+  ASIO_STATIC_CONSTANT(uint64_t, 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);+  ASIO_STATIC_CONSTANT(uint64_t, no_tlsv1_3 = SSL_OP_NO_TLSv1_3); # else // defined(SSL_OP_NO_TLSv1_3)-  ASIO_STATIC_CONSTANT(long, no_tlsv1_3 = 0x20000000L);+  ASIO_STATIC_CONSTANT(uint64_t, 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);+  ASIO_STATIC_CONSTANT(uint64_t, no_compression = SSL_OP_NO_COMPRESSION); # else // defined(SSL_OP_NO_COMPRESSION)-  ASIO_STATIC_CONSTANT(long, no_compression = 0x20000L);+  ASIO_STATIC_CONSTANT(uint64_t, no_compression = 0x20000L); # endif // defined(SSL_OP_NO_COMPRESSION) #endif 
link/modules/asio-standalone/asio/include/asio/ssl/detail/buffered_handshake_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/buffered_handshake_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -56,7 +56,7 @@       const asio::error_code& ec,       const std::size_t& bytes_transferred) const   {-    handler(ec, bytes_transferred);+    ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec, bytes_transferred);   }  private:
link/modules/asio-standalone/asio/include/asio/ssl/detail/engine.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/engine.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -58,6 +58,9 @@   // Construct a new engine for the specified context.   ASIO_DECL explicit engine(SSL_CTX* context); +  // Construct a new engine for an existing native SSL implementation.+  ASIO_DECL explicit engine(SSL* ssl_impl);+ #if defined(ASIO_HAS_MOVE)   // Move construct from another engine.   ASIO_DECL engine(engine&& other) ASIO_NOEXCEPT;@@ -65,6 +68,11 @@    // Destructor.   ASIO_DECL ~engine();++#if defined(ASIO_HAS_MOVE)+  // Move assign from another engine.+  ASIO_DECL engine& operator=(engine&& other) ASIO_NOEXCEPT;+#endif // defined(ASIO_HAS_MOVE)    // Get the underlying implementation in the native type.   ASIO_DECL SSL* native_handle();
link/modules/asio-standalone/asio/include/asio/ssl/detail/handshake_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/handshake_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,7 +51,7 @@       const asio::error_code& ec,       const std::size_t&) const   {-    handler(ec);+    ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec);   }  private:
link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/engine.ipp view
@@ -2,7 +2,7 @@ // ssl/detail/impl/engine.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,6 +55,24 @@   ::SSL_set_bio(ssl_, int_bio, int_bio); } +engine::engine(SSL* ssl_impl)+  : ssl_(ssl_impl)+{+#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_),@@ -79,6 +97,20 @@   if (ssl_)     ::SSL_free(ssl_); }++#if defined(ASIO_HAS_MOVE)+engine& engine::operator=(engine&& other) ASIO_NOEXCEPT+{+  if (this != &other)+  {+    ssl_ = other.ssl_;+    ext_bio_ = other.ext_bio_;+    other.ssl_ = 0;+    other.ext_bio_ = 0;+  }+  return *this;+}+#endif // defined(ASIO_HAS_MOVE)  SSL* engine::native_handle() {
link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/openssl_init.ipp view
@@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com-// Copyright (c) 2005-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2005-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -85,9 +85,13 @@ #endif // (OPENSSL_VERSION_NUMBER >= 0x10002000L)        // && (OPENSSL_VERSION_NUMBER < 0x10100000L)        // && !defined(SSL_OP_NO_COMPRESSION)-#if !defined(OPENSSL_IS_BORINGSSL) && !defined(ASIO_USE_WOLFSSL)+#if !defined(OPENSSL_IS_BORINGSSL) \+    && !defined(ASIO_USE_WOLFSSL) \+    && (OPENSSL_VERSION_NUMBER < 0x30000000L)     ::CONF_modules_unload(1);-#endif // !defined(OPENSSL_IS_BORINGSSL) && !defined(ASIO_USE_WOLFSSL)+#endif // !defined(OPENSSL_IS_BORINGSSL)+       //   && !defined(ASIO_USE_WOLFSSL)+       //   && (OPENSSL_VERSION_NUMBER < 0x30000000L) #if !defined(OPENSSL_NO_ENGINE) \   && (OPENSSL_VERSION_NUMBER < 0x10100000L)     ::ENGINE_cleanup();
link/modules/asio-standalone/asio/include/asio/ssl/detail/io.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/io.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -17,6 +17,7 @@  #include "asio/detail/config.hpp" +#include "asio/detail/base_from_cancellation_state.hpp" #include "asio/detail/handler_tracking.hpp" #include "asio/ssl/detail/engine.hpp" #include "asio/ssl/detail/stream_core.hpp"@@ -94,11 +95,13 @@  template <typename Stream, typename Operation, typename Handler> class io_op+  : public asio::detail::base_from_cancellation_state<Handler> { public:   io_op(Stream& next_layer, stream_core& core,       const Operation& op, Handler& handler)-    : next_layer_(next_layer),+    : asio::detail::base_from_cancellation_state<Handler>(handler),+      next_layer_(next_layer),       core_(core),       op_(op),       start_(0),@@ -110,7 +113,8 @@  #if defined(ASIO_HAS_MOVE)   io_op(const io_op& other)-    : next_layer_(other.next_layer_),+    : asio::detail::base_from_cancellation_state<Handler>(other),+      next_layer_(other.next_layer_),       core_(other.core_),       op_(other.op_),       start_(other.start_),@@ -122,7 +126,11 @@   }    io_op(io_op&& other)-    : next_layer_(other.next_layer_),+    : asio::detail::base_from_cancellation_state<Handler>(+        ASIO_MOVE_CAST(+          asio::detail::base_from_cancellation_state<Handler>)(+            other)),+      next_layer_(other.next_layer_),       core_(other.core_),       op_(ASIO_MOVE_CAST(Operation)(other.op_)),       start_(other.start_),@@ -262,6 +270,13 @@           // Release any waiting read operations.           core_.pending_read_.expires_at(core_.neg_infin()); +          // Check for cancellation before continuing.+          if (this->cancelled() != cancellation_type::none)+          {+            ec_ = asio::error::operation_aborted;+            break;+          }+           // Try the operation again.           continue; @@ -270,6 +285,13 @@           // Release any waiting write operations.           core_.pending_write_.expires_at(core_.neg_infin()); +          // Check for cancellation before continuing.+          if (this->cancelled() != cancellation_type::none)+          {+            ec_ = asio::error::operation_aborted;+            break;+          }+           // Try the operation again.           continue; @@ -380,31 +402,29 @@ } // namespace detail } // namespace ssl -template <typename Stream, typename Operation,-    typename Handler, typename Allocator>-struct associated_allocator<-    ssl::detail::io_op<Stream, Operation, Handler>, Allocator>+template <template <typename, typename> class Associator,+    typename Stream, typename Operation,+    typename Handler, typename DefaultCandidate>+struct associator<Associator,+    ssl::detail::io_op<Stream, Operation, Handler>,+    DefaultCandidate>+  : Associator<Handler, DefaultCandidate> {-  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+  static typename Associator<Handler, DefaultCandidate>::type+  get(const ssl::detail::io_op<Stream, Operation, Handler>& h)+    ASIO_NOEXCEPT   {-    return associated_allocator<Handler, Allocator>::get(h.handler_, a);+    return Associator<Handler, DefaultCandidate>::get(h.handler_);   }-}; -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+  static ASIO_AUTO_RETURN_TYPE_PREFIX2(+      typename Associator<Handler, DefaultCandidate>::type)+  get(const ssl::detail::io_op<Stream, Operation, Handler>& h,+      const DefaultCandidate& c) ASIO_NOEXCEPT+    ASIO_AUTO_RETURN_TYPE_SUFFIX((+      Associator<Handler, DefaultCandidate>::get(h.handler_, c)))   {-    return associated_executor<Handler, Executor>::get(h.handler_, ex);+    return Associator<Handler, DefaultCandidate>::get(h.handler_, c);   } }; 
link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_init.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/openssl_init.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_types.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/openssl_types.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/detail/password_callback.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/password_callback.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/detail/read_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/read_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -56,7 +56,7 @@       const asio::error_code& ec,       const std::size_t& bytes_transferred) const   {-    handler(ec, bytes_transferred);+    ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec, bytes_transferred);   }  private:
link/modules/asio-standalone/asio/include/asio/ssl/detail/shutdown_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/shutdown_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,11 +51,11 @@       // 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());+      ASIO_MOVE_OR_LVALUE(Handler)(handler)(asio::error_code());     }     else     {-      handler(ec);+      ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec);     }   } };
link/modules/asio-standalone/asio/include/asio/ssl/detail/stream_core.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/stream_core.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -51,6 +51,20 @@     pending_write_.expires_at(neg_infin());   } +  template <typename Executor>+  stream_core(SSL* ssl_impl, const Executor& ex)+    : engine_(ssl_impl),+      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_)),@@ -88,6 +102,44 @@   ~stream_core()   {   }++#if defined(ASIO_HAS_MOVE)+  stream_core& operator=(stream_core&& other)+  {+    if (this != &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);+    }+    return *this;+  }+#endif // defined(ASIO_HAS_MOVE)    // The SSL engine.   engine engine_;
link/modules/asio-standalone/asio/include/asio/ssl/detail/verify_callback.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/verify_callback.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/detail/write_op.hpp view
@@ -2,7 +2,7 @@ // ssl/detail/write_op.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -60,7 +60,7 @@       const asio::error_code& ec,       const std::size_t& bytes_transferred) const   {-    handler(ec, bytes_transferred);+    ASIO_MOVE_OR_LVALUE(Handler)(handler)(ec, bytes_transferred);   }  private:
link/modules/asio-standalone/asio/include/asio/ssl/error.hpp view
@@ -2,7 +2,7 @@ // ssl/error.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/host_name_verification.hpp view
@@ -2,7 +2,7 @@ // ssl/host_name_verification.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/impl/context.hpp view
@@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com-// Copyright (c) 2005-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2005-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/impl/context.ipp view
@@ -3,7 +3,7 @@ // ~~~~~~~~~~~~~~~~~~~~ // // Copyright (c) 2005 Voipster / Indrek dot Juhani at voipster dot com-// Copyright (c) 2005-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2005-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -47,6 +47,7 @@   ~evp_pkey_cleanup() { if (p) ::EVP_PKEY_free(p); } }; +#if (OPENSSL_VERSION_NUMBER < 0x30000000L) struct context::rsa_cleanup {   RSA* p;@@ -58,6 +59,7 @@   DH* p;   ~dh_cleanup() { if (p) ::DH_free(p); } };+#endif // (OPENSSL_VERSION_NUMBER < 0x30000000L)  context::context(context::method m)   : handle_(0)@@ -357,9 +359,7 @@    if (handle_ == 0)   {-    asio::error_code ec(-        static_cast<int>(::ERR_get_error()),-        asio::error::get_ssl_category());+    asio::error_code ec = translate_error(::ERR_get_error());     asio::detail::throw_error(ec, "context");   } @@ -397,7 +397,8 @@   if (handle_)   { #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \-      && !defined(LIBRESSL_VERSION_NUMBER)) \+      && (!defined(LIBRESSL_VERSION_NUMBER) \+        || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \     || defined(ASIO_USE_WOLFSSL)     void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_); #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)@@ -410,7 +411,8 @@             cb_userdata);       delete callback; #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \-      && !defined(LIBRESSL_VERSION_NUMBER)) \+      && (!defined(LIBRESSL_VERSION_NUMBER) \+        || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \     || defined(ASIO_USE_WOLFSSL)       ::SSL_CTX_set_default_passwd_cb_userdata(handle_, 0); #else // (OPENSSL_VERSION_NUMBER >= 0x10100000L)@@ -543,9 +545,7 @@    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());+    ec = translate_error(::ERR_get_error());     ASIO_SYNC_OP_VOID_RETURN(ec);   } @@ -580,17 +580,13 @@               && ERR_GET_REASON(err) == PEM_R_NO_START_LINE)             break; -          ec = asio::error_code(-              static_cast<int>(err),-              asio::error::get_ssl_category());+          ec = translate_error(err);           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());+          ec = translate_error(::ERR_get_error());           ASIO_SYNC_OP_VOID_RETURN(ec);         }       }@@ -615,9 +611,7 @@    if (::SSL_CTX_set_default_verify_paths(handle_) != 1)   {-    ec = asio::error_code(-        static_cast<int>(::ERR_get_error()),-        asio::error::get_ssl_category());+    ec = translate_error(::ERR_get_error());     ASIO_SYNC_OP_VOID_RETURN(ec);   } @@ -639,9 +633,7 @@    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());+    ec = translate_error(::ERR_get_error());     ASIO_SYNC_OP_VOID_RETURN(ec);   } @@ -695,9 +687,7 @@     ASIO_SYNC_OP_VOID_RETURN(ec);   } -  ec = asio::error_code(-      static_cast<int>(::ERR_get_error()),-      asio::error::get_ssl_category());+  ec = translate_error(::ERR_get_error());   ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -733,9 +723,7 @@    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());+    ec = translate_error(::ERR_get_error());     ASIO_SYNC_OP_VOID_RETURN(ec);   } @@ -759,7 +747,8 @@   if (bio.p)   { #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \-      && !defined(LIBRESSL_VERSION_NUMBER)) \+      && (!defined(LIBRESSL_VERSION_NUMBER) \+        || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \     || 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_);@@ -773,22 +762,20 @@           cb_userdata) };     if (!cert.p)     {-      ec = asio::error_code(ERR_R_PEM_LIB,-          asio::error::get_ssl_category());+      ec = translate_error(ERR_R_PEM_LIB);       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());+      ec = translate_error(::ERR_get_error());       ASIO_SYNC_OP_VOID_RETURN(ec);     }  #if ((OPENSSL_VERSION_NUMBER >= 0x10002000L) \-      && !defined(LIBRESSL_VERSION_NUMBER)) \+      && (!defined(LIBRESSL_VERSION_NUMBER) \+        || LIBRESSL_VERSION_NUMBER >= 0x2090100fL)) \     || defined(ASIO_USE_WOLFSSL)     ::SSL_CTX_clear_chain_certs(handle_); #else@@ -805,9 +792,7 @@     {       if (!::SSL_CTX_add_extra_chain_cert(handle_, cacert))       {-        ec = asio::error_code(-            static_cast<int>(::ERR_get_error()),-            asio::error::get_ssl_category());+        ec = translate_error(::ERR_get_error());         ASIO_SYNC_OP_VOID_RETURN(ec);       }     }@@ -822,9 +807,7 @@     }   } -  ec = asio::error_code(-      static_cast<int>(::ERR_get_error()),-      asio::error::get_ssl_category());+  ec = translate_error(::ERR_get_error());   ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -842,9 +825,7 @@    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());+    ec = translate_error(::ERR_get_error());     ASIO_SYNC_OP_VOID_RETURN(ec);   } @@ -867,7 +848,8 @@   ::ERR_clear_error();  #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \-      && !defined(LIBRESSL_VERSION_NUMBER)) \+      && (!defined(LIBRESSL_VERSION_NUMBER) \+        || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \     || 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_);@@ -907,9 +889,7 @@     }   } -  ec = asio::error_code(-      static_cast<int>(::ERR_get_error()),-      asio::error::get_ssl_category());+  ec = translate_error(::ERR_get_error());   ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -936,18 +916,54 @@   ::ERR_clear_error();  #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \-      && !defined(LIBRESSL_VERSION_NUMBER)) \+      && (!defined(LIBRESSL_VERSION_NUMBER) \+        || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \     || 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_);+  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;+  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)   {+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)+    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 (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0)+      {+        ec = translate_error(+            ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY));+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }++      if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)+      {+        ec = asio::error_code();+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }+    }+#else // (OPENSSL_VERSION_NUMBER >= 0x30000000L)     rsa_cleanup rsa_private_key = { 0 };     switch (format)     {@@ -974,11 +990,10 @@         ASIO_SYNC_OP_VOID_RETURN(ec);       }     }+#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L)   } -  ec = asio::error_code(-      static_cast<int>(::ERR_get_error()),-      asio::error::get_ssl_category());+  ec = translate_error(::ERR_get_error());   ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1006,9 +1021,7 @@    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());+    ec = translate_error(::ERR_get_error());     ASIO_SYNC_OP_VOID_RETURN(ec);   } @@ -1028,6 +1041,53 @@     const std::string& filename, context::file_format format,     asio::error_code& ec) {+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)+  ::ERR_clear_error();++  pem_password_cb* callback = ::SSL_CTX_get_default_passwd_cb(handle_);+  void* cb_userdata = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);++  bio_cleanup bio = { ::BIO_new_file(filename.c_str(), "r") };+  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 (::EVP_PKEY_is_a(evp_private_key.p, "RSA") == 0)+      {+        ec = translate_error(+            ERR_PACK(ERR_LIB_EVP, 0, EVP_R_EXPECTING_AN_RSA_KEY));+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }++      if (::SSL_CTX_use_PrivateKey(handle_, evp_private_key.p) == 1)+      {+        ec = asio::error_code();+        ASIO_SYNC_OP_VOID_RETURN(ec);+      }+    }+  }++  ec = translate_error(::ERR_get_error());+  ASIO_SYNC_OP_VOID_RETURN(ec);+#else // (OPENSSL_VERSION_NUMBER >= 0x30000000L)   int file_type;   switch (format)   {@@ -1049,14 +1109,13 @@   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());+    ec = translate_error(::ERR_get_error());     ASIO_SYNC_OP_VOID_RETURN(ec);   }    ec = asio::error_code();   ASIO_SYNC_OP_VOID_RETURN(ec);+#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L) }  void context::use_tmp_dh(const const_buffer& dh)@@ -1077,9 +1136,7 @@     return do_use_tmp_dh(bio.p, ec);   } -  ec = asio::error_code(-      static_cast<int>(::ERR_get_error()),-      asio::error::get_ssl_category());+  ec = translate_error(::ERR_get_error());   ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1101,9 +1158,7 @@     return do_use_tmp_dh(bio.p, ec);   } -  ec = asio::error_code(-      static_cast<int>(::ERR_get_error()),-      asio::error::get_ssl_category());+  ec = translate_error(::ERR_get_error());   ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1112,6 +1167,19 @@ {   ::ERR_clear_error(); +#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)+  EVP_PKEY* p = ::PEM_read_bio_Parameters(bio, 0);+  if (p)+  {+    if (::SSL_CTX_set0_tmp_dh_pkey(handle_, p) == 1)+    {+      ec = asio::error_code();+      ASIO_SYNC_OP_VOID_RETURN(ec);+    }+    else+      ::EVP_PKEY_free(p);+  }+#else // (OPENSSL_VERSION_NUMBER >= 0x30000000L)   dh_cleanup dh = { ::PEM_read_bio_DHparams(bio, 0, 0, 0) };   if (dh.p)   {@@ -1121,10 +1189,9 @@       ASIO_SYNC_OP_VOID_RETURN(ec);     }   }+#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L) -  ec = asio::error_code(-      static_cast<int>(::ERR_get_error()),-      asio::error::get_ssl_category());+  ec = translate_error(::ERR_get_error());   ASIO_SYNC_OP_VOID_RETURN(ec); } @@ -1177,7 +1244,8 @@     detail::password_callback_base* callback, asio::error_code& ec) { #if ((OPENSSL_VERSION_NUMBER >= 0x10100000L) \-      && !defined(LIBRESSL_VERSION_NUMBER)) \+      && (!defined(LIBRESSL_VERSION_NUMBER) \+        || LIBRESSL_VERSION_NUMBER >= 0x2070000fL)) \     || defined(ASIO_USE_WOLFSSL)   void* old_callback = ::SSL_CTX_get_default_passwd_cb_userdata(handle_);   ::SSL_CTX_set_default_passwd_cb_userdata(handle_, callback);@@ -1228,6 +1296,21 @@   return ::BIO_new_mem_buf(       const_cast<void*>(b.data()),       static_cast<int>(b.size()));+}++asio::error_code context::translate_error(long error)+{+#if (OPENSSL_VERSION_NUMBER >= 0x30000000L)+  if (ERR_SYSTEM_ERROR(error))+  {+    return asio::error_code(+        static_cast<int>(ERR_GET_REASON(error)),+        asio::error::get_system_category());+  }+#endif // (OPENSSL_VERSION_NUMBER >= 0x30000000L)++  return asio::error_code(static_cast<int>(error),+      asio::error::get_ssl_category()); }  } // namespace ssl
link/modules/asio-standalone/asio/include/asio/ssl/impl/error.ipp view
@@ -2,7 +2,7 @@ // ssl/impl/error.ipp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -35,8 +35,30 @@    std::string message(int value) const   {-    const char* s = ::ERR_reason_error_string(value);-    return s ? s : "asio.ssl error";+    const char* reason = ::ERR_reason_error_string(value);+    if (reason)+    {+      const char* lib = ::ERR_lib_error_string(value);+#if (OPENSSL_VERSION_NUMBER < 0x30000000L)+      const char* func = ::ERR_func_error_string(value);+#else // (OPENSSL_VERSION_NUMBER < 0x30000000L)+      const char* func = 0;+#endif // (OPENSSL_VERSION_NUMBER < 0x30000000L)+      std::string result(reason);+      if (lib || func)+      {+        result += " (";+        if (lib)+          result += lib;+        if (lib && func)+          result += ", ";+        if (func)+          result += func;+        result += ")";+      }+      return result;+    }+    return "asio.ssl error";   } }; 
link/modules/asio-standalone/asio/include/asio/ssl/impl/host_name_verification.ipp view
@@ -2,7 +2,7 @@ // ssl/impl/host_name_verification.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/impl/rfc2818_verification.ipp view
@@ -2,7 +2,7 @@ // ssl/impl/rfc2818_verification.ipp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/impl/src.hpp view
@@ -2,7 +2,7 @@ // impl/ssl/src.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/rfc2818_verification.hpp view
@@ -2,7 +2,7 @@ // ssl/rfc2818_verification.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/stream.hpp view
@@ -2,7 +2,7 @@ // ssl/stream.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -65,6 +65,13 @@   public stream_base,   private noncopyable {+private:+  class initiate_async_handshake;+  class initiate_async_buffered_handshake;+  class initiate_async_shutdown;+  class initiate_async_write_some;+  class initiate_async_read_some;+ public:   /// The native handle type of the SSL stream.   typedef SSL* native_handle_type;@@ -100,6 +107,23 @@       core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor())   {   }++  /// Construct a stream from an existing native implementation.+  /**+   * This constructor creates a stream and initialises the underlying stream+   * object. On success, ownership of the native implementation is transferred+   * to the stream, and it will be cleaned up when the stream is destroyed.+   *+   * @param arg The argument to be passed to initialise the underlying stream.+   *+   * @param handle An existing native SSL implementation.+   */+  template <typename Arg>+  stream(Arg&& arg, native_handle_type handle)+    : next_layer_(ASIO_MOVE_CAST(Arg)(arg)),+      core_(handle, next_layer_.lowest_layer().get_executor())+  {+  } #else // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)   template <typename Arg>   stream(Arg& arg, context& ctx)@@ -107,6 +131,13 @@       core_(ctx.native_handle(), next_layer_.lowest_layer().get_executor())   {   }++  template <typename Arg>+  stream(Arg& arg, native_handle_type handle)+    : next_layer_(arg),+      core_(handle, next_layer_.lowest_layer().get_executor())+  {+  } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)  #if defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)@@ -115,13 +146,30 @@    * @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.+   * operation is destruction, or use as the target of a move assignment.    */   stream(stream&& other)     : next_layer_(ASIO_MOVE_CAST(Stream)(other.next_layer_)),       core_(ASIO_MOVE_CAST(detail::stream_core)(other.core_))   {   }++  /// Move-assign 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, or use as the target of a move assignment.+   */+  stream& operator=(stream&& other)+  {+    if (this != &other)+    {+      next_layer_ = ASIO_MOVE_CAST(Stream)(other.next_layer_);+      core_ = ASIO_MOVE_CAST(detail::stream_core)(other.core_);+    }+    return *this;+  } #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION)    /// Destructor.@@ -433,37 +481,63 @@   /// Start an asynchronous SSL handshake.   /**    * This function is used to asynchronously perform an SSL handshake on the-   * stream. This function call always returns immediately.+   * stream. It is an initiating function for an @ref asynchronous_operation,+   * and 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the handshake completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error // Result of operation.    * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * if they are also supported by the @c Stream type's @c async_read_some and+   * @c async_write_some operations.    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        HandshakeHandler+        HandshakeToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(HandshakeHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(HandshakeToken,       void (asio::error_code))   async_handshake(handshake_type type,-      ASIO_MOVE_ARG(HandshakeHandler) handler+      ASIO_MOVE_ARG(HandshakeToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<HandshakeToken,+        void (asio::error_code)>(+          declval<initiate_async_handshake>(), token, type)))   {-    return async_initiate<HandshakeHandler,+    return async_initiate<HandshakeToken,       void (asio::error_code)>(-        initiate_async_handshake(this), handler, type);+        initiate_async_handshake(this), token, 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.+   * stream. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param type The type of handshaking to be performed, i.e. as a client or as    * a server.@@ -471,29 +545,53 @@    * @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.+   * valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the handshake completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.    *   std::size_t bytes_transferred // Amount of buffers used in handshake.    * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * if they are also supported by the @c Stream type's @c async_read_some and+   * @c async_write_some operations.    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) BufferedHandshakeHandler+        std::size_t)) BufferedHandshakeToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(BufferedHandshakeHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(BufferedHandshakeToken,       void (asio::error_code, std::size_t))   async_handshake(handshake_type type, const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(BufferedHandshakeHandler) handler+      ASIO_MOVE_ARG(BufferedHandshakeToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<BufferedHandshakeToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_buffered_handshake>(), token, type, buffers)))   {-    return async_initiate<BufferedHandshakeHandler,+    return async_initiate<BufferedHandshakeToken,       void (asio::error_code, std::size_t)>(-        initiate_async_buffered_handshake(this), handler, type, buffers);+        initiate_async_buffered_handshake(this), token, type, buffers);   }    /// Shut down SSL on the stream.@@ -525,29 +623,54 @@    /// 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.+   * This function is used to asynchronously shut down SSL on the stream. It is+   * an initiating function for an @ref asynchronous_operation, and 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the shutdown completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error // Result of operation.    * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * if they are also supported by the @c Stream type's @c async_read_some and+   * @c async_write_some operations.    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        ShutdownHandler+        ShutdownToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ShutdownHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ShutdownToken,       void (asio::error_code))   async_shutdown(-      ASIO_MOVE_ARG(ShutdownHandler) handler+      ASIO_MOVE_ARG(ShutdownToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ShutdownToken,+        void (asio::error_code)>(+          declval<initiate_async_shutdown>(), token)))   {-    return async_initiate<ShutdownHandler,+    return async_initiate<ShutdownToken,       void (asio::error_code)>(-        initiate_async_shutdown(this), handler);+        initiate_async_shutdown(this), token);   }    /// Write some data to the stream.@@ -602,39 +725,64 @@   /// 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.+   * the stream. It is an initiating function for an @ref+   * asynchronous_operation, and 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.+   * the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the write completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes written.+   *   std::size_t bytes_transferred // Number of bytes written.    * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * if they are also supported by the @c Stream type's @c async_read_some and+   * @c async_write_some operations.    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_write_some(const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_write_some>(), token, buffers)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_write_some(this), handler, buffers);+        initiate_async_write_some(this), token, buffers);   }    /// Read some data from the stream.@@ -689,39 +837,64 @@   /// 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.+   * the stream. It is an initiating function for an @ref+   * asynchronous_operation, and 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.+   * valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the read completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes read.+   *   std::size_t bytes_transferred // Number of bytes read.    * ); @endcode+   * Regardless of whether the asynchronous operation completes immediately or+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a+   * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The 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.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * if they are also supported by the @c Stream type's @c async_read_some and+   * @c async_write_some operations.    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_read_some(const MutableBufferSequence& buffers,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_read_some>(), token, buffers)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_read_some(this), handler, buffers);+        initiate_async_read_some(this), token, buffers);   }  private:
link/modules/asio-standalone/asio/include/asio/ssl/stream_base.hpp view
@@ -2,7 +2,7 @@ // ssl/stream_base.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/verify_context.hpp view
@@ -2,7 +2,7 @@ // ssl/verify_context.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ssl/verify_mode.hpp view
@@ -2,7 +2,7 @@ // ssl/verify_mode.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/static_thread_pool.hpp view
@@ -2,7 +2,7 @@ // static_thread_pool.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/steady_timer.hpp view
@@ -2,7 +2,7 @@ // steady_timer.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/strand.hpp view
@@ -2,7 +2,7 @@ // strand.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include "asio/detail/strand_executor_service.hpp" #include "asio/detail/type_traits.hpp"+#include "asio/execution/blocking.hpp" #include "asio/execution/executor.hpp" #include "asio/is_executor.hpp" @@ -47,13 +48,13 @@   /// Construct a strand for the specified executor.   template <typename Executor1>   explicit strand(const Executor1& e,-      typename enable_if<+      typename constraint<         conditional<           !is_same<Executor1, strand>::value,           is_convertible<Executor1, Executor>,           false_type         >::type::value-      >::type* = 0)+      >::type = 0)     : executor_(e),       impl_(strand::create_implementation(executor_))   {@@ -157,7 +158,7 @@   /// Forward a query to the underlying executor.   /**    * Do not call this function directly. It is intended for use with the-   * execution::execute customisation point.+   * asio::query customisation point.    *    * For example:    * @code asio::strand<my_executor_type> ex = ...;@@ -166,14 +167,19 @@    *   ... @endcode    */   template <typename Property>-  typename enable_if<+  typename constraint<     can_query<const Executor&, Property>::value,-    typename query_result<const Executor&, Property>::type+    typename conditional<+      is_convertible<Property, execution::blocking_t>::value,+      execution::blocking_t,+      typename query_result<const Executor&, Property>::type+    >::type   >::type query(const Property& p) const     ASIO_NOEXCEPT_IF((       is_nothrow_query<const Executor&, Property>::value))   {-    return asio::query(executor_, p);+    return this->query_helper(+        is_convertible<Property, execution::blocking_t>(), p);   }    /// Forward a requirement to the underlying executor.@@ -187,8 +193,9 @@    *     asio::execution::blocking.never); @endcode    */   template <typename Property>-  typename enable_if<-    can_require<const Executor&, Property>::value,+  typename constraint<+    can_require<const Executor&, Property>::value+      && !is_convertible<Property, execution::blocking_t::always_t>::value,     strand<typename decay<       typename require_result<const Executor&, Property>::type     >::type>@@ -212,8 +219,9 @@    *     asio::execution::blocking.never); @endcode    */   template <typename Property>-  typename enable_if<-    can_prefer<const Executor&, Property>::value,+  typename constraint<+    can_prefer<const Executor&, Property>::value+      && !is_convertible<Property, execution::blocking_t::always_t>::value,     strand<typename decay<       typename prefer_result<const Executor&, Property>::type     >::type>@@ -254,13 +262,6 @@    /// 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.@@ -270,8 +271,16 @@    * function object must be: @code void function(); @endcode    */   template <typename Function>-  typename enable_if<-    execution::can_execute<const Executor&, Function>::value+  typename constraint<+#if defined(ASIO_NO_DEPRECATED) \+  || defined(GENERATING_DOCUMENTATION)+    traits::execute_member<const Executor&, Function>::is_valid,+#else // defined(ASIO_NO_DEPRECATED)+      //   || defined(GENERATING_DOCUMENTATION)+    execution::can_execute<const Executor&, Function>::value,+#endif // defined(ASIO_NO_DEPRECATED)+       //   || defined(GENERATING_DOCUMENTATION)+    void   >::type execute(ASIO_MOVE_ARG(Function) f) const   {     detail::strand_executor_service::execute(impl_,@@ -381,9 +390,9 @@    template <typename InnerExecutor>   static implementation_type create_implementation(const InnerExecutor& ex,-      typename enable_if<+      typename constraint<         can_query<InnerExecutor, execution::context_t>::value-      >::type* = 0)+      >::type = 0)   {     return use_service<detail::strand_executor_service>(         asio::query(ex, execution::context)).create_implementation();@@ -391,9 +400,9 @@    template <typename InnerExecutor>   static implementation_type create_implementation(const InnerExecutor& ex,-      typename enable_if<+      typename constraint<         !can_query<InnerExecutor, execution::context_t>::value-      >::type* = 0)+      >::type = 0)   {     return use_service<detail::strand_executor_service>(         ex.context()).create_implementation();@@ -405,6 +414,21 @@   {   } +  template <typename Property>+  typename query_result<const Executor&, Property>::type query_helper(+      false_type, const Property& property) const+  {+    return asio::query(executor_, property);+  }++  template <typename Property>+  execution::blocking_t query_helper(true_type, const Property& property) const+  {+    execution::blocking_t result = asio::query(executor_, property);+    return result == execution::blocking.always+      ? execution::blocking.possibly : result;+  }+   Executor executor_;   implementation_type impl_; };@@ -417,22 +441,33 @@ /*@{*/  /// Create a @ref strand object for an executor.+/**+ * @param ex An executor.+ *+ * @returns A strand constructed with the specified executor.+ */ template <typename Executor> inline strand<Executor> make_strand(const Executor& ex,-    typename enable_if<+    typename constraint<       is_executor<Executor>::value || execution::is_executor<Executor>::value-    >::type* = 0)+    >::type = 0) {   return strand<Executor>(ex); }  /// Create a @ref strand object for an execution context.+/**+ * @param ctx An execution context, from which an executor will be obtained.+ *+ * @returns A strand constructed with the execution context's executor, obtained+ * by performing <tt>ctx.get_executor()</tt>.+ */ template <typename ExecutionContext> inline strand<typename ExecutionContext::executor_type> make_strand(ExecutionContext& ctx,-    typename enable_if<+    typename constraint<       is_convertible<ExecutionContext&, execution_context&>::value-    >::type* = 0)+    >::type = 0) {   return strand<typename ExecutionContext::executor_type>(ctx.get_executor()); }@@ -457,7 +492,14 @@ #if !defined(ASIO_HAS_DEDUCED_EXECUTE_MEMBER_TRAIT)  template <typename Executor, typename Function>-struct execute_member<strand<Executor>, Function>+struct execute_member<strand<Executor>, Function,+    typename enable_if<+#if defined(ASIO_NO_DEPRECATED)+      traits::execute_member<const Executor&, Function>::is_valid+#else // defined(ASIO_NO_DEPRECATED)+      execution::can_execute<const Executor&, Function>::value+#endif // defined(ASIO_NO_DEPRECATED)+    >::type> {   ASIO_STATIC_CONSTEXPR(bool, is_valid = true);   ASIO_STATIC_CONSTEXPR(bool, is_noexcept = false);@@ -477,7 +519,10 @@   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;+  typedef typename conditional<+    is_convertible<Property, execution::blocking_t>::value,+      execution::blocking_t, typename query_result<Executor, Property>::type+        >::type result_type; };  #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)@@ -488,6 +533,7 @@ struct require_member<strand<Executor>, Property,     typename enable_if<       can_require<const Executor&, Property>::value+        && !is_convertible<Property, execution::blocking_t::always_t>::value     >::type> {   ASIO_STATIC_CONSTEXPR(bool, is_valid = true);@@ -506,6 +552,7 @@ struct prefer_member<strand<Executor>, Property,     typename enable_if<       can_prefer<const Executor&, Property>::value+        && !is_convertible<Property, execution::blocking_t::always_t>::value     >::type> {   ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
+ link/modules/asio-standalone/asio/include/asio/stream_file.hpp view
@@ -0,0 +1,35 @@+//+// stream_file.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_STREAM_FILE_HPP+#define ASIO_STREAM_FILE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_FILE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_stream_file.hpp"++namespace asio {++/// Typedef for the typical usage of a stream-oriented file.+typedef basic_stream_file<> stream_file;++} // namespace asio++#endif // defined(ASIO_HAS_FILE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_STREAM_FILE_HPP
link/modules/asio-standalone/asio/include/asio/streambuf.hpp view
@@ -2,7 +2,7 @@ // streambuf.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/system_context.hpp view
@@ -2,7 +2,7 @@ // system_context.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/system_error.hpp view
@@ -2,7 +2,7 @@ // system_error.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/system_executor.hpp view
@@ -2,7 +2,7 @@ // system_executor.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -44,6 +44,12 @@   {   } +#if !defined(GENERATING_DOCUMENTATION)+private:+  friend struct asio_require_fn::impl;+  friend struct asio_prefer_fn::impl;+#endif // !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@@ -169,6 +175,15 @@         Relationship, std::allocator<void> >();   } +#if !defined(GENERATING_DOCUMENTATION)+private:+  friend struct asio_query_fn::impl;+  friend struct asio::execution::detail::blocking_t<0>;+  friend struct asio::execution::detail::mapping_t<0>;+  friend struct asio::execution::detail::outstanding_work_t<0>;+  friend struct asio::execution::detail::relationship_t<0>;+#endif // !defined(GENERATING_DOCUMENTATION)+   /// Query the current value of the @c mapping property.   /**    * Do not call this function directly. It is intended for use with the@@ -278,6 +293,7 @@    */   std::size_t query(execution::occupancy_t) const ASIO_NOEXCEPT; +public:   /// Compare two executors for equality.   /**    * Two executors are equal if they refer to the same underlying io_context.@@ -299,14 +315,6 @@   }    /// 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   {@@ -314,6 +322,7 @@   }  #if !defined(ASIO_NO_TS_EXECUTORS)+public:   /// Obtain the underlying execution context.   system_context& context() const ASIO_NOEXCEPT; 
link/modules/asio-standalone/asio/include/asio/system_timer.hpp view
@@ -2,7 +2,7 @@ // system_timer.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/this_coro.hpp view
@@ -2,7 +2,7 @@ // this_coro.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -16,6 +16,7 @@ #endif // defined(_MSC_VER) && (_MSC_VER >= 1200)  #include "asio/detail/config.hpp"+#include "asio/detail/type_traits.hpp"  #include "asio/detail/push_options.hpp" @@ -36,6 +37,240 @@ #elif defined(ASIO_MSVC) __declspec(selectany) executor_t executor; #endif++/// Awaitable type that returns the cancellation state of the current coroutine.+struct cancellation_state_t+{+  ASIO_CONSTEXPR cancellation_state_t()+  {+  }+};++/// Awaitable object that returns the cancellation state of the current+/// coroutine.+/**+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ *   asio::cancellation_state cs+ *     = co_await asio::this_coro::cancellation_state;+ *+ *   // ...+ *+ *   if (cs.cancelled() != asio::cancellation_type::none)+ *     // ...+ * } @endcode+ */+#if defined(ASIO_HAS_CONSTEXPR) || defined(GENERATING_DOCUMENTATION)+constexpr cancellation_state_t cancellation_state;+#elif defined(ASIO_MSVC)+__declspec(selectany) cancellation_state_t cancellation_state;+#endif++#if defined(GENERATING_DOCUMENTATION)++/// Returns an awaitable object that may be used to reset the cancellation state+/// of the current coroutine.+/**+ * Let <tt>P</tt> be the cancellation slot associated with the current+ * coroutine's @ref co_spawn completion handler. Assigns a new+ * asio::cancellation_state object <tt>S</tt>, constructed as+ * <tt>S(P)</tt>, into the current coroutine's cancellation state object.+ *+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ *   co_await asio::this_coro::reset_cancellation_state();+ *+ *   // ...+ * } @endcode+ *+ * @note The cancellation state is shared by all coroutines in the same "thread+ * of execution" that was created using asio::co_spawn.+ */+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+reset_cancellation_state();++/// Returns an awaitable object that may be used to reset the cancellation state+/// of the current coroutine.+/**+ * Let <tt>P</tt> be the cancellation slot associated with the current+ * coroutine's @ref co_spawn completion handler. Assigns a new+ * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P,+ * std::forward<Filter>(filter))</tt>, into the current coroutine's+ * cancellation state object.+ *+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ *   co_await asio::this_coro::reset_cancellation_state(+ *       asio::enable_partial_cancellation());+ *+ *   // ...+ * } @endcode+ *+ * @note The cancellation state is shared by all coroutines in the same "thread+ * of execution" that was created using asio::co_spawn.+ */+template <typename Filter>+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter);++/// Returns an awaitable object that may be used to reset the cancellation state+/// of the current coroutine.+/**+ * Let <tt>P</tt> be the cancellation slot associated with the current+ * coroutine's @ref co_spawn completion handler. Assigns a new+ * asio::cancellation_state object <tt>S</tt>, constructed as <tt>S(P,+ * std::forward<InFilter>(in_filter),+ * std::forward<OutFilter>(out_filter))</tt>, into the current coroutine's+ * cancellation state object.+ *+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ *   co_await asio::this_coro::reset_cancellation_state(+ *       asio::enable_partial_cancellation(),+ *       asio::disable_cancellation());+ *+ *   // ...+ * } @endcode+ *+ * @note The cancellation state is shared by all coroutines in the same "thread+ * of execution" that was created using asio::co_spawn.+ */+template <typename InFilter, typename OutFilter>+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+reset_cancellation_state(+    ASIO_MOVE_ARG(InFilter) in_filter,+    ASIO_MOVE_ARG(OutFilter) out_filter);++/// Returns an awaitable object that may be used to determine whether the+/// coroutine throws if trying to suspend when it has been cancelled.+/**+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ *   if (co_await asio::this_coro::throw_if_cancelled)+ *     // ...+ *+ *   // ...+ * } @endcode+ */+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+throw_if_cancelled();++/// Returns an awaitable object that may be used to specify whether the+/// coroutine throws if trying to suspend when it has been cancelled.+/**+ * @par Example+ * @code asio::awaitable<void> my_coroutine()+ * {+ *   co_await asio::this_coro::throw_if_cancelled(false);+ *+ *   // ...+ * } @endcode+ */+ASIO_NODISCARD ASIO_CONSTEXPR unspecified+throw_if_cancelled(bool value);++#else // defined(GENERATING_DOCUMENTATION)++struct reset_cancellation_state_0_t+{+  ASIO_CONSTEXPR reset_cancellation_state_0_t()+  {+  }+};++ASIO_NODISCARD inline ASIO_CONSTEXPR reset_cancellation_state_0_t+reset_cancellation_state()+{+  return reset_cancellation_state_0_t();+}++template <typename Filter>+struct reset_cancellation_state_1_t+{+  template <typename F>+  explicit ASIO_CONSTEXPR reset_cancellation_state_1_t(+      ASIO_MOVE_ARG(F) filt)+    : filter(ASIO_MOVE_CAST(F)(filt))+  {+  }++  Filter filter;+};++template <typename Filter>+ASIO_NODISCARD inline ASIO_CONSTEXPR reset_cancellation_state_1_t<+    typename decay<Filter>::type>+reset_cancellation_state(ASIO_MOVE_ARG(Filter) filter)+{+  return reset_cancellation_state_1_t<typename decay<Filter>::type>(+      ASIO_MOVE_CAST(Filter)(filter));+}++template <typename InFilter, typename OutFilter>+struct reset_cancellation_state_2_t+{+  template <typename F1, typename F2>+  ASIO_CONSTEXPR reset_cancellation_state_2_t(+      ASIO_MOVE_ARG(F1) in_filt, ASIO_MOVE_ARG(F2) out_filt)+    : in_filter(ASIO_MOVE_CAST(F1)(in_filt)),+      out_filter(ASIO_MOVE_CAST(F2)(out_filt))+  {+  }++  InFilter in_filter;+  OutFilter out_filter;+};++template <typename InFilter, typename OutFilter>+ASIO_NODISCARD inline ASIO_CONSTEXPR reset_cancellation_state_2_t<+    typename decay<InFilter>::type,+    typename decay<OutFilter>::type>+reset_cancellation_state(+    ASIO_MOVE_ARG(InFilter) in_filter,+    ASIO_MOVE_ARG(OutFilter) out_filter)+{+  return reset_cancellation_state_2_t<+      typename decay<InFilter>::type,+      typename decay<OutFilter>::type>(+        ASIO_MOVE_CAST(InFilter)(in_filter),+        ASIO_MOVE_CAST(OutFilter)(out_filter));+}++struct throw_if_cancelled_0_t+{+  ASIO_CONSTEXPR throw_if_cancelled_0_t()+  {+  }+};++ASIO_NODISCARD inline ASIO_CONSTEXPR throw_if_cancelled_0_t+throw_if_cancelled()+{+  return throw_if_cancelled_0_t();+}++struct throw_if_cancelled_1_t+{+  explicit ASIO_CONSTEXPR throw_if_cancelled_1_t(bool val)+    : value(val)+  {+  }++  bool value;+};++ASIO_NODISCARD inline ASIO_CONSTEXPR throw_if_cancelled_1_t+throw_if_cancelled(bool value)+{+  return throw_if_cancelled_1_t(value);+}++#endif // defined(GENERATING_DOCUMENTATION)  } // namespace this_coro } // namespace asio
link/modules/asio-standalone/asio/include/asio/thread.hpp view
@@ -2,7 +2,7 @@ // thread.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/thread_pool.hpp view
@@ -2,7 +2,7 @@ // thread_pool.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -165,8 +165,10 @@ class thread_pool::basic_executor_type : detail::thread_pool_bits { public:-  /// The sender type, when this type is used as a scheduler.+#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated.) The sender type, when this type is used as a scheduler.   typedef basic_executor_type sender_type;+#endif // !defined(ASIO_NO_DEPRECATED)    /// The bulk execution shape type.   typedef std::size_t shape_type;@@ -230,6 +232,12 @@       basic_executor_type&& other) ASIO_NOEXCEPT; #endif // defined(ASIO_HAS_MOVE) || defined(GENERATING_DOCUMENTATION) +#if !defined(GENERATING_DOCUMENTATION)+private:+  friend struct asio_require_fn::impl;+  friend struct asio_prefer_fn::impl;+#endif // !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@@ -390,7 +398,15 @@         pool_, std::allocator<void>(), bits_);   } -  /// Query the current value of the @c bulk_guarantee property.+#if !defined(GENERATING_DOCUMENTATION)+private:+  friend struct asio_query_fn::impl;+  friend struct asio::execution::detail::mapping_t<0>;+  friend struct asio::execution::detail::outstanding_work_t<0>;+#endif // !defined(GENERATING_DOCUMENTATION)++#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated.) 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.@@ -406,6 +422,7 @@   {     return execution::bulk_guarantee.parallel;   }+#endif // !defined(ASIO_NO_DEPRECATED)    /// Query the current value of the @c mapping property.   /**@@ -546,6 +563,7 @@     return static_cast<std::size_t>(pool_->num_threads_);   } +public:   /// Determine whether the thread pool is running in the current thread.   /**    * @return @c true if the current thread is running the thread pool. Otherwise@@ -578,14 +596,6 @@   }    /// 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   {@@ -593,7 +603,9 @@         integral_constant<bool, (Bits & blocking_always) != 0>());   } -  /// Bulk execution function.+public:+#if !defined(ASIO_NO_DEPRECATED)+  /// (Deprecated.) Bulk execution function.   template <typename Function>   void bulk_execute(ASIO_MOVE_ARG(Function) f, std::size_t n) const   {@@ -601,7 +613,7 @@         integral_constant<bool, (Bits & blocking_always) != 0>());   } -  /// Schedule function.+  /// (Deprecated.) Schedule function.   /**    * Do not call this function directly. It is intended for use with the    * execution::schedule customisation point.@@ -613,7 +625,7 @@     return *this;   } -  /// Connect function.+  /// (Deprecated.) Connect function.   /**    * Do not call this function directly. It is intended for use with the    * execution::connect customisation point.@@ -632,6 +644,7 @@     return execution::detail::as_operation<basic_executor_type, Receiver>(         *this, ASIO_MOVE_CAST(Receiver)(r));   }+#endif // !defined(ASIO_NO_DEPRECATED)  #if !defined(ASIO_NO_TS_EXECUTORS)   /// Obtain the underlying execution context.@@ -798,6 +811,8 @@  #if !defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT) +#if !defined(ASIO_NO_DEPRECATED)+ template <typename Allocator, unsigned int Bits> struct schedule_member<     const asio::thread_pool::basic_executor_type<Allocator, Bits>@@ -809,10 +824,14 @@       Allocator, Bits> result_type; }; +#endif // !defined(ASIO_NO_DEPRECATED)+ #endif // !defined(ASIO_HAS_DEDUCED_SCHEDULE_MEMBER_TRAIT)  #if !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT) +#if !defined(ASIO_NO_DEPRECATED)+ template <typename Allocator, unsigned int Bits, typename Receiver> struct connect_member<     const asio::thread_pool::basic_executor_type<Allocator, Bits>,@@ -826,6 +845,8 @@       Receiver> result_type; }; +#endif // !defined(ASIO_NO_DEPRECATED)+ #endif // !defined(ASIO_HAS_DEDUCED_CONNECT_MEMBER_TRAIT)  #if !defined(ASIO_HAS_DEDUCED_REQUIRE_MEMBER_TRAIT)@@ -943,6 +964,8 @@  #if !defined(ASIO_HAS_DEDUCED_QUERY_STATIC_CONSTEXPR_MEMBER_TRAIT) +#if !defined(ASIO_NO_DEPRECATED)+ template <typename Allocator, unsigned int Bits, typename Property> struct query_static_constexpr_member<     asio::thread_pool::basic_executor_type<Allocator, Bits>,@@ -965,6 +988,8 @@   } }; +#endif // !defined(ASIO_NO_DEPRECATED)+ template <typename Allocator, unsigned int Bits, typename Property> struct query_static_constexpr_member<     asio::thread_pool::basic_executor_type<Allocator, Bits>,@@ -1096,6 +1121,15 @@ #endif // !defined(ASIO_HAS_DEDUCED_QUERY_MEMBER_TRAIT)  } // namespace traits++namespace execution {++template <>+struct is_executor<thread_pool> : false_type+{+};++} // namespace execution  #endif // !defined(GENERATING_DOCUMENTATION) 
link/modules/asio-standalone/asio/include/asio/time_traits.hpp view
@@ -2,7 +2,7 @@ // time_traits.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_free.hpp view
@@ -2,7 +2,7 @@ // traits/bulk_execute_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_member.hpp view
@@ -2,7 +2,7 @@ // traits/bulk_execute_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/connect_free.hpp view
@@ -2,7 +2,7 @@ // traits/connect_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/connect_member.hpp view
@@ -2,7 +2,7 @@ // traits/connect_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/equality_comparable.hpp view
@@ -2,7 +2,7 @@ // traits/equality_comparable.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -55,8 +55,12 @@ 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>())+      static_cast<void>(+        static_cast<bool>(declval<const T>() == declval<const T>())+      ),+      static_cast<void>(+        static_cast<bool>(declval<const T>() != declval<const T>())+      )     )   >::type> {
link/modules/asio-standalone/asio/include/asio/traits/execute_free.hpp view
@@ -2,7 +2,7 @@ // traits/execute_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/execute_member.hpp view
@@ -2,7 +2,7 @@ // traits/execute_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/prefer_free.hpp view
@@ -2,7 +2,7 @@ // traits/prefer_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/prefer_member.hpp view
@@ -2,7 +2,7 @@ // traits/prefer_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/query_free.hpp view
@@ -2,7 +2,7 @@ // traits/query_free.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/query_member.hpp view
@@ -2,7 +2,7 @@ // traits/query_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/query_static_constexpr_member.hpp view
@@ -2,7 +2,7 @@ // traits/query_static_constexpr_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/require_concept_free.hpp view
@@ -2,7 +2,7 @@ // traits/require_concept_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/require_concept_member.hpp view
@@ -2,7 +2,7 @@ // traits/require_concept_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/require_free.hpp view
@@ -2,7 +2,7 @@ // traits/require_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/require_member.hpp view
@@ -2,7 +2,7 @@ // traits/require_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/schedule_free.hpp view
@@ -2,7 +2,7 @@ // traits/schedule_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/schedule_member.hpp view
@@ -2,7 +2,7 @@ // traits/schedule_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_done_free.hpp view
@@ -2,7 +2,7 @@ // traits/set_done_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_done_member.hpp view
@@ -2,7 +2,7 @@ // traits/set_done_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_error_free.hpp view
@@ -2,7 +2,7 @@ // traits/set_error_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_error_member.hpp view
@@ -2,7 +2,7 @@ // traits/set_error_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_value_free.hpp view
@@ -2,7 +2,7 @@ // traits/set_value_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/set_value_member.hpp view
@@ -2,7 +2,7 @@ // traits/set_value_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/start_free.hpp view
@@ -2,7 +2,7 @@ // traits/start_free.hpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/start_member.hpp view
@@ -2,7 +2,7 @@ // traits/start_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/static_query.hpp view
@@ -2,7 +2,7 @@ // traits/static_query.hpp // ~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/static_require.hpp view
@@ -2,7 +2,7 @@ // traits/static_require.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/static_require_concept.hpp view
@@ -2,7 +2,7 @@ // traits/static_require_concept.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -91,7 +91,8 @@ 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+    has_static_require_concept<typename decay<T>::type,+      typename decay<Property>::type>::value   >::type> {   ASIO_STATIC_CONSTEXPR(bool, is_valid = true);
link/modules/asio-standalone/asio/include/asio/traits/submit_free.hpp view
@@ -2,7 +2,7 @@ // traits/submit_free.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/traits/submit_member.hpp view
@@ -2,7 +2,7 @@ // traits/submit_member.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/buffer.hpp view
@@ -2,7 +2,7 @@ // ts/buffer.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/executor.hpp view
@@ -2,7 +2,7 @@ // ts/executor.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/internet.hpp view
@@ -2,7 +2,7 @@ // ts/internet.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/io_context.hpp view
@@ -2,7 +2,7 @@ // ts/io_context.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/net.hpp view
@@ -2,7 +2,7 @@ // ts/net.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/netfwd.hpp view
@@ -2,7 +2,7 @@ // ts/netfwd.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -45,7 +45,7 @@ #if !defined(ASIO_EXECUTOR_WORK_GUARD_DECL) #define ASIO_EXECUTOR_WORK_GUARD_DECL -template <typename Executor, typename = void>+template <typename Executor, typename = void, typename = void> class executor_work_guard;  #endif // !defined(ASIO_EXECUTOR_WORK_GUARD_DECL)@@ -90,15 +90,7 @@  } // 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;+class any_io_executor;  #endif // defined(ASIO_USE_TS_EXECUTOR_AS_DEFAULT) 
link/modules/asio-standalone/asio/include/asio/ts/socket.hpp view
@@ -2,7 +2,7 @@ // ts/socket.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/ts/timer.hpp view
@@ -2,7 +2,7 @@ // ts/timer.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/unyield.hpp view
@@ -2,7 +2,7 @@ // unyield.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/use_awaitable.hpp view
@@ -2,7 +2,7 @@ // use_awaitable.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -32,7 +32,7 @@  namespace asio { -/// A completion token that represents the currently executing coroutine.+/// A @ref 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@@ -99,18 +99,15 @@     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+    template <typename InnerExecutor1>+    executor_with_default(const InnerExecutor1& ex,+        typename constraint<+          conditional<+            !is_same<InnerExecutor1, executor_with_default>::value,+            is_convertible<InnerExecutor1, InnerExecutor>,+            false_type+          >::type::value+        >::type = 0) ASIO_NOEXCEPT       : InnerExecutor(ex)     {     }@@ -146,7 +143,8 @@ #endif // defined(ASIO_ENABLE_HANDLER_TRACKING) }; -/// A completion token object that represents the currently executing coroutine.+/// A @ref completion_token object that represents the currently executing+/// coroutine. /**  * See the documentation for asio::use_awaitable_t for a usage example.  */
link/modules/asio-standalone/asio/include/asio/use_future.hpp view
@@ -2,7 +2,7 @@ // use_future.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -37,12 +37,14 @@  } // namespace detail -/// Class used to specify that an asynchronous operation should return a future.+/// A @ref completion_token type that causes an asynchronous operation to 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:+ * The use_future_t class is a completion token type that is used to indicate+ * that an asynchronous operation should return a std::future object. A+ * use_future_t object may be passed as a completion token 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@@ -138,7 +140,8 @@     std_allocator_void, Allocator>::type allocator_; }; -/// A special value, similar to std::nothrow.+/// A @ref completion_token object that causes an asynchronous operation to+/// return a future. /**  * See the documentation for asio::use_future_t for a usage example.  */
link/modules/asio-standalone/asio/include/asio/uses_executor.hpp view
@@ -2,7 +2,7 @@ // uses_executor.hpp // ~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/version.hpp view
@@ -2,7 +2,7 @@ // version.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,6 @@ // 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+#define ASIO_VERSION 102800 // 1.28.0  #endif // ASIO_VERSION_HPP
link/modules/asio-standalone/asio/include/asio/wait_traits.hpp view
@@ -2,7 +2,7 @@ // wait_traits.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/windows/basic_object_handle.hpp view
@@ -2,7 +2,7 @@ // windows/basic_object_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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@@ -50,6 +50,9 @@ template <typename Executor = any_io_executor> class basic_object_handle {+private:+  class initiate_async_wait;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -82,7 +85,7 @@    * object handle.    */   explicit basic_object_handle(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -96,11 +99,11 @@    */   template <typename ExecutionContext>   explicit basic_object_handle(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value,-        basic_object_handle-      >::type* = 0)-    : impl_(context)+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {   } @@ -119,7 +122,7 @@    */   basic_object_handle(const executor_type& ex,       const native_handle_type& native_handle)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);@@ -142,10 +145,10 @@   template <typename ExecutionContext>   basic_object_handle(ExecutionContext& context,       const native_handle_type& native_handle,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);@@ -185,10 +188,56 @@     impl_ = std::move(other.impl_);     return *this;   }++  // All handles have access to each other's implementations.+  template <typename Executor1>+  friend class basic_object_handle;++  /// Move-construct an object handle from a handle of another executor type.+  /**+   * 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.+   */+  template<typename Executor1>+  basic_object_handle(basic_object_handle<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign an object handle from a handle of another executor type.+  /**+   * 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.+   */+  template<typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_object_handle&+  >::type operator=(basic_object_handle<Executor1>&& 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+  const executor_type& get_executor() ASIO_NOEXCEPT   {     return impl_.get_executor();   }@@ -357,30 +406,39 @@   /// 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.+   * object handle. It is an initiating function for an @ref+   * asynchronous_operation, and 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the wait completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error // Result of operation.    * ); @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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().+   *+   * @par Completion Signature+   * @code void(asio::error_code) @endcode    */   template <       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code))-        WaitHandler ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WaitHandler,+        WaitToken ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WaitToken,       void (asio::error_code))   async_wait(-      ASIO_MOVE_ARG(WaitHandler) handler+      ASIO_MOVE_ARG(WaitToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WaitToken, void (asio::error_code)>(+          declval<initiate_async_wait>(), token)))   {-    return async_initiate<WaitHandler, void (asio::error_code)>(-        initiate_async_wait(this), handler);+    return async_initiate<WaitToken, void (asio::error_code)>(+        initiate_async_wait(this), token);   }  private:@@ -398,7 +456,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
link/modules/asio-standalone/asio/include/asio/windows/basic_overlapped_handle.hpp view
@@ -2,7 +2,7 @@ // windows/basic_overlapped_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -85,7 +85,7 @@    * overlapped handle.    */   explicit basic_overlapped_handle(const executor_type& ex)-    : impl_(ex)+    : impl_(0, ex)   {   } @@ -99,11 +99,11 @@    */   template <typename ExecutionContext>   explicit basic_overlapped_handle(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value,-        basic_overlapped_handle-      >::type* = 0)-    : impl_(context)+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(0, 0, context)   {   } @@ -122,7 +122,7 @@    */   basic_overlapped_handle(const executor_type& ex,       const native_handle_type& native_handle)-    : impl_(ex)+    : impl_(0, ex)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);@@ -145,10 +145,10 @@   template <typename ExecutionContext>   basic_overlapped_handle(ExecutionContext& context,       const native_handle_type& native_handle,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)-    : impl_(context)+      >::type = 0)+    : impl_(0, 0, context)   {     asio::error_code ec;     impl_.get_service().assign(impl_.get_implementation(), native_handle, ec);@@ -188,10 +188,57 @@     impl_ = std::move(other.impl_);     return *this;   }++  // All overlapped handles have access to each other's implementations.+  template <typename Executor1>+  friend class basic_overlapped_handle;++  /// Move-construct an overlapped handle from a handle of another executor+  /// type.+  /**+   * 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.+   */+  template<typename Executor1>+  basic_overlapped_handle(basic_overlapped_handle<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : impl_(std::move(other.impl_))+  {+  }++  /// Move-assign an overlapped handle from a handle of another executor type.+  /**+   * 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.+   */+  template<typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_overlapped_handle&+  >::type operator=(basic_overlapped_handle<Executor1>&& 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+  const executor_type& get_executor() ASIO_NOEXCEPT   {     return impl_.get_executor();   }@@ -287,6 +334,58 @@   {     impl_.get_service().close(impl_.get_implementation(), ec);     ASIO_SYNC_OP_VOID_RETURN(ec);+  }++  /// Release ownership of the underlying native handle.+  /**+   * This function causes all outstanding asynchronous operations to finish+   * immediately, and the handlers for cancelled operations will be passed the+   * asio::error::operation_aborted error. Ownership of the native handle+   * 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 handle.+  /**+   * This function causes all outstanding asynchronous operations to finish+   * immediately, and the handlers for cancelled operations will be passed the+   * asio::error::operation_aborted error. Ownership of the native handle+   * 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 handle representation.
link/modules/asio-standalone/asio/include/asio/windows/basic_random_access_handle.hpp view
@@ -2,7 +2,7 @@ // windows/basic_random_access_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -39,6 +39,10 @@ class basic_random_access_handle   : public basic_overlapped_handle<Executor> {+private:+  class initiate_async_write_some_at;+  class initiate_async_read_some_at;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -75,8 +79,8 @@   /// 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.+   * handle needs to be opened or assigned before data can be written to or read+   * from 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@@ -84,10 +88,10 @@    */   template <typename ExecutionContext>   explicit basic_random_access_handle(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value,-        basic_random_access_handle-      >::type* = 0)+        defaulted_constraint+      >::type = defaulted_constraint())     : basic_overlapped_handle<Executor>(context)   {   }@@ -127,9 +131,9 @@   template <typename ExecutionContext>   basic_random_access_handle(ExecutionContext& context,       const native_handle_type& handle,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_overlapped_handle<Executor>(context, handle)   {   }@@ -168,6 +172,51 @@     basic_overlapped_handle<Executor>::operator=(std::move(other));     return *this;   }++  /// Move-construct a random-access handle from a handle of another executor+  /// type.+  /**+   * 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.+   */+  template<typename Executor1>+  basic_random_access_handle(basic_random_access_handle<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_overlapped_handle<Executor>(std::move(other))+  {+  }++  /// Move-assign a random-access handle from a handle of another executor+  /// type.+  /**+   * 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.+   */+  template<typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_random_access_handle&+  >::type operator=(basic_random_access_handle<Executor1>&& 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.@@ -239,27 +288,33 @@   /// 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.+   * handle. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param offset The offset at which the data will be written.    *    * @param buffers One or more data buffers to be written to the handle.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the write completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes written.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The write operation may not transmit all of the data to the peer.    * Consider using the @ref async_write_at function if you need to ensure that    * all data is written before the asynchronous operation completes.@@ -272,21 +327,35 @@    * See the @ref buffer documentation for information on writing multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_write_some_at(uint64_t offset,       const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_write_some_at>(), token, offset, buffers)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_write_some_at(this), handler, offset, buffers);+        initiate_async_write_some_at(this), token, offset, buffers);   }    /// Read some data from the handle at the specified offset.@@ -360,27 +429,33 @@   /// 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.+   * handle. It is an initiating function for an @ref asynchronous_operation,+   * and always returns immediately.    *    * @param offset The offset at which the data will be read.    *    * @param buffers One or more buffers into which the data will be read.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the read completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes read.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The read operation may not read all of the requested number of bytes.    * Consider using the @ref async_read_at function if you need to ensure that    * the requested amount of data is read before the asynchronous operation@@ -394,21 +469,35 @@    * See the @ref buffer documentation for information on reading into multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_read_some_at(uint64_t offset,       const MutableBufferSequence& buffers,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_read_some_at>(), token, offset, buffers)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_read_some_at(this), handler, offset, buffers);+        initiate_async_read_some_at(this), token, offset, buffers);   }  private:@@ -422,7 +511,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -455,7 +544,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
link/modules/asio-standalone/asio/include/asio/windows/basic_stream_handle.hpp view
@@ -2,7 +2,7 @@ // windows/basic_stream_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -42,6 +42,10 @@ class basic_stream_handle   : public basic_overlapped_handle<Executor> {+private:+  class initiate_async_write_some;+  class initiate_async_read_some;+ public:   /// The type of the executor associated with the object.   typedef Executor executor_type;@@ -78,7 +82,8 @@   /// 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.+   * needs to be opened or assigned before data can be written to or read from+   * 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@@ -86,10 +91,10 @@    */   template <typename ExecutionContext>   explicit basic_stream_handle(ExecutionContext& context,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value,-        basic_stream_handle-      >::type* = 0)+        defaulted_constraint+      >::type = defaulted_constraint())     : basic_overlapped_handle<Executor>(context)   {   }@@ -128,9 +133,9 @@   template <typename ExecutionContext>   basic_stream_handle(ExecutionContext& context,       const native_handle_type& handle,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : basic_overlapped_handle<Executor>(context, handle)   {   }@@ -168,6 +173,48 @@     basic_overlapped_handle<Executor>::operator=(std::move(other));     return *this;   }++  /// Move-construct a stream handle from a handle of another executor type.+  /**+   * 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.+   */+  template<typename Executor1>+  basic_stream_handle(basic_stream_handle<Executor1>&& other,+      typename constraint<+        is_convertible<Executor1, Executor>::value,+        defaulted_constraint+      >::type = defaulted_constraint())+    : basic_overlapped_handle<Executor>(std::move(other))+  {+  }++  /// Move-assign a stream handle from a handle of another executor type.+  /**+   * 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.+   */+  template<typename Executor1>+  typename constraint<+    is_convertible<Executor1, Executor>::value,+    basic_stream_handle&+  >::type operator=(basic_stream_handle<Executor1>&& 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.@@ -234,25 +281,31 @@   /// Start an asynchronous write.   /**    * This function is used to asynchronously write data to the stream handle.-   * The function call always returns immediately.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more data buffers to be written to the 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.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the write completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes written.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The write operation may not transmit all of the data to the peer.    * Consider using the @ref async_write function if you need to ensure that all    * data is written before the asynchronous operation completes.@@ -265,20 +318,34 @@    * See the @ref buffer documentation for information on writing multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename ConstBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) WriteHandler+        std::size_t)) WriteToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,       void (asio::error_code, std::size_t))   async_write_some(const ConstBufferSequence& buffers,-      ASIO_MOVE_ARG(WriteHandler) handler+      ASIO_MOVE_ARG(WriteToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<WriteToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_write_some>(), token, buffers)))   {-    return async_initiate<WriteHandler,+    return async_initiate<WriteToken,       void (asio::error_code, std::size_t)>(-        initiate_async_write_some(this), handler, buffers);+        initiate_async_write_some(this), token, buffers);   }    /// Read some data from the handle.@@ -347,25 +414,31 @@   /// Start an asynchronous read.   /**    * This function is used to asynchronously read data from the stream handle.-   * The function call always returns immediately.+   * It is an initiating function for an @ref asynchronous_operation, and always+   * returns immediately.    *    * @param buffers One or more buffers into which the data will be read.    * Although the buffers object may be copied as necessary, ownership of the    * underlying memory blocks is retained by the caller, which must guarantee-   * that they remain valid until the handler is called.+   * that they remain valid until the completion 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:+   * @param token The @ref completion_token that will be used to produce a+   * completion handler, which will be called when the read completes.+   * Potential completion tokens include @ref use_future, @ref use_awaitable,+   * @ref yield_context, or a function object with the correct completion+   * signature. The function signature of the completion handler must be:    * @code void handler(    *   const asio::error_code& error, // Result of operation.-   *   std::size_t bytes_transferred           // Number of bytes read.+   *   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+   * not, the completion handler will not be invoked from within this function.+   * On immediate completion, invocation of the handler will be performed in a    * manner equivalent to using asio::post().    *+   * @par Completion Signature+   * @code void(asio::error_code, std::size_t) @endcode+   *    * @note The read operation may not read all of the requested number of bytes.    * Consider using the @ref async_read function if you need to ensure that the    * requested amount of data is read before the asynchronous operation@@ -379,20 +452,34 @@    * See the @ref buffer documentation for information on reading into multiple    * buffers in one go, and how to use it with arrays, boost::array or    * std::vector.+   *+   * @par Per-Operation Cancellation+   * This asynchronous operation supports cancellation for the following+   * asio::cancellation_type values:+   *+   * @li @c cancellation_type::terminal+   *+   * @li @c cancellation_type::partial+   *+   * @li @c cancellation_type::total    */   template <typename MutableBufferSequence,       ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-        std::size_t)) ReadHandler+        std::size_t)) ReadToken           ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(executor_type)>-  ASIO_INITFN_AUTO_RESULT_TYPE(ReadHandler,+  ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(ReadToken,       void (asio::error_code, std::size_t))   async_read_some(const MutableBufferSequence& buffers,-      ASIO_MOVE_ARG(ReadHandler) handler+      ASIO_MOVE_ARG(ReadToken) token         ASIO_DEFAULT_COMPLETION_TOKEN(executor_type))+    ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+      async_initiate<ReadToken,+        void (asio::error_code, std::size_t)>(+          declval<initiate_async_read_some>(), token, buffers)))   {-    return async_initiate<ReadHandler,+    return async_initiate<ReadToken,       void (asio::error_code, std::size_t)>(-        initiate_async_read_some(this), handler, buffers);+        initiate_async_read_some(this), token, buffers);   }  private:@@ -406,7 +493,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }@@ -439,7 +526,7 @@     {     } -    executor_type get_executor() const ASIO_NOEXCEPT+    const executor_type& get_executor() const ASIO_NOEXCEPT     {       return self_->get_executor();     }
link/modules/asio-standalone/asio/include/asio/windows/object_handle.hpp view
@@ -2,7 +2,7 @@ // windows/object_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 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
link/modules/asio-standalone/asio/include/asio/windows/overlapped_handle.hpp view
@@ -2,7 +2,7 @@ // windows/overlapped_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/windows/overlapped_ptr.hpp view
@@ -2,7 +2,7 @@ // windows/overlapped_ptr.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -52,9 +52,9 @@   template <typename ExecutionContext, typename Handler>   explicit overlapped_ptr(ExecutionContext& context,       ASIO_MOVE_ARG(Handler) handler,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)     : impl_(context.get_executor(), ASIO_MOVE_CAST(Handler)(handler))   {   }@@ -63,10 +63,10 @@   template <typename Executor, typename Handler>   explicit overlapped_ptr(const Executor& ex,       ASIO_MOVE_ARG(Handler) handler,-      typename enable_if<+      typename constraint<         execution::is_executor<Executor>::value           || is_executor<Executor>::value-      >::type* = 0)+      >::type = 0)     : impl_(ex, ASIO_MOVE_CAST(Handler)(handler))   {   }@@ -86,9 +86,9 @@   /// object.   template <typename ExecutionContext, typename Handler>   void reset(ExecutionContext& context, ASIO_MOVE_ARG(Handler) handler,-      typename enable_if<+      typename constraint<         is_convertible<ExecutionContext&, execution_context&>::value-      >::type* = 0)+      >::type = 0)   {     impl_.reset(context.get_executor(), ASIO_MOVE_CAST(Handler)(handler));   }@@ -97,10 +97,10 @@   /// object.   template <typename Executor, typename Handler>   void reset(const Executor& ex, ASIO_MOVE_ARG(Handler) handler,-      typename enable_if<+      typename constraint<         execution::is_executor<Executor>::value           || is_executor<Executor>::value-      >::type* = 0)+      >::type = 0)   {     impl_.reset(ex, ASIO_MOVE_CAST(Handler)(handler));   }
link/modules/asio-standalone/asio/include/asio/windows/random_access_handle.hpp view
@@ -2,7 +2,7 @@ // windows/random_access_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/include/asio/windows/stream_handle.hpp view
@@ -2,7 +2,7 @@ // windows/stream_handle.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/include/asio/writable_pipe.hpp view
@@ -0,0 +1,35 @@+//+// writable_pipe.hpp+// ~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef ASIO_WRITABLE_PIPE_HPP+#define ASIO_WRITABLE_PIPE_HPP++#if defined(_MSC_VER) && (_MSC_VER >= 1200)+# pragma once+#endif // defined(_MSC_VER) && (_MSC_VER >= 1200)++#include "asio/detail/config.hpp"++#if defined(ASIO_HAS_PIPE) \+  || defined(GENERATING_DOCUMENTATION)++#include "asio/basic_writable_pipe.hpp"++namespace asio {++/// Typedef for the typical usage of a writable pipe.+typedef basic_writable_pipe<> writable_pipe;++} // namespace asio++#endif // defined(ASIO_HAS_PIPE)+       //   || defined(GENERATING_DOCUMENTATION)++#endif // ASIO_WRITABLE_PIPE_HPP
link/modules/asio-standalone/asio/include/asio/write.hpp view
@@ -2,7 +2,7 @@ // write.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -19,6 +19,7 @@ #include <cstddef> #include "asio/async_result.hpp" #include "asio/buffer.hpp"+#include "asio/completion_condition.hpp" #include "asio/error.hpp"  #if !defined(ASIO_NO_EXTENSIONS)@@ -28,7 +29,16 @@ #include "asio/detail/push_options.hpp"  namespace asio {+namespace detail { +template <typename> class initiate_async_write;+#if !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_write_dynbuf_v1;+#endif // !defined(ASIO_NO_DYNAMIC_BUFFER_V1)+template <typename> class initiate_async_write_dynbuf_v2;++} // namespace detail+ /**  * @defgroup write asio::write  *@@ -75,9 +85,9 @@  */ template <typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,-    typename enable_if<+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type* = 0);+    >::type = 0);  /// Write all of the supplied data to a stream before returning. /**@@ -118,9 +128,9 @@ template <typename SyncWriteStream, typename ConstBufferSequence> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type* = 0);+    >::type = 0);  /// Write a certain amount of data to a stream before returning. /**@@ -172,9 +182,9 @@     typename CompletionCondition> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type* = 0);+    >::type = 0);  /// Write a certain amount of data to a stream before returning. /**@@ -219,9 +229,9 @@     typename CompletionCondition> std::size_t write(SyncWriteStream& s, const ConstBufferSequence& buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type* = 0);+    >::type = 0);  #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -255,10 +265,12 @@ template <typename SyncWriteStream, typename DynamicBuffer_v1> std::size_t write(SyncWriteStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0);  /// Write all of the supplied data to a stream before returning. /**@@ -291,10 +303,12 @@ std::size_t write(SyncWriteStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0);  /// Write a certain amount of data to a stream before returning. /**@@ -337,10 +351,12 @@ std::size_t write(SyncWriteStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0);  /// Write a certain amount of data to a stream before returning. /**@@ -384,10 +400,12 @@ std::size_t write(SyncWriteStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0);  #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -565,9 +583,9 @@  */ template <typename SyncWriteStream, typename DynamicBuffer_v2> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Write all of the supplied data to a stream before returning. /**@@ -599,9 +617,9 @@ template <typename SyncWriteStream, typename DynamicBuffer_v2> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,     asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Write a certain amount of data to a stream before returning. /**@@ -643,9 +661,9 @@     typename CompletionCondition> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,     CompletionCondition completion_condition,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /// Write a certain amount of data to a stream before returning. /**@@ -688,9 +706,9 @@     typename CompletionCondition> std::size_t write(SyncWriteStream& s, DynamicBuffer_v2 buffers,     CompletionCondition completion_condition, asio::error_code& ec,-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0);  /*@}*/ /**@@ -705,9 +723,9 @@ /// 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:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -726,24 +744,29 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @par Example  * To write a single data buffer use the @ref buffer function as follows:  * @code@@ -752,29 +775,45 @@  * See the @ref buffer documentation for information on writing multiple  * buffers in one go, and how to use it with arrays, boost::array or  * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation.  */ template <typename AsyncWriteStream, typename ConstBufferSequence,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) WriteHandler+      std::size_t)) WriteToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncWriteStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, const ConstBufferSequence& buffers,-    ASIO_MOVE_ARG(WriteHandler) handler+    ASIO_MOVE_ARG(WriteToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncWriteStream::executor_type),-    typename enable_if<+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write<AsyncWriteStream> >(),+        token, buffers, transfer_all())));  /// 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:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.@@ -793,7 +832,7 @@  * @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.+ * that they remain valid until the completion 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@@ -809,22 +848,27 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @par Example  * To write a single data buffer use the @ref buffer function as follows:  * @code asio::async_write(s,@@ -834,19 +878,36 @@  * See the @ref buffer documentation for information on writing multiple  * buffers in one go, and how to use it with arrays, boost::array or  * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+   *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation.  */ 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,+      std::size_t)) WriteToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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<+    ASIO_MOVE_ARG(WriteToken) token,+    typename constraint<       is_const_buffer_sequence<ConstBufferSequence>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write<AsyncWriteStream> >(),+        token, buffers,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  #if !defined(ASIO_NO_DYNAMIC_BUFFER_V1) @@ -854,9 +915,9 @@ /// 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:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.  *@@ -874,49 +935,73 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation.  */ template <typename AsyncWriteStream, typename DynamicBuffer_v1,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) WriteHandler+      std::size_t)) WriteToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncWriteStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s,     ASIO_MOVE_ARG(DynamicBuffer_v1) buffers,-    ASIO_MOVE_ARG(WriteHandler) handler+    ASIO_MOVE_ARG(WriteToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncWriteStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        transfer_all())));  /// 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:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.  *@@ -934,8 +1019,8 @@  * @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.+ * that they remain valid until the completion 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@@ -951,36 +1036,60 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation.  */ 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,+      std::size_t)) WriteToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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<+    ASIO_MOVE_ARG(WriteToken) token,+    typename constraint<       is_dynamic_buffer_v1<typename decay<DynamicBuffer_v1>::type>::value-        && !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value-    >::type* = 0);+    >::type = 0,+    typename constraint<+      !is_dynamic_buffer_v2<typename decay<DynamicBuffer_v1>::type>::value+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_dynbuf_v1<AsyncWriteStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v1)(buffers),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -989,9 +1098,9 @@ /// 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:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.  *@@ -1008,43 +1117,62 @@  *  * @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.+ * remains valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation.  */ template <typename AsyncWriteStream, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) WriteHandler+      std::size_t)) WriteToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncWriteStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,-    ASIO_MOVE_ARG(WriteHandler) handler+    ASIO_MOVE_ARG(WriteToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncWriteStream::executor_type));+        typename AsyncWriteStream::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_write(s, basic_streambuf_ref<Allocator>(b),+        ASIO_MOVE_CAST(WriteToken)(token))));  /// 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:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.  *@@ -1061,7 +1189,7 @@  *  * @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.+ * remains valid until the completion 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@@ -1077,31 +1205,51 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation.  */ 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,+      std::size_t)) WriteToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, basic_streambuf<Allocator>& b,     CompletionCondition completion_condition,-    ASIO_MOVE_ARG(WriteHandler) handler);+    ASIO_MOVE_ARG(WriteToken) token)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_write(s, basic_streambuf_ref<Allocator>(b),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition),+        ASIO_MOVE_CAST(WriteToken)(token))));  #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)@@ -1111,9 +1259,9 @@ /// 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:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.  *@@ -1131,47 +1279,69 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation.  */ template <typename AsyncWriteStream, typename DynamicBuffer_v2,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) WriteHandler+      std::size_t)) WriteToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncWriteStream::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write(AsyncWriteStream& s, DynamicBuffer_v2 buffers,-    ASIO_MOVE_ARG(WriteHandler) handler+    ASIO_MOVE_ARG(WriteToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(         typename AsyncWriteStream::executor_type),-    typename enable_if<+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        transfer_all())));  /// 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:+ * data to a stream. It is an initiating function for an @ref+ * asynchronous_operation, and 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.  *@@ -1189,8 +1359,8 @@  * @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.+ * that they remain valid until the completion 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@@ -1206,34 +1376,56 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(- *   const asio::error_code& error, // Result of operation.+ *   // Result of operation.+ *   const asio::error_code& error,  *- *   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.+ *   // 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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncWriteStream type's+ * @c async_write_some operation.  */ 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,+      std::size_t)) WriteToken>+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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<+    ASIO_MOVE_ARG(WriteToken) token,+    typename constraint<       is_dynamic_buffer_v2<DynamicBuffer_v2>::value-    >::type* = 0);+    >::type = 0)+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_dynbuf_v2<AsyncWriteStream> >(),+        token, ASIO_MOVE_CAST(DynamicBuffer_v2)(buffers),+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  /*@}*/ 
link/modules/asio-standalone/asio/include/asio/write_at.hpp view
@@ -2,7 +2,7 @@ // write_at.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,6 +18,7 @@ #include "asio/detail/config.hpp" #include <cstddef> #include "asio/async_result.hpp"+#include "asio/completion_condition.hpp" #include "asio/detail/cstdint.hpp" #include "asio/error.hpp" @@ -28,7 +29,15 @@ #include "asio/detail/push_options.hpp"  namespace asio {+namespace detail { +template <typename> class initiate_async_write_at;+#if !defined(ASIO_NO_IOSTREAM)+template <typename> class initiate_async_write_at_streambuf;+#endif // !defined(ASIO_NO_IOSTREAM)++} // namespace detail+ /**  * @defgroup write_at asio::write_at  *@@ -403,9 +412,10 @@ /// 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:+ * data to a random access device at a specified offset. It is an initiating+ * function for an @ref asynchronous_operation, and 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.@@ -428,11 +438,13 @@  * @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.+ * that they remain valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -442,10 +454,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @par Example  * To write a single data buffer use the @ref buffer function as follows:  * @code@@ -454,27 +469,45 @@  * See the @ref buffer documentation for information on writing multiple  * buffers in one go, and how to use it with arrays, boost::array or  * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessWriteDevice type's+ * async_write_some_at operation.  */ template <typename AsyncRandomAccessWriteDevice, typename ConstBufferSequence,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) WriteHandler+      std::size_t)) WriteToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncRandomAccessWriteDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     void (asio::error_code, std::size_t)) async_write_at(AsyncRandomAccessWriteDevice& d, uint64_t offset,     const ConstBufferSequence& buffers,-    ASIO_MOVE_ARG(WriteHandler) handler+    ASIO_MOVE_ARG(WriteToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncRandomAccessWriteDevice::executor_type));+        typename AsyncRandomAccessWriteDevice::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_at<+          AsyncRandomAccessWriteDevice> >(),+        token, offset, buffers, transfer_all())));  /// 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:+ * data to a random access device at a specified offset. It is an initiating+ * function for an @ref asynchronous_operation, and 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.@@ -497,7 +530,7 @@  * @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.+ * that they remain valid until the completion 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@@ -513,9 +546,11 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -525,10 +560,13 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().  *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *  * @par Example  * To write a single data buffer use the @ref buffer function as follows:  * @code asio::async_write_at(d, 42,@@ -538,21 +576,39 @@  * See the @ref buffer documentation for information on writing multiple  * buffers in one go, and how to use it with arrays, boost::array or  * std::vector.+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessWriteDevice type's+ * async_write_some_at operation.  */ template <typename AsyncRandomAccessWriteDevice,     typename ConstBufferSequence, typename CompletionCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) WriteHandler+      std::size_t)) WriteToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncRandomAccessWriteDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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_MOVE_ARG(WriteToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncRandomAccessWriteDevice::executor_type));+        typename AsyncRandomAccessWriteDevice::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_at<+          AsyncRandomAccessWriteDevice> >(),+        token, offset, buffers,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  #if !defined(ASIO_NO_EXTENSIONS) #if !defined(ASIO_NO_IOSTREAM)@@ -561,9 +617,10 @@ /// 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:+ * data to a random access device at a specified offset. It is an initiating+ * function for an @ref asynchronous_operation, and 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.  *@@ -584,11 +641,13 @@  *  * @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.+ * remains valid until the completion 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -598,30 +657,51 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessWriteDevice type's+ * async_write_some_at operation.  */ template <typename AsyncRandomAccessWriteDevice, typename Allocator,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) WriteHandler+      std::size_t)) WriteToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncRandomAccessWriteDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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_MOVE_ARG(WriteToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncRandomAccessWriteDevice::executor_type));+        typename AsyncRandomAccessWriteDevice::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_at_streambuf<+          AsyncRandomAccessWriteDevice> >(),+        token, offset, &b, transfer_all())));  /// 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:+ * data to a random access device at a specified offset. It is an initiating+ * function for an @ref asynchronous_operation, and 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.  *@@ -642,7 +722,7 @@  *  * @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.+ * remains valid until the completion 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@@ -658,9 +738,11 @@  * 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:+ * @param token The @ref completion_token that will be used to produce a+ * completion handler, which will be called when the write completes.+ * Potential completion tokens include @ref use_future, @ref use_awaitable,+ * @ref yield_context, or a function object with the correct completion+ * signature. The function signature of the completion handler must be:  * @code void handler(  *   // Result of operation.  *   const asio::error_code& error,@@ -670,23 +752,44 @@  *   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+ * not, the completion handler will not be invoked from within this function.+ * On immediate completion, invocation of the handler will be performed in a  * manner equivalent to using asio::post().+ *+ * @par Completion Signature+ * @code void(asio::error_code, std::size_t) @endcode+ *+ * @par Per-Operation Cancellation+ * This asynchronous operation supports cancellation for the following+ * asio::cancellation_type values:+ *+ * @li @c cancellation_type::terminal+ *+ * @li @c cancellation_type::partial+ *+ * if they are also supported by the @c AsyncRandomAccessWriteDevice type's+ * async_write_some_at operation.  */ template <typename AsyncRandomAccessWriteDevice,     typename Allocator, typename CompletionCondition,     ASIO_COMPLETION_TOKEN_FOR(void (asio::error_code,-      std::size_t)) WriteHandler+      std::size_t)) WriteToken         ASIO_DEFAULT_COMPLETION_TOKEN_TYPE(           typename AsyncRandomAccessWriteDevice::executor_type)>-ASIO_INITFN_AUTO_RESULT_TYPE(WriteHandler,+ASIO_INITFN_AUTO_RESULT_TYPE_PREFIX(WriteToken,     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_MOVE_ARG(WriteToken) token       ASIO_DEFAULT_COMPLETION_TOKEN(-        typename AsyncRandomAccessWriteDevice::executor_type));+        typename AsyncRandomAccessWriteDevice::executor_type))+  ASIO_INITFN_AUTO_RESULT_TYPE_SUFFIX((+    async_initiate<WriteToken,+      void (asio::error_code, std::size_t)>(+        declval<detail::initiate_async_write_at_streambuf<+          AsyncRandomAccessWriteDevice> >(),+        token, offset, &b,+        ASIO_MOVE_CAST(CompletionCondition)(completion_condition))));  #endif // !defined(ASIO_NO_IOSTREAM) #endif // !defined(ASIO_NO_EXTENSIONS)
link/modules/asio-standalone/asio/include/asio/yield.hpp view
@@ -2,7 +2,7 @@ // yield.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/chat/chat_message.hpp view
@@ -2,7 +2,7 @@ // chat_message.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,8 +18,11 @@ class chat_message { public:-  enum { header_length = 4 };-  enum { max_body_length = 512 };+  enum+  {+    header_length = 4,+    max_body_length = 512+  };    chat_message()     : body_length_(0)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection_manager.hpp view
@@ -2,7 +2,7 @@ // connection_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_handler.hpp view
@@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/io_context_pool.hpp view
@@ -2,7 +2,7 @@ // io_context_pool.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -39,12 +39,14 @@  private:   typedef boost::shared_ptr<asio::io_context> io_context_ptr;+  typedef asio::executor_work_guard<+    asio::io_context::executor_type> io_context_work;    /// 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 work that keeps the io_contexts running.+  std::list<io_context_work> work_;    /// The next io_context to use for a connection.   std::size_t next_io_context_;
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_handler.hpp view
@@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_handler.hpp view
@@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/file_handler.hpp view
@@ -2,7 +2,7 @@ // file_handler.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/icmp/icmp_header.hpp view
@@ -2,7 +2,7 @@ // icmp_header.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/icmp/ipv4_header.hpp view
@@ -2,7 +2,7 @@ // ipv4_header.hpp // ~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/porthopper/protocol.hpp view
@@ -2,7 +2,7 @@ // protocol.hpp // ~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/serialization/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/serialization/stock.hpp view
@@ -2,7 +2,7 @@ // stock.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/services/basic_logger.hpp view
@@ -2,7 +2,7 @@ // basic_logger.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/services/logger.hpp view
@@ -2,7 +2,7 @@ // logger.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp03/services/logger_service.hpp view
@@ -2,7 +2,7 @@ // logger_service.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -44,8 +44,7 @@   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_(asio::make_work_guard(work_io_context_)),       work_thread_(new asio::thread(             boost::bind(&asio::io_context::run, &work_io_context_)))   {@@ -56,7 +55,7 @@   {     /// 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();+    work_.reset();     if (work_thread_)       work_thread_->join();   }@@ -128,10 +127,11 @@   /// 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_;+  /// 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::executor_work_guard<+      asio::io_context::executor_type> work_;    /// Thread used for running the work io_context's run loop.   boost::scoped_ptr<asio::thread> work_thread_;
link/modules/asio-standalone/asio/src/examples/cpp03/socks4/socks4.hpp view
@@ -2,7 +2,7 @@ // socks4.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/chat/chat_message.hpp view
@@ -2,7 +2,7 @@ // chat_message.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -18,8 +18,8 @@ class chat_message { public:-  enum { header_length = 4 };-  enum { max_body_length = 512 };+  static constexpr std::size_t header_length = 4;+  static constexpr std::size_t max_body_length = 512;    chat_message()     : body_length_(0)
link/modules/asio-standalone/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp view
@@ -2,7 +2,7 @@ // custom_tracking.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection.hpp view
@@ -2,7 +2,7 @@ // connection.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection_manager.hpp view
@@ -2,7 +2,7 @@ // connection_manager.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/header.hpp view
@@ -2,7 +2,7 @@ // header.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/mime_types.hpp view
@@ -2,7 +2,7 @@ // mime_types.hpp // ~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/reply.hpp view
@@ -2,7 +2,7 @@ // reply.hpp // ~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request.hpp view
@@ -2,7 +2,7 @@ // request.hpp // ~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_handler.hpp view
@@ -2,7 +2,7 @@ // request_handler.hpp // ~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_parser.hpp view
@@ -2,7 +2,7 @@ // request_parser.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/http/server/server.hpp view
@@ -2,7 +2,7 @@ // server.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/examples/cpp11/socks4/socks4.hpp view
@@ -2,7 +2,7 @@ // socks4.hpp // ~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
+ link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/line_reader.hpp view
@@ -0,0 +1,48 @@+//+// line_reader.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef LINE_READER_HPP+#define LINE_READER_HPP++#include <asio/any_completion_handler.hpp>+#include <asio/async_result.hpp>+#include <asio/error.hpp>+#include <string>++class line_reader+{+private:+  virtual void async_read_line_impl(std::string prompt,+      asio::any_completion_handler<void(asio::error_code, std::string)> handler) = 0;++  struct initiate_read_line+  {+    template <typename Handler>+    void operator()(Handler handler, line_reader* self, std::string prompt)+    {+      self->async_read_line_impl(std::move(prompt), std::move(handler));+    }+  };++public:+  virtual ~line_reader() {}++  template <typename CompletionToken>+  auto async_read_line(std::string prompt, CompletionToken&& token)+    -> decltype(+        asio::async_initiate<CompletionToken, void(asio::error_code, std::string)>(+          initiate_read_line(), token, this, prompt))+  {+    return asio::async_initiate<CompletionToken, void(asio::error_code, std::string)>(+        initiate_read_line(), token, this, prompt);+  }+};++#endif // LINE_READER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/sleep.hpp view
@@ -0,0 +1,35 @@+//+// sleep.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef SLEEP_HPP+#define SLEEP_HPP++#include <asio/any_completion_handler.hpp>+#include <asio/any_io_executor.hpp>+#include <asio/async_result.hpp>+#include <asio/error.hpp>+#include <chrono>++void async_sleep_impl(+    asio::any_completion_handler<void(std::error_code)> handler,+    asio::any_io_executor ex, std::chrono::nanoseconds duration);++template <typename CompletionToken>+inline auto async_sleep(asio::any_io_executor ex,+    std::chrono::nanoseconds duration, CompletionToken&& token)+  -> decltype(+      asio::async_initiate<CompletionToken, void(std::error_code)>(+        async_sleep_impl, token, std::move(ex), duration))+{+  return asio::async_initiate<CompletionToken, void(std::error_code)>(+      async_sleep_impl, token, std::move(ex), duration);+}++#endif // SLEEP_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/stdin_line_reader.hpp view
@@ -0,0 +1,30 @@+//+// stdin_line_reader.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef STDIN_LINE_READER_HPP+#define STDIN_LINE_READER_HPP++#include "line_reader.hpp"+#include <asio/posix/stream_descriptor.hpp>++class stdin_line_reader : public line_reader+{+public:+  explicit stdin_line_reader(asio::any_io_executor ex);++private:+  void async_read_line_impl(std::string prompt,+      asio::any_completion_handler<void(asio::error_code, std::string)> handler) override;++  asio::posix::stream_descriptor stdin_;+  std::string buffer_;+};++#endif
+ link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/line_reader.hpp view
@@ -0,0 +1,39 @@+//+// line_reader.hpp+// ~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef LINE_READER_HPP+#define LINE_READER_HPP++#include <asio/any_completion_handler.hpp>+#include <asio/async_result.hpp>+#include <asio/error.hpp>+#include <string>++class line_reader+{+public:+  virtual ~line_reader() {}++  template <typename CompletionToken>+  auto async_read_line(std::string prompt, CompletionToken&& token)+  {+    return asio::async_initiate<CompletionToken, void(asio::error_code, std::string)>(+        [](auto handler, line_reader* self, std::string prompt)+        {+          self->async_read_line_impl(std::move(prompt), std::move(handler));+        }, token, this, prompt);+  }++private:+  virtual void async_read_line_impl(std::string prompt,+      asio::any_completion_handler<void(asio::error_code, std::string)> handler) = 0;+};++#endif // LINE_READER_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/sleep.hpp view
@@ -0,0 +1,32 @@+//+// sleep.hpp+// ~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef SLEEP_HPP+#define SLEEP_HPP++#include <asio/any_completion_handler.hpp>+#include <asio/any_io_executor.hpp>+#include <asio/async_result.hpp>+#include <asio/error.hpp>+#include <chrono>++void async_sleep_impl(+    asio::any_completion_handler<void(std::error_code)> handler,+    asio::any_io_executor ex, std::chrono::nanoseconds duration);++template <typename CompletionToken>+inline auto async_sleep(asio::any_io_executor ex,+    std::chrono::nanoseconds duration, CompletionToken&& token)+{+  return asio::async_initiate<CompletionToken, void(std::error_code)>(+      async_sleep_impl, token, std::move(ex), duration);+}++#endif // SLEEP_HPP
+ link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/stdin_line_reader.hpp view
@@ -0,0 +1,30 @@+//+// stdin_line_reader.hpp+// ~~~~~~~~~~~~~~~~~~~~~+//+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com)+//+// Distributed under the Boost Software License, Version 1.0. (See accompanying+// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)+//++#ifndef STDIN_LINE_READER_HPP+#define STDIN_LINE_READER_HPP++#include "line_reader.hpp"+#include <asio/posix/stream_descriptor.hpp>++class stdin_line_reader : public line_reader+{+public:+  explicit stdin_line_reader(asio::any_io_executor ex);++private:+  void async_read_line_impl(std::string prompt,+      asio::any_completion_handler<void(asio::error_code, std::string)> handler) override;++  asio::posix::stream_descriptor stdin_;+  std::string buffer_;+};++#endif
link/modules/asio-standalone/asio/src/tests/latency/allocator.hpp view
@@ -2,7 +2,7 @@ // allocator.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/latency/high_res_clock.hpp view
@@ -2,7 +2,7 @@ // high_res_clock.hpp // ~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/performance/handler_allocator.hpp view
@@ -2,7 +2,7 @@ // handler_allocator.cpp // ~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_ops.hpp view
@@ -2,7 +2,7 @@ // async_ops.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_result.hpp view
@@ -2,7 +2,7 @@ // async_result.hpp // ~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)@@ -12,9 +12,14 @@ #define ARCHETYPES_ASYNC_RESULT_HPP  #include <asio/async_result.hpp>+#include <asio/system_executor.hpp>  namespace archetypes { +struct immediate_handler+{+};+ struct lazy_handler { };@@ -25,7 +30,7 @@ template <typename R, typename Arg1> struct concrete_handler<R(Arg1)> {-  concrete_handler(lazy_handler)+  concrete_handler()   {   } @@ -43,31 +48,88 @@ template <typename R, typename Arg1, typename Arg2> struct concrete_handler<R(Arg1, Arg2)> {-  concrete_handler(lazy_handler)+  concrete_handler()   {   } -  void operator()(typename asio::decay<Arg1>::type, typename asio::decay<Arg2>::type)+  void operator()(typename asio::decay<Arg1>::type,+      typename asio::decay<Arg2>::type)   {   }+}; +template <typename Signature>+struct immediate_concrete_handler : concrete_handler<Signature>+{+  typedef asio::system_executor immediate_executor_type;++  immediate_concrete_handler(immediate_handler)+  {+  }++  immediate_executor_type get_immediate_executor() const ASIO_NOEXCEPT+  {+    return immediate_executor_type();+  }+ #if defined(ASIO_HAS_MOVE)-  concrete_handler(concrete_handler&&) {}+  immediate_concrete_handler(immediate_concrete_handler&&) {} private:-  concrete_handler(const concrete_handler&);+  immediate_concrete_handler(const immediate_concrete_handler&); #endif // defined(ASIO_HAS_MOVE) }; +template <typename Signature>+struct lazy_concrete_handler : concrete_handler<Signature>+{+  lazy_concrete_handler(lazy_handler)+  {+  }++#if defined(ASIO_HAS_MOVE)+  lazy_concrete_handler(lazy_concrete_handler&&) {}+private:+  lazy_concrete_handler(const lazy_concrete_handler&);+#endif // defined(ASIO_HAS_MOVE)+};+ } // namespace archetypes  namespace asio {  template <typename Signature>+class async_result<archetypes::immediate_handler, Signature>+{+public:+  // The concrete completion handler type.+  typedef archetypes::immediate_concrete_handler<Signature>+    completion_handler_type;++  // The return type of the initiating function.+  typedef void 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.+  void get()+  {+  }++private:+  // Disallow copying and assignment.+  async_result(const async_result&) ASIO_DELETED;+  async_result& operator=(const async_result&) ASIO_DELETED;+};++template <typename Signature> class async_result<archetypes::lazy_handler, Signature> { public:   // The concrete completion handler type.-  typedef archetypes::concrete_handler<Signature> completion_handler_type;+  typedef archetypes::lazy_concrete_handler<Signature> completion_handler_type;    // The return type of the initiating function.   typedef int return_type;
link/modules/asio-standalone/asio/src/tests/unit/archetypes/gettable_socket_option.hpp view
@@ -2,7 +2,7 @@ // gettable_socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/archetypes/io_control_command.hpp view
@@ -2,7 +2,7 @@ // io_control_command.hpp // ~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/archetypes/settable_socket_option.hpp view
@@ -2,7 +2,7 @@ // settable_socket_option.hpp // ~~~~~~~~~~~~~~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
link/modules/asio-standalone/asio/src/tests/unit/unit_test.hpp view
@@ -2,7 +2,7 @@ // unit_test.hpp // ~~~~~~~~~~~~~ //-// Copyright (c) 2003-2020 Christopher M. Kohlhoff (chris at kohlhoff dot com)+// Copyright (c) 2003-2023 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
tidal-link.cabal view
@@ -1,6 +1,6 @@ cabal-version:       2.4 name:                tidal-link-version:             1.0.1+version:             1.0.2 synopsis:            Ableton Link integration for Tidal -- description: homepage:            http://tidalcycles.org/@@ -39,7 +39,7 @@       winmm       ws2_32     cxx-options:-      -DLINK_PLATFORM_WINDOWS=1 -Wno-multichar -Wno-subobject-linkage+      -DLINK_PLATFORM_WINDOWS=1 -Wno-multichar   elif os(darwin)     cxx-options:       -DLINK_PLATFORM_MACOSX=1 -std=c++14 -Wno-multichar -Wno-subobject-linkage