aboutsummaryrefslogtreecommitdiffstats
path: root/library/cpp/threading/cancellation/README.md
blob: 98e0e9b299f80612ca11dc7bbc714a5d95e92574 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
The Cancellation library
========================

Intro
-----

This small library provides primitives for implementation of a cooperative cancellation of long running or asynchronous operations.
The design has been copied from the well-known CancellationTokenSource/CancellationToken classes of the .NET Framework

To use the library include `cancellation_token.h`.

Examples
--------

1. Simple check for cancellation

    ```c++
    void LongRunningOperation(TCancellationToken token) {
        ...
        if (token.IsCancellationRequested()) {
            return;
        }
        ...
    }

    TCancellationTokenSource source;
    TThread thread([token = source.Token()]() { LongRunningOperation(std::move(token)); });
    thread.Start();
    ...
    source.Cancel();
    thread.Join();
    ```

2. Exit via an exception

    ```c++
    void LongRunningOperation(TCancellationToken token) {
        try {
            for (;;) {
                ...
                token.ThrowIfCancellationRequested();
                ...
            }
        } catch (TOperationCancelledException const&) {
            return;
        } catch (...) {
            Y_FAIL("Never should be there")
        }
    }

    TCancellationTokenSource source;
    TThread thread([token = source.Token()]() { LongRunningOperation(std::move(token)); });
    thread.Start();
    ...
    source.Cancel();
    thread.Join();
    ```

3. Periodic poll with cancellation

    ```c++
    void LongRunningOperation(TCancellationToken token) {
        while (!token.Wait(PollInterval)) {
            ...
        }
    }

    TCancellationTokenSource source;
    TThread thread([token = source.Token()]() { LongRunningOperation(std::move(token)); });
    thread.Start();
    ...
    source.Cancel();
    thread.Join();
    ```

4. Waiting on the future

    ```c++
    TFuture<void> InnerOperation();
    TFuture<void> OuterOperation(TCancellationToken token) {
        return WaitAny(FirstOperation(), token.Future())
                    .Apply([token = std::move(token)](auto&&) {
                        token.ThrowIfCancellationRequested();
                    });
    }

    TCancellationTokenSource source;
    auto future = OuterOperation();
    ...
    source.Cancel()
    ...
    try {
        auto value = future.ExtractValueSync();
    } catch (TOperationCancelledException const&) {
        // cancelled
    }
    ```

5. Using default token when no cancellation needed

    ```c++
    void LongRunningOperation(TCancellationToken token) {
        ...
        if (token.IsCancellationRequested()) {
            return;
        }
        ...
    }

    // We do not want to cancel the operation. So, there is no need to create a cancellation token source
    LongRunningOperation(TCancellationToken::Default);
    ```