|  | 
| ![[Note]](../../../note.png) | Note | 
|---|---|
| 
            These type requirements and classes are the low level building blocks
            of cancellation. For most use cases, consider using a higher level abstraction,
            such as experimental::make_parallel_group
            or the logical
            operators for  | 
          I/O objects, such as sockets and timers, support object-wide cancellation
          of outstanding asynchronous operations via their close
          or cancel member functions.
          However, certain asynchronous operations also support individual, targeted
          cancellation. This per-operation cancellation is enabled by specifying
          that a completion handler has an associated
          cancellation slot which satisfies the CancellationSlot
          type requirements. A cancellation slot is a lightweight channel used for
          delivering a cancellation request.
        
          Given a copy of a user-defined Handler
          object h, if an asynchronous
          operation supports cancellation it will obtain a cancellation slot using
          the get_associated_cancellation_slot
          function. For example:
        
asio::associated_cancellation_slot_t<Handler> s = asio::get_associated_cancellation_slot(h);
The associated cancellation slot must satisfy the CancellationSlot type requirements.
          By default, handlers use a default-constructed cancellation_slot, which means
          that per-operation cancellation is disabled. The cancellation slot may
          be customised for a particular handler type by specifying a nested type
          cancellation_slot_type
          and member function get_cancellation_slot():
        
class my_handler { public: // Custom implementation of CancellationSlot type requirements. typedef my_cancellation_slot cancellation_slot_type; // Return a custom cancellation slot implementation. cancellation_slot_type get_cancellation_slot() const noexcept { return my_cancellation_slot(...); } void operator()() { ... } };
          In more complex cases, the associated_cancellation_slot
          template may be partially specialised directly:
        
namespace asio { template <typename CancellationSlot> struct associated_cancellation_slot<my_handler, CancellationSlot> { // Custom implementation of CancellationSlot type requirements. typedef my_cancellation_slot type; // Return a custom cancellation_slot implementation. static type get(const my_handler&, const CancellationSlot& a = CancellationSlot()) noexcept { return my_cancellation_slot(...); } }; } // namespace asio
          For convenience, a cancellation slot may be associated with a handler by
          using the bind_cancellation_slot function.
          This is particularly useful when associating a cancellation slot with a
          lambda:
        
asio::async_read(my_socket, my_buffer, asio::bind_cancellation_slot( my_cancellation_slot, [](asio::error_code e, std::size_t n) { ... } ) );
          Asio provides a ready-to-use cancellation slot in the form of cancellation_slot and its counterpart
          cancellation_signal.
          These two classes implement a one-to-one pairing of producer (signal) and
          consumer (slot) interfaces. The following example shows its use:
        
class session : public std::enable_shared_from_this<proxy> { ... void do_read() { auto self = shared_from_this(); socket_.async_read_some( buffer(data_), asio::bind_cancellation_slot( cancel_signal_.slot(), [self](std::error_code error, std::size_t n) { ... } ) ); } ... void request_cancel() { cancel_signal_.emit(asio::cancellation_type::total); } ... asio::cancellation_signal cancel_signal_; };
          A cancellation_signal contains
          a single slot, and consequently a cancellation signal/slot pair may be
          used with at most one operation at a time. However, the same slot may be
          reused for subsequent operations.
        
          To support cancellation, an asynchronous operation installs a cancellation
          handler into the slot by calling the slot's assign
          or emplace functions. This
          handler will be invoked when a cancellation signal is emitted. A slot holds
          exactly one handler at a time, and installing a new handler will overwrite
          any previously installed handler.
        
When emitting a cancellation signal, the caller must specify a cancellation type. This value is a bitmask that dictates what guarantees the cancellation target must make if successful cancellation occurs. The possible bit values are, from weakest to strongest guarantee, are:
Table 1. cancellation types
| Bit | Guarantee if cancellation is successful | Examples where this is the strongest supported guarantee | 
|---|---|---|
| 
                     | The operation had unspecified side effects, and it is only safe to close or destroy the I/O object. | A stateful implementation of a message framing protocol, where an asynchronous operation sends or receives a complete message. If cancellation occurs part-way through the message body, it is not possible to report a sensible state to the completion handler. | 
| 
                     | The operation had well-defined side effects, and the completion handler for the operation indicates what these side effects were. | 
                    Composed operations such as  | 
| 
                     | The operation had no side effects that are observable through the API. | 
                    Low level system calls that transfer either zero or non-zero
                    bytes. | 
          For example, if application logic requires that an operation complete with
          all-or-nothing side effects, it should emit only the total
          cancellation type. If this type is unsupported by the target operation,
          no cancellation will occur.
        
          Furthermore, a stronger guarantee always satisfies the requirements of
          a weaker guarantee. The partial
          guarantee still satisfies the terminal
          guarantee. The total guarantee
          satisfies both partial
          and total. This means that
          when an operation supports a given cancellation type as its strongest guarantee,
          it should honour cancellation requests for any of the weaker guarantees.
        
Cancellation requests should not be emitted during an asynchronous operation's initiating function. Cancellation requests that are emitted before an operation starts have no effect. Similarly, cancellation requests made after completion have no effect.
When emitting a cancellation signal, the thread safety rules apply as if calling a member function on the target operation's I/O object. For non-composed operations, this means that it is safe to emit the cancellation signal from any thread provided there are no other concurrent calls to the I/O object, and no other concurrent cancellation signal requests. For composed operations, care must be taken to ensure the cancellation request does not occur concurrently with the operation's intermediate completion handlers.
Consult the documentation for individual asynchronous operations for their supported cancellation types, if any. The ability to cancel individual operations, or composed operations, is currently supported by:
async_read
              and async_write
            async_compose
            awaitable
            experimental::coro
            experimental::parallel_group operation
            experimental::promise class
            CancellationSlot, associated_cancellation_slot, bind_cancellation_slot, cancellation_signal, cancellation_slot, cancellation_state, cancellation_type, get_associated_cancellation_slot, experimental::parallel_group, experimental::make_parallel_group