forked from activeloopai/deeplake
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathqueue.hpp
More file actions
235 lines (195 loc) · 6.44 KB
/
Copy pathqueue.hpp
File metadata and controls
235 lines (195 loc) · 6.44 KB
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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
#pragma once
/**
* @file queue.hpp
* @brief Definition of the `queue` class.
*/
#include "priority.hpp"
#include <base/function.hpp>
#include <atomic>
#include <memory>
namespace async {
/**
* @brief Priority queue to submit and execute asynchronous tasks.
* The queue is used to submit tasks to be executed asynchronously.
* The tasks are executed in the order of their priority.
* The tasks can be submitted with the priority, which can be changed later. The tasks can be cancelled or waited to
* finish.
* The queue can be paused and resumed. When the queue is paused, the tasks are not executed, but they are not
* removed.
*/
class queue
{
protected:
class impl;
std::shared_ptr<impl> impl_;
protected:
explicit queue(std::shared_ptr<impl> i)
: impl_(std::move(i))
{
}
queue(const queue&) = delete;
queue& operator=(const queue&) = delete;
queue(queue&&) = delete;
queue& operator=(queue&&) = delete;
~queue();
/// @name Type definitions
/// @{
public:
/**
* @brief Class representing unique id of the task submitted to the queue.
*/
class id_type
{
friend class impl;
public:
/**
* @brief Default constructor.
* The id is being default constructed and then passed to the `queue::submit` function as an argument. The
* `submit` stores the id of the task.
*/
id_type() = default;
id_type(const id_type&) = delete;
id_type& operator=(const id_type&) = delete;
id_type(id_type&&) = delete;
id_type& operator=(id_type&&) = delete;
~id_type() noexcept;
/**
* @brief Returns `true` if the task is still valid. If the task is completed, this conversion will return
* `false`.
*/
explicit inline operator bool() const noexcept
{
return (queue_impl_.load(std::memory_order_acquire) != nullptr);
}
/// Priority of the task.
int priority() const;
/// Change the priority of the task.
void set_priority(int p) const;
/**
* @brief Cancel the task.
* If the task is already running, it will not be cancelled. To wait for the task to finish please use
* `remove_or_wait` function.
*/
void remove() const noexcept;
/**
* @brief Cancel the task or waits to finish.
* If the task is already running, this function will wait for its completion.
*/
void remove_or_wait() const;
/// Waits for the task to finish.
void wait() const noexcept;
/// Reset the id connection to the queue.
void reset() noexcept;
private:
std::atomic<impl*> queue_impl_ = nullptr;
std::atomic<int> worker_id_ = -1;
int task_id_ = -1;
};
/// @}
public:
/**
* @brief This function will handle exceptions thrown by the tasks.
* @note The functor should be thread safe.
*/
void set_exception_handler(base::function<void(std::exception_ptr)> handler) noexcept;
/// Checks if the calling thread is a worker thread of the queue.
bool is_this_thread_worker() const noexcept;
public:
/**
* @brief Pauses the queue execution.
* If the queue is paused, this function has no any effect.
* The execution can be resumed by `resume` function.
*/
void pause() noexcept;
/**
* @brief Resumes the queue execution.
* If the queue is not paused, this function has no any effect.
*/
void resume() noexcept;
public:
/**
* @brief Submits the given function to the queue with the highest priority.
* @param f Function to run in queue.
* @param task_id If non-null, then the id of the task will be stored in `task_id`.
*/
inline void submit(base::function<void()>&& f, id_type* task_id = nullptr)
{
submit(std::move(f), max_priority, task_id);
}
/**
* @brief Submits the given function to the queue with the given priority.
* @param f Function to run in queue.
* @param task_id If non-null, then the id of the task will be stored in `task_id`.
*/
void submit(base::function<void()>&& f, int priority, id_type* task_id = nullptr);
/**
* @brief Runs the given function in the current thread if it is a worker thread of the queue; otherwise, submits
* the function
* @param f Function to run in queue.
* @param priority Priority of the task.
* @param task_id If non-null, then the id of the task will be stored in `task_id`.
*/
inline void run_or_submit(base::function<void()>&& f, int priority = max_priority, id_type* task_id = nullptr)
{
if (is_this_thread_worker()) {
f();
} else {
submit(std::move(f), priority, task_id);
}
}
/**
* @brief Removes all tasks from the queue.
*/
void clear() noexcept;
/// Returns the number of task in the queue.
unsigned size() const noexcept;
/// Checks if the queue is empty.
inline bool empty() const noexcept
{
return size() == 0;
}
/// Returns number of threads of this queue.
int num_threads() const noexcept;
};
class main_queue final : public queue
{
public:
/// Depends on the platform this may be initialized with a single worker thread.
main_queue();
/**
* @brief Enable/disable detailed tracking (impacts performance)
* @param enable Whether to track detailed metrics per task
*/
void enable_detailed_pressure_tracking(bool enable);
/// @name Internal functions not intended for public use.
/// @{
public:
static bool iterate_all();
bool try_iterate();
/// @}
private:
class impl;
};
class bg_queue final : public queue
{
public:
/**
* @brief Creates queue with the given number of threads.
*
* Checks system available memory periodically if memory monitoring is enabled.
* In case if there is no available memory the worker threads will sleep for some
* time and again check for free memory to resume.
*
* @param num_threads Number of queue threads.
* @param monitor_system_memory Enable system memory monitoring if true.
*/
explicit bg_queue(int num_threads, bool monitor_system_memory = false);
/**
* @brief Changes the number of threads of the queue.
* @param nt New number of threads.
*/
void change_num_threads(int nt);
private:
class impl;
};
} // namespace async