threads wait

This commit is contained in:
2026-05-27 09:41:15 +02:00
parent 2e150d5856
commit b9fb1f39ac
3 changed files with 97 additions and 32 deletions

View File

@@ -2,6 +2,7 @@
#include <pthread.h> #include <pthread.h>
#include <stddef.h> #include <stddef.h>
#include <stdlib.h> #include <stdlib.h>
#include <unistd.h>
const int directions[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, const int directions[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1},
{0, 1}, {1, -1}, {1, 0}, {1, 1}}; {0, 1}, {1, -1}, {1, 0}, {1, 1}};
@@ -79,6 +80,17 @@ Board process_game(Board board) {
void* process_chunk(void* arg) { void* process_chunk(void* arg) {
ThreadArgs* ta = (ThreadArgs*)arg; ThreadArgs* ta = (ThreadArgs*)arg;
Board board = *ta->board; Board board = *ta->board;
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; size_t x, y;
uint8_t count = 0; uint8_t count = 0;
for (y = ta->y_start; y < ta->y_end; y++) { for (y = ta->y_start; y < ta->y_end; y++) {
@@ -95,6 +107,11 @@ void* process_chunk(void* arg) {
} }
} }
} }
pthread_mutex_lock(&ta->mutex);
ta->done = 1;
pthread_cond_signal(&ta->cond_done);
pthread_mutex_unlock(&ta->mutex);
}
return NULL; return NULL;
} }
@@ -111,22 +128,57 @@ ThreadArgs* make_chunk(Board* board, size_t n_threads) {
return output; return output;
} }
Board process_game_mt(ThreadArgs* ta, void launch_threads(ThreadArgs* ta,
Board board, Board* board,
pthread_t* threads, pthread_t* threads,
size_t n_threads) { size_t n_threads) {
size_t i = 0; size_t i = 0;
for (i = 0; i < n_threads; i++) { 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]); 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);
}

View File

@@ -18,17 +18,29 @@ typedef struct {
Board* board; Board* board;
size_t y_start; size_t y_start;
size_t y_end; 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; } ThreadArgs;
void free_board(Board board); void free_board(Board board);
Board init_board(size_t width, size_t height, int random); Board init_board(size_t width, size_t height, int random);
int count_adjacent(Board board, size_t x, size_t y); int count_adjacent(Board board, size_t x, size_t y);
ThreadArgs* make_chunk(Board* board, size_t n_threads); ThreadArgs* make_chunk(Board* board, size_t n_threads);
void* process_chunk(void* arg);
Board process_game(Board board); Board process_game(Board board);
Board process_game_mt(ThreadArgs* ta, Board process_game_mt(ThreadArgs* ta,
Board board, Board* board,
pthread_t* threads, pthread_t* threads,
size_t n_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 display_board(Board board);
void* process_chunk(void* ta); void* process_chunk(void* ta);

View File

@@ -12,8 +12,8 @@
#include "utils.h" #include "utils.h"
#define SEED (5) #define SEED (5)
#define WIDTH (800) #define WIDTH (1600)
#define HEIGHT (600) #define HEIGHT (1200)
#define SIM_WIDTH (800) #define SIM_WIDTH (800)
#define SIM_HEIGHT (600) #define SIM_HEIGHT (600)
#define N_SIMULATION (1000) #define N_SIMULATION (1000)
@@ -34,6 +34,7 @@ int main(int argc, char* argv[]) {
if (flags.multithread) { if (flags.multithread) {
ta = make_chunk(&b, (int)n_threads); ta = make_chunk(&b, (int)n_threads);
threads = malloc(sizeof(pthread_t) * n_threads); threads = malloc(sizeof(pthread_t) * n_threads);
launch_threads(ta, &b, threads, n_threads);
} }
TimeFrameHeap* timeframe = NULL; TimeFrameHeap* timeframe = NULL;
@@ -82,7 +83,7 @@ int main(int argc, char* argv[]) {
SDL_RenderPresent(ren); SDL_RenderPresent(ren);
b = !flags.multithread b = !flags.multithread
? process_game(b) ? 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; frame_time = SDL_GetTicks() - frame_start;
clock_gettime(CLOCK_MONOTONIC, &end); clock_gettime(CLOCK_MONOTONIC, &end);
@@ -105,8 +106,9 @@ int main(int argc, char* argv[]) {
struct timespec start, end; struct timespec start, end;
clock_gettime(CLOCK_MONOTONIC, &start); clock_gettime(CLOCK_MONOTONIC, &start);
for (int i = 0; i < N_SIMULATION; i++) { for (int i = 0; i < N_SIMULATION; i++) {
b = !flags.multithread ? process_game(b) b = !flags.multithread
: process_game_mt(ta, b, threads, n_threads); ? process_game(b)
: process_game_mt(ta, &b, threads, n_threads);
} }
clock_gettime(CLOCK_MONOTONIC, &end); clock_gettime(CLOCK_MONOTONIC, &end);
double elapsed = double elapsed =
@@ -120,4 +122,3 @@ int main(int argc, char* argv[]) {
free(threads); free(threads);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }