diff --git a/defines.h b/defines.h index e9d7c1a..709772a 100644 --- a/defines.h +++ b/defines.h @@ -3,11 +3,10 @@ #define STATUS_QUIT_PROGRAM 1 #define STATUS_RUN_BACKEND 2 #define STATUS_RELOAD_DIRECTORY 4 -#define STATUS_UPDATE_SCREEN_GENERIC 8 +#define STATUS_UPDATE_ASYNC_REFRESH 8 #define STATUS_UPDATE_SCREEN_RESIZE 16 #define STATUS_UPDATE_SCREEN_CLEAR 32 -#define STATUS_UPDATE_SCREEN_DIR_CHANGE 64 -#define STATUS_UPDATE_SCREEN_MASK (STATUS_UPDATE_SCREEN_GENERIC | STATUS_UPDATE_SCREEN_RESIZE | STATUS_UPDATE_SCREEN_CLEAR | STATUS_UPDATE_SCREEN_DIR_CHANGE) +#define STATUS_UPDATE_SCREEN_MASK (STATUS_UPDATE_ASYNC_REFRESH | STATUS_UPDATE_SCREEN_RESIZE | STATUS_UPDATE_SCREEN_CLEAR) #define STATUS_USER_ROOT 128 #define STATUS_INPUT_MATCH 256 #define STATUS_DELTA_TIME 512 @@ -15,6 +14,12 @@ #define SETTINGS_HAS_COLOR 1 +#define RENDER_QUEUE_TOP 0 +#define RENDER_QUEUE_LFT 1 +#define RENDER_QUEUE_MID 2 +#define RENDER_QUEUE_RGT 3 +#define RENDER_QUEUE_BTM 4 + #define FILE_MODIFIERS_HIDDEN_FILES 1 #define FILE_MODIFIERS_SORT_BITMASK 126 /* 00000000000000000000000001111110*/ #define FILE_MODIFIERS_SORT_ALPHABETIC 2 diff --git a/interactions.c b/interactions.c index c50f8cc..39d9bab 100644 --- a/interactions.c +++ b/interactions.c @@ -177,14 +177,14 @@ void move_down(unsigned long passes){ /*bounds checking happens within thread_mid*/ mid_dir.current_file += passes; - status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_GENERIC); + status |= (STATUS_RUN_BACKEND); } void move_up(unsigned long passes){ /*bounds checking happens within thread_mid*/ mid_dir.current_file -= passes; - status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_GENERIC); + status |= (STATUS_RUN_BACKEND); } void move_left(unsigned long passes){ unsigned long i; @@ -194,7 +194,7 @@ void move_left(unsigned long passes){ FAIL("move_left", "unhandled error of chdir"); } } - status |= (STATUS_RUN_BACKEND | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_GENERIC | STATUS_UPDATE_SCREEN_DIR_CHANGE); + status |= (STATUS_RUN_BACKEND | STATUS_RELOAD_DIRECTORY); } void move_right(){ @@ -244,7 +244,7 @@ void move_right(){ free(cmd); free(mime); } - status |= (STATUS_RUN_BACKEND | STATUS_RELOAD_DIRECTORY | STATUS_UPDATE_SCREEN_GENERIC | STATUS_UPDATE_SCREEN_DIR_CHANGE); + status |= (STATUS_RUN_BACKEND | STATUS_RELOAD_DIRECTORY); } void toggle_hidden_files(){ @@ -256,11 +256,11 @@ void toggle_selection(){ } void jump_bottom(){ mid_dir.current_file = mid_dir.file_list + mid_dir.file_count - 1; - status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_GENERIC); + status |= (STATUS_RUN_BACKEND); } void jump_top(){ mid_dir.current_file = mid_dir.file_list; - status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_GENERIC); + status |= (STATUS_RUN_BACKEND); } void open_with(){ TODO; @@ -297,7 +297,7 @@ void order_by(unsigned long passes, int index){ seed = time(NULL); order_func = key_binding[index].black_magic; - status |= (STATUS_RUN_BACKEND | STATUS_UPDATE_SCREEN_GENERIC | STATUS_RELOAD_DIRECTORY); + status |= (STATUS_RUN_BACKEND | STATUS_RELOAD_DIRECTORY); } void cmd_on_selected(unsigned long passes, int index){ TODO; diff --git a/main.c b/main.c index 3c038be..527e337 100644 --- a/main.c +++ b/main.c @@ -36,6 +36,7 @@ extern pthread_mutex_t mutex_btm; extern pthread_mutex_t mutex_lft; extern pthread_mutex_t mutex_mid; extern pthread_mutex_t mutex_rgt; +extern volatile char render_queue[5]; char *input; /*used in user_interactions*/ char *terminal_width_empty_line; /* used in user_interactions */ @@ -141,6 +142,7 @@ void render_pass(){ if (status & STATUS_UPDATE_SCREEN_CLEAR) { clear(); + status &= ~STATUS_UPDATE_SCREEN_CLEAR; } if (status & STATUS_UPDATE_SCREEN_RESIZE) { @@ -158,48 +160,43 @@ void render_pass(){ mvwin(win_b, terminal_height-1, 0); } - if (status & STATUS_UPDATE_SCREEN_MASK) { - if (pthread_mutex_trylock(&mutex_top) == 0) { - wnoutrefresh(win_t); - pthread_mutex_unlock(&mutex_top); - } else { - mvwaddstr(win_t, terminal_height/2, terminal_width/4, "LOADING"); - status |= STATUS_UPDATE_SCREEN_GENERIC; - } - if (pthread_mutex_trylock(&mutex_rgt) == 0) { - wnoutrefresh(win_r); - pthread_mutex_unlock(&mutex_rgt); - } else { - mvwaddstr(win_r, terminal_height/2, terminal_width/4, "LOADING"); - status |= STATUS_UPDATE_SCREEN_GENERIC; - } - if (pthread_mutex_lock(&mutex_mid) == 0) { - wnoutrefresh(win_m); - pthread_mutex_unlock(&mutex_mid); - } else { - mvwaddstr(win_m, terminal_height/2, terminal_width/4, "LOADING"); - status |= STATUS_UPDATE_SCREEN_GENERIC; - } - if (pthread_mutex_trylock(&mutex_lft) == 0) { - wnoutrefresh(win_l); - pthread_mutex_unlock(&mutex_lft); - } else { - mvwaddstr(win_l, terminal_height/2, terminal_width/4, "LOADING"); - status |= STATUS_UPDATE_SCREEN_GENERIC; - } - if (pthread_mutex_trylock(&mutex_btm) == 0) { - wnoutrefresh(win_b); - pthread_mutex_unlock(&mutex_btm); - } else { - mvwaddstr(win_b, terminal_height/2, terminal_width/4, "LOADING"); - status |= STATUS_UPDATE_SCREEN_GENERIC; - } - doupdate(); - status &= ~(STATUS_UPDATE_SCREEN_MASK - STATUS_UPDATE_SCREEN_DIR_CHANGE); + /* render_queue is modified both by this and its associated thread without mutexes, this is intentional. + * reason being that since rendering is done in the same thread as the logic, + * using mutexes actually slows this down more than the result of an unknown state. + * an unknown state may be an incomplete render, which in my tests wont crash, or one too many renders. + * both of these chances are non distructive. + * doing rendering async is done because + * A: its funny + * B: previous render pipelines may have caused win_r to lack behind + * C: slowdown as a result of too many renders */ + if (render_queue[RENDER_QUEUE_TOP] || status & (STATUS_UPDATE_SCREEN_RESIZE | STATUS_UPDATE_SCREEN_CLEAR)) { + wnoutrefresh(win_t); + render_queue[RENDER_QUEUE_TOP] = 0; + status |= STATUS_UPDATE_ASYNC_REFRESH; } - if (status & STATUS_UPDATE_SCREEN_DIR_CHANGE) { - status &= ~STATUS_UPDATE_SCREEN_DIR_CHANGE; - status |= STATUS_UPDATE_SCREEN_GENERIC; + if (render_queue[RENDER_QUEUE_LFT] || status & (STATUS_UPDATE_SCREEN_RESIZE | STATUS_UPDATE_SCREEN_CLEAR)) { + wnoutrefresh(win_l); + render_queue[RENDER_QUEUE_LFT] = 0; + status |= STATUS_UPDATE_ASYNC_REFRESH; + } + if (render_queue[RENDER_QUEUE_MID] || status & (STATUS_UPDATE_SCREEN_RESIZE | STATUS_UPDATE_SCREEN_CLEAR)) { + wnoutrefresh(win_m); + render_queue[RENDER_QUEUE_MID] = 0; + status |= STATUS_UPDATE_ASYNC_REFRESH; + } + if (render_queue[RENDER_QUEUE_RGT] || status & (STATUS_UPDATE_SCREEN_RESIZE | STATUS_UPDATE_SCREEN_CLEAR)) { + wnoutrefresh(win_r); + render_queue[RENDER_QUEUE_RGT] = 0; + status |= STATUS_UPDATE_ASYNC_REFRESH; + } + if (render_queue[RENDER_QUEUE_BTM] || status & (STATUS_UPDATE_SCREEN_RESIZE | STATUS_UPDATE_SCREEN_CLEAR)) { + wnoutrefresh(win_b); + render_queue[RENDER_QUEUE_BTM] = 0; + status |= STATUS_UPDATE_ASYNC_REFRESH; + } + if (status & STATUS_UPDATE_SCREEN_MASK) { + doupdate(); + status &= ~STATUS_UPDATE_SCREEN_MASK; } } /*this function exists for things done at startup (initialization, reading config, etc)*/ diff --git a/threading.c b/threading.c index 24ac03f..152b11c 100644 --- a/threading.c +++ b/threading.c @@ -46,6 +46,7 @@ unsigned long top_width; extern unsigned int terminal_width; extern unsigned int status; +volatile char render_queue[RENDER_QUEUE_BTM+1]; extern char *global_path; unsigned int btm_status; @@ -71,6 +72,7 @@ void *thread_mid(){ char *path = malloc(strlen(global_path)+1); memcpy(path, global_path, strlen(global_path)+1); + if (local_status & STATUS_RELOAD_DIRECTORY) { long index = mid_dir.current_file - mid_dir.file_list; @@ -85,6 +87,8 @@ void *thread_mid(){ } else { /* the hovered dir is empty */ mid_dir.current_file = NULL; } + + } if (mid_dir.current_file > mid_dir.file_list + mid_dir.file_count - 1) { @@ -95,12 +99,14 @@ void *thread_mid(){ } /* rendering */ + render_queue[RENDER_QUEUE_MID] = 0; werase(win_m); if (mid_dir.file_count == 0) { mvwaddstr(win_m, 0, 0, "empty"); } else { print_dir(win_m, 1, &mid_dir); } + render_queue[RENDER_QUEUE_MID] = 1; pthread_cond_signal(&cond_rgt); pthread_cond_signal(&cond_top); @@ -138,6 +144,7 @@ void *thread_lft(){ char *path = malloc(strlen(global_path)+1); memcpy(path, global_path, strlen(global_path)+1); + render_queue[RENDER_QUEUE_LFT] = 0; if (strcmp(path, "/") != 0) { path[strrchr(path, '/')-path+1] = '\0'; path[strrchr(path, '/')-path] = '\0'; @@ -166,6 +173,8 @@ void *thread_lft(){ /* rendering */ werase(win_l); print_dir(win_l, 0, &lft_dir); + render_queue[RENDER_QUEUE_LFT] = 1; + pthread_mutex_unlock(&mutex_lft); free(path); @@ -200,6 +209,8 @@ void *thread_rgt(){ pthread_mutex_unlock(&mutex_mid); + render_queue[RENDER_QUEUE_RGT] = 0; + werase(win_r); if (rgt_dir.current_file->permissions & S_IRUSR) { if (rgt_dir.current_file->file_type &= FILE_TYPE_DIR) { #if SETTINGS_UEBERZUG_IMAGE_PREVIEW != 0 @@ -215,32 +226,22 @@ void *thread_rgt(){ } else { /* the hovered dir is empty */ rgt_dir.current_file = NULL; } + print_dir(win_r, 0, &rgt_dir); } else if ((status & STATUS_DELTA_TIME) != STATUS_DELTA_TIME && rgt_dir.file_count > 0) { - free(rgt_buffer); rgt_buffer = preview_file(rgt_dir.current_file); rgt_dir.current_file->file_type |= FILE_TYPE_OPEN_FILE; - - - + if (rgt_dir.current_file->file_type == FILE_TYPE_OPEN_FILE) { + mvwaddnstr(win_r, 0, 0, rgt_buffer, (terminal_width/2) * terminal_width); + } else if ((rgt_dir.current_file->permissions & S_IRUSR) == 0) { + mvwaddstr(win_r, 0, 0, "not accessible"); + } } } - /* rendering */ - werase(win_r); - wattroff(win_r, A_REVERSE); - if (!rgt_dir.current_file) { - mvwaddstr(win_r, 0, 0, "not accessible"); - }else if (rgt_dir.current_file->file_type == FILE_TYPE_OPEN_FILE) { - mvwaddnstr(win_r, 0, 0, rgt_buffer, (terminal_width/2) * terminal_width); - } else if ((rgt_dir.current_file->permissions & S_IRUSR) == 0) { - mvwaddstr(win_r, 0, 0, "not accessible"); - } else { - print_dir(win_r, 0, &rgt_dir); - } - + render_queue[RENDER_QUEUE_RGT] = 1; pthread_mutex_unlock(&mutex_rgt); long i; @@ -261,6 +262,8 @@ void *thread_top(){ pthread_mutex_lock(&mutex_top); pthread_cond_wait(&cond_top, &mutex_top); + + render_queue[RENDER_QUEUE_TOP] = 0; free(top_buffer); if(global_path == NULL) { @@ -286,6 +289,7 @@ void *thread_top(){ mvwaddstr(win_t, 0, strlen(top_buffer)+1, mid_dir.current_file->file_name); } } + render_queue[RENDER_QUEUE_TOP] = 1; pthread_mutex_unlock(&mutex_top); @@ -303,6 +307,7 @@ void *thread_btm(){ pthread_cond_wait(&cond_btm, &mutex_btm); unsigned int local_status = btm_status; + render_queue[RENDER_QUEUE_BTM] = 0; if (local_status & (STATUS_RUN_BACKEND | STATUS_RELOAD_DIRECTORY)) { /*{{{ parse storage info; the fold of shame*/ @@ -404,8 +409,8 @@ void *thread_btm(){ if (*top_buffer != ' ') { /*printing ' ' (standard initialized value, see threading_init) makes valgrind throw a fuss*/ mvwprintw(win_b, 0, 0, "%s", btm_buffer); } + render_queue[RENDER_QUEUE_BTM] = 1; pthread_mutex_unlock(&mutex_btm); - /*the printing of the input char is done in user_interactions*/ /*the printing of all possible inputs are done in user_interactions */ diff --git a/window.c b/window.c index bd89369..c77b991 100644 --- a/window.c +++ b/window.c @@ -45,7 +45,9 @@ void window_top(WINDOW *win){ pthread_mutex_unlock(&mutex_top); } else { mvwaddstr(win, 0, terminal_width/2, "LOADING"); + /* status |= STATUS_UPDATE_SCREEN_GENERIC; + */ } } void window_btm(WINDOW *win){ @@ -59,7 +61,9 @@ void window_btm(WINDOW *win){ /*the printing of all possible inputs are done in user_interactions */ } else { mvwaddstr(win, 0, terminal_width/2, "LOADING"); + /* status |= STATUS_UPDATE_SCREEN_GENERIC; + */ } } void window_lft(WINDOW *win){ @@ -70,7 +74,9 @@ void window_lft(WINDOW *win){ } else { mvwaddstr(win, terminal_height/2, terminal_width/8, "LOADING"); + /* status |= STATUS_UPDATE_SCREEN_GENERIC; + */ } } void window_mid(WINDOW *win){ @@ -84,7 +90,9 @@ void window_mid(WINDOW *win){ pthread_mutex_unlock(&mutex_mid); } else { mvwaddstr(win, terminal_height/2, terminal_width/4, "LOADING"); + /* status |= STATUS_UPDATE_SCREEN_GENERIC; + */ } } void window_rgt(WINDOW *win){ @@ -103,6 +111,8 @@ void window_rgt(WINDOW *win){ pthread_mutex_unlock(&mutex_rgt); } else { mvwaddstr(win, terminal_height/2, terminal_width/4, "LOADING"); + /* status |= STATUS_UPDATE_SCREEN_GENERIC; + */ } }