-
-
Save galek/016fd96d2a578b31aa32 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
include <iostream> | |
#include <thread> | |
#include <mutex> | |
#include <condition_variable> | |
std::mutex mtx; | |
std::mutex mtx2; | |
std::condition_variable cv; | |
std::condition_variable cv2; | |
bool threadsRunning = false; | |
bool threadsShouldExit = false; | |
int numThreadsDone = 0; | |
void worker() { | |
while(1){ | |
//wait until signaled to do work | |
{ | |
std::unique_lock<std::mutex> lck(mtx); | |
while (!threadsRunning || threadsShouldExit) cv.wait(lck); | |
//reset the condition so we won't start again prematurely | |
//Is this safe to set to false here? Would notify_all() vs notify_one() make a difference? | |
threadsRunning = false; | |
if(threadsShouldExit) | |
return; | |
} | |
doSomeWork(); | |
//wake up main thread when all threads are done | |
{ | |
std::unique_lock<std::mutex> lck(mtx2); | |
numThreadsDone++; | |
cv2.notify_one(); | |
} | |
} | |
} | |
const int NUM_THREADS = 4; | |
int main () | |
{ | |
std::thread threads[NUM_THREADS]; | |
for (int i=0; i<NUM_THREADS; ++i) | |
threads[i] = std::thread(worker); | |
bool usefulWorkIsToBeDone = false; | |
do { | |
//Signal threads to start work | |
{ | |
std::unique_lock<std::mutex> lck(mtx); | |
threadsRunning = true; | |
cv.notify_all(); | |
} | |
//While threads are busy, do some work here too | |
usefulWorkIsToBeDone = doSomeWorkOnMainThread(); | |
//Idle and wait for all threads to signal that they're finished | |
{ | |
std::unique_lock<std::mutex> lck2(mtx2); | |
while(numThreadsDone != NUM_THREADS) cv.wait(lck2); | |
//Is resetting the condition here safe? | |
numThreadsDone = 0; | |
} | |
} while(usefulWorkIsToBeDone); | |
//Change condition so threads can exit | |
//Is this safe to write here without a lock? | |
threadsShouldExit = true; | |
//Notify all threads one last time, so they can exit gracefully | |
{ | |
std::unique_lock<std::mutex> lck(mtx); | |
threadsRunning = true; | |
cv.notify_all(); | |
} | |
for (auto& th : threads) | |
th.join(); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment