changeset 29:dae463bbf5ca

implementing multi-thread and refactoring
author Dennis C. M. <dennis@denniscm.com>
date Wed, 28 Jun 2023 20:10:55 +0100
parents 99592fae8ea1
children f945bcc3571f
files CMakeLists.txt src/algorithms.c src/algorithms.h src/main.c src/utils.c src/utils.h
diffstat 6 files changed, 198 insertions(+), 245 deletions(-) [+]
line wrap: on
line diff
--- a/CMakeLists.txt	Wed Jun 28 08:59:28 2023 +0100
+++ b/CMakeLists.txt	Wed Jun 28 20:10:55 2023 +0100
@@ -1,12 +1,17 @@
 cmake_minimum_required(VERSION 3.22)
 project(algo_animator)
 
-set(SOURCES src/main.c)
 set(FREETYPE_DIR /usr/local/include/freetype2)
 
 include_directories(${FREETYPE_DIR})
 
-add_executable(algo_animator ${SOURCES})
+add_executable(algo_animator 
+	src/main.c
+	src/algorithms.c
+	src/algorithms.h
+	src/utils.c
+	src/utils.h
+)
 
 target_link_libraries(algo_animator
     glut
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/algorithms.c	Wed Jun 28 20:10:55 2023 +0100
@@ -0,0 +1,29 @@
+#include "algorithms.h"
+
+
+void *bubble_sort(void *arguments) {
+	struct AlgoArgs *args = (struct AlgoArgs *)arguments;
+
+	printf("Size: %i\n", args->arr_size);
+	printf("Comparisons: %i\n", args->comparisons);
+	(args->comparisons)++;
+	printf("Comparisons: %i\n", args->comparisons);
+	/*
+	for (int i = 0; i < args->arr_size - 1; i++) {
+		//(*args->comparisons)++;
+
+		for (int j = 0; j < args->arr_size - i - 1; j++) {
+			//(*args->comparisons)++;
+			
+			if (args->arr[j].value > args->arr[j + 1].value) {
+				//swap_elements(j, j + 1, args->arr);
+			}
+			
+			
+			//usleep((*args->delay));
+			//bool test = false;
+			//delay_flow(args->delay, &test);
+		}
+	}
+	*/
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/algorithms.h	Wed Jun 28 20:10:55 2023 +0100
@@ -0,0 +1,18 @@
+#ifndef ALGORITHMS_H
+#define ALGORITHMS_H
+
+#include "utils.h"
+
+
+struct AlgoArgs {
+	struct Element *arr;
+	int arr_size;
+	int *comparisons;
+	useconds_t *delay;
+	bool pause;
+};
+
+void *bubble_sort(void *arguments);
+
+
+#endif // ALGORITHMS_H
--- a/src/main.c	Wed Jun 28 08:59:28 2023 +0100
+++ b/src/main.c	Wed Jun 28 20:10:55 2023 +0100
@@ -1,182 +1,27 @@
-#include <stdio.h>
-#include <stdlib.h>
+#include "algorithms.h"
 #include <GL/glut.h>
-#include <math.h>
-#include <time.h>
-#include <stdbool.h>
+#include <pthread.h>
 #include <ft2build.h>
 #include FT_FREETYPE_H
 
 
-#define WINDOW_WIDTH 1920
-#define WINDOW_HEIGHT 1080
-#define VPADDING 150
-#define RECT_WIDTH 5
-#define SPACE 1
-
-
-/* Helper functions */
-
-struct Element {
-	float value;
-	bool current;
-};
-
-struct Element *arr;
-int arr_size;
-
-void create_array() {
-	arr_size = WINDOW_WIDTH / (RECT_WIDTH + SPACE);
-	arr = malloc(arr_size * sizeof(struct Element));
-
-	float rect_increase = (WINDOW_HEIGHT - VPADDING * 2) / (float)(arr_size - 1);
-
-	for (int i = 1; i <= arr_size; i++) {
-		arr[i - 1].value = i * rect_increase;
-		arr[i - 1].current = false;
-	}
-}
-
+int window_width = 1920;
+int window_height = 1080;
+int vpadding = 150;
+int rect_width = 5;
+int space = 1;
 
-void swap_elements(int x, int y) {
-	struct Element temp = arr[x];
-	arr[x] = arr[y];
-	arr[y] = temp;
-}
-
-
-void randomize_array() {
-	srand(time(NULL));
-
-	// Fisher-Yates shuffle
-	for (int i = arr_size - 1; i > 0; i--) {
-		int j = rand() % (i + 1);
-
-		// Swap
-		swap_elements(i, j);
-	}
-}
-
-
-bool array_sorted() {
-	for (int i = 0; i < arr_size - 1; i++) {
-		if (arr[i].value > arr[i + 1].value) {
-			return false;
-		}
-	}
-
-	return true;
-}
-
-
-struct Algo {
-	char name[50];
-	void (*function)();
-};
-
-struct Algo algos[2];
+struct Algo algos[1];
 int selected_algo = 0;
 
-void algo_selector(int direction) {
-	int selection = selected_algo + direction;
-	int lower = 0;
-	int upper = (sizeof(algos) / sizeof(algos[0])) - 1;
-
-	if (selection >= lower && selection <= upper) {
-		selected_algo = selection;
-	}
-}
-
-
-/* Algorithms */
-
-// Just some variables to store the state of the running algorithm
-struct AlgoState {
-	int a;
-	int b;
-	int c;
-};
-
-struct AlgoState as;
-
-void reset_state() {
-	as.a = 0;
-	as.b = 0;
-	as.c = 0;
-}
-
-
-void bubble_sort() {
-
-	/*
-	 * a: Index of the current selection
-	 * b: Index boundary of the sorted array
-	 */
-
-	if (as.a < arr_size - 1 - as.b) {
-		arr[as.a].current = true;
-
-		if (arr[as.a].value > arr[as.a + 1].value) {
-			swap_elements(as.a + 1, as.a);
-		}
-
-		as.a++;
-	} else {
-		as.b++;
-		as.a = 0;
-	}
-}
-
-
-void selection_sort() {
-
-	/*
-	 * a: Index of current selection
-	 * b: Index of boundary of sorted array
-	 * c: Index of the minimum element
-	 */
-
-
-	if (as.a < arr_size) {
-		arr[as.a].current = true;
-
-		if (arr[as.a].value < arr[as.c].value) {
-
-			// Save new minimum
-			as.c = as.a;
-		}
-
-		as.a++;
-	} else {
-		swap_elements(as.b, as.c);
-
-		as.b++;
-		as.a = as.b;
-		as.c = as.a;
-	}
-}
-
-
-void quick_sort() {
-
-}
-
-
-void insertion_sort() {
-
-}
-
-
-void merge_sort() {
-
-}
-
-
-/* Render functions */
+struct AlgoArgs algo_args;
 
 FT_Library ft_library;
 FT_Face ft_face;
 
+pthread_t thread_id;
+
+
 void render_text(int x, int y, char* text) {
 	for (const char *c = text; *c; c++) {
 
@@ -225,38 +70,35 @@
 }
 
 
-int speed = 50;
-int iter_counter = 0;
-
 void display() {
 	glClear(GL_COLOR_BUFFER_BIT);
 
 	glBegin(GL_QUADS);
 
 	int x = 0;
-	for (int i = 0; i < arr_size; i++) {
+	for (int i = 0; i < algo_args.arr_size; i++) {
 
-		if (arr[i].current) {
+		if (algo_args.arr[i].current) {
 			glColor3f(1.0, 1.0, 1.0);
 		} else {
 			glColor3f(1.0, 0.7569, 0.0);
 		}
 
 		// Bottom left
-		glVertex2f(x, VPADDING);
+		glVertex2f(x, vpadding);
 
 		// Top left
-		glVertex2f(x, VPADDING + arr[i].value);
+		glVertex2f(x, vpadding + algo_args.arr[i].value);
 
 		// Top right
-		glVertex2f(x + RECT_WIDTH, VPADDING + arr[i].value);
+		glVertex2f(x + rect_width, vpadding + algo_args.arr[i].value);
 
 		// Bottom right
-		glVertex2f(x + RECT_WIDTH, VPADDING);
+		glVertex2f(x + rect_width, vpadding);
 
-		x += RECT_WIDTH + SPACE;
+		x += rect_width + space;
 
-		arr[i].current = false;
+		algo_args.arr[i].current = false;
 	}
 
 	glEnd();
@@ -266,112 +108,77 @@
 
 	// Top: Column 1
 	sprintf(text, "Algorithm: %s", algos[selected_algo].name);
-	render_text(20, WINDOW_HEIGHT - 50, text);
+	render_text(20, window_height - 50, text);
 
-	sprintf(text, "Speed: %i", speed);
-	render_text(20, WINDOW_HEIGHT - 80, text);
+	sprintf(text, "Delay: %u microseconds", algo_args.delay);
+	render_text(20, window_height - 80, text);
 
 	// Top: Column 2
-	sprintf(text, "Number of elements: %i", arr_size);
-	render_text(500, WINDOW_HEIGHT - 50, text);
+	sprintf(text, "Number of elements: %i", algo_args.arr_size);
+	render_text(500, window_height - 50, text);
 
-	sprintf(text, "Iterations: %i", iter_counter);
-	render_text(500, WINDOW_HEIGHT - 80, text);
-
+	sprintf(text, "Comparisons: %i", algo_args.comparisons);
+	render_text(500, window_height - 80, text);
 
 	// Bottom: Column 1
-	render_text(20, VPADDING - 50, "Press a or s to select an algorithm.");
-	render_text(20, VPADDING - 80, "Press u or d to modify speed.");
-	render_text(20, VPADDING - 110, "Press r to randomize the array.");
+	render_text(20, vpadding - 50, "Press a or s to select an algorithm.");
+	render_text(20, vpadding - 80, "Press u or d to modify speed.");
+	render_text(20, vpadding - 110, "Press r to randomize the array.");
 
 	// Bottom: Column 2
-	render_text(800, VPADDING - 50, "Press enter to run the algorithm.");
-	render_text(800, VPADDING - 80, "Press p to pause the algorithm.");
+	render_text(800, vpadding - 50, "Press enter to run the algorithm.");
+	render_text(800, vpadding - 80, "Press p to pause the algorithm.");
 
 	glutSwapBuffers();
 }
 
 
-/* Refresh function */
-
-
-bool run;
-int refresh_counter = 0;
-
 void idle() {
-	if (run) {
-		algos[selected_algo].function();
-		refresh_counter++;
-		iter_counter++;
-
-		if (refresh_counter == speed) {
-			glutPostRedisplay();
-			refresh_counter = 0;
-		}
-
-	} else {
-		glutPostRedisplay();
-	}
-
-	if (array_sorted()) {
-		run = false;
-	}
+	glutPostRedisplay();	
 }
 
 
-/* User input handler */
-
 void keyboard(unsigned char key, int x, int y) {
 
 	// s: Next algorithm
 	if (key == 115) {
-		algo_selector(1);
+
 	}
 
 	// a: Previous algorithm
 	if (key == 97) {
-		algo_selector(-1);
+
 	}
 
 	// r: Reset state
 	if (key == 114) {
-		randomize_array();
-
-		// Reset state
-		iter_counter = 0;
-		refresh_counter = 0;
-		run = false;
-
-		// Reset algo steps
-		reset_state();
+		randomize_array(algo_args.arr, algo_args.arr_size);
 	}
 
 	// u: Increase speed
 	if (key == 117) {
-		speed++;
+		algo_args.delay += 10;
 	}
 
 	// d: reduce speed
 	if (key == 100) {
-		if (speed > 1) {
-			speed--;
+		if (algo_args.delay > 10) {
+			algo_args.delay -= 10;
 		}
 	}
 
 	// enter: Run program
 	if (key == 13) {
-		run = true;
+		pthread_create(&thread_id, NULL, algos[selected_algo].function, (void *)&algo_args);
 	}
 
 	// p: Pause program
 	if (key == 112) {
-		run = false;
+
 	}
 }
 
 
-/* Set up functions */
-
 void setup_gl() {
 
 	// Set background dark
@@ -385,15 +192,15 @@
 	glMatrixMode(GL_PROJECTION);
 	glLoadIdentity();
 
-	/* 
+	/*
 	 * Creates projection matrix
 	 * x increases from left to right (0 to WINDOW_WIDTH)
 	 * y increases from bottom to top (0 to WINDOW_HEIGHT)
 	 */
 
-	gluOrtho2D(0, WINDOW_WIDTH, 0, WINDOW_HEIGHT);
+	gluOrtho2D(0, window_width, 0, window_height);
 
-	/* 
+	/*
 	 * This fucking line... I spent a day rendering weird symbols
 	 * because the padding that adds FreeType to each row of the bitmap
 	 * does not match the padding expected by GL.
@@ -429,17 +236,21 @@
 
 
 int main(int argc, char** argv) {
+	algo_args.comparisons = 0;
+	algo_args.delay = 100;
+
 	strcpy(algos[0].name, "Bubble sort");
-	algos[0].function = &bubble_sort;
+	algos[0].function = bubble_sort;
 
-	strcpy(algos[1].name, "Selection sort");
-	algos[1].function = &selection_sort;
+	algo_args.arr_size = window_width / (rect_width + space);
+	algo_args.arr = malloc(algo_args.arr_size * sizeof(struct Element));
 
-	create_array();
+	create_array(algo_args.arr, algo_args.arr_size, window_height, vpadding);
+	randomize_array(algo_args.arr, algo_args.arr_size);
 
 	glutInit(&argc, argv);
 	glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
-	glutInitWindowSize(WINDOW_WIDTH, WINDOW_HEIGHT);
+	glutInitWindowSize(window_width, window_height);
 	glutCreateWindow("Algorithm animator");
 
 	setup_gl();
@@ -450,7 +261,7 @@
 	glutIdleFunc(idle);
 	glutMainLoop();
 
-	free(arr);
+	free(algo_args.arr);
 
 	FT_Done_Face(ft_face);
 	FT_Done_FreeType(ft_library);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils.c	Wed Jun 28 20:10:55 2023 +0100
@@ -0,0 +1,61 @@
+#include "utils.h"
+
+
+void create_array(struct Element *arr, int arr_size, int window_height, int vpadding) {
+	float rect_increase = (window_height - vpadding * 2) / (float)(arr_size - 1);
+	for (int i = 1; i <= arr_size; i++) {
+		arr[i - 1].value = i * rect_increase;
+		arr[i - 1].current = false;
+	}
+}
+
+
+void swap_elements(int x, int y, struct Element *arr) {
+	struct Element temp = arr[x];
+	arr[x] = arr[y];
+	arr[y] = temp;
+}
+
+
+void randomize_array(struct Element *arr, int arr_size) {
+	srand(time(NULL));
+
+	// Fisher-Yates shuffle
+	for (int i = arr_size - 1; i > 0; i--) {
+		int j = rand() % (i + 1);
+
+		// Swap
+		swap_elements(i, j, arr);
+	}
+}
+
+
+bool array_sorted(struct Element *arr, int arr_size) {
+	for (int i = 0; i < arr_size - 1; i++) {
+		if (arr[i].value > arr[i + 1].value) {
+			return false;
+		}
+	}
+
+	return true;
+}
+
+
+void algorithm_selector(struct Algo *algos, int direction, int *selected_algorithm) {
+	int selection = *selected_algorithm + direction;
+	int lower = 0;
+	int upper = (int)((sizeof(algos) / sizeof(algos[0])) - 1);
+
+	if (selection >= lower && selection <= upper) {
+		*selected_algorithm = selection;
+	}
+}
+
+
+void delay_flow(useconds_t *delay, bool *pause) {
+	while (*pause) {
+		// Wait to resume
+	}
+	
+	usleep(*delay);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/utils.h	Wed Jun 28 20:10:55 2023 +0100
@@ -0,0 +1,29 @@
+#ifndef UTILS_H
+#define UTILS_H
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
+#include <stdbool.h>
+#include <unistd.h>
+
+
+struct Element {
+	float value;
+	bool current;
+};
+
+struct Algo {
+	char name[50];
+	void *(*function)(void *);
+};
+
+void create_array(struct Element *arr, int arr_size, int window_height, int vpadding);
+void swap_elements(int x, int y, struct Element *arr);
+void randomize_array(struct Element *arr, int arr_size);
+bool array_sorted(struct Element *arr, int arr_size);
+void algorithm_selector(struct Algo *algos, int direction, int *selected_algorithm);
+void delay_flow(useconds_t *delay, bool *pause);
+
+
+#endif // UTILS_H