Commit d32eb3f 1 parent a7bca33 commit d32eb3f Copy full SHA for d32eb3f
File tree 4 files changed +67
-17
lines changed
4 files changed +67
-17
lines changed Original file line number Diff line number Diff line change @@ -33,10 +33,33 @@ task_token& task::start(thread_pool& pool)
33
33
m_state = state::ENQUEUED;
34
34
m_token.reset ();
35
35
36
- pool.execute ([this ] { in_worker_thread (); });
36
+ m_token. m_work = pool.execute ([this ] { in_worker_thread (); });
37
37
return m_token;
38
38
}
39
39
40
+ bool task::try_skip (thread_pool& pool)
41
+ {
42
+ bool skipped = pool.try_skip (m_token.m_work );
43
+ if (skipped) {
44
+ m_token.m_canceled = true ;
45
+ call_finished ();
46
+ }
47
+
48
+ return skipped;
49
+ }
50
+
51
+ void task::call_finished ()
52
+ {
53
+ if (m_finished) {
54
+ try {
55
+ m_finished (m_token);
56
+ }
57
+ catch (const std::exception & ex) {
58
+ LOG (ERROR, " Exception executing 'finished' callback: %s\n " , ex.what ());
59
+ }
60
+ }
61
+ }
62
+
40
63
void task::in_worker_thread ()
41
64
{
42
65
m_state = state::RUNNING;
@@ -50,14 +73,7 @@ void task::in_worker_thread()
50
73
51
74
m_state = state::FINISHED;
52
75
53
- if (m_finished) {
54
- try {
55
- m_finished (m_token);
56
- }
57
- catch (const std::exception & ex) {
58
- LOG (ERROR, " Exception executing 'finished' callback: %s\n " , ex.what ());
59
- }
60
- }
76
+ call_finished ();
61
77
}
62
78
63
79
} // namespace base
Original file line number Diff line number Diff line change @@ -27,7 +27,6 @@ class task_token {
27
27
28
28
bool canceled () const { return m_canceled; }
29
29
float progress () const { return m_progress; }
30
- bool finished () const { return m_canceled || m_progress == m_progress_max; }
31
30
32
31
void cancel () { m_canceled = true ; }
33
32
void set_progress (float p)
@@ -51,6 +50,7 @@ class task_token {
51
50
std::atomic<bool > m_canceled;
52
51
std::atomic<float > m_progress;
53
52
float m_progress_min, m_progress_max;
53
+ const thread_pool::work* m_work = nullptr ;
54
54
};
55
55
56
56
class task {
@@ -71,6 +71,7 @@ class task {
71
71
void on_finished (func_t && f) { m_finished = std::move (f); }
72
72
73
73
task_token& start (thread_pool& pool);
74
+ bool try_skip (thread_pool& pool);
74
75
75
76
bool running () const { return m_state == state::RUNNING; }
76
77
@@ -86,6 +87,7 @@ class task {
86
87
87
88
private:
88
89
void in_worker_thread ();
90
+ void call_finished ();
89
91
90
92
std::atomic<state> m_state;
91
93
task_token m_token;
Original file line number Diff line number Diff line change @@ -26,12 +26,27 @@ thread_pool::~thread_pool()
26
26
join_all ();
27
27
}
28
28
29
- void thread_pool::execute (std::function<void ()>&& func)
29
+ const thread_pool::work* thread_pool::execute (std::function<void ()>&& func)
30
30
{
31
+ thread_pool::work_ptr work = std::make_unique<thread_pool::work>(std::move (func));
32
+ const thread_pool::work* result = work.get ();
31
33
const std::unique_lock lock (m_mutex);
32
34
ASSERT (m_running);
33
- m_work.push (std::move (func ));
35
+ m_work.push_back (std::move (work ));
34
36
m_cv.notify_one ();
37
+ return result;
38
+ }
39
+
40
+ bool thread_pool::try_skip (const work* w)
41
+ {
42
+ std::unique_lock<std::mutex> lock (m_mutex);
43
+ for (auto it = m_work.begin (); it != m_work.end (); ++it) {
44
+ if (w == it->get ()) {
45
+ m_work.erase (it);
46
+ return true ;
47
+ }
48
+ }
49
+ return false ;
35
50
}
36
51
37
52
void thread_pool::wait_all ()
@@ -79,9 +94,9 @@ void thread_pool::worker()
79
94
m_cv.wait (lock, [this ]() -> bool { return !m_running || !m_work.empty (); });
80
95
running = m_running;
81
96
if (m_running && !m_work.empty ()) {
82
- func = std::move (m_work.front ());
97
+ func = std::move (m_work.front ()-> m_func );
83
98
++m_doingWork;
84
- m_work.pop ();
99
+ m_work.pop_front ();
85
100
}
86
101
}
87
102
try {
Original file line number Diff line number Diff line change 9
9
#pragma once
10
10
11
11
#include < condition_variable>
12
+ #include < deque>
12
13
#include < functional>
13
14
#include < mutex>
14
- #include < queue>
15
15
#include < thread>
16
16
#include < vector>
17
17
18
18
namespace base {
19
19
20
20
class thread_pool {
21
21
public:
22
+ class work {
23
+ friend class thread_pool ;
24
+
25
+ public:
26
+ work (std::function<void ()>&& func) { m_func = std::move (func); }
27
+
28
+ private:
29
+ std::function<void ()> m_func = nullptr ;
30
+ };
31
+
32
+ typedef std::unique_ptr<work> work_ptr;
33
+
22
34
thread_pool (const size_t n);
23
35
~thread_pool ();
24
36
25
- void execute (std::function<void ()>&& func);
37
+ const work* execute (std::function<void ()>&& func);
38
+
39
+ // Tries to skip the work if it was not started yet, in other words, it
40
+ // removes the specified work from the queue if possible. Returns true if it
41
+ // was able to do so, or false otherwise.
42
+ bool try_skip (const work* w);
26
43
27
44
// Waits until the queue is empty.
28
45
void wait_all ();
@@ -39,7 +56,7 @@ class thread_pool {
39
56
std::mutex m_mutex;
40
57
std::condition_variable m_cv;
41
58
std::condition_variable m_cvWait;
42
- std::queue<std::function< void ()> > m_work;
59
+ std::deque<work_ptr > m_work;
43
60
int m_doingWork;
44
61
};
45
62
You can’t perform that action at this time.
0 commit comments