feat: improved task counting thread safety

This commit is contained in:
Sara Gerretsen 2025-09-23 12:56:44 +02:00
parent df31dea9c7
commit 32a9fc24e5

View file

@ -17,7 +17,7 @@
#define likely(cond_) (cond_)
#endif
#define SIM_MULTITHREADING 0
#define SIM_MULTITHREADING 1
namespace simulation {
bool drawDebugInfo{ true };
@ -35,6 +35,7 @@ static std::vector<std::shared_ptr<ThreadWorkload>> underpopulated{};
static std::vector<std::shared_ptr<ThreadWorkload>> born{};
static uint64_t generationStartTime{ 0 };
static unsigned tasks{ 0 }; std::mutex tasksMutex{};
static std::condition_variable tasksChanged{};
CellIterator::CellIterator(Cell begin, Cell end)
: state{ begin } , begin{ begin }, end{ end } {}
@ -77,14 +78,28 @@ static size_t CountNeighbors(Cell const &cell) {
return count;
}
static void BlockUntilTasksDone() {
std::unique_lock lock{ tasksMutex };
while (tasks > 0) {
tasksChanged.wait(lock);
}
}
static void TaskBegin() {
std::scoped_lock lock{ tasksMutex };
tasks++;
}
static void TaskComplete() {
std::scoped_lock lock{ tasksMutex };
if (--tasks == 0) {
SDL_Log("Generation Complete %lfs", (double)(SDL_GetTicksNS() - generationStartTime) * 0.0000000001);
}
tasksChanged.notify_all();
}
static void FindOverpopulated(std::shared_ptr<ThreadWorkload> wl) {
TaskBegin();
std::scoped_lock lock{ wl->mtx };
wl->changes.clear();
@ -102,6 +117,7 @@ static void FindOverpopulated(std::shared_ptr<ThreadWorkload> wl) {
}
static void FindUnderpopulated(std::shared_ptr<ThreadWorkload> wl) {
TaskBegin();
std::scoped_lock lock{ wl->mtx };
wl->changes.clear();
@ -119,6 +135,7 @@ static void FindUnderpopulated(std::shared_ptr<ThreadWorkload> wl) {
}
static void FindBorn(std::shared_ptr<ThreadWorkload> wl) {
TaskBegin();
std::scoped_lock lock{ wl->mtx };
wl->changes.clear();
@ -139,6 +156,7 @@ static void FindBorn(std::shared_ptr<ThreadWorkload> wl) {
static void PopulateChanges() {
static bool first_run{ true };
#if SIM_MULTITHREADING
BlockUntilTasksDone();
constexpr size_t split{ 4 };
if (first_run) {
first_run = false;
@ -148,8 +166,6 @@ static void PopulateChanges() {
}
SDL_Log("Multithreading ON");
{ std::scoped_lock lock{ tasksMutex };
tasks = 3 * split; }
generationStartTime = SDL_GetTicksNS();
size_t const seg_length{ living.size() / split };
for (size_t i{ 0 }; i < split; ++i) {
@ -196,6 +212,7 @@ static void PopulateChanges() {
}
void InitializeRandom(size_t livingChance, int64_t fillArea) {
BlockUntilTasksDone();
living.clear();
Cell itr{ 0, 0 };
@ -213,6 +230,7 @@ void InitializeRandom(size_t livingChance, int64_t fillArea) {
}
void Step() {
BlockUntilTasksDone();
for (std::shared_ptr<ThreadWorkload> wl : underpopulated) {
if (wl == nullptr) continue;
std::scoped_lock l{ wl->mtx };
@ -258,6 +276,7 @@ void Draw(SDL_Renderer *renderer, double cellSizePercent) {
if (!drawDebugInfo) {
return;
}
BlockUntilTasksDone();
for (std::shared_ptr<ThreadWorkload> wl : overpopulated) {
std::scoped_lock l{ wl->mtx };
SDL_SetRenderDrawColor(renderer, 255, 0, 0, 255);