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"
|
#include "openbsd.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "update-cb.hh"
|
||||||
|
|
||||||
/* folds a string over top of itself, like so:
|
/* 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"
|
* 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);
|
conky::simple_config_setting<bool> no_buffers("no_buffers", true, true);
|
||||||
|
|
||||||
void update_stuff(void)
|
void update_stuff(void)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
struct update_cb *uc;
|
|
||||||
|
|
||||||
/* clear speeds and up status in case device was removed and doesn't get
|
/* clear speeds and up status in case device was removed and doesn't get
|
||||||
* updated */
|
* updated */
|
||||||
@ -390,21 +269,7 @@ void update_stuff(void)
|
|||||||
|
|
||||||
prepare_update();
|
prepare_update();
|
||||||
|
|
||||||
for (uc = update_cb_head.next; uc; uc = uc->next) {
|
conky::run_all_callbacks();
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* XXX: move the following into the update_meminfo() functions? */
|
/* XXX: move the following into the update_meminfo() functions? */
|
||||||
if (no_buffers.get(*state)) {
|
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 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);
|
void strfold(char *start, int count);
|
||||||
int check_mount(struct text_object *);
|
int check_mount(struct text_object *);
|
||||||
void prepare_update(void);
|
void prepare_update(void);
|
||||||
|
@ -2593,7 +2593,7 @@ void clean_up_without_threads(void *memtofree1, void* memtofree2)
|
|||||||
|
|
||||||
void clean_up(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);
|
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));
|
text_buffer = (char*)malloc(max_user_text.get(*state));
|
||||||
memset(text_buffer, 0, max_user_text.get(*state));
|
memset(text_buffer, 0, max_user_text.get(*state));
|
||||||
tmpstring1 = (char*)malloc(text_buffer_size.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 */
|
#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 */
|
/* construct_text_object() creates a new text_object */
|
||||||
struct text_object *construct_text_object(char *s, const char *arg, long
|
struct text_object *construct_text_object(char *s, const char *arg, long
|
||||||
line, void **ifblock_opaque, void *free_at_crash)
|
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 */
|
/* helper defines for internal use only */
|
||||||
#define __OBJ_HEAD(a, n) if (!strcmp(s, #a)) { \
|
#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_IF obj_be_ifblock_if(ifblock_opaque, obj)
|
||||||
#define __OBJ_ARG(...) if (!arg) { free(s); CRIT_ERR(obj, free_at_crash, __VA_ARGS__); }
|
#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__
|
#ifdef __linux__
|
||||||
determine_longstat_file();
|
determine_longstat_file();
|
||||||
#endif
|
#endif
|
||||||
add_update_callback(&update_top);
|
obj->cb_handle = create_cb_handle(update_top);
|
||||||
} else {
|
} else {
|
||||||
free(obj);
|
free(obj);
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -2016,6 +2024,7 @@ void free_text_objects(struct text_object *root)
|
|||||||
free_text_objects(obj->sub);
|
free_text_objects(obj->sub);
|
||||||
free_and_zero(obj->sub);
|
free_and_zero(obj->sub);
|
||||||
free_and_zero(obj->special_data);
|
free_and_zero(obj->special_data);
|
||||||
|
delete obj->cb_handle;
|
||||||
|
|
||||||
free(obj);
|
free(obj);
|
||||||
}
|
}
|
||||||
|
@ -32,6 +32,7 @@
|
|||||||
#include <stdint.h> /* uint8_t */
|
#include <stdint.h> /* uint8_t */
|
||||||
#include "config.h" /* for the defines */
|
#include "config.h" /* for the defines */
|
||||||
#include "specials.h" /* enum special_types */
|
#include "specials.h" /* enum special_types */
|
||||||
|
#include "update-cb.hh"
|
||||||
|
|
||||||
/* text object callbacks */
|
/* text object callbacks */
|
||||||
struct obj_cb {
|
struct obj_cb {
|
||||||
@ -74,6 +75,20 @@ void gen_print_nothing(struct text_object *, char *, int);
|
|||||||
* used by the $text object */
|
* used by the $text object */
|
||||||
void gen_print_obj_data_s(struct text_object *, char *, int);
|
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 {
|
||||||
struct text_object *next, *prev; /* doubly linked list of text objects */
|
struct text_object *next, *prev; /* doubly linked list of text objects */
|
||||||
struct text_object *sub; /* for objects parsing text into objects */
|
struct text_object *sub; /* for objects parsing text into objects */
|
||||||
@ -93,6 +108,8 @@ struct text_object {
|
|||||||
struct obj_cb callbacks;
|
struct obj_cb callbacks;
|
||||||
bool parse; //if this true then data.s should still be parsed
|
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
|
bool thread; //if this true then data.s should be set by a seperate thread
|
||||||
|
|
||||||
|
legacy_cb_handle *cb_handle;
|
||||||
};
|
};
|
||||||
|
|
||||||
/* text object list helpers */
|
/* text object list helpers */
|
||||||
|
@ -383,6 +383,9 @@ static void process_find_top(struct process **cpu, struct process **mem,
|
|||||||
|
|
||||||
int update_top(void)
|
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
|
process_find_top(info.cpu, info.memu, info.time
|
||||||
#ifdef BUILD_IOSTATS
|
#ifdef BUILD_IOSTATS
|
||||||
, info.io
|
, 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;
|
obj->callbacks.print = &print_top_pid;
|
||||||
} else if (strcmp(buf, "mem") == EQUAL) {
|
} else if (strcmp(buf, "mem") == EQUAL) {
|
||||||
obj->callbacks.print = &print_top_mem;
|
obj->callbacks.print = &print_top_mem;
|
||||||
add_update_callback(&update_meminfo);
|
|
||||||
} else if (strcmp(buf, "time") == EQUAL) {
|
} else if (strcmp(buf, "time") == EQUAL) {
|
||||||
obj->callbacks.print = &print_top_time;
|
obj->callbacks.print = &print_top_time;
|
||||||
} else if (strcmp(buf, "mem_res") == EQUAL) {
|
} else if (strcmp(buf, "mem_res") == EQUAL) {
|
||||||
|
Loading…
Reference in New Issue
Block a user