mirror of
https://github.com/Llewellynvdm/conky.git
synced 2024-11-17 18:45:10 +00:00
Use the new callback system instead of add_update_callback() & co.
This commit is contained in:
parent
c5fe259ae0
commit
9d0932d711
141
src/common.cc
141
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<struct update_cb *>(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<bool> 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)) {
|
||||
|
@ -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);
|
||||
|
@ -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));
|
||||
|
13
src/core.cc
13
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<legacy_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);
|
||||
}
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <stdint.h> /* 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<void *, int (*)()> {
|
||||
typedef conky::callback<void *, int (*)()> 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> 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 */
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user