Ik ben bezig met het multithreaded maken van een applicatie. Deze bestaat uit een main loop en een aantal workers. De workers kunnen onafhankelijk van elkaar tegelijk worden uitgevoerd, maar de main loop mag niet worden uitgevoerd als de workers aan het werk zijn. Dit alles moet continue worden uitgevoerd, zoals hieronder met pseudocode kan worden weergegeven
Middels boost heb ik zelf wat geprobeerd middels een aantal mutexen en condition variables, maar ik krijg nog niet het gewenste resultaat. Met de onderstaande code krijg ik als output dat de mainLoop twee keer wordt uitgevoerd en slechts een enkele worker wordt drie keer uitgevoerd. De gewenste output is dat continue de mainLoop wordt uitgevoerd gevolgd door alle workers.
C++:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| mainLoop() { while (true) { wachtTotAlleWorkersKlaarZijn(); DoeZelfBerekeningen(); NotifyWorkersDatZeVerderKunnen(); } } worker(int id) { while (true) { wachtOpNotifyVanMainLoop(); DoeBerekeningen(); } } |
Middels boost heb ik zelf wat geprobeerd middels een aantal mutexen en condition variables, maar ik krijg nog niet het gewenste resultaat. Met de onderstaande code krijg ik als output dat de mainLoop twee keer wordt uitgevoerd en slechts een enkele worker wordt drie keer uitgevoerd. De gewenste output is dat continue de mainLoop wordt uitgevoerd gevolgd door alle workers.
C++:
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
| class ThreadManager { private: boost::condition_variable updateReadyCondition; boost::mutex updateReadyMutex; bool updateReady = false; boost::condition_variable threadsReadyCondition; boost::mutex threadsReadyMutex; bool threadsReady = true; int numThreadsRunning = 0; int numThreadsStarted = 0; boost::mutex numThreadsRunningMutex; boost::mutex numThreadsStartedMutex; public: void threadStarted() { numThreadsStartedMutex.lock(); numThreadsStarted++; if (numThreadsStarted == NUM_THREADS) { updateReady = false; } checkIfThreadsAreReady(); numThreadsStartedMutex.unlock(); } void threadEnded() { numThreadsRunningMutex.lock(); numThreadsRunning--; checkIfThreadsAreReady(); numThreadsRunningMutex.unlock(); } void checkIfThreadsAreReady() { if (numThreadsRunning == 0 && numThreadsStarted == NUM_THREADS) { boost::unique_lock<boost::mutex> lock(threadsReadyMutex); threadsReady = true; updateReady = false; threadsReadyCondition.notify_all(); } } void mainLoop() { while (true) { boost::unique_lock<boost::mutex> lockThread(threadsReadyMutex); while (!threadsReady) { threadsReadyCondition.wait(lockThread); } cout << "update\n"; std::this_thread::sleep_for(std::chrono::milliseconds(1000)); cout << "update done\n"; numThreadsRunning = NUM_THREADS; numThreadsStarted = 0; boost::unique_lock<boost::mutex> lockUpdate(updateReadyMutex); updateReady = true; updateReadyCondition.notify_all(); } } void runThread(int id) { while (true) { boost::unique_lock<boost::mutex> lockUpdate(updateReadyMutex); while (!updateReady) { updateReadyCondition.wait(lockUpdate); } threadStarted(); cout << "start " << id << "\n"; std::this_thread::sleep_for(std::chrono::milliseconds(1000 * id)); cout << "end " << id << "\n"; threadEnded(); } } void start() { vector<boost::thread> threads; threads.push_back(boost::thread(&ThreadManager::mainLoop, this)); for (int i = 0; i < NUM_THREADS; i++) { threads.push_back(boost::thread(&ThreadManager::runThread, this, i)); } for (int i = 0; i < NUM_THREADS + 1; i++) { threads[i].join(); } } }; |