threads wait
This commit is contained in:
102
src/game_core.c
102
src/game_core.c
@@ -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,21 +80,37 @@ 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;
|
||||||
size_t x, y;
|
while (!ta->stop) {
|
||||||
uint8_t count = 0;
|
pthread_mutex_lock(&ta->mutex);
|
||||||
for (y = ta->y_start; y < ta->y_end; y++) {
|
while (!ta->ready && !ta->stop)
|
||||||
for (x = 0; x < board.width; x++) {
|
pthread_cond_wait(&ta->cond_start, &ta->mutex);
|
||||||
count = count_adjacent(board, x, y);
|
if (ta->stop) {
|
||||||
if (board.pixels[y * board.width + x] == BLACK && count == 3) {
|
pthread_mutex_unlock(&ta->mutex);
|
||||||
board.next_pixels[y * board.width + x] = WHITE;
|
return NULL;
|
||||||
} else if (board.pixels[y * board.width + x] == WHITE &&
|
}
|
||||||
count != 2 && count != 3) {
|
ta->ready = 0;
|
||||||
board.next_pixels[y * board.width + x] = BLACK;
|
board = *ta->board;
|
||||||
} else {
|
pthread_mutex_unlock(&ta->mutex);
|
||||||
board.next_pixels[y * board.width + x] =
|
size_t x, y;
|
||||||
board.pixels[y * board.width + x];
|
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;
|
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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|
||||||
|
|||||||
13
src/main.c
13
src/main.c
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user