From b9fb1f39ac38a6649265ff7f429fd4af5ff9ccb2 Mon Sep 17 00:00:00 2001 From: Dukantic Date: Wed, 27 May 2026 09:41:15 +0200 Subject: [PATCH] threads wait --- src/game_core.c | 102 ++++++++++++++++++++++++++++++++++++------------ src/game_core.h | 14 ++++++- src/main.c | 13 +++--- 3 files changed, 97 insertions(+), 32 deletions(-) diff --git a/src/game_core.c b/src/game_core.c index feee7ad..ec8efe2 100644 --- a/src/game_core.c +++ b/src/game_core.c @@ -2,6 +2,7 @@ #include #include #include +#include const int directions[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}}; @@ -79,21 +80,37 @@ Board process_game(Board board) { void* process_chunk(void* arg) { ThreadArgs* ta = (ThreadArgs*)arg; Board board = *ta->board; - size_t x, y; - uint8_t count = 0; - for (y = ta->y_start; y < ta->y_end; y++) { - for (x = 0; x < board.width; x++) { - count = count_adjacent(board, x, y); - if (board.pixels[y * board.width + x] == BLACK && count == 3) { - board.next_pixels[y * board.width + x] = WHITE; - } else if (board.pixels[y * board.width + x] == WHITE && - count != 2 && count != 3) { - board.next_pixels[y * board.width + x] = BLACK; - } else { - board.next_pixels[y * board.width + x] = - board.pixels[y * board.width + x]; + while (!ta->stop) { + pthread_mutex_lock(&ta->mutex); + while (!ta->ready && !ta->stop) + pthread_cond_wait(&ta->cond_start, &ta->mutex); + if (ta->stop) { + pthread_mutex_unlock(&ta->mutex); + return NULL; + } + ta->ready = 0; + board = *ta->board; + pthread_mutex_unlock(&ta->mutex); + size_t x, y; + uint8_t count = 0; + for (y = ta->y_start; y < ta->y_end; y++) { + for (x = 0; x < board.width; x++) { + count = count_adjacent(board, x, y); + if (board.pixels[y * board.width + x] == BLACK && count == 3) { + board.next_pixels[y * board.width + x] = WHITE; + } else if (board.pixels[y * board.width + x] == WHITE && + count != 2 && count != 3) { + board.next_pixels[y * board.width + x] = BLACK; + } else { + board.next_pixels[y * board.width + x] = + board.pixels[y * board.width + x]; + } } } + pthread_mutex_lock(&ta->mutex); + ta->done = 1; + pthread_cond_signal(&ta->cond_done); + pthread_mutex_unlock(&ta->mutex); } return NULL; } @@ -111,22 +128,57 @@ ThreadArgs* make_chunk(Board* board, size_t n_threads) { return output; } -Board process_game_mt(ThreadArgs* ta, - Board board, - pthread_t* threads, - size_t n_threads) { +void launch_threads(ThreadArgs* ta, + Board* board, + pthread_t* threads, + size_t n_threads) { size_t i = 0; for (i = 0; i < n_threads; i++) { - ta[i].board = &board; + ta[i].board = board; + pthread_mutex_init(&ta[i].mutex, NULL); + pthread_cond_init(&ta[i].cond_done, NULL); + pthread_cond_init(&ta[i].cond_start, NULL); + ta[i].ready = 0; + ta[i].done = 0; + ta[i].stop = 0; pthread_create(&threads[i], NULL, process_chunk, &ta[i]); } - for (i = 0; i < n_threads; i++) { - pthread_join(threads[i], NULL); - } - uint32_t* tmp = board.next_pixels; - board.next_pixels = board.pixels; - board.pixels = tmp; - return board; } +void destroy_threads(pthread_t* threads, size_t n_threads, ThreadArgs* ta) { + for (size_t i = 0; i < n_threads; i++) { + pthread_mutex_lock(&ta[i].mutex); + ta[i].stop = 1; + pthread_cond_signal(&ta[i].cond_start); + pthread_mutex_unlock(&ta[i].mutex); + pthread_join(threads[i], NULL); + pthread_mutex_destroy(&ta[i].mutex); + pthread_cond_destroy(&ta[i].cond_start); + pthread_cond_destroy(&ta[i].cond_done); + } +} + +Board process_game_mt(ThreadArgs* ta, + Board* board, + pthread_t* threads, + size_t n_threads) { + for (size_t i = 0; i < n_threads; i++) { + pthread_mutex_lock(&ta[i].mutex); + ta[i].board = board; + ta[i].ready = 1; + ta[i].done = 0; + pthread_cond_signal(&ta[i].cond_start); + pthread_mutex_unlock(&ta[i].mutex); + } + for (size_t i = 0; i < n_threads; i++) { + pthread_mutex_lock(&ta[i].mutex); + while (!ta[i].done) + pthread_cond_wait(&ta[i].cond_done, &ta[i].mutex); + pthread_mutex_unlock(&ta[i].mutex); + } + uint32_t* tmp = board->next_pixels; + board->next_pixels = board->pixels; + board->pixels = tmp; + return (*board); +} diff --git a/src/game_core.h b/src/game_core.h index e7818ba..121e7d8 100644 --- a/src/game_core.h +++ b/src/game_core.h @@ -18,17 +18,29 @@ typedef struct { Board* board; size_t y_start; size_t y_end; + pthread_mutex_t mutex; + pthread_cond_t cond_start; + pthread_cond_t cond_done; + int ready; + int done; + int stop; } ThreadArgs; void free_board(Board board); Board init_board(size_t width, size_t height, int random); int count_adjacent(Board board, size_t x, size_t y); ThreadArgs* make_chunk(Board* board, size_t n_threads); +void* process_chunk(void* arg); Board process_game(Board board); Board process_game_mt(ThreadArgs* ta, - Board board, + Board* board, pthread_t* threads, size_t n_threads); +void launch_threads(ThreadArgs* ta, + Board* board, + pthread_t* threads, + size_t n_threads); +void destroy_threads(pthread_t* threads, size_t n_threads, ThreadArgs* ta); void display_board(Board board); void* process_chunk(void* ta); diff --git a/src/main.c b/src/main.c index 4396967..25575a1 100644 --- a/src/main.c +++ b/src/main.c @@ -12,8 +12,8 @@ #include "utils.h" #define SEED (5) -#define WIDTH (800) -#define HEIGHT (600) +#define WIDTH (1600) +#define HEIGHT (1200) #define SIM_WIDTH (800) #define SIM_HEIGHT (600) #define N_SIMULATION (1000) @@ -34,6 +34,7 @@ int main(int argc, char* argv[]) { if (flags.multithread) { ta = make_chunk(&b, (int)n_threads); threads = malloc(sizeof(pthread_t) * n_threads); + launch_threads(ta, &b, threads, n_threads); } TimeFrameHeap* timeframe = NULL; @@ -82,7 +83,7 @@ int main(int argc, char* argv[]) { SDL_RenderPresent(ren); b = !flags.multithread ? process_game(b) - : process_game_mt(ta, b, threads, n_threads); + : process_game_mt(ta, &b, threads, n_threads); } frame_time = SDL_GetTicks() - frame_start; clock_gettime(CLOCK_MONOTONIC, &end); @@ -105,8 +106,9 @@ int main(int argc, char* argv[]) { struct timespec start, end; clock_gettime(CLOCK_MONOTONIC, &start); for (int i = 0; i < N_SIMULATION; i++) { - b = !flags.multithread ? process_game(b) - : process_game_mt(ta, b, threads, n_threads); + b = !flags.multithread + ? process_game(b) + : process_game_mt(ta, &b, threads, n_threads); } clock_gettime(CLOCK_MONOTONIC, &end); double elapsed = @@ -120,4 +122,3 @@ int main(int argc, char* argv[]) { free(threads); return EXIT_SUCCESS; } -