Adobe Source Libraries 1.49.0
A collection of C++ libraries.
Loading...
Searching...
No Matches
task.hpp
Go to the documentation of this file.
1/*
2 Copyright 2013 Adobe Systems Incorporated
3 Distributed under the Boost Software License - Version 1.0 (see the accompanying file LICENSE
4 or a copy at https://stlab.github.io/adobe_source_libraries/licenses.html)
5*/
6
7/**************************************************************************************************/
8
9#ifndef ADOBE_TASK_HPP
10#define ADOBE_TASK_HPP
11
12/**************************************************************************************************/
13
14#if defined(_MSC_VER)
15
16#include <ppltasks.h>
17
18#else
19
20#include <exception>
21#include <functional>
22#include <list>
23#include <memory>
24#include <mutex>
25#include <string>
26#include <utility>
27
28#endif
29
30/**************************************************************************************************/
31
47
48/**************************************************************************************************/
49
50namespace adobe {
51
52/**************************************************************************************************/
53
54#if defined(_MSC_VER)
55
56using concurrency::cancel_current_task;
57using concurrency::cancellation_token;
58using concurrency::cancellation_token_registration;
59using concurrency::cancellation_token_source;
60using concurrency::task_canceled;
61
62#else
63
64/**************************************************************************************************/
65
66typedef std::function<void()>* cancellation_token_registration;
67
68/**************************************************************************************************/
69
70namespace detail {
71
72/**************************************************************************************************/
73
74struct cancel_state {
75 typedef std::list<std::function<void()>> list_type;
76
77 cancel_state() : canceled_(false) {}
78
79 void cancel() {
80 list_type list;
81 {
82 std::lock_guard<std::mutex> lock(guard_);
83 if (!canceled_) {
84 canceled_ = true;
85 swap(list, callback_list_);
86 }
87 }
88 for (const auto& f : list)
89 f();
90 }
91
92 template <typename F> // F models void ()
93 cancellation_token_registration register_callback(F f) {
94 /*
95 Avoid heap operations in the lock by inserting the element in a temporary list then
96 splicing that list into the callback_list_ under the lock.
97 */
98 list_type list;
99 list.push_back(std::move(f));
100 cancellation_token_registration result = nullptr;
101 bool canceled;
102 {
103 std::lock_guard<std::mutex> lock(guard_);
104 canceled = canceled_;
105 if (!canceled) {
106 /*
107 We splice the item on the front of the list, under the assumption that
108 if we do deregister, it will likely be in lifo order.
109 */
110 callback_list_.splice(begin(callback_list_), list);
111 result = &callback_list_.back();
112 }
113 }
114 if (canceled)
115 list.front()();
116 return result;
117 }
118
119 void deregister_callback(const cancellation_token_registration& token) {
120 /*
121 Avoid heap operations or user destructors in the lock by splicing out
122 the element to a temporary and allowing it to destruct with the temporary list
123 outside the lock.
124 */
125 list_type list;
126 {
127 std::lock_guard<std::mutex> lock(guard_);
128
129 auto i = find_if(begin(callback_list_), end(callback_list_),
130 [token](const std::function<void()>& x) { return &x == token; });
131 if (i != end(callback_list_))
132 list.splice(end(list), callback_list_, i);
133 }
134 }
135
136 bool is_canceled() const { return canceled_; }
137
138 std::mutex guard_;
139 volatile bool canceled_; // Write once, read many
140 list_type callback_list_;
141};
142
143/**************************************************************************************************/
144
145} // namespace detail
146
147/**************************************************************************************************/
148
149class cancellation_token_source;
150
151class cancellation_token {
152public:
153 template <typename F> // F models void ()
155 return state_ ? state_->register_callback(std::move(f)) : nullptr;
156 }
157
159 if (state_)
160 state_->deregister_callback(token);
161 }
162
163 bool is_cancelable() const { return static_cast<bool>(state_); }
164
165
166 bool is_canceled() const { return state_ ? state_->is_canceled() : false; }
167
168 static cancellation_token none() { return cancellation_token(); }
169
170 friend inline bool operator==(const cancellation_token& x, const cancellation_token& y) {
171 return x.state_ == y.state_;
172 }
173
174private:
176 cancellation_token() {}
177 explicit cancellation_token(std::shared_ptr<detail::cancel_state> s) : state_(std::move(s)) {}
178
179 std::shared_ptr<detail::cancel_state> state_;
180};
181
182inline bool operator!=(const cancellation_token& x, const cancellation_token& y) {
183 return !(x == y);
184}
185
186/**************************************************************************************************/
187
189public:
190 cancellation_token_source() : state_(std::make_shared<detail::cancel_state>()) {}
191
192 void cancel() const { state_->cancel(); }
193
195
196 friend inline bool operator==(const cancellation_token_source& x,
197 const cancellation_token_source& y) {
198 return x.state_ == y.state_;
199 }
200
201private:
202 std::shared_ptr<detail::cancel_state> state_;
203};
204
206 return !(x == y);
207}
208
209/**************************************************************************************************/
210
211class task_canceled : public std::exception {
212public:
213 task_canceled() noexcept {}
214 task_canceled(const char* message) : what_(message) {}
215 const char* what() const noexcept { return what_.empty() ? "task_canceled" : what_.c_str(); }
216
217private:
218 std::string what_;
219};
220
221/**************************************************************************************************/
222
223[[noreturn]] inline void cancel_current_task() { throw task_canceled(); }
224
225/**************************************************************************************************/
226
227#endif
228
229/**************************************************************************************************/
230
231} // namespace adobe
232
233/**************************************************************************************************/
234
235#endif
236
237/**************************************************************************************************/
friend bool operator==(const cancellation_token_source &x, const cancellation_token_source &y)
Definition task.hpp:196
cancellation_token get_token() const
Definition task.hpp:194
static cancellation_token none()
Definition task.hpp:168
bool is_cancelable() const
Definition task.hpp:163
cancellation_token_registration register_callback(F f) const
Definition task.hpp:154
friend class cancellation_token_source
Definition task.hpp:175
bool is_canceled() const
Definition task.hpp:166
friend bool operator==(const cancellation_token &x, const cancellation_token &y)
Definition task.hpp:170
void deregister_callback(const cancellation_token_registration &token) const
Definition task.hpp:158
const char * what() const noexcept
Definition task.hpp:215
task_canceled() noexcept
Definition task.hpp:213
task_canceled(const char *message)
Definition task.hpp:214
InputIterator find_if(InputIterator first, InputIterator last, Predicate pred)
find implementation
Definition find.hpp:165
void swap(any_regular_t &x, any_regular_t &y)
std::function< void()> * cancellation_token_registration
Definition task.hpp:66
bool operator!=(const forest< T > &x, const forest< T > &y)
Definition forest.hpp:722
void cancel_current_task()
Definition task.hpp:223
STL namespace.