1
0
mirror of https://github.com/Llewellynvdm/conky.git synced 2024-09-29 21:49:07 +00:00

Use the new callback system instead of add_update_callback() & co.

This commit is contained in:
Pavel Labath 2010-12-31 13:39:54 +01:00
parent c5fe259ae0
commit 9d0932d711
6 changed files with 35 additions and 148 deletions

View File

@ -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)) {

View File

@ -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);

View File

@ -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));

View File

@ -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);
}

View File

@ -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 */

View File

@ -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) {