threads wait
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
#include <pthread.h>
|
||||
#include <stddef.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
const int directions[8][2] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1},
|
||||
{0, 1}, {1, -1}, {1, 0}, {1, 1}};
|
||||
@@ -79,6 +80,17 @@ Board process_game(Board board) {
|
||||
void* process_chunk(void* arg) {
|
||||
ThreadArgs* ta = (ThreadArgs*)arg;
|
||||
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;
|
||||
uint8_t count = 0;
|
||||
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;
|
||||
}
|
||||
|
||||
@@ -111,22 +128,57 @@ ThreadArgs* make_chunk(Board* board, size_t n_threads) {
|
||||
return output;
|
||||
}
|
||||
|
||||
Board process_game_mt(ThreadArgs* ta,
|
||||
Board board,
|
||||
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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
13
src/main.c
13
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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user