@@ -29,29 +29,48 @@ class TaskScheduler;
29
29
30
30
template <typename ResultType>
31
31
void Continuation<ResultType>::Run() {
32
+ // Run should not start an execution if the `Finally` method is not called
33
+ // for the task continuation.
32
34
if (!finally_callback_) {
33
35
impl_.Clear ();
34
36
return ;
35
37
}
36
38
37
- impl_.SetFailedCallback (
38
- [this ](client::ApiError error) { finally_callback_ (std::move (error)); });
39
-
39
+ // In case of the continuation is cancelled before calling the `Run` method,
40
+ // return the `Cancelled` error.
40
41
if (impl_.Cancelled ()) {
41
- finally_callback_ (client::ApiError::Cancelled ());
42
+ const auto finally_callback = std::move (finally_callback_);
43
+ if (finally_callback) {
44
+ finally_callback (client::ApiError::Cancelled ());
45
+ }
46
+
42
47
impl_.Clear ();
43
- finally_callback_ = nullptr ;
44
48
return ;
45
49
}
46
50
47
- impl_.Run ([this ](void * input, bool cancelled) {
48
- if (cancelled) {
49
- finally_callback_ (client::ApiError::Cancelled ());
50
- } else {
51
- auto value = std::move (*static_cast <ResultType*>(input));
52
- finally_callback_ (std::move (value));
51
+ // Use std::move to set the `finally_callback_` member to nullptr.
52
+ // It's needed to check if the execution is done, and prevent calling
53
+ // the `Cancel` method of the `Continuation` object.
54
+ // The `SetError` method of the `ExecutionContext` should not execute a
55
+ // callback as well.
56
+ impl_.SetFailedCallback ([=](client::ApiError error) {
57
+ const auto finally_callback = std::move (finally_callback_);
58
+ if (finally_callback) {
59
+ finally_callback (std::move (error));
60
+ }
61
+ });
62
+
63
+ impl_.Run ([=](void * input, bool cancelled) {
64
+ impl_.Clear ();
65
+
66
+ const auto finally_callback = std::move (finally_callback_);
67
+ if (finally_callback) {
68
+ if (cancelled) {
69
+ finally_callback (client::ApiError::Cancelled ());
70
+ } else {
71
+ finally_callback (std::move (*static_cast <ResultType*>(input)));
72
+ }
53
73
}
54
- finally_callback_ = nullptr ;
55
74
});
56
75
}
57
76
@@ -104,21 +123,19 @@ Continuation<ResultType>::Then(std::function<void(ExecutionContext, ResultType,
104
123
std::function<void (NewType)>)>
105
124
task) {
106
125
using NewResultType = internal::RemoveRefAndConst<NewType>;
107
- auto context = impl_.GetExecutionContext ();
108
-
109
- return impl_.Then ({[=](void * input, CallbackType callback) {
110
- auto in = *static_cast <ResultType*>(input);
111
- task (std::move (context), std::move (in),
112
- [callback, context](NewResultType arg) {
113
- callback (static_cast <void *>(&arg));
114
- });
115
- },
116
- [](void * input) {
117
- auto in = *static_cast <NewResultType*>(input);
118
- auto result =
119
- std::make_unique<NewResultType>(std::move (in));
120
- return internal::MakeUntypedUnique (std::move (result));
121
- }});
126
+ const auto context = impl_.GetExecutionContext ();
127
+
128
+ return impl_.Then (
129
+ {[=](void * input, CallbackType callback) {
130
+ auto in = *static_cast <ResultType*>(input);
131
+ task (std::move (context), std::move (in),
132
+ [=](NewResultType arg) { callback (static_cast <void *>(&arg)); });
133
+ },
134
+ [](void * input) {
135
+ auto in = *static_cast <NewResultType*>(input);
136
+ auto result = std::make_unique<NewResultType>(std::move (in));
137
+ return internal::MakeUntypedUnique (std::move (result));
138
+ }});
122
139
}
123
140
124
141
template <typename ResultType>
@@ -127,9 +144,9 @@ client::CancellationToken Continuation<ResultType>::CancelToken() {
127
144
return client::CancellationToken ();
128
145
}
129
146
130
- auto context = impl_.GetContext ();
147
+ auto context = impl_.GetExecutionContext ();
131
148
return client::CancellationToken (
132
- [context ]() mutable { context.CancelOperation (); });
149
+ [= ]() mutable { context.CancelOperation (); });
133
150
}
134
151
135
152
template <typename ResultType>
0 commit comments