Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Side by Side Diff: src/Scheduler.cpp

Issue 29367507: Issue #3595 - Add an actual scheduler; use joined threads for file system
Patch Set: Created Dec. 14, 2016, 5:38 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * This file is part of Adblock Plus <https://adblockplus.org/>, 2 * This file is part of Adblock Plus <https://adblockplus.org/>,
3 * Copyright (C) 2006-2016 Eyeo GmbH 3 * Copyright (C) 2006-2016 Eyeo GmbH
4 * 4 *
5 * Adblock Plus is free software: you can redistribute it and/or modify 5 * Adblock Plus is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 3 as 6 * it under the terms of the GNU General Public License version 3 as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
8 * 8 *
9 * Adblock Plus is distributed in the hope that it will be useful, 9 * Adblock Plus is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details. 12 * GNU General Public License for more details.
13 * 13 *
14 * You should have received a copy of the GNU General Public License 14 * You should have received a copy of the GNU General Public License
15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>. 15 * along with Adblock Plus. If not, see <http://www.gnu.org/licenses/>.
16 */ 16 */
17 17
18 #include "Scheduler.h" 18 #include "Scheduler.h"
19 #include <thread> 19 #include <thread>
20 using namespace AdblockPlus; 20 using namespace AdblockPlus;
21 21
22 namespace 22 namespace
23 { 23 {
24 void SingleUseThreadMain(std::function<void()> task) 24 void SingleUseThreadMain(std::function<void()> task)
25 { 25 {
26 task(); 26 task();
27 } 27 }
28 } 28 }
29 29
30 void Scheduler::StartImmediatelyInSingleUseThread(std::function<void()> task) 30 void StartImmediatelyInSingleUseDetachedThread(std::function<void()> task)
31 { 31 {
32 if (!task) 32 if (!task)
33 { 33 {
34 return; 34 return;
35 } 35 }
36 auto th = std::thread(SingleUseThreadMain, task); 36 auto th = std::thread(SingleUseThreadMain, task);
37 th.detach(); 37 th.detach();
38 } 38 }
39
40 OperationRunner::OperationRunner()
41 : isRunning(true)
42 {
43 th = std::thread([this]() { ThreadMain(); });
44 /*
45 * Note that we don't need to wait for our thread to start running
46 * before we consider the object fully constructed.
47 * Because of how the `wait()` statement in `ThreadMain` is written,
48 * any operation arriving before the thread begins will be
49 * processed immediately, without blocking on a notification.
50 */
sergei 2017/01/20 13:08:13 That comment is good however I don't think we need
Eric 2017/03/30 17:16:58 Behavior is always clearer *after* you read the co
sergei 2017/04/03 15:35:32 I'm talking about implementation without race cond
51 }
52
53 OperationRunner::~OperationRunner()
54 {
55 // Shut down the operation queue
56 Run([this]() { isRunning = false; });
57 th.join();
58 }
59
60 void OperationRunner::Run(std::function<void()> f)
61 {
62 UniqueLockType ul(m);
63 queue.push(f);
64 cv.notify_one();
65 }
66
67 void OperationRunner::ThreadMain()
68 {
69 while (true)
70 {
71 std::function<void()> op;
72 {
73 UniqueLockType ul(m);
74 // Checking the flag here avoids needing a second lock object
75 if (!isRunning)
sergei 2017/01/20 13:08:13 Why not to put isRunning into while condition? we
Eric 2017/03/30 17:16:58 Because it's not correct. It opens up an opportuni
sergei 2017/04/03 15:35:31 Could you please explain when that race condition
76 {
77 break;
78 }
79 cv.wait(ul, [this]() -> bool { return !queue.empty(); });
80 op = queue.front();
81 queue.pop();
82 }
83 // Assert `m` is unlocked
sergei 2017/01/20 13:08:13 I would remove that comment.
Eric 2017/03/30 17:16:58 Nope; it stays. Tracking when the mutex is locked
84 try
85 {
86 if (op)
sergei 2017/04/03 15:35:31 Why not to prevent putting of empty functions in t
87 {
88 op();
89 }
90 }
91 catch (std::exception& e)
sergei 2017/04/03 15:35:32 it generates a warning about unused local variable
92 {
93 // suppress
94 }
95 }
96 }
97
98 SingleUseWorker::SingleUseWorker()
99 {}
100
101 SingleUseWorker::~SingleUseWorker()
102 {
103 if (th.joinable())
sergei 2017/01/20 13:08:13 This implementation with if (th.joinable()) should
Eric 2017/03/30 17:16:58 Yes, you need to be able to join the thread either
104 {
105 th.join();
106 }
107 }
108
109 void SingleUseWorker::Run(std::function<void()> f)
110 {
111 th = std::move(std::thread(f));
sergei 2017/01/20 13:08:13 Do we really need to explicitly say std::move here
Eric 2017/03/30 17:16:58 It avoids a second copy, since there's already one
sergei 2017/04/03 15:35:32 Copy of what? JIC, std::thread cannot be copied.
112 }
113
114 void SingleUseWorker::Join()
115 {
116 th.join();
117 }
OLDNEW

Powered by Google App Engine
This is Rietveld