diff --git a/src/common.cc b/src/common.cc index d4fe02e0..ab7ba81b 100644 --- a/src/common.cc +++ b/src/common.cc @@ -59,6 +59,8 @@ #include "openbsd.h" #endif +#include "update-cb.hh" + /* folds a string over top of itself, like so: * * if start is "blah", and you call it with count = 1, the result will be "lah" @@ -245,134 +247,11 @@ void format_seconds_short(char *buf, unsigned int n, long seconds) } } -/* Linked list containing the functions to call upon each update interval. - * Populated while initialising text objects in construct_text_object(). */ -struct update_cb { - struct update_cb *next; - int (*func)(void); - pthread_t thread; - sem_t start_wait, end_wait; - update_cb() : next(NULL), func(NULL) {} - - /* set to 1 when starting the thread - * set to 0 to request thread termination */ - volatile char running; -}; - -static struct update_cb update_cb_head; - -static void *run_update_callback(void *); - -static int threading_started = 0; - -/* Register an update callback. Don't allow duplicates, to minimise side - * effects and overhead. */ -void add_update_callback(int (*func)(void)) -{ - struct update_cb *uc = &update_cb_head; - - if (!func) - return; - - while (uc->next) { - if (uc->next->func == func) - return; - uc = uc->next; - } - - uc->next = new update_cb; - uc = uc->next; - - memset(uc, 0, sizeof(struct update_cb)); - uc->func = func; - sem_init(&uc->start_wait, 0, 0); - sem_init(&uc->end_wait, 0, 0); - - if (threading_started) { - if (!uc->running) { - uc->running = 1; - pthread_create(&uc->thread, NULL, &run_update_callback, uc); - } - } -} - -/* Free the list element uc and all decendants recursively. */ -static void __free_update_callbacks(struct update_cb *uc) -{ - if (uc->next) - __free_update_callbacks(uc->next); - - if (uc->running) { - /* send cancellation request, then trigger and join the thread */ - uc->running = 0; - sem_post(&uc->start_wait); - } - if (uc->thread && pthread_join(uc->thread, NULL)) { - NORM_ERR("Error destroying thread"); - } - - /* finally destroy the semaphores */ - sem_destroy(&uc->start_wait); - sem_destroy(&uc->end_wait); - - delete uc; -} - -/* Free the whole list of update callbacks. */ -void free_update_callbacks(void) -{ - if (update_cb_head.next) - __free_update_callbacks(update_cb_head.next); - update_cb_head.next = NULL; -} - -/* We cannot start threads before we forked to background, because the threads - * would remain in the wrong process. Because of that, add_update_callback() - * doesn't create threads before start_update_threading() is called. - * start_update_threading() starts all threads previously registered, and sets a - * flag so that future threads are automagically started by - * add_update_callback(). - * This text is almost longer than the actual code. - */ -void start_update_threading(void) -{ - struct update_cb *uc; - - threading_started = 1; - - for (uc = update_cb_head.next; uc; uc = uc->next) { - if (!uc->running) { - uc->running = 1; - pthread_create(&uc->thread, NULL, &run_update_callback, uc); - } - } -} - -static void *run_update_callback(void *data) -{ - struct update_cb *ucb = static_cast(data); - - if (!ucb || !ucb->func) return(NULL); - - while (1) { - if (sem_wait(&ucb->start_wait)) return(NULL); - if (ucb->running == 0) return(NULL); - if((*ucb->func)()) { - ucb->next = ucb; //this is normally not be possible, so we use it to show that there was a critical error - sem_post(&ucb->end_wait); - sem_post(&ucb->end_wait); - pthread_exit(NULL); - } - if (sem_post(&ucb->end_wait)) return(NULL); - } -} - conky::simple_config_setting no_buffers("no_buffers", true, true); void update_stuff(void) { int i; - struct update_cb *uc; /* clear speeds and up status in case device was removed and doesn't get * updated */ @@ -390,21 +269,7 @@ void update_stuff(void) prepare_update(); - for (uc = update_cb_head.next; uc; uc = uc->next) { - if (sem_post(&uc->start_wait)) { - NORM_ERR("Semaphore error"); - } - } - /* need to synchronise here, otherwise locking is needed (as data - * would be printed with some update callbacks still running) */ - for (uc = update_cb_head.next; uc; uc = uc->next) { - sem_wait(&uc->end_wait); - if(uc == uc->next) { - pthread_join(uc->thread, NULL); - delete uc; - exit(EXIT_FAILURE); - } - } + conky::run_all_callbacks(); /* XXX: move the following into the update_meminfo() functions? */ if (no_buffers.get(*state)) { diff --git a/src/common.h b/src/common.h index 55f301d5..34255db2 100644 --- a/src/common.h +++ b/src/common.h @@ -38,10 +38,6 @@ char* readfile(const char* filename, int* total_read, char showerror); void print_to_bytes(struct text_object *, char *, int); -void add_update_callback(int (*func)(void)); -void free_update_callbacks(void); -void start_update_threading(void); - void strfold(char *start, int count); int check_mount(struct text_object *); void prepare_update(void); diff --git a/src/conky.cc b/src/conky.cc index ce9ee7df..9c31a45f 100644 --- a/src/conky.cc +++ b/src/conky.cc @@ -2593,7 +2593,7 @@ void clean_up_without_threads(void *memtofree1, void* memtofree2) void clean_up(void *memtofree1, void* memtofree2) { - free_update_callbacks(); + /* free_update_callbacks(); XXX: some new equivalent of this? */ clean_up_without_threads(memtofree1, memtofree2); } @@ -2994,8 +2994,6 @@ void initialisation(int argc, char **argv) { } } - start_update_threading(); - text_buffer = (char*)malloc(max_user_text.get(*state)); memset(text_buffer, 0, max_user_text.get(*state)); tmpstring1 = (char*)malloc(text_buffer_size.get(*state)); diff --git a/src/core.cc b/src/core.cc index 41b6c094..38cc1089 100644 --- a/src/core.cc +++ b/src/core.cc @@ -244,6 +244,14 @@ void stock_parse_arg(struct text_object *obj, const char *arg) } #endif /* BUILD_CURL */ +legacy_cb_handle *create_cb_handle(int (*fn)()) +{ + if(fn) + return new legacy_cb_handle(conky::register_cb(1, fn)); + else + return NULL; +} + /* construct_text_object() creates a new text_object */ struct text_object *construct_text_object(char *s, const char *arg, long line, void **ifblock_opaque, void *free_at_crash) @@ -255,7 +263,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long /* helper defines for internal use only */ #define __OBJ_HEAD(a, n) if (!strcmp(s, #a)) { \ - add_update_callback(n); + obj->cb_handle = create_cb_handle(n); #define __OBJ_IF obj_be_ifblock_if(ifblock_opaque, obj) #define __OBJ_ARG(...) if (!arg) { free(s); CRIT_ERR(obj, free_at_crash, __VA_ARGS__); } @@ -852,7 +860,7 @@ struct text_object *construct_text_object(char *s, const char *arg, long #ifdef __linux__ determine_longstat_file(); #endif - add_update_callback(&update_top); + obj->cb_handle = create_cb_handle(update_top); } else { free(obj); return NULL; @@ -2016,6 +2024,7 @@ void free_text_objects(struct text_object *root) free_text_objects(obj->sub); free_and_zero(obj->sub); free_and_zero(obj->special_data); + delete obj->cb_handle; free(obj); } diff --git a/src/text_object.h b/src/text_object.h index d1c958f7..a97d231d 100644 --- a/src/text_object.h +++ b/src/text_object.h @@ -32,6 +32,7 @@ #include /* uint8_t */ #include "config.h" /* for the defines */ #include "specials.h" /* enum special_types */ +#include "update-cb.hh" /* text object callbacks */ struct obj_cb { @@ -74,6 +75,20 @@ void gen_print_nothing(struct text_object *, char *, int); * used by the $text object */ void gen_print_obj_data_s(struct text_object *, char *, int); +class legacy_cb: public conky::callback { + typedef conky::callback Base; + +protected: + virtual void work() + { std::get<0>(tuple)(); } + +public: + legacy_cb(uint32_t period, int (*fn)()) + : Base(period, true, Base::Tuple(fn)) + {} +}; +typedef conky::callback_handle legacy_cb_handle; + struct text_object { struct text_object *next, *prev; /* doubly linked list of text objects */ struct text_object *sub; /* for objects parsing text into objects */ @@ -93,6 +108,8 @@ struct text_object { struct obj_cb callbacks; bool parse; //if this true then data.s should still be parsed bool thread; //if this true then data.s should be set by a seperate thread + + legacy_cb_handle *cb_handle; }; /* text object list helpers */ diff --git a/src/top.cc b/src/top.cc index 4b8afd6c..f0d2d417 100644 --- a/src/top.cc +++ b/src/top.cc @@ -383,6 +383,9 @@ static void process_find_top(struct process **cpu, struct process **mem, int update_top(void) { + // XXX: this was a separate callback. and it should be again, as soon as it's possible + update_meminfo(); + process_find_top(info.cpu, info.memu, info.time #ifdef BUILD_IOSTATS , info.io @@ -568,7 +571,6 @@ int parse_top_args(const char *s, const char *arg, struct text_object *obj) obj->callbacks.print = &print_top_pid; } else if (strcmp(buf, "mem") == EQUAL) { obj->callbacks.print = &print_top_mem; - add_update_callback(&update_meminfo); } else if (strcmp(buf, "time") == EQUAL) { obj->callbacks.print = &print_top_time; } else if (strcmp(buf, "mem_res") == EQUAL) {