diff --git a/link/include/ableton/Link.ipp b/link/include/ableton/Link.ipp
--- a/link/include/ableton/Link.ipp
+++ b/link/include/ableton/Link.ipp
@@ -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>
diff --git a/link/include/ableton/discovery/AsioTypes.hpp b/link/include/ableton/discovery/AsioTypes.hpp
new file mode 100644
--- /dev/null
+++ b/link/include/ableton/discovery/AsioTypes.hpp
@@ -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
diff --git a/link/include/ableton/discovery/InterfaceScanner.hpp b/link/include/ableton/discovery/InterfaceScanner.hpp
--- a/link/include/ableton/discovery/InterfaceScanner.hpp
+++ b/link/include/ableton/discovery/InterfaceScanner.hpp
@@ -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));
diff --git a/link/include/ableton/discovery/IpInterface.hpp b/link/include/ableton/discovery/IpInterface.hpp
new file mode 100644
--- /dev/null
+++ b/link/include/ableton/discovery/IpInterface.hpp
@@ -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
diff --git a/link/include/ableton/discovery/IpV4Interface.hpp b/link/include/ableton/discovery/IpV4Interface.hpp
deleted file mode 100644
--- a/link/include/ableton/discovery/IpV4Interface.hpp
+++ /dev/null
@@ -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
diff --git a/link/include/ableton/discovery/NetworkByteStreamSerializable.hpp b/link/include/ableton/discovery/NetworkByteStreamSerializable.hpp
--- a/link/include/ableton/discovery/NetworkByteStreamSerializable.hpp
+++ b/link/include/ableton/discovery/NetworkByteStreamSerializable.hpp
@@ -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)
diff --git a/link/include/ableton/discovery/Payload.hpp b/link/include/ableton/discovery/Payload.hpp
--- a/link/include/ableton/discovery/Payload.hpp
+++ b/link/include/ableton/discovery/Payload.hpp
@@ -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)));
   }
diff --git a/link/include/ableton/discovery/PeerGateway.hpp b/link/include/ableton/discovery/PeerGateway.hpp
--- a/link/include/ableton/discovery/PeerGateway.hpp
+++ b/link/include/ableton/discovery/PeerGateway.hpp
@@ -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);
diff --git a/link/include/ableton/discovery/PeerGateways.hpp b/link/include/ableton/discovery/PeerGateways.hpp
--- a/link/include/ableton/discovery/PeerGateways.hpp
+++ b/link/include/ableton/discovery/PeerGateways.hpp
@@ -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)
         {
diff --git a/link/include/ableton/discovery/Service.hpp b/link/include/ableton/discovery/Service.hpp
--- a/link/include/ableton/discovery/Service.hpp
+++ b/link/include/ableton/discovery/Service.hpp
@@ -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);
   }
diff --git a/link/include/ableton/discovery/UdpMessenger.hpp b/link/include/ableton/discovery/UdpMessenger.hpp
--- a/link/include/ableton/discovery/UdpMessenger.hpp
+++ b/link/include/ableton/discovery/UdpMessenger.hpp
@@ -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);
 
diff --git a/link/include/ableton/discovery/test/Interface.hpp b/link/include/ableton/discovery/test/Interface.hpp
--- a/link/include/ableton/discovery/test/Interface.hpp
+++ b/link/include/ableton/discovery/test/Interface.hpp
@@ -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;
 };
 
diff --git a/link/include/ableton/discovery/test/Socket.hpp b/link/include/ableton/discovery/test/Socket.hpp
--- a/link/include/ableton/discovery/test/Socket.hpp
+++ b/link/include/ableton/discovery/test/Socket.hpp
@@ -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;
 };
 
diff --git a/link/include/ableton/link/Controller.hpp b/link/include/ableton/link/Controller.hpp
--- a/link/include/ableton/link/Controller.hpp
+++ b/link/include/ableton/link/Controller.hpp
@@ -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;
diff --git a/link/include/ableton/link/Gateway.hpp b/link/include/ableton/link/Gateway.hpp
--- a/link/include/ableton/link/Gateway.hpp
+++ b/link/include/ableton/link/Gateway.hpp
@@ -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,
diff --git a/link/include/ableton/link/Measurement.hpp b/link/include/ableton/link/Measurement.hpp
--- a/link/include/ableton/link/Measurement.hpp
+++ b/link/include/ableton/link/Measurement.hpp
@@ -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;
diff --git a/link/include/ableton/link/MeasurementEndpointV4.hpp b/link/include/ableton/link/MeasurementEndpointV4.hpp
--- a/link/include/ableton/link/MeasurementEndpointV4.hpp
+++ b/link/include/ableton/link/MeasurementEndpointV4.hpp
@@ -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
diff --git a/link/include/ableton/link/MeasurementEndpointV6.hpp b/link/include/ableton/link/MeasurementEndpointV6.hpp
new file mode 100644
--- /dev/null
+++ b/link/include/ableton/link/MeasurementEndpointV6.hpp
@@ -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
diff --git a/link/include/ableton/link/MeasurementService.hpp b/link/include/ableton/link/MeasurementService.hpp
--- a/link/include/ableton/link/MeasurementService.hpp
+++ b/link/include/ableton/link/MeasurementService.hpp
@@ -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
diff --git a/link/include/ableton/link/PeerState.hpp b/link/include/ableton/link/PeerState.hpp
--- a/link/include/ableton/link/PeerState.hpp
+++ b/link/include/ableton/link/PeerState.hpp
@@ -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
diff --git a/link/include/ableton/link/Peers.hpp b/link/include/ableton/link/Peers.hpp
--- a/link/include/ableton/link/Peers.hpp
+++ b/link/include/ableton/link/Peers.hpp
@@ -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;
 
diff --git a/link/include/ableton/link/PingResponder.hpp b/link/include/ableton/link/PingResponder.hpp
--- a/link/include/ableton/link/PingResponder.hpp
+++ b/link/include/ableton/link/PingResponder.hpp
@@ -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;
 
diff --git a/link/include/ableton/link/SessionState.hpp b/link/include/ableton/link/SessionState.hpp
--- a/link/include/ableton/link/SessionState.hpp
+++ b/link/include/ableton/link/SessionState.hpp
@@ -23,6 +23,7 @@
 #include <ableton/link/StartStopState.hpp>
 #include <ableton/link/Timeline.hpp>
 #include <ableton/link/TripleBuffer.hpp>
+#include <mutex>
 
 namespace ableton
 {
diff --git a/link/include/ableton/platforms/Config.hpp b/link/include/ableton/platforms/Config.hpp
--- a/link/include/ableton/platforms/Config.hpp
+++ b/link/include/ableton/platforms/Config.hpp
@@ -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)
diff --git a/link/include/ableton/platforms/asio/AsioTimer.hpp b/link/include/ableton/platforms/asio/AsioTimer.hpp
--- a/link/include/ableton/platforms/asio/AsioTimer.hpp
+++ b/link/include/ableton/platforms/asio/AsioTimer.hpp
@@ -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
diff --git a/link/include/ableton/platforms/asio/AsioWrapper.hpp b/link/include/ableton/platforms/asio/AsioWrapper.hpp
--- a/link/include/ableton/platforms/asio/AsioWrapper.hpp
+++ b/link/include/ableton/platforms/asio/AsioWrapper.hpp
@@ -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
diff --git a/link/include/ableton/platforms/asio/Context.hpp b/link/include/ableton/platforms/asio/Context.hpp
--- a/link/include/ableton/platforms/asio/Context.hpp
+++ b/link/include/ableton/platforms/asio/Context.hpp
@@ -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
diff --git a/link/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp b/link/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp
--- a/link/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp
+++ b/link/include/ableton/platforms/asio/LockFreeCallbackDispatcher.hpp
@@ -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
diff --git a/link/include/ableton/platforms/asio/Socket.hpp b/link/include/ableton/platforms/asio/Socket.hpp
--- a/link/include/ableton/platforms/asio/Socket.hpp
+++ b/link/include/ableton/platforms/asio/Socket.hpp
@@ -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
diff --git a/link/include/ableton/platforms/asio/Util.hpp b/link/include/ableton/platforms/asio/Util.hpp
deleted file mode 100644
--- a/link/include/ableton/platforms/asio/Util.hpp
+++ /dev/null
@@ -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
diff --git a/link/include/ableton/platforms/darwin/Clock.hpp b/link/include/ableton/platforms/darwin/Clock.hpp
--- a/link/include/ableton/platforms/darwin/Clock.hpp
+++ b/link/include/ableton/platforms/darwin/Clock.hpp
@@ -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);
   }
 
diff --git a/link/include/ableton/platforms/esp32/Context.hpp b/link/include/ableton/platforms/esp32/Context.hpp
--- a/link/include/ableton/platforms/esp32/Context.hpp
+++ b/link/include/ableton/platforms/esp32/Context.hpp
@@ -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;
   }
 
diff --git a/link/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp b/link/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp
--- a/link/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp
+++ b/link/include/ableton/platforms/esp32/ScanIpIfAddrs.hpp
@@ -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)
diff --git a/link/include/ableton/platforms/linux/Clock.hpp b/link/include/ableton/platforms/linux/Clock.hpp
--- a/link/include/ableton/platforms/linux/Clock.hpp
+++ b/link/include/ableton/platforms/linux/Clock.hpp
@@ -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
diff --git a/link/include/ableton/platforms/linux/ThreadFactory.hpp b/link/include/ableton/platforms/linux/ThreadFactory.hpp
--- a/link/include/ableton/platforms/linux/ThreadFactory.hpp
+++ b/link/include/ableton/platforms/linux/ThreadFactory.hpp
@@ -26,7 +26,7 @@
 {
 namespace platforms
 {
-namespace linux
+namespace linux_
 {
 
 struct ThreadFactory
@@ -40,6 +40,6 @@
   }
 };
 
-} // namespace linux
+} // namespace linux_
 } // namespace platforms
 } // namespace ableton
diff --git a/link/include/ableton/platforms/posix/ScanIpIfAddrs.hpp b/link/include/ableton/platforms/posix/ScanIpIfAddrs.hpp
--- a/link/include/ableton/platforms/posix/ScanIpIfAddrs.hpp
+++ b/link/include/ableton/platforms/posix/ScanIpIfAddrs.hpp
@@ -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
diff --git a/link/include/ableton/platforms/windows/ScanIpIfAddrs.hpp b/link/include/ableton/platforms/windows/ScanIpIfAddrs.hpp
--- a/link/include/ableton/platforms/windows/ScanIpIfAddrs.hpp
+++ b/link/include/ableton/platforms/windows/ScanIpIfAddrs.hpp
@@ -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;
   }
 };
diff --git a/link/include/ableton/test/serial_io/Context.hpp b/link/include/ableton/test/serial_io/Context.hpp
--- a/link/include/ableton/test/serial_io/Context.hpp
+++ b/link/include/ableton/test/serial_io/Context.hpp
@@ -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;
diff --git a/link/include/ableton/test/serial_io/Fixture.hpp b/link/include/ableton/test/serial_io/Fixture.hpp
--- a/link/include/ableton/test/serial_io/Fixture.hpp
+++ b/link/include/ableton/test/serial_io/Fixture.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio.hpp b/link/modules/asio-standalone/asio/include/asio.hpp
--- a/link/modules/asio-standalone/asio/include/asio.hpp
+++ b/link/modules/asio-standalone/asio/include/asio.hpp
@@ -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"
 
diff --git a/link/modules/asio-standalone/asio/include/asio/any_completion_executor.hpp b/link/modules/asio-standalone/asio/include/asio/any_completion_executor.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/any_completion_executor.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/any_completion_handler.hpp b/link/modules/asio-standalone/asio/include/asio/any_completion_handler.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/any_completion_handler.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/any_io_executor.hpp b/link/modules/asio-standalone/asio/include/asio/any_io_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/any_io_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/any_io_executor.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/append.hpp b/link/modules/asio-standalone/asio/include/asio/append.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/append.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/as_tuple.hpp b/link/modules/asio-standalone/asio/include/asio/as_tuple.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/as_tuple.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/associated_allocator.hpp b/link/modules/asio-standalone/asio/include/asio/associated_allocator.hpp
--- a/link/modules/asio-standalone/asio/include/asio/associated_allocator.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/associated_allocator.hpp
@@ -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
 
diff --git a/link/modules/asio-standalone/asio/include/asio/associated_cancellation_slot.hpp b/link/modules/asio-standalone/asio/include/asio/associated_cancellation_slot.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/associated_cancellation_slot.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/associated_executor.hpp b/link/modules/asio-standalone/asio/include/asio/associated_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/associated_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/associated_executor.hpp
@@ -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"
diff --git a/link/modules/asio-standalone/asio/include/asio/associated_immediate_executor.hpp b/link/modules/asio-standalone/asio/include/asio/associated_immediate_executor.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/associated_immediate_executor.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/associator.hpp b/link/modules/asio-standalone/asio/include/asio/associator.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/associator.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/async_result.hpp b/link/modules/asio-standalone/asio/include/asio/async_result.hpp
--- a/link/modules/asio-standalone/asio/include/asio/async_result.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/async_result.hpp
@@ -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 {
 
diff --git a/link/modules/asio-standalone/asio/include/asio/awaitable.hpp b/link/modules/asio-standalone/asio/include/asio/awaitable.hpp
--- a/link/modules/asio-standalone/asio/include/asio/awaitable.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/awaitable.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_datagram_socket.hpp b/link/modules/asio-standalone/asio/include/asio/basic_datagram_socket.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_datagram_socket.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_datagram_socket.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_deadline_timer.hpp b/link/modules/asio-standalone/asio/include/asio/basic_deadline_timer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_deadline_timer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_deadline_timer.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_file.hpp b/link/modules/asio-standalone/asio/include/asio/basic_file.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/basic_file.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_io_object.hpp b/link/modules/asio-standalone/asio/include/asio/basic_io_object.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_io_object.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_io_object.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_random_access_file.hpp b/link/modules/asio-standalone/asio/include/asio/basic_random_access_file.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/basic_random_access_file.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_raw_socket.hpp b/link/modules/asio-standalone/asio/include/asio/basic_raw_socket.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_raw_socket.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_raw_socket.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_readable_pipe.hpp b/link/modules/asio-standalone/asio/include/asio/basic_readable_pipe.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/basic_readable_pipe.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_seq_packet_socket.hpp b/link/modules/asio-standalone/asio/include/asio/basic_seq_packet_socket.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_seq_packet_socket.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_seq_packet_socket.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_serial_port.hpp b/link/modules/asio-standalone/asio/include/asio/basic_serial_port.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_serial_port.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_serial_port.hpp
@@ -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
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_signal_set.hpp b/link/modules/asio-standalone/asio/include/asio/basic_signal_set.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_signal_set.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_signal_set.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_socket.hpp b/link/modules/asio-standalone/asio/include/asio/basic_socket.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_socket.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_socket.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_socket_acceptor.hpp b/link/modules/asio-standalone/asio/include/asio/basic_socket_acceptor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_socket_acceptor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_socket_acceptor.hpp
@@ -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_;
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_socket_iostream.hpp b/link/modules/asio-standalone/asio/include/asio/basic_socket_iostream.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_socket_iostream.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_socket_iostream.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_socket_streambuf.hpp b/link/modules/asio-standalone/asio/include/asio/basic_socket_streambuf.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_socket_streambuf.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_socket_streambuf.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_stream_file.hpp b/link/modules/asio-standalone/asio/include/asio/basic_stream_file.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/basic_stream_file.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_stream_socket.hpp b/link/modules/asio-standalone/asio/include/asio/basic_stream_socket.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_stream_socket.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_stream_socket.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_streambuf.hpp b/link/modules/asio-standalone/asio/include/asio/basic_streambuf.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_streambuf.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_streambuf.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_streambuf_fwd.hpp b/link/modules/asio-standalone/asio/include/asio/basic_streambuf_fwd.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_streambuf_fwd.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_streambuf_fwd.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_waitable_timer.hpp b/link/modules/asio-standalone/asio/include/asio/basic_waitable_timer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/basic_waitable_timer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/basic_waitable_timer.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/basic_writable_pipe.hpp b/link/modules/asio-standalone/asio/include/asio/basic_writable_pipe.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/basic_writable_pipe.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/bind_allocator.hpp b/link/modules/asio-standalone/asio/include/asio/bind_allocator.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/bind_allocator.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/bind_cancellation_slot.hpp b/link/modules/asio-standalone/asio/include/asio/bind_cancellation_slot.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/bind_cancellation_slot.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/bind_executor.hpp b/link/modules/asio-standalone/asio/include/asio/bind_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/bind_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/bind_executor.hpp
@@ -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();
   }
diff --git a/link/modules/asio-standalone/asio/include/asio/bind_immediate_executor.hpp b/link/modules/asio-standalone/asio/include/asio/bind_immediate_executor.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/bind_immediate_executor.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/buffer.hpp b/link/modules/asio-standalone/asio/include/asio/buffer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/buffer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/buffer.hpp
@@ -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
 
diff --git a/link/modules/asio-standalone/asio/include/asio/buffer_registration.hpp b/link/modules/asio-standalone/asio/include/asio/buffer_registration.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/buffer_registration.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/buffered_read_stream.hpp b/link/modules/asio-standalone/asio/include/asio/buffered_read_stream.hpp
--- a/link/modules/asio-standalone/asio/include/asio/buffered_read_stream.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/buffered_read_stream.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/buffered_read_stream_fwd.hpp b/link/modules/asio-standalone/asio/include/asio/buffered_read_stream_fwd.hpp
--- a/link/modules/asio-standalone/asio/include/asio/buffered_read_stream_fwd.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/buffered_read_stream_fwd.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/buffered_stream.hpp b/link/modules/asio-standalone/asio/include/asio/buffered_stream.hpp
--- a/link/modules/asio-standalone/asio/include/asio/buffered_stream.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/buffered_stream.hpp
@@ -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));
diff --git a/link/modules/asio-standalone/asio/include/asio/buffered_stream_fwd.hpp b/link/modules/asio-standalone/asio/include/asio/buffered_stream_fwd.hpp
--- a/link/modules/asio-standalone/asio/include/asio/buffered_stream_fwd.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/buffered_stream_fwd.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/buffered_write_stream.hpp b/link/modules/asio-standalone/asio/include/asio/buffered_write_stream.hpp
--- a/link/modules/asio-standalone/asio/include/asio/buffered_write_stream.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/buffered_write_stream.hpp
@@ -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));
diff --git a/link/modules/asio-standalone/asio/include/asio/buffered_write_stream_fwd.hpp b/link/modules/asio-standalone/asio/include/asio/buffered_write_stream_fwd.hpp
--- a/link/modules/asio-standalone/asio/include/asio/buffered_write_stream_fwd.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/buffered_write_stream_fwd.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/buffers_iterator.hpp b/link/modules/asio-standalone/asio/include/asio/buffers_iterator.hpp
--- a/link/modules/asio-standalone/asio/include/asio/buffers_iterator.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/buffers_iterator.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/cancellation_signal.hpp b/link/modules/asio-standalone/asio/include/asio/cancellation_signal.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/cancellation_signal.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/cancellation_state.hpp b/link/modules/asio-standalone/asio/include/asio/cancellation_state.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/cancellation_state.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/cancellation_type.hpp b/link/modules/asio-standalone/asio/include/asio/cancellation_type.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/cancellation_type.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/co_spawn.hpp b/link/modules/asio-standalone/asio/include/asio/co_spawn.hpp
--- a/link/modules/asio-standalone/asio/include/asio/co_spawn.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/co_spawn.hpp
@@ -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
 
diff --git a/link/modules/asio-standalone/asio/include/asio/completion_condition.hpp b/link/modules/asio-standalone/asio/include/asio/completion_condition.hpp
--- a/link/modules/asio-standalone/asio/include/asio/completion_condition.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/completion_condition.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/compose.hpp b/link/modules/asio-standalone/asio/include/asio/compose.hpp
--- a/link/modules/asio-standalone/asio/include/asio/compose.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/compose.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/connect.hpp b/link/modules/asio-standalone/asio/include/asio/connect.hpp
--- a/link/modules/asio-standalone/asio/include/asio/connect.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/connect.hpp
@@ -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)));
 
 /*@}*/
 
diff --git a/link/modules/asio-standalone/asio/include/asio/connect_pipe.hpp b/link/modules/asio-standalone/asio/include/asio/connect_pipe.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/connect_pipe.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/consign.hpp b/link/modules/asio-standalone/asio/include/asio/consign.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/consign.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/coroutine.hpp b/link/modules/asio-standalone/asio/include/asio/coroutine.hpp
--- a/link/modules/asio-standalone/asio/include/asio/coroutine.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/coroutine.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/deadline_timer.hpp b/link/modules/asio-standalone/asio/include/asio/deadline_timer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/deadline_timer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/deadline_timer.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/defer.hpp b/link/modules/asio-standalone/asio/include/asio/defer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/defer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/defer.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/deferred.hpp b/link/modules/asio-standalone/asio/include/asio/deferred.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/deferred.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detached.hpp b/link/modules/asio-standalone/asio/include/asio/detached.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detached.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detached.hpp
@@ -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.
  */
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/array.hpp b/link/modules/asio-standalone/asio/include/asio/detail/array.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/array.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/array.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/array_fwd.hpp b/link/modules/asio-standalone/asio/include/asio/detail/array_fwd.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/array_fwd.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/array_fwd.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/assert.hpp b/link/modules/asio-standalone/asio/include/asio/detail/assert.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/assert.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/assert.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/atomic_count.hpp b/link/modules/asio-standalone/asio/include/asio/detail/atomic_count.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/atomic_count.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/atomic_count.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/base_from_cancellation_state.hpp b/link/modules/asio-standalone/asio/include/asio/detail/base_from_cancellation_state.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/base_from_cancellation_state.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/base_from_completion_cond.hpp b/link/modules/asio-standalone/asio/include/asio/detail/base_from_completion_cond.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/base_from_completion_cond.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/base_from_completion_cond.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/bind_handler.hpp b/link/modules/asio-standalone/asio/include/asio/detail/bind_handler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/bind_handler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/bind_handler.hpp
@@ -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);
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/blocking_executor_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/blocking_executor_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/blocking_executor_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/blocking_executor_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/buffer_resize_guard.hpp b/link/modules/asio-standalone/asio/include/asio/detail/buffer_resize_guard.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/buffer_resize_guard.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/buffer_resize_guard.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/buffer_sequence_adapter.hpp b/link/modules/asio-standalone/asio/include/asio/detail/buffer_sequence_adapter.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/buffer_sequence_adapter.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/buffer_sequence_adapter.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/buffered_stream_storage.hpp b/link/modules/asio-standalone/asio/include/asio/detail/buffered_stream_storage.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/buffered_stream_storage.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/buffered_stream_storage.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/bulk_executor_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/bulk_executor_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/bulk_executor_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/bulk_executor_op.hpp
@@ -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 };
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/call_stack.hpp b/link/modules/asio-standalone/asio/include/asio/detail/call_stack.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/call_stack.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/call_stack.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/chrono.hpp b/link/modules/asio-standalone/asio/include/asio/detail/chrono.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/chrono.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/chrono.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/chrono_time_traits.hpp b/link/modules/asio-standalone/asio/include/asio/detail/chrono_time_traits.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/chrono_time_traits.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/chrono_time_traits.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/completion_handler.hpp b/link/modules/asio-standalone/asio/include/asio/detail/completion_handler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/completion_handler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/completion_handler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/composed_work.hpp b/link/modules/asio-standalone/asio/include/asio/detail/composed_work.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/composed_work.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/concurrency_hint.hpp b/link/modules/asio-standalone/asio/include/asio/detail/concurrency_hint.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/concurrency_hint.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/concurrency_hint.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_event.hpp b/link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_event.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_event.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_event.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/conditionally_enabled_mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/config.hpp b/link/modules/asio-standalone/asio/include/asio/detail/config.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/config.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/config.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/consuming_buffers.hpp b/link/modules/asio-standalone/asio/include/asio/detail/consuming_buffers.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/consuming_buffers.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/consuming_buffers.hpp
@@ -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>,
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/cstddef.hpp b/link/modules/asio-standalone/asio/include/asio/detail/cstddef.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/cstddef.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/cstddef.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/cstdint.hpp b/link/modules/asio-standalone/asio/include/asio/detail/cstdint.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/cstdint.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/cstdint.hpp
@@ -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)
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/date_time_fwd.hpp b/link/modules/asio-standalone/asio/include/asio/detail/date_time_fwd.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/date_time_fwd.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/date_time_fwd.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/deadline_timer_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/deadline_timer_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/deadline_timer_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/deadline_timer_service.hpp
@@ -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_;
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/dependent_type.hpp b/link/modules/asio-standalone/asio/include/asio/detail/dependent_type.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/dependent_type.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/dependent_type.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/descriptor_ops.hpp b/link/modules/asio-standalone/asio/include/asio/detail/descriptor_ops.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/descriptor_ops.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/descriptor_ops.hpp
@@ -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);
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/descriptor_read_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/descriptor_read_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/descriptor_read_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/descriptor_read_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/descriptor_write_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/descriptor_write_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/descriptor_write_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/descriptor_write_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/dev_poll_reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/dev_poll_reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/dev_poll_reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/dev_poll_reactor.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/epoll_reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/epoll_reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/epoll_reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/epoll_reactor.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/event.hpp b/link/modules/asio-standalone/asio/include/asio/detail/event.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/event.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/event.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/eventfd_select_interrupter.hpp b/link/modules/asio-standalone/asio/include/asio/detail/eventfd_select_interrupter.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/eventfd_select_interrupter.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/eventfd_select_interrupter.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/exception.hpp b/link/modules/asio-standalone/asio/include/asio/detail/exception.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/exception.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/executor_function.hpp b/link/modules/asio-standalone/asio/include/asio/detail/executor_function.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/executor_function.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/executor_function.hpp
@@ -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);
     }
   }
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/executor_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/executor_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/executor_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/executor_op.hpp
@@ -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 };
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/fd_set_adapter.hpp b/link/modules/asio-standalone/asio/include/asio/detail/fd_set_adapter.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/fd_set_adapter.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/fd_set_adapter.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/fenced_block.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/functional.hpp b/link/modules/asio-standalone/asio/include/asio/detail/functional.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/functional.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/functional.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/future.hpp b/link/modules/asio-standalone/asio/include/asio/detail/future.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/future.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/future.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/gcc_arm_fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/gcc_arm_fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/gcc_arm_fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/gcc_arm_fenced_block.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/gcc_hppa_fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/gcc_hppa_fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/gcc_hppa_fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/gcc_hppa_fenced_block.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/gcc_sync_fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/gcc_sync_fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/gcc_sync_fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/gcc_sync_fenced_block.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/gcc_x86_fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/gcc_x86_fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/gcc_x86_fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/gcc_x86_fenced_block.hpp
@@ -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");
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/global.hpp b/link/modules/asio-standalone/asio/include/asio/detail/global.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/global.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/global.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/handler_alloc_helpers.hpp b/link/modules/asio-standalone/asio/include/asio/detail/handler_alloc_helpers.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/handler_alloc_helpers.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/handler_alloc_helpers.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/handler_cont_helpers.hpp b/link/modules/asio-standalone/asio/include/asio/detail/handler_cont_helpers.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/handler_cont_helpers.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/handler_cont_helpers.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/handler_invoke_helpers.hpp b/link/modules/asio-standalone/asio/include/asio/detail/handler_invoke_helpers.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/handler_invoke_helpers.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/handler_invoke_helpers.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/handler_tracking.hpp b/link/modules/asio-standalone/asio/include/asio/detail/handler_tracking.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/handler_tracking.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/handler_tracking.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/handler_type_requirements.hpp b/link/modules/asio-standalone/asio/include/asio/detail/handler_type_requirements.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/handler_type_requirements.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/handler_type_requirements.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/handler_work.hpp b/link/modules/asio-standalone/asio/include/asio/detail/handler_work.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/handler_work.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/handler_work.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/hash_map.hpp b/link/modules/asio-standalone/asio/include/asio/detail/hash_map.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/hash_map.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/hash_map.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/buffer_sequence_adapter.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/descriptor_ops.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/descriptor_ops.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/descriptor_ops.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/descriptor_ops.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/dev_poll_reactor.ipp
@@ -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,
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/epoll_reactor.ipp
@@ -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();
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/eventfd_select_interrupter.ipp
@@ -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;
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/handler_tracking.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/handler_tracking.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/handler_tracking.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/handler_tracking.ipp
@@ -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);
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_descriptor_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_descriptor_service.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_descriptor_service.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_file_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_file_service.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_file_service.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_service.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_socket_service_base.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_socket_service_base.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/io_uring_socket_service_base.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/kqueue_reactor.ipp
@@ -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();
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/null_event.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/null_event.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/null_event.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/null_event.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/pipe_select_interrupter.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/pipe_select_interrupter.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/pipe_select_interrupter.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/pipe_select_interrupter.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_event.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_event.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_event.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_event.ipp
@@ -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))
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_mutex.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_mutex.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_mutex.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_mutex.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_serial_port_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_serial_port_service.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_serial_port_service.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_thread.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_thread.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_thread.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_thread.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_tss_ptr.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_tss_ptr.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_tss_ptr.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/posix_tss_ptr.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_descriptor_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_descriptor_service.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_descriptor_service.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_descriptor_service.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_serial_port_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_serial_port_service.ipp
deleted file mode 100644
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_serial_port_service.ipp
+++ /dev/null
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_socket_service_base.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_socket_service_base.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_socket_service_base.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/reactive_socket_service_base.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/resolver_service_base.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/resolver_service_base.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/resolver_service_base.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/resolver_service_base.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/scheduler.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/scheduler.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/scheduler.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/scheduler.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/select_reactor.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/service_registry.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/signal_set_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/signal_set_service.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/signal_set_service.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/signal_set_service.ipp
@@ -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__)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/socket_ops.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/socket_ops.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/socket_ops.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/socket_ops.ipp
@@ -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)
 {
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/socket_select_interrupter.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/socket_select_interrupter.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/socket_select_interrupter.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/socket_select_interrupter.ipp
@@ -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");
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.hpp
@@ -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));
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_executor_service.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/strand_service.ipp
@@ -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,
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/thread_context.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/thread_context.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/thread_context.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/throw_error.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/throw_error.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/throw_error.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/throw_error.ipp
@@ -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
 }
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_ptime.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_ptime.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_ptime.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_ptime.ipp
@@ -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(
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_set.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_set.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_set.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/timer_queue_set.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_event.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_event.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_event.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_event.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_file_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_file_service.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_file_service.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_handle_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_handle_service.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_handle_service.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_handle_service.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_io_context.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_serial_port_service.ipp
@@ -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;
   }
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_iocp_socket_service_base.ipp
@@ -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(
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_mutex.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_mutex.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_mutex.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_mutex.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_object_handle_service.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_object_handle_service.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_object_handle_service.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_object_handle_service.ipp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_static_mutex.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_static_mutex.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_static_mutex.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_static_mutex.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_thread.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_thread.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_thread.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_thread.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_tss_ptr.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_tss_ptr.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/win_tss_ptr.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/win_tss_ptr.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_ssocket_service_base.ipp
@@ -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),
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp b/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/winrt_timer_scheduler.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/impl/winsock_init.ipp b/link/modules/asio-standalone/asio/include/asio/detail/impl/winsock_init.ipp
--- a/link/modules/asio-standalone/asio/include/asio/detail/impl/winsock_init.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/impl/winsock_init.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/initiate_defer.hpp b/link/modules/asio-standalone/asio/include/asio/detail/initiate_defer.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/initiate_defer.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/initiate_dispatch.hpp b/link/modules/asio-standalone/asio/include/asio/detail/initiate_dispatch.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/initiate_dispatch.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/initiate_post.hpp b/link/modules/asio-standalone/asio/include/asio/detail/initiate_post.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/initiate_post.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_control.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_control.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/io_control.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_control.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_object_impl.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_object_impl.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/io_object_impl.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_object_impl.hpp
@@ -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;
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_at_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_at_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_at_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_read_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_service.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_at_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_at_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_at_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_descriptor_write_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_file_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_file_service.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_file_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_null_buffers_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_null_buffers_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_null_buffers_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_operation.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_operation.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_operation.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_service.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_accept_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_accept_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_accept_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_connect_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_connect_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_connect_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recv_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recv_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recv_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvfrom_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvfrom_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvfrom_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvmsg_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvmsg_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_recvmsg_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_send_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_send_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_send_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_sendto_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_sendto_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_sendto_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service_base.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service_base.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_socket_service_base.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/io_uring_wait_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_wait_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/io_uring_wait_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/is_buffer_sequence.hpp b/link/modules/asio-standalone/asio/include/asio/detail/is_buffer_sequence.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/is_buffer_sequence.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/is_buffer_sequence.hpp
@@ -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
 {
 };
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/is_executor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/is_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/is_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/is_executor.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/keyword_tss_ptr.hpp b/link/modules/asio-standalone/asio/include/asio/detail/keyword_tss_ptr.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/keyword_tss_ptr.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/keyword_tss_ptr.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/kqueue_reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/kqueue_reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/kqueue_reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/kqueue_reactor.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/local_free_on_block_exit.hpp b/link/modules/asio-standalone/asio/include/asio/detail/local_free_on_block_exit.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/local_free_on_block_exit.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/local_free_on_block_exit.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/macos_fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/macos_fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/macos_fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/macos_fenced_block.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/memory.hpp b/link/modules/asio-standalone/asio/include/asio/detail/memory.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/memory.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/memory.hpp
@@ -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
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/non_const_lvalue.hpp b/link/modules/asio-standalone/asio/include/asio/detail/non_const_lvalue.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/non_const_lvalue.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/non_const_lvalue.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/noncopyable.hpp b/link/modules/asio-standalone/asio/include/asio/detail/noncopyable.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/noncopyable.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/noncopyable.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_event.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_event.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_event.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_event.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_fenced_block.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_global.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_global.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_global.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_global.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_mutex.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_reactor.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_signal_blocker.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_signal_blocker.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_signal_blocker.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_signal_blocker.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_socket_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_socket_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_socket_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_socket_service.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_static_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_static_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_static_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_static_mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_thread.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_thread.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_thread.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_thread.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/null_tss_ptr.hpp b/link/modules/asio-standalone/asio/include/asio/detail/null_tss_ptr.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/null_tss_ptr.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/null_tss_ptr.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/object_pool.hpp b/link/modules/asio-standalone/asio/include/asio/detail/object_pool.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/object_pool.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/object_pool.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/old_win_sdk_compat.hpp b/link/modules/asio-standalone/asio/include/asio/detail/old_win_sdk_compat.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/old_win_sdk_compat.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/old_win_sdk_compat.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/op_queue.hpp b/link/modules/asio-standalone/asio/include/asio/detail/op_queue.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/op_queue.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/op_queue.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/operation.hpp b/link/modules/asio-standalone/asio/include/asio/detail/operation.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/operation.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/operation.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/pipe_select_interrupter.hpp b/link/modules/asio-standalone/asio/include/asio/detail/pipe_select_interrupter.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/pipe_select_interrupter.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/pipe_select_interrupter.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/pop_options.hpp b/link/modules/asio-standalone/asio/include/asio/detail/pop_options.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/pop_options.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/pop_options.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/posix_event.hpp b/link/modules/asio-standalone/asio/include/asio/detail/posix_event.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/posix_event.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/posix_event.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/posix_fd_set_adapter.hpp b/link/modules/asio-standalone/asio/include/asio/detail/posix_fd_set_adapter.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/posix_fd_set_adapter.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/posix_fd_set_adapter.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/posix_global.hpp b/link/modules/asio-standalone/asio/include/asio/detail/posix_global.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/posix_global.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/posix_global.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/posix_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/posix_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/posix_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/posix_mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/posix_serial_port_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/posix_serial_port_service.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/posix_serial_port_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/posix_signal_blocker.hpp b/link/modules/asio-standalone/asio/include/asio/detail/posix_signal_blocker.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/posix_signal_blocker.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/posix_signal_blocker.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/posix_static_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/posix_static_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/posix_static_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/posix_static_mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/posix_thread.hpp b/link/modules/asio-standalone/asio/include/asio/detail/posix_thread.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/posix_thread.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/posix_thread.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/posix_tss_ptr.hpp b/link/modules/asio-standalone/asio/include/asio/detail/posix_tss_ptr.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/posix_tss_ptr.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/posix_tss_ptr.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/push_options.hpp b/link/modules/asio-standalone/asio/include/asio/detail/push_options.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/push_options.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/push_options.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_descriptor_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_descriptor_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_descriptor_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_descriptor_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_null_buffers_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_null_buffers_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_null_buffers_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_null_buffers_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_serial_port_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_serial_port_service.hpp
deleted file mode 100644
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_serial_port_service.hpp
+++ /dev/null
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_accept_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_accept_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_accept_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_accept_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_connect_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_connect_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_connect_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_connect_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recv_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recv_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recv_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recv_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvfrom_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_recvmsg_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_send_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_send_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_send_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_send_op.hpp
@@ -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_;
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_sendto_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_sendto_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_sendto_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_sendto_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service_base.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_socket_service_base.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactive_wait_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactive_wait_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactive_wait_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactive_wait_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactor.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactor_fwd.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactor_fwd.hpp
deleted file mode 100644
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactor_fwd.hpp
+++ /dev/null
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactor_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactor_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactor_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactor_op.hpp
@@ -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)
   {
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/reactor_op_queue.hpp b/link/modules/asio-standalone/asio/include/asio/detail/reactor_op_queue.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/reactor_op_queue.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/reactor_op_queue.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/recycling_allocator.hpp b/link/modules/asio-standalone/asio/include/asio/detail/recycling_allocator.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/recycling_allocator.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/recycling_allocator.hpp
@@ -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);
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/regex_fwd.hpp b/link/modules/asio-standalone/asio/include/asio/detail/regex_fwd.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/regex_fwd.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/regex_fwd.hpp
@@ -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 {
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/resolve_endpoint_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/resolve_endpoint_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/resolve_endpoint_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/resolve_endpoint_op.hpp
@@ -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_);
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/resolve_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/resolve_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/resolve_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/resolve_op.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/resolve_query_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/resolve_query_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/resolve_query_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/resolve_query_op.hpp
@@ -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 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/resolver_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/resolver_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/resolver_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/resolver_service.hpp
@@ -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);
   }
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/resolver_service_base.hpp b/link/modules/asio-standalone/asio/include/asio/detail/resolver_service_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/resolver_service_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/resolver_service_base.hpp
@@ -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);
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/scheduler.hpp b/link/modules/asio-standalone/asio/include/asio/detail/scheduler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/scheduler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/scheduler.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/scheduler_operation.hpp b/link/modules/asio-standalone/asio/include/asio/detail/scheduler_operation.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/scheduler_operation.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/scheduler_operation.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/scheduler_task.hpp b/link/modules/asio-standalone/asio/include/asio/detail/scheduler_task.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/scheduler_task.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/scheduler_thread_info.hpp b/link/modules/asio-standalone/asio/include/asio/detail/scheduler_thread_info.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/scheduler_thread_info.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/scheduler_thread_info.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/scoped_lock.hpp b/link/modules/asio-standalone/asio/include/asio/detail/scoped_lock.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/scoped_lock.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/scoped_lock.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/scoped_ptr.hpp b/link/modules/asio-standalone/asio/include/asio/detail/scoped_ptr.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/scoped_ptr.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/scoped_ptr.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/select_interrupter.hpp b/link/modules/asio-standalone/asio/include/asio/detail/select_interrupter.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/select_interrupter.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/select_interrupter.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/select_reactor.hpp b/link/modules/asio-standalone/asio/include/asio/detail/select_reactor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/select_reactor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/select_reactor.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/service_registry.hpp b/link/modules/asio-standalone/asio/include/asio/detail/service_registry.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/service_registry.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/service_registry.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/signal_blocker.hpp b/link/modules/asio-standalone/asio/include/asio/detail/signal_blocker.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/signal_blocker.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/signal_blocker.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/signal_handler.hpp b/link/modules/asio-standalone/asio/include/asio/detail/signal_handler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/signal_handler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/signal_handler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/signal_init.hpp b/link/modules/asio-standalone/asio/include/asio/detail/signal_init.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/signal_init.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/signal_init.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/signal_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/signal_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/signal_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/signal_op.hpp
@@ -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)
   {
   }
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/signal_set_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/signal_set_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/signal_set_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/signal_set_service.hpp
@@ -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__)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/socket_holder.hpp b/link/modules/asio-standalone/asio/include/asio/detail/socket_holder.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/socket_holder.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/socket_holder.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/socket_ops.hpp b/link/modules/asio-standalone/asio/include/asio/detail/socket_ops.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/socket_ops.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/socket_ops.hpp
@@ -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);
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/socket_option.hpp b/link/modules/asio-standalone/asio/include/asio/detail/socket_option.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/socket_option.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/socket_option.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/socket_select_interrupter.hpp b/link/modules/asio-standalone/asio/include/asio/detail/socket_select_interrupter.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/socket_select_interrupter.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/socket_select_interrupter.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/socket_types.hpp b/link/modules/asio-standalone/asio/include/asio/detail/socket_types.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/socket_types.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/socket_types.hpp
@@ -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;
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/solaris_fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/solaris_fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/solaris_fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/solaris_fenced_block.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/source_location.hpp b/link/modules/asio-standalone/asio/include/asio/detail/source_location.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/source_location.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/source_location.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/static_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/static_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/static_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/static_mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/std_event.hpp b/link/modules/asio-standalone/asio/include/asio/detail/std_event.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/std_event.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/std_event.hpp
@@ -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;
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/std_fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/std_fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/std_fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/std_fenced_block.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/std_global.hpp b/link/modules/asio-standalone/asio/include/asio/detail/std_global.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/std_global.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/std_global.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/std_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/std_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/std_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/std_mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/std_static_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/std_static_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/std_static_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/std_static_mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/std_thread.hpp b/link/modules/asio-standalone/asio/include/asio/detail/std_thread.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/std_thread.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/std_thread.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/strand_executor_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/strand_executor_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/strand_executor_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/strand_executor_service.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/strand_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/strand_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/strand_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/strand_service.hpp
@@ -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);
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/string_view.hpp b/link/modules/asio-standalone/asio/include/asio/detail/string_view.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/string_view.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/string_view.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/thread.hpp b/link/modules/asio-standalone/asio/include/asio/detail/thread.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/thread.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/thread.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/thread_context.hpp b/link/modules/asio-standalone/asio/include/asio/detail/thread_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/thread_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/thread_context.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/thread_group.hpp b/link/modules/asio-standalone/asio/include/asio/detail/thread_group.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/thread_group.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/thread_group.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/thread_info_base.hpp b/link/modules/asio-standalone/asio/include/asio/detail/thread_info_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/thread_info_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/thread_info_base.hpp
@@ -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) \
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/throw_error.hpp b/link/modules/asio-standalone/asio/include/asio/detail/throw_error.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/throw_error.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/throw_error.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/throw_exception.hpp b/link/modules/asio-standalone/asio/include/asio/detail/throw_exception.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/throw_exception.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/throw_exception.hpp
@@ -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;
 }
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/timer_queue.hpp b/link/modules/asio-standalone/asio/include/asio/detail/timer_queue.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/timer_queue.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/timer_queue.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_base.hpp b/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_base.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_ptime.hpp b/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_ptime.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_ptime.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_ptime.hpp
@@ -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,
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_set.hpp b/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_set.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_set.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/timer_queue_set.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler.hpp b/link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler_fwd.hpp b/link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler_fwd.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler_fwd.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/timer_scheduler_fwd.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/tss_ptr.hpp b/link/modules/asio-standalone/asio/include/asio/detail/tss_ptr.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/tss_ptr.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/tss_ptr.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/type_traits.hpp b/link/modules/asio-standalone/asio/include/asio/detail/type_traits.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/type_traits.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/type_traits.hpp
@@ -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
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/utility.hpp b/link/modules/asio-standalone/asio/include/asio/detail/utility.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/utility.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/variadic_templates.hpp b/link/modules/asio-standalone/asio/include/asio/detail/variadic_templates.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/variadic_templates.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/variadic_templates.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/wait_handler.hpp b/link/modules/asio-standalone/asio/include/asio/detail/wait_handler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/wait_handler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/wait_handler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/wait_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/wait_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/wait_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/wait_op.hpp
@@ -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)
   {
   }
 };
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_event.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_event.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_event.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_event.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_fd_set_adapter.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_fd_set_adapter.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_fd_set_adapter.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_fd_set_adapter.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_fenced_block.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_fenced_block.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_fenced_block.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_fenced_block.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_global.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_global.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_global.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_global.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_file_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_file_service.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_file_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_read_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_read_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_read_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_read_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_service.hpp
@@ -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_;
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_write_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_write_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_write_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_handle_write_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_io_context.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_io_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_io_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_io_context.hpp
@@ -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,
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_null_buffers_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_null_buffers_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_null_buffers_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_null_buffers_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_operation.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_operation.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_operation.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_operation.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_overlapped_ptr.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_serial_port_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_serial_port_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_serial_port_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_serial_port_service.hpp
@@ -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;
   }
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_accept_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_accept_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_accept_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_accept_op.hpp
@@ -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_;
 };
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_connect_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_connect_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_connect_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_connect_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recv_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recv_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recv_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recv_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvfrom_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_recvmsg_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_send_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_send_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_send_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_send_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service.hpp
@@ -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);
+    }
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service_base.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_socket_service_base.hpp
@@ -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_;
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_thread_info.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_thread_info.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_thread_info.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_thread_info.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_wait_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_wait_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_wait_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_iocp_wait_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_object_handle_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_object_handle_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_object_handle_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_object_handle_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_static_mutex.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_static_mutex.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_static_mutex.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_static_mutex.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_thread.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_thread.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_thread.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_thread.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/win_tss_ptr.hpp b/link/modules/asio-standalone/asio/include/asio/detail/win_tss_ptr.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/win_tss_ptr.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/win_tss_ptr.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winapp_thread.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winapp_thread.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winapp_thread.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winapp_thread.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/wince_thread.hpp b/link/modules/asio-standalone/asio/include/asio/detail/wince_thread.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/wince_thread.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/wince_thread.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_async_manager.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_async_manager.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_async_manager.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_async_manager.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_async_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_async_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_async_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_async_op.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_resolve_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_resolve_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_resolve_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_resolve_op.hpp
@@ -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 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_resolver_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_resolver_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_resolver_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_resolver_service.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_connect_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_connect_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_connect_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_connect_op.hpp
@@ -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 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_recv_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_recv_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_recv_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_recv_op.hpp
@@ -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 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_send_op.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_send_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_send_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_socket_send_op.hpp
@@ -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 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service_base.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_ssocket_service_base.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_timer_scheduler.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_timer_scheduler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_timer_scheduler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_timer_scheduler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winrt_utils.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winrt_utils.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winrt_utils.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winrt_utils.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/winsock_init.hpp b/link/modules/asio-standalone/asio/include/asio/detail/winsock_init.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/winsock_init.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/winsock_init.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/work_dispatcher.hpp b/link/modules/asio-standalone/asio/include/asio/detail/work_dispatcher.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/work_dispatcher.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/work_dispatcher.hpp
@@ -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();
   }
 
diff --git a/link/modules/asio-standalone/asio/include/asio/detail/wrapped_handler.hpp b/link/modules/asio-standalone/asio/include/asio/detail/wrapped_handler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/detail/wrapped_handler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/detail/wrapped_handler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/dispatch.hpp b/link/modules/asio-standalone/asio/include/asio/dispatch.hpp
--- a/link/modules/asio-standalone/asio/include/asio/dispatch.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/dispatch.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/error.hpp b/link/modules/asio-standalone/asio/include/asio/error.hpp
--- a/link/modules/asio-standalone/asio/include/asio/error.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/error.hpp
@@ -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()
 {
diff --git a/link/modules/asio-standalone/asio/include/asio/error_code.hpp b/link/modules/asio-standalone/asio/include/asio/error_code.hpp
--- a/link/modules/asio-standalone/asio/include/asio/error_code.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/error_code.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution.hpp b/link/modules/asio-standalone/asio/include/asio/execution.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/allocator.hpp b/link/modules/asio-standalone/asio/include/asio/execution/allocator.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/allocator.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/allocator.hpp
@@ -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();
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/any_executor.hpp b/link/modules/asio-standalone/asio/include/asio/execution/any_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/any_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/any_executor.hpp
@@ -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, \
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/bad_executor.hpp b/link/modules/asio-standalone/asio/include/asio/execution/bad_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/bad_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/bad_executor.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/blocking.hpp b/link/modules/asio-standalone/asio/include/asio/execution/blocking.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/blocking.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/blocking.hpp
@@ -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();
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/blocking_adaptation.hpp b/link/modules/asio-standalone/asio/include/asio/execution/blocking_adaptation.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/blocking_adaptation.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/blocking_adaptation.hpp
@@ -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();
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/bulk_execute.hpp b/link/modules/asio-standalone/asio/include/asio/execution/bulk_execute.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/bulk_execute.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/bulk_execute.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/bulk_guarantee.hpp b/link/modules/asio-standalone/asio/include/asio/execution/bulk_guarantee.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/bulk_guarantee.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/bulk_guarantee.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/connect.hpp b/link/modules/asio-standalone/asio/include/asio/execution/connect.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/connect.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/connect.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/context.hpp b/link/modules/asio-standalone/asio/include/asio/execution/context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/context.hpp
@@ -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();
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/context_as.hpp b/link/modules/asio-standalone/asio/include/asio/execution/context_as.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/context_as.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/context_as.hpp
@@ -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)
+    >
 {
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/detail/as_invocable.hpp b/link/modules/asio-standalone/asio/include/asio/execution/detail/as_invocable.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/detail/as_invocable.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/detail/as_invocable.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/detail/as_operation.hpp b/link/modules/asio-standalone/asio/include/asio/execution/detail/as_operation.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/detail/as_operation.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/detail/as_operation.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/detail/as_receiver.hpp b/link/modules/asio-standalone/asio/include/asio/execution/detail/as_receiver.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/detail/as_receiver.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/detail/as_receiver.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/detail/bulk_sender.hpp b/link/modules/asio-standalone/asio/include/asio/execution/detail/bulk_sender.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/detail/bulk_sender.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/detail/bulk_sender.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/detail/submit_receiver.hpp b/link/modules/asio-standalone/asio/include/asio/execution/detail/submit_receiver.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/detail/submit_receiver.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/detail/submit_receiver.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/detail/void_receiver.hpp b/link/modules/asio-standalone/asio/include/asio/execution/detail/void_receiver.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/detail/void_receiver.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/detail/void_receiver.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/execute.hpp b/link/modules/asio-standalone/asio/include/asio/execution/execute.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/execute.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/execute.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/executor.hpp b/link/modules/asio-standalone/asio/include/asio/execution/executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/executor.hpp
@@ -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
 {
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/impl/bad_executor.ipp b/link/modules/asio-standalone/asio/include/asio/execution/impl/bad_executor.ipp
--- a/link/modules/asio-standalone/asio/include/asio/execution/impl/bad_executor.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/impl/bad_executor.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/impl/receiver_invocation_error.ipp b/link/modules/asio-standalone/asio/include/asio/execution/impl/receiver_invocation_error.ipp
--- a/link/modules/asio-standalone/asio/include/asio/execution/impl/receiver_invocation_error.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/impl/receiver_invocation_error.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/invocable_archetype.hpp b/link/modules/asio-standalone/asio/include/asio/execution/invocable_archetype.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/invocable_archetype.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/invocable_archetype.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/mapping.hpp b/link/modules/asio-standalone/asio/include/asio/execution/mapping.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/mapping.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/mapping.hpp
@@ -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();
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/occupancy.hpp b/link/modules/asio-standalone/asio/include/asio/execution/occupancy.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/occupancy.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/occupancy.hpp
@@ -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();
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/operation_state.hpp b/link/modules/asio-standalone/asio/include/asio/execution/operation_state.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/operation_state.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/operation_state.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/outstanding_work.hpp b/link/modules/asio-standalone/asio/include/asio/execution/outstanding_work.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/outstanding_work.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/outstanding_work.hpp
@@ -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();
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/prefer_only.hpp b/link/modules/asio-standalone/asio/include/asio/execution/prefer_only.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/prefer_only.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/prefer_only.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/receiver.hpp b/link/modules/asio-standalone/asio/include/asio/execution/receiver.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/receiver.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/receiver.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/receiver_invocation_error.hpp b/link/modules/asio-standalone/asio/include/asio/execution/receiver_invocation_error.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/receiver_invocation_error.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/receiver_invocation_error.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/relationship.hpp b/link/modules/asio-standalone/asio/include/asio/execution/relationship.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/relationship.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/relationship.hpp
@@ -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();
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/schedule.hpp b/link/modules/asio-standalone/asio/include/asio/execution/schedule.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/schedule.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/schedule.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/scheduler.hpp b/link/modules/asio-standalone/asio/include/asio/execution/scheduler.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/scheduler.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/scheduler.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/sender.hpp b/link/modules/asio-standalone/asio/include/asio/execution/sender.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/sender.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/sender.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/set_done.hpp b/link/modules/asio-standalone/asio/include/asio/execution/set_done.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/set_done.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/set_done.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/set_error.hpp b/link/modules/asio-standalone/asio/include/asio/execution/set_error.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/set_error.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/set_error.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/set_value.hpp b/link/modules/asio-standalone/asio/include/asio/execution/set_value.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/set_value.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/set_value.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/start.hpp b/link/modules/asio-standalone/asio/include/asio/execution/start.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/start.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/start.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution/submit.hpp b/link/modules/asio-standalone/asio/include/asio/execution/submit.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution/submit.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution/submit.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/execution_context.hpp b/link/modules/asio-standalone/asio/include/asio/execution_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/execution_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/execution_context.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/executor.hpp b/link/modules/asio-standalone/asio/include/asio/executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/executor.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/executor_work_guard.hpp b/link/modules/asio-standalone/asio/include/asio/executor_work_guard.hpp
--- a/link/modules/asio-standalone/asio/include/asio/executor_work_guard.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/executor_work_guard.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/append.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/append.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/append.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/as_single.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/as_single.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/as_single.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/as_tuple.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/as_tuple.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/as_tuple.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/awaitable_operators.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/awaitable_operators.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/awaitable_operators.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/basic_channel.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/basic_channel.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/basic_channel.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/basic_concurrent_channel.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/basic_concurrent_channel.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/basic_concurrent_channel.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/cancellation_condition.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/cancellation_condition.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/cancellation_condition.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/channel.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/channel.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/channel.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/channel_error.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/channel_error.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/channel_error.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/channel_traits.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/channel_traits.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/channel_traits.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/co_composed.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/co_composed.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/co_composed.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/co_spawn.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/co_spawn.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/co_spawn.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/concurrent_channel.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/concurrent_channel.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/concurrent_channel.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/coro.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/coro.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/coro.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/coro_traits.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/coro_traits.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/coro_traits.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/deferred.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/deferred.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/deferred.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_handler.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_handler.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_handler.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_message.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_message.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_message.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_operation.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_operation.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_operation.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_payload.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_payload.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_payload.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_receive_op.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_receive_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_receive_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_functions.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_functions.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_functions.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_op.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_op.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_send_op.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_service.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_service.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/channel_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_completion_handler.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_completion_handler.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_completion_handler.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_promise_allocator.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_promise_allocator.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/coro_promise_allocator.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/has_signature.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/has_signature.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/has_signature.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/impl/channel_service.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/impl/channel_service.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/impl/channel_service.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/detail/partial_promise.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/detail/partial_promise.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/detail/partial_promise.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/impl/as_single.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/impl/as_single.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/impl/as_single.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/impl/channel_error.ipp b/link/modules/asio-standalone/asio/include/asio/experimental/impl/channel_error.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/impl/channel_error.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/impl/co_composed.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/impl/co_composed.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/impl/co_composed.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/impl/coro.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/impl/coro.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/impl/coro.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/impl/parallel_group.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/impl/parallel_group.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/impl/parallel_group.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/impl/promise.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/impl/promise.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/impl/promise.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/impl/use_coro.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/impl/use_coro.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/impl/use_coro.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/impl/use_promise.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/impl/use_promise.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/impl/use_promise.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/parallel_group.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/parallel_group.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/parallel_group.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/prepend.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/prepend.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/prepend.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/promise.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/promise.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/promise.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/use_coro.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/use_coro.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/use_coro.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/experimental/use_promise.hpp b/link/modules/asio-standalone/asio/include/asio/experimental/use_promise.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/experimental/use_promise.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/file_base.hpp b/link/modules/asio-standalone/asio/include/asio/file_base.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/file_base.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/generic/basic_endpoint.hpp b/link/modules/asio-standalone/asio/include/asio/generic/basic_endpoint.hpp
--- a/link/modules/asio-standalone/asio/include/asio/generic/basic_endpoint.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/generic/basic_endpoint.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/generic/datagram_protocol.hpp b/link/modules/asio-standalone/asio/include/asio/generic/datagram_protocol.hpp
--- a/link/modules/asio-standalone/asio/include/asio/generic/datagram_protocol.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/generic/datagram_protocol.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/generic/detail/endpoint.hpp b/link/modules/asio-standalone/asio/include/asio/generic/detail/endpoint.hpp
--- a/link/modules/asio-standalone/asio/include/asio/generic/detail/endpoint.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/generic/detail/endpoint.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/generic/detail/impl/endpoint.ipp b/link/modules/asio-standalone/asio/include/asio/generic/detail/impl/endpoint.ipp
--- a/link/modules/asio-standalone/asio/include/asio/generic/detail/impl/endpoint.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/generic/detail/impl/endpoint.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/generic/raw_protocol.hpp b/link/modules/asio-standalone/asio/include/asio/generic/raw_protocol.hpp
--- a/link/modules/asio-standalone/asio/include/asio/generic/raw_protocol.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/generic/raw_protocol.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/generic/seq_packet_protocol.hpp b/link/modules/asio-standalone/asio/include/asio/generic/seq_packet_protocol.hpp
--- a/link/modules/asio-standalone/asio/include/asio/generic/seq_packet_protocol.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/generic/seq_packet_protocol.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/generic/stream_protocol.hpp b/link/modules/asio-standalone/asio/include/asio/generic/stream_protocol.hpp
--- a/link/modules/asio-standalone/asio/include/asio/generic/stream_protocol.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/generic/stream_protocol.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/handler_alloc_hook.hpp b/link/modules/asio-standalone/asio/include/asio/handler_alloc_hook.hpp
--- a/link/modules/asio-standalone/asio/include/asio/handler_alloc_hook.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/handler_alloc_hook.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/handler_continuation_hook.hpp b/link/modules/asio-standalone/asio/include/asio/handler_continuation_hook.hpp
--- a/link/modules/asio-standalone/asio/include/asio/handler_continuation_hook.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/handler_continuation_hook.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/handler_invoke_hook.hpp b/link/modules/asio-standalone/asio/include/asio/handler_invoke_hook.hpp
--- a/link/modules/asio-standalone/asio/include/asio/handler_invoke_hook.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/handler_invoke_hook.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/high_resolution_timer.hpp b/link/modules/asio-standalone/asio/include/asio/high_resolution_timer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/high_resolution_timer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/high_resolution_timer.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/any_completion_executor.ipp b/link/modules/asio-standalone/asio/include/asio/impl/any_completion_executor.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/any_completion_executor.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/any_io_executor.ipp b/link/modules/asio-standalone/asio/include/asio/impl/any_io_executor.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/any_io_executor.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/append.hpp b/link/modules/asio-standalone/asio/include/asio/impl/append.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/append.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/as_tuple.hpp b/link/modules/asio-standalone/asio/include/asio/impl/as_tuple.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/as_tuple.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/awaitable.hpp b/link/modules/asio-standalone/asio/include/asio/impl/awaitable.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/awaitable.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/awaitable.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/buffered_read_stream.hpp b/link/modules/asio-standalone/asio/include/asio/impl/buffered_read_stream.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/buffered_read_stream.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/buffered_read_stream.hpp
@@ -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)>(
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/buffered_write_stream.hpp b/link/modules/asio-standalone/asio/include/asio/impl/buffered_write_stream.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/buffered_write_stream.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/buffered_write_stream.hpp
@@ -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)>(
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/cancellation_signal.ipp b/link/modules/asio-standalone/asio/include/asio/impl/cancellation_signal.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/cancellation_signal.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/co_spawn.hpp b/link/modules/asio-standalone/asio/include/asio/impl/co_spawn.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/co_spawn.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/co_spawn.hpp
@@ -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));
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/compose.hpp b/link/modules/asio-standalone/asio/include/asio/impl/compose.hpp
deleted file mode 100644
--- a/link/modules/asio-standalone/asio/include/asio/impl/compose.hpp
+++ /dev/null
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/connect.hpp b/link/modules/asio-standalone/asio/include/asio/impl/connect.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/connect.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/connect.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.hpp b/link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.ipp b/link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.ipp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/connect_pipe.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/consign.hpp b/link/modules/asio-standalone/asio/include/asio/impl/consign.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/consign.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/defer.hpp b/link/modules/asio-standalone/asio/include/asio/impl/defer.hpp
deleted file mode 100644
--- a/link/modules/asio-standalone/asio/include/asio/impl/defer.hpp
+++ /dev/null
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/deferred.hpp b/link/modules/asio-standalone/asio/include/asio/impl/deferred.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/deferred.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/detached.hpp b/link/modules/asio-standalone/asio/include/asio/impl/detached.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/detached.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/detached.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/dispatch.hpp b/link/modules/asio-standalone/asio/include/asio/impl/dispatch.hpp
deleted file mode 100644
--- a/link/modules/asio-standalone/asio/include/asio/impl/dispatch.hpp
+++ /dev/null
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/error.ipp b/link/modules/asio-standalone/asio/include/asio/impl/error.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/error.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/error.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/error_code.ipp b/link/modules/asio-standalone/asio/include/asio/impl/error_code.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/error_code.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/error_code.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/execution_context.hpp b/link/modules/asio-standalone/asio/include/asio/impl/execution_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/execution_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/execution_context.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/execution_context.ipp b/link/modules/asio-standalone/asio/include/asio/impl/execution_context.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/execution_context.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/execution_context.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/executor.hpp b/link/modules/asio-standalone/asio/include/asio/impl/executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/executor.hpp
@@ -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"
 
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/executor.ipp b/link/modules/asio-standalone/asio/include/asio/impl/executor.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/executor.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/executor.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/handler_alloc_hook.ipp b/link/modules/asio-standalone/asio/include/asio/impl/handler_alloc_hook.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/handler_alloc_hook.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/handler_alloc_hook.ipp
@@ -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)
 }
 
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/io_context.hpp b/link/modules/asio-standalone/asio/include/asio/impl/io_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/io_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/io_context.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/io_context.ipp b/link/modules/asio-standalone/asio/include/asio/impl/io_context.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/io_context.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/io_context.ipp
@@ -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()
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/multiple_exceptions.ipp b/link/modules/asio-standalone/asio/include/asio/impl/multiple_exceptions.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/multiple_exceptions.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/multiple_exceptions.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/post.hpp b/link/modules/asio-standalone/asio/include/asio/impl/post.hpp
deleted file mode 100644
--- a/link/modules/asio-standalone/asio/include/asio/impl/post.hpp
+++ /dev/null
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/prepend.hpp b/link/modules/asio-standalone/asio/include/asio/impl/prepend.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/impl/prepend.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/read.hpp b/link/modules/asio-standalone/asio/include/asio/impl/read.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/read.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/read.hpp
@@ -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));
 }
 
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/read_at.hpp b/link/modules/asio-standalone/asio/include/asio/impl/read_at.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/read_at.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/read_at.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/read_until.hpp b/link/modules/asio-standalone/asio/include/asio/impl/read_until.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/read_until.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/read_until.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/redirect_error.hpp b/link/modules/asio-standalone/asio/include/asio/impl/redirect_error.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/redirect_error.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/redirect_error.hpp
@@ -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);
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.hpp b/link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.ipp b/link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/serial_port_base.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/spawn.hpp b/link/modules/asio-standalone/asio/include/asio/impl/spawn.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/spawn.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/spawn.hpp
@@ -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
 
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/src.hpp b/link/modules/asio-standalone/asio/include/asio/impl/src.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/src.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/src.hpp
@@ -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"
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/system_context.hpp b/link/modules/asio-standalone/asio/include/asio/impl/system_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/system_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/system_context.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/system_context.ipp b/link/modules/asio-standalone/asio/include/asio/impl/system_context.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/system_context.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/system_context.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/system_executor.hpp b/link/modules/asio-standalone/asio/include/asio/impl/system_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/system_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/system_executor.hpp
@@ -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"
 
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/thread_pool.hpp b/link/modules/asio-standalone/asio/include/asio/impl/thread_pool.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/thread_pool.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/thread_pool.hpp
@@ -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;
 }
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/thread_pool.ipp b/link/modules/asio-standalone/asio/include/asio/impl/thread_pool.ipp
--- a/link/modules/asio-standalone/asio/include/asio/impl/thread_pool.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/thread_pool.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/use_awaitable.hpp b/link/modules/asio-standalone/asio/include/asio/impl/use_awaitable.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/use_awaitable.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/use_awaitable.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/use_future.hpp b/link/modules/asio-standalone/asio/include/asio/impl/use_future.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/use_future.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/use_future.hpp
@@ -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)
 
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/write.hpp b/link/modules/asio-standalone/asio/include/asio/impl/write.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/write.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/write.hpp
@@ -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));
 }
 
diff --git a/link/modules/asio-standalone/asio/include/asio/impl/write_at.hpp b/link/modules/asio-standalone/asio/include/asio/impl/write_at.hpp
--- a/link/modules/asio-standalone/asio/include/asio/impl/write_at.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/impl/write_at.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/io_context.hpp b/link/modules/asio-standalone/asio/include/asio/io_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/io_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/io_context.hpp
@@ -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)
 
diff --git a/link/modules/asio-standalone/asio/include/asio/io_context_strand.hpp b/link/modules/asio-standalone/asio/include/asio/io_context_strand.hpp
--- a/link/modules/asio-standalone/asio/include/asio/io_context_strand.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/io_context_strand.hpp
@@ -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);
diff --git a/link/modules/asio-standalone/asio/include/asio/io_service.hpp b/link/modules/asio-standalone/asio/include/asio/io_service.hpp
--- a/link/modules/asio-standalone/asio/include/asio/io_service.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/io_service.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/io_service_strand.hpp b/link/modules/asio-standalone/asio/include/asio/io_service_strand.hpp
--- a/link/modules/asio-standalone/asio/include/asio/io_service_strand.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/io_service_strand.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/address.hpp b/link/modules/asio-standalone/asio/include/asio/ip/address.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/address.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/address.hpp
@@ -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"
 
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/address_v4.hpp b/link/modules/asio-standalone/asio/include/asio/ip/address_v4.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/address_v4.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/address_v4.hpp
@@ -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"
 
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/address_v4_iterator.hpp b/link/modules/asio-standalone/asio/include/asio/ip/address_v4_iterator.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/address_v4_iterator.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/address_v4_iterator.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/address_v4_range.hpp b/link/modules/asio-standalone/asio/include/asio/ip/address_v4_range.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/address_v4_range.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/address_v4_range.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/address_v6.hpp b/link/modules/asio-standalone/asio/include/asio/ip/address_v6.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/address_v6.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/address_v6.hpp
@@ -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"
 
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/address_v6_iterator.hpp b/link/modules/asio-standalone/asio/include/asio/ip/address_v6_iterator.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/address_v6_iterator.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/address_v6_iterator.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/address_v6_range.hpp b/link/modules/asio-standalone/asio/include/asio/ip/address_v6_range.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/address_v6_range.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/address_v6_range.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/bad_address_cast.hpp b/link/modules/asio-standalone/asio/include/asio/ip/bad_address_cast.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/bad_address_cast.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/bad_address_cast.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/basic_endpoint.hpp b/link/modules/asio-standalone/asio/include/asio/ip/basic_endpoint.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/basic_endpoint.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/basic_endpoint.hpp
@@ -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"
 
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver.hpp b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_entry.hpp b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_entry.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_entry.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_entry.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_iterator.hpp b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_iterator.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_iterator.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_iterator.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_query.hpp b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_query.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_query.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_query.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_results.hpp b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_results.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_results.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/basic_resolver_results.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/detail/endpoint.hpp b/link/modules/asio-standalone/asio/include/asio/ip/detail/endpoint.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/detail/endpoint.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/detail/endpoint.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/detail/impl/endpoint.ipp b/link/modules/asio-standalone/asio/include/asio/ip/detail/impl/endpoint.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ip/detail/impl/endpoint.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/detail/impl/endpoint.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/detail/socket_option.hpp b/link/modules/asio-standalone/asio/include/asio/ip/detail/socket_option.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/detail/socket_option.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/detail/socket_option.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/host_name.hpp b/link/modules/asio-standalone/asio/include/asio/ip/host_name.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/host_name.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/host_name.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/icmp.hpp b/link/modules/asio-standalone/asio/include/asio/ip/icmp.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/icmp.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/icmp.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/address.hpp b/link/modules/asio-standalone/asio/include/asio/ip/impl/address.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/address.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/address.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/address.ipp b/link/modules/asio-standalone/asio/include/asio/ip/impl/address.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/address.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/address.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.hpp b/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.ipp b/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v4.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.hpp b/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.ipp b/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/address_v6.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/basic_endpoint.hpp b/link/modules/asio-standalone/asio/include/asio/ip/impl/basic_endpoint.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/basic_endpoint.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/basic_endpoint.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/host_name.ipp b/link/modules/asio-standalone/asio/include/asio/ip/impl/host_name.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/host_name.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/host_name.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.hpp b/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.ipp b/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v4.ipp
@@ -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_);
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.hpp b/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.ipp b/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/impl/network_v6.ipp
@@ -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_);
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/multicast.hpp b/link/modules/asio-standalone/asio/include/asio/ip/multicast.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/multicast.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/multicast.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/network_v4.hpp b/link/modules/asio-standalone/asio/include/asio/ip/network_v4.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/network_v4.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/network_v4.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/network_v6.hpp b/link/modules/asio-standalone/asio/include/asio/ip/network_v6.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/network_v6.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/network_v6.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/resolver_base.hpp b/link/modules/asio-standalone/asio/include/asio/ip/resolver_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/resolver_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/resolver_base.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/resolver_query_base.hpp b/link/modules/asio-standalone/asio/include/asio/ip/resolver_query_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/resolver_query_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/resolver_query_base.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/tcp.hpp b/link/modules/asio-standalone/asio/include/asio/ip/tcp.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/tcp.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/tcp.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/udp.hpp b/link/modules/asio-standalone/asio/include/asio/ip/udp.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/udp.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/udp.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/unicast.hpp b/link/modules/asio-standalone/asio/include/asio/ip/unicast.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/unicast.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/unicast.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ip/v6_only.hpp b/link/modules/asio-standalone/asio/include/asio/ip/v6_only.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ip/v6_only.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ip/v6_only.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/is_applicable_property.hpp b/link/modules/asio-standalone/asio/include/asio/is_applicable_property.hpp
--- a/link/modules/asio-standalone/asio/include/asio/is_applicable_property.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/is_applicable_property.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/is_contiguous_iterator.hpp b/link/modules/asio-standalone/asio/include/asio/is_contiguous_iterator.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/is_contiguous_iterator.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/is_executor.hpp b/link/modules/asio-standalone/asio/include/asio/is_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/is_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/is_executor.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/is_read_buffered.hpp b/link/modules/asio-standalone/asio/include/asio/is_read_buffered.hpp
--- a/link/modules/asio-standalone/asio/include/asio/is_read_buffered.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/is_read_buffered.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/is_write_buffered.hpp b/link/modules/asio-standalone/asio/include/asio/is_write_buffered.hpp
--- a/link/modules/asio-standalone/asio/include/asio/is_write_buffered.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/is_write_buffered.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/local/basic_endpoint.hpp b/link/modules/asio-standalone/asio/include/asio/local/basic_endpoint.hpp
--- a/link/modules/asio-standalone/asio/include/asio/local/basic_endpoint.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/local/basic_endpoint.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/local/connect_pair.hpp b/link/modules/asio-standalone/asio/include/asio/local/connect_pair.hpp
--- a/link/modules/asio-standalone/asio/include/asio/local/connect_pair.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/local/connect_pair.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/local/datagram_protocol.hpp b/link/modules/asio-standalone/asio/include/asio/local/datagram_protocol.hpp
--- a/link/modules/asio-standalone/asio/include/asio/local/datagram_protocol.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/local/datagram_protocol.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/local/detail/endpoint.hpp b/link/modules/asio-standalone/asio/include/asio/local/detail/endpoint.hpp
--- a/link/modules/asio-standalone/asio/include/asio/local/detail/endpoint.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/local/detail/endpoint.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/local/detail/impl/endpoint.ipp b/link/modules/asio-standalone/asio/include/asio/local/detail/impl/endpoint.ipp
--- a/link/modules/asio-standalone/asio/include/asio/local/detail/impl/endpoint.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/local/detail/impl/endpoint.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/local/seq_packet_protocol.hpp b/link/modules/asio-standalone/asio/include/asio/local/seq_packet_protocol.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/local/seq_packet_protocol.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/local/stream_protocol.hpp b/link/modules/asio-standalone/asio/include/asio/local/stream_protocol.hpp
--- a/link/modules/asio-standalone/asio/include/asio/local/stream_protocol.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/local/stream_protocol.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/multiple_exceptions.hpp b/link/modules/asio-standalone/asio/include/asio/multiple_exceptions.hpp
--- a/link/modules/asio-standalone/asio/include/asio/multiple_exceptions.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/multiple_exceptions.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/packaged_task.hpp b/link/modules/asio-standalone/asio/include/asio/packaged_task.hpp
--- a/link/modules/asio-standalone/asio/include/asio/packaged_task.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/packaged_task.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/placeholders.hpp b/link/modules/asio-standalone/asio/include/asio/placeholders.hpp
--- a/link/modules/asio-standalone/asio/include/asio/placeholders.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/placeholders.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/posix/basic_descriptor.hpp b/link/modules/asio-standalone/asio/include/asio/posix/basic_descriptor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/posix/basic_descriptor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/posix/basic_descriptor.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/posix/basic_stream_descriptor.hpp b/link/modules/asio-standalone/asio/include/asio/posix/basic_stream_descriptor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/posix/basic_stream_descriptor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/posix/basic_stream_descriptor.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/posix/descriptor.hpp b/link/modules/asio-standalone/asio/include/asio/posix/descriptor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/posix/descriptor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/posix/descriptor.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/posix/descriptor_base.hpp b/link/modules/asio-standalone/asio/include/asio/posix/descriptor_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/posix/descriptor_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/posix/descriptor_base.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/posix/stream_descriptor.hpp b/link/modules/asio-standalone/asio/include/asio/posix/stream_descriptor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/posix/stream_descriptor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/posix/stream_descriptor.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/post.hpp b/link/modules/asio-standalone/asio/include/asio/post.hpp
--- a/link/modules/asio-standalone/asio/include/asio/post.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/post.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/prefer.hpp b/link/modules/asio-standalone/asio/include/asio/prefer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/prefer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/prefer.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/prepend.hpp b/link/modules/asio-standalone/asio/include/asio/prepend.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/prepend.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/query.hpp b/link/modules/asio-standalone/asio/include/asio/query.hpp
--- a/link/modules/asio-standalone/asio/include/asio/query.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/query.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/random_access_file.hpp b/link/modules/asio-standalone/asio/include/asio/random_access_file.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/random_access_file.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/read.hpp b/link/modules/asio-standalone/asio/include/asio/read.hpp
--- a/link/modules/asio-standalone/asio/include/asio/read.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/read.hpp
@@ -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))));
 
 /*@}*/
 
diff --git a/link/modules/asio-standalone/asio/include/asio/read_at.hpp b/link/modules/asio-standalone/asio/include/asio/read_at.hpp
--- a/link/modules/asio-standalone/asio/include/asio/read_at.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/read_at.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/read_until.hpp b/link/modules/asio-standalone/asio/include/asio/read_until.hpp
--- a/link/modules/asio-standalone/asio/include/asio/read_until.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/read_until.hpp
@@ -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)
 
diff --git a/link/modules/asio-standalone/asio/include/asio/readable_pipe.hpp b/link/modules/asio-standalone/asio/include/asio/readable_pipe.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/readable_pipe.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/recycling_allocator.hpp b/link/modules/asio-standalone/asio/include/asio/recycling_allocator.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/recycling_allocator.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/redirect_error.hpp b/link/modules/asio-standalone/asio/include/asio/redirect_error.hpp
--- a/link/modules/asio-standalone/asio/include/asio/redirect_error.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/redirect_error.hpp
@@ -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,
diff --git a/link/modules/asio-standalone/asio/include/asio/registered_buffer.hpp b/link/modules/asio-standalone/asio/include/asio/registered_buffer.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/registered_buffer.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/require.hpp b/link/modules/asio-standalone/asio/include/asio/require.hpp
--- a/link/modules/asio-standalone/asio/include/asio/require.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/require.hpp
@@ -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>
diff --git a/link/modules/asio-standalone/asio/include/asio/require_concept.hpp b/link/modules/asio-standalone/asio/include/asio/require_concept.hpp
--- a/link/modules/asio-standalone/asio/include/asio/require_concept.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/require_concept.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/serial_port.hpp b/link/modules/asio-standalone/asio/include/asio/serial_port.hpp
--- a/link/modules/asio-standalone/asio/include/asio/serial_port.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/serial_port.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/serial_port_base.hpp b/link/modules/asio-standalone/asio/include/asio/serial_port_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/serial_port_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/serial_port_base.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/signal_set.hpp b/link/modules/asio-standalone/asio/include/asio/signal_set.hpp
--- a/link/modules/asio-standalone/asio/include/asio/signal_set.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/signal_set.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/signal_set_base.hpp b/link/modules/asio-standalone/asio/include/asio/signal_set_base.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/signal_set_base.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/socket_base.hpp b/link/modules/asio-standalone/asio/include/asio/socket_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/socket_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/socket_base.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/spawn.hpp b/link/modules/asio-standalone/asio/include/asio/spawn.hpp
--- a/link/modules/asio-standalone/asio/include/asio/spawn.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/spawn.hpp
@@ -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)
 
 /*@}*/
 
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl.hpp b/link/modules/asio-standalone/asio/include/asio/ssl.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/context.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/context.hpp
@@ -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_;
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/context_base.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/context_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/context_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/context_base.hpp
@@ -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
 
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/buffered_handshake_op.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/buffered_handshake_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/buffered_handshake_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/buffered_handshake_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/engine.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/engine.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/engine.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/engine.hpp
@@ -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();
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/handshake_op.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/handshake_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/handshake_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/handshake_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/engine.ipp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/engine.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/engine.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/engine.ipp
@@ -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()
 {
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/openssl_init.ipp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/openssl_init.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/openssl_init.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/impl/openssl_init.ipp
@@ -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();
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/io.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/io.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/io.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/io.hpp
@@ -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);
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_init.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_init.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_init.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_init.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_types.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_types.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_types.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/openssl_types.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/password_callback.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/password_callback.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/password_callback.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/password_callback.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/read_op.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/read_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/read_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/read_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/shutdown_op.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/shutdown_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/shutdown_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/shutdown_op.hpp
@@ -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);
     }
   }
 };
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/stream_core.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/stream_core.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/stream_core.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/stream_core.hpp
@@ -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_;
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/verify_callback.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/verify_callback.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/verify_callback.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/verify_callback.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/detail/write_op.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/detail/write_op.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/detail/write_op.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/detail/write_op.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/error.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/error.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/error.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/error.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/host_name_verification.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/host_name_verification.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/host_name_verification.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/host_name_verification.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/impl/context.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/impl/context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/impl/context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/impl/context.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/impl/context.ipp b/link/modules/asio-standalone/asio/include/asio/ssl/impl/context.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/impl/context.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/impl/context.ipp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/impl/error.ipp b/link/modules/asio-standalone/asio/include/asio/ssl/impl/error.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/impl/error.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/impl/error.ipp
@@ -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";
   }
 };
 
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/impl/host_name_verification.ipp b/link/modules/asio-standalone/asio/include/asio/ssl/impl/host_name_verification.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/impl/host_name_verification.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/impl/host_name_verification.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/impl/rfc2818_verification.ipp b/link/modules/asio-standalone/asio/include/asio/ssl/impl/rfc2818_verification.ipp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/impl/rfc2818_verification.ipp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/impl/rfc2818_verification.ipp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/impl/src.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/impl/src.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/impl/src.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/impl/src.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/rfc2818_verification.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/rfc2818_verification.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/rfc2818_verification.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/rfc2818_verification.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/stream.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/stream.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/stream.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/stream.hpp
@@ -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:
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/stream_base.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/stream_base.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/stream_base.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/stream_base.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/verify_context.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/verify_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/verify_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/verify_context.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ssl/verify_mode.hpp b/link/modules/asio-standalone/asio/include/asio/ssl/verify_mode.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ssl/verify_mode.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ssl/verify_mode.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/static_thread_pool.hpp b/link/modules/asio-standalone/asio/include/asio/static_thread_pool.hpp
--- a/link/modules/asio-standalone/asio/include/asio/static_thread_pool.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/static_thread_pool.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/steady_timer.hpp b/link/modules/asio-standalone/asio/include/asio/steady_timer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/steady_timer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/steady_timer.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/strand.hpp b/link/modules/asio-standalone/asio/include/asio/strand.hpp
--- a/link/modules/asio-standalone/asio/include/asio/strand.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/strand.hpp
@@ -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);
diff --git a/link/modules/asio-standalone/asio/include/asio/stream_file.hpp b/link/modules/asio-standalone/asio/include/asio/stream_file.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/stream_file.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/streambuf.hpp b/link/modules/asio-standalone/asio/include/asio/streambuf.hpp
--- a/link/modules/asio-standalone/asio/include/asio/streambuf.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/streambuf.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/system_context.hpp b/link/modules/asio-standalone/asio/include/asio/system_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/system_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/system_context.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/system_error.hpp b/link/modules/asio-standalone/asio/include/asio/system_error.hpp
--- a/link/modules/asio-standalone/asio/include/asio/system_error.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/system_error.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/system_executor.hpp b/link/modules/asio-standalone/asio/include/asio/system_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/system_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/system_executor.hpp
@@ -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;
 
diff --git a/link/modules/asio-standalone/asio/include/asio/system_timer.hpp b/link/modules/asio-standalone/asio/include/asio/system_timer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/system_timer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/system_timer.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/this_coro.hpp b/link/modules/asio-standalone/asio/include/asio/this_coro.hpp
--- a/link/modules/asio-standalone/asio/include/asio/this_coro.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/this_coro.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/thread.hpp b/link/modules/asio-standalone/asio/include/asio/thread.hpp
--- a/link/modules/asio-standalone/asio/include/asio/thread.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/thread.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/thread_pool.hpp b/link/modules/asio-standalone/asio/include/asio/thread_pool.hpp
--- a/link/modules/asio-standalone/asio/include/asio/thread_pool.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/thread_pool.hpp
@@ -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)
 
diff --git a/link/modules/asio-standalone/asio/include/asio/time_traits.hpp b/link/modules/asio-standalone/asio/include/asio/time_traits.hpp
--- a/link/modules/asio-standalone/asio/include/asio/time_traits.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/time_traits.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/bulk_execute_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/connect_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/connect_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/connect_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/connect_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/connect_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/connect_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/connect_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/connect_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/equality_comparable.hpp b/link/modules/asio-standalone/asio/include/asio/traits/equality_comparable.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/equality_comparable.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/equality_comparable.hpp
@@ -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>
 {
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/execute_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/execute_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/execute_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/execute_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/execute_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/execute_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/execute_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/execute_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/prefer_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/prefer_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/prefer_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/prefer_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/prefer_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/prefer_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/prefer_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/prefer_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/query_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/query_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/query_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/query_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/query_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/query_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/query_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/query_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/query_static_constexpr_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/query_static_constexpr_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/query_static_constexpr_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/query_static_constexpr_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/require_concept_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/require_concept_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/require_concept_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/require_concept_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/require_concept_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/require_concept_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/require_concept_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/require_concept_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/require_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/require_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/require_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/require_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/require_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/require_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/require_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/require_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/schedule_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/schedule_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/schedule_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/schedule_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/schedule_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/schedule_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/schedule_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/schedule_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/set_done_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/set_done_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/set_done_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/set_done_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/set_done_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/set_done_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/set_done_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/set_done_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/set_error_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/set_error_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/set_error_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/set_error_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/set_error_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/set_error_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/set_error_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/set_error_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/set_value_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/set_value_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/set_value_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/set_value_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/set_value_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/set_value_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/set_value_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/set_value_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/start_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/start_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/start_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/start_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/start_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/start_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/start_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/start_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/static_query.hpp b/link/modules/asio-standalone/asio/include/asio/traits/static_query.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/static_query.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/static_query.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/static_require.hpp b/link/modules/asio-standalone/asio/include/asio/traits/static_require.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/static_require.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/static_require.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/static_require_concept.hpp b/link/modules/asio-standalone/asio/include/asio/traits/static_require_concept.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/static_require_concept.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/static_require_concept.hpp
@@ -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);
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/submit_free.hpp b/link/modules/asio-standalone/asio/include/asio/traits/submit_free.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/submit_free.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/submit_free.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/traits/submit_member.hpp b/link/modules/asio-standalone/asio/include/asio/traits/submit_member.hpp
--- a/link/modules/asio-standalone/asio/include/asio/traits/submit_member.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/traits/submit_member.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ts/buffer.hpp b/link/modules/asio-standalone/asio/include/asio/ts/buffer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ts/buffer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ts/buffer.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ts/executor.hpp b/link/modules/asio-standalone/asio/include/asio/ts/executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ts/executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ts/executor.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ts/internet.hpp b/link/modules/asio-standalone/asio/include/asio/ts/internet.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ts/internet.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ts/internet.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ts/io_context.hpp b/link/modules/asio-standalone/asio/include/asio/ts/io_context.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ts/io_context.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ts/io_context.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ts/net.hpp b/link/modules/asio-standalone/asio/include/asio/ts/net.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ts/net.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ts/net.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ts/netfwd.hpp b/link/modules/asio-standalone/asio/include/asio/ts/netfwd.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ts/netfwd.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ts/netfwd.hpp
@@ -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)
 
diff --git a/link/modules/asio-standalone/asio/include/asio/ts/socket.hpp b/link/modules/asio-standalone/asio/include/asio/ts/socket.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ts/socket.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ts/socket.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/ts/timer.hpp b/link/modules/asio-standalone/asio/include/asio/ts/timer.hpp
--- a/link/modules/asio-standalone/asio/include/asio/ts/timer.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/ts/timer.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/unyield.hpp b/link/modules/asio-standalone/asio/include/asio/unyield.hpp
--- a/link/modules/asio-standalone/asio/include/asio/unyield.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/unyield.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/use_awaitable.hpp b/link/modules/asio-standalone/asio/include/asio/use_awaitable.hpp
--- a/link/modules/asio-standalone/asio/include/asio/use_awaitable.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/use_awaitable.hpp
@@ -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.
  */
diff --git a/link/modules/asio-standalone/asio/include/asio/use_future.hpp b/link/modules/asio-standalone/asio/include/asio/use_future.hpp
--- a/link/modules/asio-standalone/asio/include/asio/use_future.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/use_future.hpp
@@ -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.
  */
diff --git a/link/modules/asio-standalone/asio/include/asio/uses_executor.hpp b/link/modules/asio-standalone/asio/include/asio/uses_executor.hpp
--- a/link/modules/asio-standalone/asio/include/asio/uses_executor.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/uses_executor.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/version.hpp b/link/modules/asio-standalone/asio/include/asio/version.hpp
--- a/link/modules/asio-standalone/asio/include/asio/version.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/version.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/wait_traits.hpp b/link/modules/asio-standalone/asio/include/asio/wait_traits.hpp
--- a/link/modules/asio-standalone/asio/include/asio/wait_traits.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/wait_traits.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/windows/basic_object_handle.hpp b/link/modules/asio-standalone/asio/include/asio/windows/basic_object_handle.hpp
--- a/link/modules/asio-standalone/asio/include/asio/windows/basic_object_handle.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/windows/basic_object_handle.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/windows/basic_overlapped_handle.hpp b/link/modules/asio-standalone/asio/include/asio/windows/basic_overlapped_handle.hpp
--- a/link/modules/asio-standalone/asio/include/asio/windows/basic_overlapped_handle.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/windows/basic_overlapped_handle.hpp
@@ -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.
diff --git a/link/modules/asio-standalone/asio/include/asio/windows/basic_random_access_handle.hpp b/link/modules/asio-standalone/asio/include/asio/windows/basic_random_access_handle.hpp
--- a/link/modules/asio-standalone/asio/include/asio/windows/basic_random_access_handle.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/windows/basic_random_access_handle.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/windows/basic_stream_handle.hpp b/link/modules/asio-standalone/asio/include/asio/windows/basic_stream_handle.hpp
--- a/link/modules/asio-standalone/asio/include/asio/windows/basic_stream_handle.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/windows/basic_stream_handle.hpp
@@ -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();
     }
diff --git a/link/modules/asio-standalone/asio/include/asio/windows/object_handle.hpp b/link/modules/asio-standalone/asio/include/asio/windows/object_handle.hpp
--- a/link/modules/asio-standalone/asio/include/asio/windows/object_handle.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/windows/object_handle.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/windows/overlapped_handle.hpp b/link/modules/asio-standalone/asio/include/asio/windows/overlapped_handle.hpp
--- a/link/modules/asio-standalone/asio/include/asio/windows/overlapped_handle.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/windows/overlapped_handle.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/windows/overlapped_ptr.hpp b/link/modules/asio-standalone/asio/include/asio/windows/overlapped_ptr.hpp
--- a/link/modules/asio-standalone/asio/include/asio/windows/overlapped_ptr.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/windows/overlapped_ptr.hpp
@@ -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));
   }
diff --git a/link/modules/asio-standalone/asio/include/asio/windows/random_access_handle.hpp b/link/modules/asio-standalone/asio/include/asio/windows/random_access_handle.hpp
--- a/link/modules/asio-standalone/asio/include/asio/windows/random_access_handle.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/windows/random_access_handle.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/windows/stream_handle.hpp b/link/modules/asio-standalone/asio/include/asio/windows/stream_handle.hpp
--- a/link/modules/asio-standalone/asio/include/asio/windows/stream_handle.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/windows/stream_handle.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/writable_pipe.hpp b/link/modules/asio-standalone/asio/include/asio/writable_pipe.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/include/asio/writable_pipe.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/include/asio/write.hpp b/link/modules/asio-standalone/asio/include/asio/write.hpp
--- a/link/modules/asio-standalone/asio/include/asio/write.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/write.hpp
@@ -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))));
 
 /*@}*/
 
diff --git a/link/modules/asio-standalone/asio/include/asio/write_at.hpp b/link/modules/asio-standalone/asio/include/asio/write_at.hpp
--- a/link/modules/asio-standalone/asio/include/asio/write_at.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/write_at.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/include/asio/yield.hpp b/link/modules/asio-standalone/asio/include/asio/yield.hpp
--- a/link/modules/asio-standalone/asio/include/asio/yield.hpp
+++ b/link/modules/asio-standalone/asio/include/asio/yield.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/chat/chat_message.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/chat/chat_message.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/chat/chat_message.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/chat/chat_message.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection_manager.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection_manager.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection_manager.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/connection_manager.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/header.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/header.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/header.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/header.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/mime_types.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/mime_types.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/mime_types.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/mime_types.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/reply.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/reply.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/reply.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/reply.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_handler.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_handler.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_handler.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_handler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_parser.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_parser.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_parser.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/request_parser.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/server.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/server.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/server.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server/server.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/connection.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/connection.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/connection.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/connection.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/header.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/header.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/header.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/header.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/io_context_pool.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/io_context_pool.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/io_context_pool.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/io_context_pool.hpp
@@ -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_;
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/mime_types.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/mime_types.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/mime_types.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/mime_types.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/reply.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/reply.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/reply.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/reply.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_handler.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_handler.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_handler.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_handler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_parser.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_parser.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_parser.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/request_parser.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/server.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/server.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/server.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server2/server.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/connection.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/connection.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/connection.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/connection.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/header.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/header.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/header.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/header.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/mime_types.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/mime_types.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/mime_types.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/mime_types.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/reply.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/reply.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/reply.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/reply.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_handler.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_handler.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_handler.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_handler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_parser.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_parser.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_parser.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/request_parser.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/server.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/server.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/server.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server3/server.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/file_handler.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/file_handler.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/file_handler.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/file_handler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/header.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/header.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/header.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/header.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/mime_types.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/mime_types.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/mime_types.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/mime_types.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/reply.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/reply.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/reply.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/reply.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request_parser.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request_parser.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request_parser.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/request_parser.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/server.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/server.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/server.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/http/server4/server.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/icmp/icmp_header.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/icmp/icmp_header.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/icmp/icmp_header.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/icmp/icmp_header.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/icmp/ipv4_header.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/icmp/ipv4_header.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/icmp/ipv4_header.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/icmp/ipv4_header.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/porthopper/protocol.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/porthopper/protocol.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/porthopper/protocol.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/porthopper/protocol.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/serialization/connection.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/serialization/connection.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/serialization/connection.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/serialization/connection.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/serialization/stock.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/serialization/stock.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/serialization/stock.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/serialization/stock.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/services/basic_logger.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/services/basic_logger.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/services/basic_logger.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/services/basic_logger.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/services/logger.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/services/logger.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/services/logger.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/services/logger.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/services/logger_service.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/services/logger_service.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/services/logger_service.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/services/logger_service.hpp
@@ -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_;
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp03/socks4/socks4.hpp b/link/modules/asio-standalone/asio/src/examples/cpp03/socks4/socks4.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp03/socks4/socks4.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp03/socks4/socks4.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/chat/chat_message.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/chat/chat_message.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/chat/chat_message.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/chat/chat_message.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/handler_tracking/custom_tracking.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection_manager.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection_manager.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection_manager.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/connection_manager.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/header.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/header.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/header.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/header.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/mime_types.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/mime_types.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/mime_types.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/mime_types.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/reply.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/reply.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/reply.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/reply.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_handler.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_handler.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_handler.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_handler.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_parser.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_parser.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_parser.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/request_parser.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/server.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/server.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/server.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/http/server/server.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/socks4/socks4.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/socks4/socks4.hpp
--- a/link/modules/asio-standalone/asio/src/examples/cpp11/socks4/socks4.hpp
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/socks4/socks4.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/line_reader.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/line_reader.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/line_reader.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/sleep.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/sleep.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/sleep.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/stdin_line_reader.hpp b/link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/stdin_line_reader.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/src/examples/cpp11/type_erasure/stdin_line_reader.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/line_reader.hpp b/link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/line_reader.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/line_reader.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/sleep.hpp b/link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/sleep.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/sleep.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/stdin_line_reader.hpp b/link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/stdin_line_reader.hpp
new file mode 100644
--- /dev/null
+++ b/link/modules/asio-standalone/asio/src/examples/cpp20/type_erasure/stdin_line_reader.hpp
@@ -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
diff --git a/link/modules/asio-standalone/asio/src/tests/latency/allocator.hpp b/link/modules/asio-standalone/asio/src/tests/latency/allocator.hpp
--- a/link/modules/asio-standalone/asio/src/tests/latency/allocator.hpp
+++ b/link/modules/asio-standalone/asio/src/tests/latency/allocator.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/tests/latency/high_res_clock.hpp b/link/modules/asio-standalone/asio/src/tests/latency/high_res_clock.hpp
--- a/link/modules/asio-standalone/asio/src/tests/latency/high_res_clock.hpp
+++ b/link/modules/asio-standalone/asio/src/tests/latency/high_res_clock.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/tests/performance/handler_allocator.hpp b/link/modules/asio-standalone/asio/src/tests/performance/handler_allocator.hpp
--- a/link/modules/asio-standalone/asio/src/tests/performance/handler_allocator.hpp
+++ b/link/modules/asio-standalone/asio/src/tests/performance/handler_allocator.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_ops.hpp b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_ops.hpp
--- a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_ops.hpp
+++ b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_ops.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_result.hpp b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_result.hpp
--- a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_result.hpp
+++ b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/async_result.hpp
@@ -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;
diff --git a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/gettable_socket_option.hpp b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/gettable_socket_option.hpp
--- a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/gettable_socket_option.hpp
+++ b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/gettable_socket_option.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/io_control_command.hpp b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/io_control_command.hpp
--- a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/io_control_command.hpp
+++ b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/io_control_command.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/settable_socket_option.hpp b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/settable_socket_option.hpp
--- a/link/modules/asio-standalone/asio/src/tests/unit/archetypes/settable_socket_option.hpp
+++ b/link/modules/asio-standalone/asio/src/tests/unit/archetypes/settable_socket_option.hpp
@@ -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)
diff --git a/link/modules/asio-standalone/asio/src/tests/unit/unit_test.hpp b/link/modules/asio-standalone/asio/src/tests/unit/unit_test.hpp
--- a/link/modules/asio-standalone/asio/src/tests/unit/unit_test.hpp
+++ b/link/modules/asio-standalone/asio/src/tests/unit/unit_test.hpp
@@ -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)
diff --git a/tidal-link.cabal b/tidal-link.cabal
--- a/tidal-link.cabal
+++ b/tidal-link.cabal
@@ -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
