# How to Use `asio bind_cancellation_slot`: Complete Guide with Examples

> Master asio bind_cancellation_slot to automatically cancel Asio operations with this comprehensive guide and examples. Ensure efficient resource management and robust error handling in your C++ network applications.

- Repository: [chriskohlhoff/asio](https://github.com/chriskohlhoff/asio)
- Tags: how-to-guide
- Published: 2026-07-17

---

**`bind_cancellation_slot` is a utility in the Asio library that associates a cancellation slot with any handler, completion token, or function object, enabling automatic cancellation of pending asynchronous operations when a signal is emitted.**

The `chriskohlhoff/asio` repository provides this mechanism through the header [`asio/bind_cancellation_slot.hpp`](https://github.com/chriskohlhoff/asio/blob/main/asio/bind_cancellation_slot.hpp). By binding a cancellation slot to your asynchronous handlers, you allow the Asio framework to inject cancellation signals directly into your callbacks when operations are aborted.

## Core Components

The implementation relies on several cooperating types that work together to wrap handlers and expose cancellation semantics to the Asio execution framework.

### cancellation_slot_binder

**`cancellation_slot_binder`** is a callable wrapper defined at line 51 in [`asio/bind_cancellation_slot.hpp`](https://github.com/chriskohlhoff/asio/blob/main/asio/bind_cancellation_slot.hpp). It stores two members: a `CancellationSlot` and a target object `T`. When invoked, it forwards all arguments to the wrapped target while making the slot available to Asio's generic algorithms.

This binder is the primary mechanism that connects your handler to the cancellation signal infrastructure.

### partial_cancellation_slot_binder

**`partial_cancellation_slot_binder`** acts as an intermediate completion token that captures a cancellation slot without immediately binding it to a handler. It enables a "partial application" syntax where you first bind the slot, then supply the handler later.

When invoked, this partial binder produces a full `cancellation_slot_binder`, allowing you to reuse the same slot binding across multiple operations.

### Free Factory Functions

Two overloads of **`bind_cancellation_slot`** provide convenient construction:

- `bind_cancellation_slot(const CancellationSlot&)` – Returns a `partial_cancellation_slot_binder`
- `bind_cancellation_slot(const CancellationSlot&, T&&)` – Returns a `cancellation_slot_binder` wrapping the target

These functions handle the template deduction and move semantics automatically.

### Trait Specializations

The header provides specializations for **`async_result`** (lines 84-136) that enable the binder to function as a completion token. Additionally, associator specializations (lines 79-98) make the binder transparently expose its associated executor, allocator, and cancellation slot to Asio's generic algorithms.

The **`associated_cancellation_slot`** trait (lines 100-108) specifically detects when a handler is a `cancellation_slot_binder` and returns the stored slot, allowing Asio to link the handler to the cancellation signal chain.

## Practical Usage Patterns

The test suite in [`src/tests/unit/bind_cancellation_slot.cpp`](https://github.com/chriskohlhoff/asio/blob/main/src/tests/unit/bind_cancellation_slot.cpp) demonstrates three common patterns for applying cancellation slots to asynchronous operations.

### Pattern 1: Binding to Function Objects

The most straightforward approach binds a cancellation slot directly to a function object or `std::bind` expression:

```cpp
asio::io_context ioc;
asio::cancellation_signal sig;
int count = 0;

asio::steady_timer t(ioc, asio::chrono::seconds(5));
t.async_wait(
    asio::bind_cancellation_slot(sig.slot(),
      std::bind(&increment_on_cancel,
                &count, std::placeholders::_1)));

```

In this example, `sig.slot()` provides the cancellation slot, while `std::bind` creates a callable matching the timer's handler signature. When `sig.emit(asio::cancellation_type::terminal)` is called, the timer operation completes immediately with `operation_aborted`, and your handler receives the error code.

### Pattern 2: Binding to Custom Completion Tokens

You can also bind slots to user-defined completion tokens that require `async_result` specialization:

```cpp
struct incrementer_token_v1 {
    explicit incrementer_token_v1(int* c) : count(c) {}
    int* count;
};

struct incrementer_handler_v1 {
    explicit incrementer_handler_v1(incrementer_token_v1 t) : count(t.count) {}
    void operator()(asio::error_code ec) { 
        increment_on_cancel(count, ec); 
    }
    int* count;
};

// Async_result specialization for incrementer_token_v1 defined elsewhere...

asio::io_context ioc;
asio::cancellation_signal sig;
int count = 0;

asio::steady_timer t(ioc, asio::chrono::seconds(5));
t.async_wait(
    asio::bind_cancellation_slot(sig.slot(),
       incrementer_token_v1(&count)));

```

Here, `bind_cancellation_slot` wraps the custom token `incrementer_token_v1`. The associated `async_result` specialization (see lines 97-105 in the test file) adapts the token so that Asio constructs the handler through the binder, preserving the cancellation slot association.

### Pattern 3: Partial Binding (Two-Step Syntax)

For scenarios where you want to bind the slot once and reuse it for multiple operations, use the partial application syntax:

```cpp
asio::io_context ioc;
asio::cancellation_signal sig;
int count = 0;

auto slot_binder = asio::bind_cancellation_slot(sig.slot());

asio::steady_timer t(ioc, asio::chrono::seconds(5));
t.async_wait(
    slot_binder(
        std::bind(&increment_on_cancel,
                  &count, std::placeholders::_1)));

```

`bind_cancellation_slot(sig.slot())` returns a `partial_cancellation_slot_binder`. The subsequent call operator `()` supplies the actual handler, producing a full `cancellation_slot_binder`. This pattern is particularly useful when managing multiple asynchronous operations that share the same cancellation signal.

## How Cancellation Propagates

When an asynchronous operation starts, Asio queries the handler's associated cancellation slot via the `associated_cancellation_slot` trait. If the handler is a `cancellation_slot_binder`, the trait returns the slot stored inside the binder (as implemented in lines 100-108 of [`asio/bind_cancellation_slot.hpp`](https://github.com/chriskohlhoff/asio/blob/main/asio/bind_cancellation_slot.hpp)).

Consequently, calling `sig.emit(...)` on the original `cancellation_signal` causes the bound handler to be invoked with an `operation_aborted` error code. The binder works for any callable type, including plain function objects, `std::bind` expressions, or user-defined completion tokens. It also supports nesting: you can bind multiple slots, or bind a slot to a token that itself creates a binder.

## Summary

- **`bind_cancellation_slot`** associates cancellation slots with handlers in [`asio/bind_cancellation_slot.hpp`](https://github.com/chriskohlhoff/asio/blob/main/asio/bind_cancellation_slot.hpp)
- **`cancellation_slot_binder`** wraps your callable and stores the slot at line 51 of the header
- **`partial_cancellation_slot_binder`** enables two-step binding syntax for reusable slot configurations
- **Trait specializations** (lines 79-136) make the binder transparent to Asio's executor and cancellation systems
- **Three patterns** cover direct function binding, custom tokens, and partial application as shown in [`src/tests/unit/bind_cancellation_slot.cpp`](https://github.com/chriskohlhoff/asio/blob/main/src/tests/unit/bind_cancellation_slot.cpp)
- **Cancellation propagation** occurs through `associated_cancellation_slot` detection when operations are initiated

## Frequently Asked Questions

### How do I create a cancellation slot to bind to my handler?

Create a `cancellation_signal` object, then call its `slot()` method. This method is defined in [`asio/cancellation_signal.hpp`](https://github.com/chriskohlhoff/asio/blob/main/asio/cancellation_signal.hpp). The returned slot object can be passed to `bind_cancellation_slot` to associate it with your handler.

### Can I use `bind_cancellation_slot` with standard function objects like lambdas?

Yes. The `cancellation_slot_binder` accepts any callable type, including lambdas, `std::function` objects, and `std::bind` expressions. The binder forwards all invocations to the wrapped target while maintaining the cancellation slot association.

### What happens if I emit a cancellation signal after the operation has already completed?

Cancellation signals only affect pending operations. If the asynchronous operation has already completed and the handler has been invoked, emitting the signal has no effect on that specific operation. The signal affects only operations currently awaiting completion that were started with handlers bound to that signal's slot.

### Where can I find the complete implementation of `async_result` for custom tokens?

The `async_result` specializations for `bind_cancellation_slot` are located at lines 84-136 in [`asio/bind_cancellation_slot.hpp`](https://github.com/chriskohlhoff/asio/blob/main/asio/bind_cancellation_slot.hpp). For examples of custom token implementations, see [`src/tests/unit/bind_cancellation_slot.cpp`](https://github.com/chriskohlhoff/asio/blob/main/src/tests/unit/bind_cancellation_slot.cpp), specifically around lines 97-105 where the test suite defines specializations for `incrementer_token_v1`.