xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
Commit 6e86c8f497f86ca1afaa7ae9c91bf29e2df09d04

Poke error thread to finish up jobs
This should make tests pass a bit faster due to waiting less, but it can
also have other uses related to synchronization with error thread.
Author: xaizek
Author date (UTC): 2024-03-11 13:44
Committer name: xaizek
Committer date (UTC): 2024-03-11 17:30
Parent(s): e5e55c1b32e7daae02f0c47856056aedd2422488
Signing key: 99DC5E4DB05F6BE2
Tree: f271c5c530fa6522f34cbe22ec6c6fc25a2d4f0a
File Lines added Lines deleted
HACKING.md 3 0
src/Makefile.am 1 0
src/Makefile.in 41 33
src/Makefile.win 1 1
src/background.c 47 15
src/utils/event.h 58 0
src/utils/event_nix.c 116 0
src/utils/event_win.c 45 27
File HACKING.md changed (mode: 100644) (index 06f28c92f..aaf69e653)
... ... of changes of each kind.
224 224 | | |-- darray.c - macros for managin dynamic arrays | | |-- darray.c - macros for managin dynamic arrays
225 225 | | |-- dynarray.c - array reallocation with fewer memory copies | | |-- dynarray.c - array reallocation with fewer memory copies
226 226 | | |-- env.c - environment variables related functions | | |-- env.c - environment variables related functions
227 | | |-- event_nix.c - pipe() wrapper to interrupt selector
228 | | |-- event_win.c - event object of manual reset kind to interrupt
229 | | | selector
227 230 | | |-- fs.c - functions to deal with file system objects | | |-- fs.c - functions to deal with file system objects
228 231 | | |-- fsdata.c - maps arbitrary data onto file system tree | | |-- fsdata.c - maps arbitrary data onto file system tree
229 232 | | |-- fsddata.c - fsdata wrapper that takes care of dynamic memory | | |-- fsddata.c - fsdata wrapper that takes care of dynamic memory
File src/Makefile.am changed (mode: 100644) (index 0d87f5e8d..2cab7f762)
... ... vifm_SOURCES = \
270 270 utils/darray.h \ utils/darray.h \
271 271 utils/dynarray.c utils/dynarray.h \ utils/dynarray.c utils/dynarray.h \
272 272 utils/env.c utils/env.h \ utils/env.c utils/env.h \
273 utils/event_nix.c utils/event.h \
273 274 utils/file_streams.c utils/file_streams.h \ utils/file_streams.c utils/file_streams.h \
274 275 utils/filemon.c utils/filemon.h \ utils/filemon.c utils/filemon.h \
275 276 utils/filter.c utils/filter.h \ utils/filter.c utils/filter.h \
File src/Makefile.in changed (mode: 100644) (index 9f594585c..c7bafe133)
... ... am_vifm_OBJECTS = cfg/config.$(OBJEXT) cfg/info.$(OBJEXT) \
198 198 ui/quickview.$(OBJEXT) ui/statusbar.$(OBJEXT) \ ui/quickview.$(OBJEXT) ui/statusbar.$(OBJEXT) \
199 199 ui/statusline.$(OBJEXT) ui/tabs.$(OBJEXT) ui/ui.$(OBJEXT) \ ui/statusline.$(OBJEXT) ui/tabs.$(OBJEXT) ui/ui.$(OBJEXT) \
200 200 utils/cancellation.$(OBJEXT) utils/dynarray.$(OBJEXT) \ utils/cancellation.$(OBJEXT) utils/dynarray.$(OBJEXT) \
201 utils/env.$(OBJEXT) utils/file_streams.$(OBJEXT) \
202 utils/filemon.$(OBJEXT) utils/filter.$(OBJEXT) \
203 utils/fs.$(OBJEXT) utils/fsdata.$(OBJEXT) \
204 utils/fsddata.$(OBJEXT) utils/fswatch_nix.$(OBJEXT) \
205 utils/globs.$(OBJEXT) utils/gmux_nix.$(OBJEXT) \
206 utils/hist.$(OBJEXT) utils/int_stack.$(OBJEXT) \
207 utils/log.$(OBJEXT) utils/matcher.$(OBJEXT) \
208 utils/matchers.$(OBJEXT) utils/mem.$(OBJEXT) \
209 utils/parson.$(OBJEXT) utils/path.$(OBJEXT) \
210 utils/regexp.$(OBJEXT) utils/selector_nix.$(OBJEXT) \
211 utils/shmem_nix.$(OBJEXT) utils/str.$(OBJEXT) \
212 utils/string_array.$(OBJEXT) utils/trie.$(OBJEXT) \
213 utils/utf8.$(OBJEXT) utils/utf8proc.$(OBJEXT) \
214 utils/utils.$(OBJEXT) utils/utils_nix.$(OBJEXT) args.$(OBJEXT) \
215 background.$(OBJEXT) bmarks.$(OBJEXT) \
216 bracket_notation.$(OBJEXT) builtin_functions.$(OBJEXT) \
217 cmd_actions.$(OBJEXT) cmd_completion.$(OBJEXT) \
218 cmd_core.$(OBJEXT) cmd_handlers.$(OBJEXT) compare.$(OBJEXT) \
219 dir_stack.$(OBJEXT) event_loop.$(OBJEXT) filelist.$(OBJEXT) \
201 utils/env.$(OBJEXT) utils/event_nix.$(OBJEXT) \
202 utils/file_streams.$(OBJEXT) utils/filemon.$(OBJEXT) \
203 utils/filter.$(OBJEXT) utils/fs.$(OBJEXT) \
204 utils/fsdata.$(OBJEXT) utils/fsddata.$(OBJEXT) \
205 utils/fswatch_nix.$(OBJEXT) utils/globs.$(OBJEXT) \
206 utils/gmux_nix.$(OBJEXT) utils/hist.$(OBJEXT) \
207 utils/int_stack.$(OBJEXT) utils/log.$(OBJEXT) \
208 utils/matcher.$(OBJEXT) utils/matchers.$(OBJEXT) \
209 utils/mem.$(OBJEXT) utils/parson.$(OBJEXT) \
210 utils/path.$(OBJEXT) utils/regexp.$(OBJEXT) \
211 utils/selector_nix.$(OBJEXT) utils/shmem_nix.$(OBJEXT) \
212 utils/str.$(OBJEXT) utils/string_array.$(OBJEXT) \
213 utils/trie.$(OBJEXT) utils/utf8.$(OBJEXT) \
214 utils/utf8proc.$(OBJEXT) utils/utils.$(OBJEXT) \
215 utils/utils_nix.$(OBJEXT) args.$(OBJEXT) background.$(OBJEXT) \
216 bmarks.$(OBJEXT) bracket_notation.$(OBJEXT) \
217 builtin_functions.$(OBJEXT) cmd_actions.$(OBJEXT) \
218 cmd_completion.$(OBJEXT) cmd_core.$(OBJEXT) \
219 cmd_handlers.$(OBJEXT) compare.$(OBJEXT) dir_stack.$(OBJEXT) \
220 event_loop.$(OBJEXT) filelist.$(OBJEXT) \
220 221 filename_modifiers.$(OBJEXT) fops_common.$(OBJEXT) \ filename_modifiers.$(OBJEXT) fops_common.$(OBJEXT) \
221 222 fops_cpmv.$(OBJEXT) fops_misc.$(OBJEXT) fops_put.$(OBJEXT) \ fops_cpmv.$(OBJEXT) fops_misc.$(OBJEXT) fops_put.$(OBJEXT) \
222 223 fops_rename.$(OBJEXT) filetype.$(OBJEXT) filtering.$(OBJEXT) \ fops_rename.$(OBJEXT) filetype.$(OBJEXT) filtering.$(OBJEXT) \
 
... ... am__depfiles_remade = ./$(DEPDIR)/args.Po ./$(DEPDIR)/background.Po \
371 372 ui/$(DEPDIR)/statusbar.Po ui/$(DEPDIR)/statusline.Po \ ui/$(DEPDIR)/statusbar.Po ui/$(DEPDIR)/statusline.Po \
372 373 ui/$(DEPDIR)/tabs.Po ui/$(DEPDIR)/ui.Po \ ui/$(DEPDIR)/tabs.Po ui/$(DEPDIR)/ui.Po \
373 374 utils/$(DEPDIR)/cancellation.Po utils/$(DEPDIR)/dynarray.Po \ utils/$(DEPDIR)/cancellation.Po utils/$(DEPDIR)/dynarray.Po \
374 utils/$(DEPDIR)/env.Po utils/$(DEPDIR)/file_streams.Po \
375 utils/$(DEPDIR)/filemon.Po utils/$(DEPDIR)/filter.Po \
376 utils/$(DEPDIR)/fs.Po utils/$(DEPDIR)/fsdata.Po \
377 utils/$(DEPDIR)/fsddata.Po utils/$(DEPDIR)/fswatch_nix.Po \
378 utils/$(DEPDIR)/globs.Po utils/$(DEPDIR)/gmux_nix.Po \
379 utils/$(DEPDIR)/hist.Po utils/$(DEPDIR)/int_stack.Po \
380 utils/$(DEPDIR)/log.Po utils/$(DEPDIR)/matcher.Po \
381 utils/$(DEPDIR)/matchers.Po utils/$(DEPDIR)/mem.Po \
382 utils/$(DEPDIR)/parson.Po utils/$(DEPDIR)/path.Po \
383 utils/$(DEPDIR)/regexp.Po utils/$(DEPDIR)/selector_nix.Po \
384 utils/$(DEPDIR)/shmem_nix.Po utils/$(DEPDIR)/str.Po \
385 utils/$(DEPDIR)/string_array.Po utils/$(DEPDIR)/trie.Po \
386 utils/$(DEPDIR)/utf8.Po utils/$(DEPDIR)/utf8proc.Po \
387 utils/$(DEPDIR)/utils.Po utils/$(DEPDIR)/utils_nix.Po
375 utils/$(DEPDIR)/env.Po utils/$(DEPDIR)/event_nix.Po \
376 utils/$(DEPDIR)/file_streams.Po utils/$(DEPDIR)/filemon.Po \
377 utils/$(DEPDIR)/filter.Po utils/$(DEPDIR)/fs.Po \
378 utils/$(DEPDIR)/fsdata.Po utils/$(DEPDIR)/fsddata.Po \
379 utils/$(DEPDIR)/fswatch_nix.Po utils/$(DEPDIR)/globs.Po \
380 utils/$(DEPDIR)/gmux_nix.Po utils/$(DEPDIR)/hist.Po \
381 utils/$(DEPDIR)/int_stack.Po utils/$(DEPDIR)/log.Po \
382 utils/$(DEPDIR)/matcher.Po utils/$(DEPDIR)/matchers.Po \
383 utils/$(DEPDIR)/mem.Po utils/$(DEPDIR)/parson.Po \
384 utils/$(DEPDIR)/path.Po utils/$(DEPDIR)/regexp.Po \
385 utils/$(DEPDIR)/selector_nix.Po utils/$(DEPDIR)/shmem_nix.Po \
386 utils/$(DEPDIR)/str.Po utils/$(DEPDIR)/string_array.Po \
387 utils/$(DEPDIR)/trie.Po utils/$(DEPDIR)/utf8.Po \
388 utils/$(DEPDIR)/utf8proc.Po utils/$(DEPDIR)/utils.Po \
389 utils/$(DEPDIR)/utils_nix.Po
388 390 am__mv = mv -f am__mv = mv -f
389 391 COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
390 392 $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
 
... ... vifm_SOURCES = \
985 987 utils/darray.h \ utils/darray.h \
986 988 utils/dynarray.c utils/dynarray.h \ utils/dynarray.c utils/dynarray.h \
987 989 utils/env.c utils/env.h \ utils/env.c utils/env.h \
990 utils/event_nix.c utils/event.h \
988 991 utils/file_streams.c utils/file_streams.h \ utils/file_streams.c utils/file_streams.h \
989 992 utils/filemon.c utils/filemon.h \ utils/filemon.c utils/filemon.h \
990 993 utils/filter.c utils/filter.h \ utils/filter.c utils/filter.h \
 
... ... utils/dynarray.$(OBJEXT): utils/$(am__dirstamp) \
1520 1523 utils/$(DEPDIR)/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp)
1521 1524 utils/env.$(OBJEXT): utils/$(am__dirstamp) \ utils/env.$(OBJEXT): utils/$(am__dirstamp) \
1522 1525 utils/$(DEPDIR)/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp)
1526 utils/event_nix.$(OBJEXT): utils/$(am__dirstamp) \
1527 utils/$(DEPDIR)/$(am__dirstamp)
1523 1528 utils/file_streams.$(OBJEXT): utils/$(am__dirstamp) \ utils/file_streams.$(OBJEXT): utils/$(am__dirstamp) \
1524 1529 utils/$(DEPDIR)/$(am__dirstamp) utils/$(DEPDIR)/$(am__dirstamp)
1525 1530 utils/filemon.$(OBJEXT): utils/$(am__dirstamp) \ utils/filemon.$(OBJEXT): utils/$(am__dirstamp) \
 
... ... distclean-compile:
1852 1857 @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/cancellation.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/cancellation.Po@am__quote@ # am--include-marker
1853 1858 @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/dynarray.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/dynarray.Po@am__quote@ # am--include-marker
1854 1859 @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/env.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/env.Po@am__quote@ # am--include-marker
1860 @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/event_nix.Po@am__quote@ # am--include-marker
1855 1861 @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/file_streams.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/file_streams.Po@am__quote@ # am--include-marker
1856 1862 @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/filemon.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/filemon.Po@am__quote@ # am--include-marker
1857 1863 @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/filter.Po@am__quote@ # am--include-marker @AMDEP_TRUE@@am__include@ @am__quote@utils/$(DEPDIR)/filter.Po@am__quote@ # am--include-marker
 
... ... distclean: distclean-am
2892 2898 -rm -f utils/$(DEPDIR)/cancellation.Po -rm -f utils/$(DEPDIR)/cancellation.Po
2893 2899 -rm -f utils/$(DEPDIR)/dynarray.Po -rm -f utils/$(DEPDIR)/dynarray.Po
2894 2900 -rm -f utils/$(DEPDIR)/env.Po -rm -f utils/$(DEPDIR)/env.Po
2901 -rm -f utils/$(DEPDIR)/event_nix.Po
2895 2902 -rm -f utils/$(DEPDIR)/file_streams.Po -rm -f utils/$(DEPDIR)/file_streams.Po
2896 2903 -rm -f utils/$(DEPDIR)/filemon.Po -rm -f utils/$(DEPDIR)/filemon.Po
2897 2904 -rm -f utils/$(DEPDIR)/filter.Po -rm -f utils/$(DEPDIR)/filter.Po
 
... ... maintainer-clean: maintainer-clean-am
3159 3166 -rm -f utils/$(DEPDIR)/cancellation.Po -rm -f utils/$(DEPDIR)/cancellation.Po
3160 3167 -rm -f utils/$(DEPDIR)/dynarray.Po -rm -f utils/$(DEPDIR)/dynarray.Po
3161 3168 -rm -f utils/$(DEPDIR)/env.Po -rm -f utils/$(DEPDIR)/env.Po
3169 -rm -f utils/$(DEPDIR)/event_nix.Po
3162 3170 -rm -f utils/$(DEPDIR)/file_streams.Po -rm -f utils/$(DEPDIR)/file_streams.Po
3163 3171 -rm -f utils/$(DEPDIR)/filemon.Po -rm -f utils/$(DEPDIR)/filemon.Po
3164 3172 -rm -f utils/$(DEPDIR)/filter.Po -rm -f utils/$(DEPDIR)/filter.Po
File src/Makefile.win changed (mode: 100644) (index 625000cdd..c8b5b7312)
... ... ui := cancellation.c color_manager.c color_scheme.c colored_line.c column_view.c
81 81 ui += escape.c fileview.c statusbar.c statusline.c tabs.c quickview.c ui.c ui += escape.c fileview.c statusbar.c statusline.c tabs.c quickview.c ui.c
82 82 ui := $(addprefix ui/, $(ui)) ui := $(addprefix ui/, $(ui))
83 83
84 utilities := cancellation.c dynarray.c env.c file_streams.c \
84 utilities := cancellation.c dynarray.c env.c event_win.c file_streams.c \
85 85 filemon.c filter.c fs.c fsdata.c fsddata.c fswatch_win.c globs.c \ filemon.c filter.c fs.c fsdata.c fsddata.c fswatch_win.c globs.c \
86 86 gmux_win.c hist.c int_stack.c log.c matcher.c matchers.c mem.c \ gmux_win.c hist.c int_stack.c log.c matcher.c matchers.c mem.c \
87 87 parson.c path.c regexp.c selector_win.c shmem_win.c str.c \ parson.c path.c regexp.c selector_win.c shmem_win.c str.c \
File src/background.c changed (mode: 100644) (index 4183f545c..523dbfc67)
49 49 #include "ui/ui.h" #include "ui/ui.h"
50 50 #include "utils/cancellation.h" #include "utils/cancellation.h"
51 51 #include "utils/env.h" #include "utils/env.h"
52 #include "utils/event.h"
52 53 #include "utils/fs.h" #include "utils/fs.h"
53 54 #include "utils/log.h" #include "utils/log.h"
54 55 #include "utils/path.h" #include "utils/path.h"
 
... ... static bg_job_t * add_background_job(pid_t pid, const char cmd[],
135 136 static void * background_task_bootstrap(void *arg); static void * background_task_bootstrap(void *arg);
136 137 static int update_job_status(bg_job_t *job); static int update_job_status(bg_job_t *job);
137 138 static void mark_job_finished(bg_job_t *job, int exit_code); static void mark_job_finished(bg_job_t *job, int exit_code);
139 static void poke_error_thread(void);
138 140 static int bg_op_cancel(bg_op_t *bg_op); static int bg_op_cancel(bg_op_t *bg_op);
139 141
140 142 bg_job_t *bg_jobs = NULL; bg_job_t *bg_jobs = NULL;
141 143
144 /* Event to wake up error thread from sleep for processing by
145 * poke_error_thread(). */
146 static event_t *error_thread_event;
142 147 /* Head of list of newly started jobs. */ /* Head of list of newly started jobs. */
143 148 static bg_job_t *new_err_jobs; static bg_job_t *new_err_jobs;
144 149 /* Mutex to protect new_err_jobs. */ /* Mutex to protect new_err_jobs. */
 
... ... static pthread_key_t current_job;
152 157 int int
153 158 bg_init(void) bg_init(void)
154 159 { {
160 error_thread_event = event_alloc();
161 if(error_thread_event == NULL)
162 {
163 return 1;
164 }
165
155 166 /* Create thread-local storage before starting any background threads. */ /* Create thread-local storage before starting any background threads. */
156 167 if(pthread_key_create(&current_job, NULL) != 0) if(pthread_key_create(&current_job, NULL) != 0)
157 168 { {
169 event_free(error_thread_event);
158 170 return 1; return 1;
159 171 } }
160 172
 
... ... bg_init(void)
162 174 if(pthread_create(&id, NULL, &error_thread, NULL) != 0) if(pthread_create(&id, NULL, &error_thread, NULL) != 0)
163 175 { {
164 176 pthread_key_delete(current_job); pthread_key_delete(current_job);
177 event_free(error_thread_event);
165 178 return 1; return 1;
166 179 } }
167 180
 
... ... bg_check(void)
183 196 return; return;
184 197 } }
185 198
199 poke_error_thread();
200
186 201 int active_jobs = 0; int active_jobs = 0;
187 202
188 203 bg_job_t *head = bg_jobs; bg_job_t *head = bg_jobs;
 
... ... error_thread(void *p)
427 442 (void)pthread_detach(pthread_self()); (void)pthread_detach(pthread_self());
428 443 block_all_thread_signals(); block_all_thread_signals();
429 444
445 const event_end_t event_end = event_wait_end(error_thread_event);
446
430 447 while(1) while(1)
431 448 { {
432 449 update_error_jobs(&jobs); update_error_jobs(&jobs);
433 450 make_ready_list(jobs, selector); make_ready_list(jobs, selector);
451 selector_add(selector, event_end);
434 452 while(selector_wait(selector, ERROR_SELECT_TIMEOUT_MS)) while(selector_wait(selector, ERROR_SELECT_TIMEOUT_MS))
435 453 { {
436 454 int need_update_list = (jobs == NULL); int need_update_list = (jobs == NULL);
437 455
456 if(selector_is_ready(selector, event_end))
457 {
458 (void)event_reset(error_thread_event);
459 }
460
438 461 bg_job_t **job = &jobs; bg_job_t **job = &jobs;
439 462 while(*job != NULL) while(*job != NULL)
440 463 { {
 
... ... error_thread(void *p)
442 465 char err_msg[ERR_MSG_LEN]; char err_msg[ERR_MSG_LEN];
443 466 ssize_t nread; ssize_t nread;
444 467
468 if(j->drained)
469 {
470 /* List update drops jobs which aren't running anymore thus allowing
471 * them to be gone. Matters at least in tests which wait for all
472 * tasks to finish and looping here leads to a timeout. */
473 need_update_list = 1;
474 goto next_job;
475 }
476
445 477 if(!selector_is_ready(selector, j->err_stream)) if(!selector_is_ready(selector, j->err_stream))
446 478 { {
447 479 goto next_job; goto next_job;
 
... ... error_thread(void *p)
458 490 nread = bytes_read; nread = bytes_read;
459 491 } }
460 492 #endif #endif
461 if(nread < 0)
493 if(nread > 0)
462 494 { {
463 need_update_list = 1;
464 j->drained = 1;
465 goto next_job;
495 err_msg[nread] = '\0';
496 append_error_msg(j, err_msg);
466 497 } }
467
468 if(nread == 0)
498 else
469 499 { {
470 /* Reached EOF, exclude corresponding file descriptor from the set,
471 * cut the job out of our list and decrement its use counter. */
472 selector_remove(selector, j->err_stream);
473 *job = j->err_next;
474 bg_job_decref(j);
475 continue;
500 /* EOF or some error. */
501 need_update_list = 1;
502 j->drained = 1;
476 503 } }
477 504
478 err_msg[nread] = '\0';
479 append_error_msg(j, err_msg);
480
481 505 next_job: next_job:
482 506 job = &j->err_next; job = &j->err_next;
483 507 } }
 
... ... error_thread(void *p)
495 519 } }
496 520
497 521 selector_free(selector); selector_free(selector);
522 event_free(error_thread_event);
498 523 return NULL; return NULL;
499 524 } }
500 525
 
... ... mark_job_finished(bg_job_t *job, int exit_code)
1667 1692 } }
1668 1693 } }
1669 1694
1695 /* Wakes up error thread to process any changes to the jobs. */
1696 static void
1697 poke_error_thread(void)
1698 {
1699 (void)event_signal(error_thread_event);
1700 }
1701
1670 1702 void void
1671 1703 bg_job_incref(bg_job_t *job) bg_job_incref(bg_job_t *job)
1672 1704 { {
File src/utils/event.h added (mode: 100644) (index 000000000..c1ea4f798)
1 /* vifm
2 * Copyright (C) 2024 xaizek.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #ifndef VIFM__UTILS__EVENT_H__
20 #define VIFM__UTILS__EVENT_H__
21
22 /* This unit is meant to provide abstraction over platform-specific mechanism
23 * for interrupting select()-like API call. It implements a manual-reset
24 * event. */
25
26 /* Type of event object handle. */
27 #ifdef _WIN32
28 #include <windows.h>
29 typedef HANDLE event_end_t;
30 #else
31 typedef int event_end_t;
32 #endif
33
34 /* Opaque event type. */
35 typedef struct event_t event_t;
36
37 /* Allocates new event object in non-signaled state. Returns the event or NULL
38 * on error. */
39 event_t * event_alloc(void);
40
41 /* Frees the event. The parameter can be NULL. */
42 void event_free(event_t *event);
43
44 /* Switches the event to the signaled state. Returns zero on success. */
45 int event_signal(event_t *event);
46
47 /* Switches the event back to the non-signaled state. Should be called after
48 * finding event in the signaled state. Returns zero on success. */
49 int event_reset(event_t *event);
50
51 /* Retrieves value that can be used to wait until the event reaches signaled
52 * state. */
53 event_end_t event_wait_end(const event_t *event);
54
55 #endif /* VIFM__UTILS__EVENT_H__ */
56
57 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
58 /* vim: set cinoptions+=t0 : */
File src/utils/event_nix.c added (mode: 100644) (index 000000000..348f72184)
1 /* vifm
2 * Copyright (C) 2024 xaizek.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #include "event.h"
20
21 #include <fcntl.h> /* F_GETFL F_SETFL O_NONBLOCK fcntl() */
22 #include <unistd.h> /* close() pipe() read() write() */
23
24 #include <stdlib.h> /* free() malloc() */
25
26 /* Event object data. */
27 struct event_t
28 {
29 int r; /* Read end of the pipe. */
30 int w; /* Write end of the pipe. */
31 };
32
33 event_t *
34 event_alloc(void)
35 {
36 event_t *event = malloc(sizeof(*event));
37 if(event == NULL)
38 {
39 return NULL;
40 }
41
42 int fds[2];
43 if(pipe(fds) != 0)
44 {
45 free(event);
46 return NULL;
47 }
48
49 event->r = fds[0];
50 event->w = fds[1];
51
52 /* Make reading from the pipe to not block. */
53 int flags = fcntl(event->r, F_GETFL, 0);
54 if(flags == -1)
55 {
56 event_free(event);
57 return NULL;
58 }
59 if(fcntl(event->r, F_SETFL, flags | O_NONBLOCK) != 0)
60 {
61 event_free(event);
62 return NULL;
63 }
64
65 return event;
66 }
67
68 void
69 event_free(event_t *event)
70 {
71 if(event != NULL)
72 {
73 close(event->r);
74 close(event->w);
75 free(event);
76 }
77 }
78
79 int
80 event_signal(event_t *event)
81 {
82 char buf = '\0';
83 if(write(event->w, &buf, sizeof(buf)) != sizeof(buf))
84 {
85 return -1;
86 }
87 return 0;
88 }
89
90 int
91 event_reset(event_t *event)
92 {
93 char buf = '\0';
94 if(read(event->r, &buf, sizeof(buf)) != sizeof(buf))
95 {
96 /* Error if we couldn't read anything for whatever reason. */
97 return -1;
98 }
99
100 ssize_t n;
101 while((n = read(event->r, &buf, sizeof(buf))) == sizeof(buf))
102 {
103 /* Keep reading. */
104 }
105 /* Don't report an error on EOF (when nothing is read). */
106 return (n == 0 ? 0 : -1);
107 }
108
109 int
110 event_wait_end(const event_t *event)
111 {
112 return event->r;
113 }
114
115 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
116 /* vim: set cinoptions+=t0 : */
File src/utils/event_win.c copied from file src/compat/dtype.c (similarity 52%) (mode: 100644) (index 3247f4e9b..a27ff7d5f)
1 1 /* vifm /* vifm
2 * Copyright (C) 2016 xaizek.
2 * Copyright (C) 2024 xaizek.
3 3 * *
4 4 * This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
5 5 * it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
 
16 16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
17 17 */ */
18 18
19 #include "dtype.h"
20 #include <dirent.h> /* dirent */
19 #include "event.h"
21 20
22 #if !defined(HAVE_STRUCT_DIRENT_D_TYPE) || !HAVE_STRUCT_DIRENT_D_TYPE
21 #include <windows.h>
23 22
24 #include "os.h"
23 #include <stdlib.h> /* free() malloc() */
25 24
26 unsigned char
27 get_dirent_type(const struct dirent *dentry, const char path[])
25 /* Event object data. */
26 struct event_t
28 27 { {
29 struct stat st;
28 HANDLE h; /* Handle to the event object. */
29 };
30 30
31 if(os_lstat(path, &st) != 0 || st.st_ino == 0)
31 event_t *
32 event_alloc(void)
33 {
34 event_t *event = malloc(sizeof(*event));
35 if(event == NULL)
36 {
37 return NULL;
38 }
39
40 event->h = CreateEvent(/*attrs=*/NULL, /*manual_reset=*/TRUE,
41 /*initial_state=*/FALSE, /*name=*/NULL);
42
43 if(event->h == NULL)
32 44 { {
33 return DT_UNKNOWN;
45 free(event);
46 return NULL;
34 47 } }
35 48
36 switch(st.st_mode & S_IFMT)
49 return event;
50 }
51
52 void
53 event_free(event_t *event)
54 {
55 if(event != NULL)
37 56 { {
38 case S_IFBLK: return DT_BLK;
39 case S_IFCHR: return DT_CHR;
40 case S_IFDIR: return DT_DIR;
41 case S_IFIFO: return DT_FIFO;
42 case S_IFREG: return DT_REG;
43 #ifndef _WIN32
44 case S_IFLNK: return DT_LNK;
45 case S_IFSOCK: return DT_SOCK;
46 #endif
47
48 default: return DT_UNKNOWN;
57 CloseHandle(event->h);
58 free(event);
49 59 } }
50 60 } }
51 61
52 #else
62 int
63 event_signal(event_t *event)
64 {
65 return (SetEvent(event->h) ? 0 : -1);
66 }
53 67
54 unsigned char
55 get_dirent_type(const struct dirent *dentry, const char path[])
68 int
69 event_reset(event_t *event)
56 70 { {
57 return dentry->d_type;
71 return (ResetEvent(event->h) ? 0 : -1);
58 72 } }
59 73
60 #endif
74 HANDLE
75 event_wait_end(const event_t *event)
76 {
77 return event->h;
78 }
61 79
62 80 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
63 81 /* vim: set cinoptions+=t0 : */ /* vim: set cinoptions+=t0 : */
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master