diff options
Diffstat (limited to '')
-rw-r--r-- | drv_T6963.c | 4 | ||||
-rwxr-xr-x | indent.sh | 2 | ||||
-rw-r--r-- | plugin_button_exec.c | 2 | ||||
-rw-r--r-- | plugin_gps.c | 2 | ||||
-rw-r--r-- | plugin_iconv.c | 2 | ||||
-rw-r--r-- | plugin_seti.c | 2 | ||||
-rw-r--r-- | plugin_wireless.c | 2 | ||||
-rw-r--r-- | timer.c | 136 | ||||
-rw-r--r-- | timer.h | 1 | ||||
-rw-r--r-- | timer_group.c | 550 | ||||
-rw-r--r-- | timer_group.h | 5 |
11 files changed, 511 insertions, 197 deletions
diff --git a/drv_T6963.c b/drv_T6963.c index ac472ca..fd7bd75 100644 --- a/drv_T6963.c +++ b/drv_T6963.c @@ -279,7 +279,7 @@ static void drv_T6_clear(const unsigned short addr, const int len) drv_T6_write_auto(0x0); if (bug) { bug = 0; - debug("bug occured at byte %d of %d", i, len); + debug("bug occurred at byte %d of %d", i, len); } } drv_T6_status2(); @@ -297,7 +297,7 @@ static void drv_T6_copy(const unsigned short addr, const unsigned char *data, co drv_T6_write_auto(*(data++)); if (bug) { bug = 0; - debug("bug occured at byte %d of %d, addr=%d", i, len, addr); + debug("bug occurred at byte %d of %d, addr=%d", i, len, addr); } } drv_T6_status2(); @@ -8,7 +8,7 @@ # -l120 Set maximum line length for non-comment lines to 150. # -npro Do not read ‘.indent.pro’ files. -rm *.c~ *.h~ +rm *.c~ *.h~ 2>/dev/null # trash "no such file or directory" warning messages indent -kr -l120 -npro *.c *.h for i in *.c *.h; do diff --git a/plugin_button_exec.c b/plugin_button_exec.c index 118ab11..7685841 100644 --- a/plugin_button_exec.c +++ b/plugin_button_exec.c @@ -85,7 +85,7 @@ static void my_button_exec(RESULT * result, int argc, RESULT * argv[]) info(strerror(errsv)); exit(0); } else if (pid == -1) { - info("weird error has occured. couldn't fork."); + info("weird error has occurred. couldn't fork."); } else { SetResult(&result, R_STRING, "0"); } diff --git a/plugin_gps.c b/plugin_gps.c index 01ecf7d..219c6e3 100644 --- a/plugin_gps.c +++ b/plugin_gps.c @@ -572,7 +572,7 @@ static void parse(RESULT * result, RESULT * theOptions, RESULT * displayOptions) status = nmeap_parseBuffer(&nmea, (const char *) &bufferTmp, &rem); //parse it if (status == -1) { errCounter++; - error("parser error occured! (cnt: %i)\n", errCounter); + error("parser error occurred! (cnt: %i)\n", errCounter); } else if (status == 0) { incomplCounter++; } else if (status > 0) diff --git a/plugin_iconv.c b/plugin_iconv.c index bd01f26..5bf005b 100644 --- a/plugin_iconv.c +++ b/plugin_iconv.c @@ -104,7 +104,7 @@ static void my_iconv(RESULT * result, RESULT * charset_from, RESULT * charset_to source_left = 0; break; default: - error("plugin_iconv: strange errno state (%d) occured", errno); + error("plugin_iconv: strange errno state (%d) occurred", errno); source_left = 0; } } diff --git a/plugin_seti.c b/plugin_seti.c index 4fe7aea..ad115aa 100644 --- a/plugin_seti.c +++ b/plugin_seti.c @@ -63,7 +63,7 @@ static int parse_seti(void) FILE *stream; int age; - /* if a fatal error occured, do nothing */ + /* if a fatal error occurred, do nothing */ if (fatal != 0) return -1; diff --git a/plugin_wireless.c b/plugin_wireless.c index 25adf26..2eb5bc0 100644 --- a/plugin_wireless.c +++ b/plugin_wireless.c @@ -490,7 +490,7 @@ static int get_stats(const char *dev, const char *key) } else { qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.level, range.max_qual.level); - qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_LEVEL);; + qprintf(key_buffer, sizeof(key_buffer), "%s.%s", dev, KEY_LEVEL); hash_put(&wireless, key_buffer, qprintf_buffer); qprintf(qprintf_buffer, sizeof(qprintf_buffer), "%d/%d", stats.qual.noise, range.max_qual.noise); @@ -1,7 +1,7 @@ /* $Id$ * $URL$ * - * generic timer handling + * Generic timer handling. * * Copyright (C) 2003, 2004 Michael Reinelt <michael@reinelt.co.at> * Copyright (C) 2004 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> @@ -72,19 +72,21 @@ #include <dmalloc.h> #endif +/* FIXME: CLOCK_SKEW_DETECT_TIME_IN_S should have a higher value */ + /* delay in seconds between timer events that is considered as being induced by clock skew */ #define CLOCK_SKEW_DETECT_TIME_IN_S 1 /* structure for storing all relevant data of a single timer */ typedef struct TIMER { - /* function of type callback(void *data) that will be called when - the timer is processed; it will also be used to identify a - specific timer */ + /* pointer to function of type void func(void *data) that will be + called when the timer is processed; it will also be used to + identify a specific timer */ void (*callback) (void *data); - /* data which will be passed to the callback function; it will - also be used to identify a specific timer */ + /* pointer to data which will be passed to the callback function; + it will also be used to identify a specific timer */ void *data; /* struct to hold the time (in seconds and milliseconds since the @@ -98,17 +100,16 @@ typedef struct TIMER { it is deleted (value of 0) or only once (all other values) */ int one_shot; - /* marks timers as being active (so it will get processed) or + /* marks timer as being active (so it will get processed) or inactive (which means the timer has been deleted and its allocated memory may be re-used) */ int active; } TIMER; - /* number of allocated timer slots */ int nTimers = 0; -/* pointer to memory used for storing the timer slots */ +/* pointer to memory allocated for storing the timer slots */ TIMER *Timers = NULL; @@ -137,7 +138,7 @@ static void timer_inc(struct timeval *tv, const int interval) int timer_remove(void (*callback) (void *data), void *data) -/* Remove a new timer with given callback and data. +/* Remove a timer with given callback and data. callback (void pointer): function of type void func(void *data); here, it will be used to identify the timer @@ -146,24 +147,29 @@ int timer_remove(void (*callback) (void *data), void *data) function; here, it will be used to identify the timer return value (integer): returns a value of 0 on successful timer - deletion; otherwise returns a value of -1 + removal; otherwise returns a value of -1 */ { - int i; /* current timer's ID */ + int timer; /* current timer's ID */ /* loop through the timer slots and try to find the specified timer slot by looking for its settings */ - for (i = 0; i < nTimers; i++) { - if (Timers[i].callback == callback && Timers[i].data == data && Timers[i].active) { + for (timer = 0; timer < nTimers; timer++) { + /* skip inactive (i.e. deleted) timers */ + if (Timers[timer].active == 0) + continue; + + if (Timers[timer].callback == callback && Timers[timer].data == data) { /* we have found the timer slot, so mark it as being inactive; - we will not actually delete the timer, so its allocated + we will not actually delete the slot, so its allocated memory may be re-used */ - Timers[i].active = 0; + Timers[timer].active = 0; /* signal successful timer removal */ return 0; } } + /* we have NOT found the timer slot, so signal failure by returning a value of -1 */ return -1; @@ -192,26 +198,30 @@ int timer_add(void (*callback) (void *data), void *data, const int interval, con creation; otherwise returns a value of -1 */ { - int i; /* current timer's ID */ + int timer; /* current timer's ID */ struct timeval now; /* struct to hold current time */ /* try to minimize memory usage by looping through the timer slots and looking for an inactive timer */ - for (i = 0; i < nTimers; i++) { - if (Timers[i].active == 0) - /* we've just found one, so let's reuse it ("i" holds its ID) - by breaking the loop */ + for (timer = 0; timer < nTimers; timer++) { + if (Timers[timer].active == 0) { + /* we've just found one, so let's reuse it ("timer" holds its + ID) by breaking the loop */ break; + } } /* no inactive timers (or none at all) found, so we have to add a new timer slot */ - if (i >= nTimers) { + if (timer >= nTimers) { /* increment number of timers and (re-)allocate memory used for storing the timer slots */ nTimers++; Timers = realloc(Timers, nTimers * sizeof(*Timers)); + /* make sure "timer" points to valid memory */ + timer = nTimers - 1; + /* realloc() has failed */ if (Timers == NULL) { /* restore old number of timers */ @@ -225,21 +235,21 @@ int timer_add(void (*callback) (void *data), void *data, const int interval, con /* get current time so the timer triggers immediately */ gettimeofday(&now, NULL); - /* fill in timer data */ - Timers[i].callback = callback; - Timers[i].data = data; - Timers[i].when = now; - Timers[i].interval = interval; - Timers[i].one_shot = one_shot; + /* initialize timer data */ + Timers[timer].callback = callback; + Timers[timer].data = data; + Timers[timer].when = now; + Timers[timer].interval = interval; + Timers[timer].one_shot = one_shot; /* set timer to active so that it is processed and not overwritten - by the memory optimisation routine above */ - Timers[i].active = 1; + by the memory optimization routine above */ + Timers[timer].active = 1; /* one-shot timers should NOT fire immediately, so delay them by a single timer interval */ if (one_shot) { - timer_inc(&Timers[i].when, interval); + timer_inc(&Timers[timer].when, interval); } /* signal successful timer creation */ @@ -279,17 +289,20 @@ int timer_add_late(void (*callback) (void *data), void *data, const int interval return -1; } - int i; /* current timer's ID */ + int timer; /* current timer's ID */ /* loop through the timer slots and try to find the new timer slot by looking for its settings */ - for (i = 0; i < nTimers; i++) { - if (Timers[i].callback == callback && Timers[i].data == data && Timers[i].active - && Timers[i].interval == interval) { + for (timer = 0; timer < nTimers; timer++) { + /* skip inactive (i.e. deleted) timers */ + if (Timers[timer].active == 0) + continue; + + if (Timers[timer].callback == callback && Timers[timer].data == data && Timers[timer].interval == interval) { /* we have found the new timer slot, so unmask it by setting its "one_shot" variable to the REAL value; then signal successful timer creation */ - Timers[i].one_shot = one_shot; + Timers[timer].one_shot = one_shot; /* signal successful timer creation */ return 0; @@ -317,73 +330,76 @@ int timer_process(struct timespec *delay) /* get current time to check which timers need processing */ gettimeofday(&now, NULL); - /* sanity check; at least one timer should need processing */ - if (nTimers == 0) { + /* sanity check; by now, at least one timer should be + instantiated */ + if (nTimers <= 0) { /* otherwise, print an error and return a value of -1 to signal an error */ - error("Huh? Not one single timer to process? Dazed and confused..."); + error("Huh? Not even a single timer to process? Dazed and confused..."); return -1; } - int i; /* current timer's ID */ + int timer; /* current timer's ID */ /* process all expired timers */ - for (i = 0; i < nTimers; i++) { + for (timer = 0; timer < nTimers; timer++) { /* skip inactive (i.e. deleted) timers */ - if (Timers[i].active == 0) + if (Timers[timer].active == 0) continue; + /* check whether current timer needs to be processed, i.e. the timer's triggering time is less than or equal to the current time; according to the man page of timercmp(), this avoids using the operators ">=", "<=" and "==" which might be broken on some systems */ - if (!timercmp(&Timers[i].when, &now, >)) { + if (!timercmp(&Timers[timer].when, &now, >)) { /* if the timer's callback function has been set, call it and pass the corresponding data */ - if (Timers[i].callback != NULL) { - Timers[i].callback(Timers[i].data); + if (Timers[timer].callback != NULL) { + Timers[timer].callback(Timers[timer].data); } /* check for one-shot timers */ - if (Timers[i].one_shot) { + if (Timers[timer].one_shot) { /* mark one-shot timer as inactive (which means the timer has been deleted and its allocated memory may be re-used) */ - Timers[i].active = 0; + Timers[timer].active = 0; } else { /* otherwise, respawn timer by adding one triggering interval to its triggering time */ - timer_inc(&Timers[i].when, Timers[i].interval); + timer_inc(&Timers[timer].when, Timers[timer].interval); } } } - int min = -1; /* ID of the next upcoming timer */ + int next_timer = -1; /* ID of the next upcoming timer */ /* loop through the timer slots and try to find the next upcoming timer */ - for (i = 0; i < nTimers; i++) { + for (timer = 0; timer < nTimers; timer++) { /* skip inactive (i.e. deleted) timers */ - if (Timers[i].active == 0) + if (Timers[timer].active == 0) continue; /* if this is the first timer that we check, mark it as the next upcoming timer; otherwise, we'll have nothing to compare against in this loop */ - if (min < 0) - min = i; + if (next_timer < 0) + next_timer = timer; /* check whether current timer needs processing prior to the one selected */ - else if (timercmp(&Timers[i].when, &Timers[min].when, <)) + else if (timercmp(&Timers[timer].when, &Timers[next_timer].when, <)) { /* if so, mark it as the next upcoming timer */ - min = i; + next_timer = timer; + } } /* sanity check; we should by now have found the next upcoming timer */ - if (min < 0) { + if (next_timer < 0) { /* otherwise, print an error and return a value of -1 to signal an error */ - error("Huh? Not one single timer left? Dazed and confused..."); + error("Huh? Not even a single timer left? Dazed and confused..."); return -1; } @@ -397,7 +413,7 @@ int timer_process(struct timespec *delay) /* calculate delay to the next upcoming timer event and store it in "diff" */ - timersub(&Timers[min].when, &now, &diff); + timersub(&Timers[next_timer].when, &now, &diff); /* for negative delays, set "diff" to the Epoch so the next update is triggered immediately */ @@ -417,7 +433,7 @@ int timer_process(struct timespec *delay) /* update time stamp and timer */ /* FIXME: shouldn't we update *all* timers? */ gettimeofday(&now, NULL); - Timers[min].when = now; + Timers[next_timer].when = now; } /* finally, set passed timespec "delay" to "diff" ... */ @@ -439,8 +455,8 @@ void timer_exit(void) /* reset number of allocated timer slots */ nTimers = 0; - if (Timers != NULL) { /* free memory used for storing the timer slots */ + if (Timers != NULL) { free(Timers); Timers = NULL; } @@ -28,6 +28,7 @@ #ifndef _TIMER_H_ #define _TIMER_H_ + int timer_add(void (*callback) (void *data), void *data, const int interval, const int one_shot); int timer_add_late(void (*callback) (void *data), void *data, const int interval, const int one_shot); diff --git a/timer_group.c b/timer_group.c index 0a72e84..893e085 100644 --- a/timer_group.c +++ b/timer_group.c @@ -1,10 +1,11 @@ /* $Id$ * $URL$ * - * generic grouping of widget timers that have been set to the same - * update interval, thus allowing synchronized updates + * Generic grouping of widgets that have been set to the same update + * interval, thus allowing synchronized updates. * * Copyright (C) 2010 Martin Zuther <code@mzuther.de> + * Copyright (C) 2010 The LCD4Linux Team <lcd4linux-devel@users.sourceforge.net> * * Based on "timer.c" which is * Copyright (C) 2003, 2004 Michael Reinelt <michael@reinelt.co.at> @@ -26,28 +27,32 @@ * */ -/* - * exported functions: +/* + * Exported functions: * - * int timer_add_group(void (*callback) (void *data), const int interval) - * make sure that generic timer exists for given update interval + * void timer_process_group(void *data) * - * int timer_remove_group(void (*callback) (void *data), const int interval) - * remove generic timer for given update interval + * Process all widgets of a timer group; if the timer group only + * contains one-shot timers, it will be deleted after processing. * - * void timer_process_group(void *data) - * process all widgets of a given update interval (*data) * * void timer_exit_group(void) - * release all timers and free reserved memory * - * int timer_add_widget(void (*callback) (void *data), void *data, const int interval, const int one_shot) - * add widget to group of the given update interval (creates a new group if - * necessary) + * Release all timer groups and widgets and free the associated + * memory blocks. + * + * + * int timer_add_widget(void (*callback) (void *data), void *data, + * const int interval, const int one_shot) + * + * Add widget to timer group of the specified update interval + * (also creates a new timer group if necessary). + * * * int timer_remove_widget(void (*callback) (void *data), void *data) - * remove widget from group of the given update interval (als removes emtpy - * groups) + * + * Remove widget from the timer group with the specified update + * interval (also removes corresponding timer group if empty). * */ @@ -68,194 +73,485 @@ #endif -/* contains the actual timers, one for each update interval */ +/* structure for storing all relevant data of a single timer group */ typedef struct TIMER_GROUP { - void (*callback) (void *data); + /* pointer to the group's triggering interval in milliseconds; + this will be used to identify a specific timer group and also + as callback data for the underlying generic timer */ int *interval; + + /* marks timer group as being active (so it will get processed) or + inactive (which means the timer group has been deleted and its + allocated memory may be re-used) */ int active; } TIMER_GROUP; -TIMER_GROUP *GroupTimers = NULL; -int nGroupTimers = 0; +/* number of allocated timer group slots */ +int nTimerGroups = 0; + +/* pointer to memory allocated for storing the timer group slots */ +TIMER_GROUP *TimerGroups = NULL; -/* contains callback and data for each widget */ -typedef struct SINGLE_TIMER { + +/* structure for storing all relevant timer data of a single widget */ +typedef struct TIMER_GROUP_WIDGET { + /* pointer to function of type void func(void *data) that will be + called when the timer is processed; it will also be used to + identify a specific widget */ void (*callback) (void *data); + + /* pointer to data which will be passed to the callback function; + it will also be used to identify a specific widget */ void *data; + + /* specifies the timer's triggering interval in milliseconds; it + will also be used to identify a specific widget */ int interval; + + /* specifies whether the timer should trigger indefinitely until + it is deleted (value of 0) or only once (all other values) */ int one_shot; + + /* marks timer as being active (so it will get processed) or + inactive (which means the timer has been deleted and its + allocated memory may be re-used) */ int active; -} SINGLE_TIMER; +} TIMER_GROUP_WIDGET; + +/* number of allocated widget slots */ +int nTimerGroupWidgets = 0; + +/* pointer to memory allocated for storing the widget slots */ +TIMER_GROUP_WIDGET *TimerGroupWidgets = NULL; + + +int timer_group_exists(const int interval) +/* Check whether a timer group for the specified interval exists. -SINGLE_TIMER *SingleTimers = NULL; -int nSingleTimers = 0; + interval (integer): the sought-after triggering interval in + milliseconds -int timer_add_group(void (*callback) (void *data), const int interval) + return value (integer): returns a value of 1 if timer group + exists; otherwise returns a value of 0 +*/ { - int group; + int group; /* current timer group's ID */ - /* check whether timer exists for given update interval */ - for (group = 0; group < nGroupTimers; group++) { - if (*GroupTimers[group].interval == interval) - return 0; + /* loop through the timer group slots to search for one that + matches the specified interval */ + for (group = 0; group < nTimerGroups; group++) { + /* skip inactive (i.e. deleted) timer groups */ + if (TimerGroups[group].active == 0) + continue; + + if (*TimerGroups[group].interval == interval) { + /* matching timer group found, so signal success by returning + a value of 1 */ + return 1; + } } - /* otherwise look for a free group */ - for (group = 0; group < nGroupTimers; group++) { - if (GroupTimers[group].active == 0) + /* matching timer group not found, so signal failure by returning + a value of 0 */ + return 0; +} + + +int timer_add_group(const int interval) +/* Create a new timer group (unless it already exists) and link it to + the timer queue. + + interval (integer): the new timer group's triggering interval in + milliseconds + + return value (integer): returns a value of 0 on successful timer + group creation; otherwise returns a value of -1 +*/ +{ + /* if timer group for update interval already exists, signal + success by returning a value of 0 */ + if (timer_group_exists(interval)) + return 0; + + /* display an info message to inform the user that a new timer + group is being created */ + info("Creating new timer group (%d ms)", interval); + + int group; /* current timer group's ID */ + + /* try to minimize memory usage by looping through timer group + slots and looking for an inactive timer group */ + for (group = 0; group < nTimerGroups; group++) { + if (TimerGroups[group].active == 0) { + /* we've just found one, so let's reuse it ("group" holds its + ID) by breaking the loop */ break; + } } - /* none found, allocate a new group */ - if (group >= nGroupTimers) { - nGroupTimers++; - GroupTimers = realloc(GroupTimers, nGroupTimers * sizeof(*GroupTimers)); + /* no inactive timer groups (or none at all) found, so we have to + add a new timer group slot */ + if (group >= nTimerGroups) { + /* increment number of timer groups and (re-)allocate memory used + for storing the timer group slots */ + nTimerGroups++; + TimerGroups = realloc(TimerGroups, nTimerGroups * sizeof(*TimerGroups)); - /* also allocate memory for callback data */ - GroupTimers[group].interval = malloc(sizeof(int)); + /* make sure "group" points to valid memory */ + group = nTimerGroups - 1; + + /* realloc() has failed */ + if (TimerGroups == NULL) { + /* restore old number of timer groups */ + nTimerGroups--; + + /* signal unsuccessful timer group creation */ + return -1; + } + + /* allocate memory for the underlying generic timer's callback + data (i.e. the group's triggering interval in milliseconds) */ + TimerGroups[group].interval = malloc(sizeof(int)); + + /* malloc() has failed */ + if (TimerGroups[group].interval == NULL) { + /* signal unsuccessful timer group creation */ + return -1; + } } - /* initialize group */ - info("Creating new timer group (%d ms)", interval); + /* initialize timer group's interval */ + *TimerGroups[group].interval = interval; - GroupTimers[group].callback = callback; - *GroupTimers[group].interval = interval; - GroupTimers[group].active = 1; + /* set timer group to active so that it is processed and not + overwritten by the memory optimization routine above */ + TimerGroups[group].active = 1; - /* finally, request a generic timer */ - return timer_add(GroupTimers[group].callback, GroupTimers[group].interval, interval, 0); + /* finally, request a generic timer that calls this group and + signal success or failure */ + return timer_add(timer_process_group, TimerGroups[group].interval, interval, 0); } -int timer_remove_group(void (*callback) (void *data), const int interval) + +int timer_remove_group(const int interval) +/* Remove a timer group and unlink it from the timer queue (also + removes all remaining widget slots in this timer group). + + interval (integer): triggering interval in milliseconds; here, it + will be used to identify the timer group + + return value (integer): returns a value of 0 on successful timer + group removal; otherwise returns a value of -1 +*/ { - int group; + /* display an info message to inform the user that a timer group + is being removed */ + info("Removing timer group (%d ms)", interval); + + int group; /* current timer group's ID */ + int widget; /* current widget's ID */ + + /* loop through the widget slots to look for remaining widgets + with the specified update interval */ + for (widget = 0; widget < nTimerGroupWidgets; widget++) { + /* skip inactive (i.e. deleted) widget slots */ + if (TimerGroupWidgets[widget].active == 0) + continue; + + if (TimerGroupWidgets[widget].interval == interval) { + /* we have found a matching widget slot, so mark it as being + inactive; we will not actually delete the slot, so its + allocated memory may be re-used */ + TimerGroupWidgets[widget].active = 0; + } + } - /* look for group with given callback function and update interval */ - for (group = 0; group < nGroupTimers; group++) { - if (GroupTimers[group].callback == callback && *GroupTimers[group].interval == interval - && GroupTimers[group].active) { - /* inactivate group */ - GroupTimers[group].active = 0; + /* loop through timer group slots and try to find the specified + timer group slot by looking for its settings */ + for (group = 0; group < nTimerGroups; group++) { + /* skip inactive (i.e. deleted) timer groups */ + if (TimerGroups[group].active == 0) + continue; - /* remove generic timer */ - return timer_remove(GroupTimers[group].callback, GroupTimers[group].interval); + if (*TimerGroups[group].interval == interval) { + /* we have found the timer group slot, so mark it as being + inactive; we will not actually delete the slot, so its + allocated memory may be re-used */ + TimerGroups[group].active = 0; + + /* remove the generic timer that calls this group */ + if (timer_remove(timer_process_group, TimerGroups[group].interval)) { + /* signal successful removal of timer group */ + return 0; + } else { + /* an error occurred on generic timer removal, so signal + failure by returning a value of -1 */ + return -1; + } } } + + /* we have NOT found the timer group slot, so signal failure by + returning a value of -1 */ return -1; } + +int timer_remove_empty_group(const int interval) +/* Remove timer group *only* if it contains no more widget slots. + + interval (integer): triggering interval in milliseconds; here, it + will be used to identify the timer group + + return value (integer): returns a value of 0 on successful + processing; otherwise returns a value of -1 +*/ +{ + int widget; /* current widget's ID */ + + /* loop through the widget slots to look for widgets with the + specified update interval */ + for (widget = 0; widget < nTimerGroupWidgets; widget++) { + /* skip inactive (i.e. deleted) widget slots */ + if (TimerGroupWidgets[widget].active == 0) + continue; + + /* at least one other widget with specified update interval + exists, so signal success by returning a value of 0 */ + if (TimerGroupWidgets[widget].interval == interval) + return 0; + } + + /* no other widgets with specified update interval exist, so + remove corresponding timer group and signal success or + failure */ + return timer_remove_group(interval); +} + + void timer_process_group(void *data) +/* Process all widgets of a timer group; if the timer group only + contains one-shot timers, it will be deleted after processing. + + data (void pointer): points to an integer holding the triggering + interval in milliseconds; here, it will be used to identify the + timer group + + return value: void +*/ { - int slot; - int *interval = (int *) data; + int widget; /* current widget's ID */ + + /* convert callback data to integer (triggering interval in + milliseconds) */ + int interval = *((int *) data); + + /* sanity check; by now, at least one timer group should be + instantiated */ + if (nTimerGroups <= 0) { + /* otherwise, print an error and return early */ + error("Huh? Not even a single timer group to process? Dazed and confused..."); + return; + } - /* sanity check */ - if (nSingleTimers == 0) { - error("huh? not even a single widget timer to process? dazed and confused..."); + /* sanity check; by now, at least one widget slot should be + instantiated */ + if (nTimerGroupWidgets <= 0) { + /* otherwise, print an error and return early */ + error("Huh? Not even a single widget slot to process? Dazed and confused..."); return; } - /* process every (active) widget associated with given update interval */ - for (slot = 0; slot < nSingleTimers; slot++) { - if (SingleTimers[slot].active == 0) + /* loop through widgets and search for those matching the timer + group's update interval */ + for (widget = 0; widget < nTimerGroupWidgets; widget++) { + /* skip inactive (i.e. deleted) widgets */ + if (TimerGroupWidgets[widget].active == 0) continue; - if (SingleTimers[slot].interval == *interval) { - /* call one-shot timers only once */ - if (SingleTimers[slot].one_shot) - SingleTimers[slot].active = 0; - /* execute callback function */ - if (SingleTimers[slot].callback != NULL) - SingleTimers[slot].callback(SingleTimers[slot].data); + /* the current widget belongs to the specified timer group */ + if (TimerGroupWidgets[widget].interval == interval) { + /* if the widget's callback function has been set, call it and + pass the corresponding data */ + if (TimerGroupWidgets[widget].callback != NULL) + TimerGroupWidgets[widget].callback(TimerGroupWidgets[widget].data); + + /* mark one-shot widget as inactive (which means the it has + been deleted and its allocated memory may be re-used) */ + if (TimerGroupWidgets[widget].one_shot) { + TimerGroupWidgets[widget].active = 0; + + /* also remove the corresponding timer group if it is empty */ + timer_remove_empty_group(interval); + } } } } + int timer_add_widget(void (*callback) (void *data), void *data, const int interval, const int one_shot) -{ - int slot; +/* Add widget to timer group of the specified update interval + (also creates a new timer group if necessary). - /* make sure that group for update interval exists or can be created */ - if (timer_add_group(timer_process_group, interval) != 0) - return -1; + callback (void pointer): function of type void func(void *data) + which will be called whenever the timer group triggers; this + pointer will also be used to identify a specific widget + + data (void pointer): data which will be passed to the callback + function; this pointer will also be used to identify a specific + widget + + interval (integer): specifies the timer's triggering interval in + milliseconds - /* find a free slot for callback data */ - for (slot = 0; slot < nSingleTimers; slot++) { - if (SingleTimers[slot].active == 0) + one_shot (integer): specifies whether the timer should trigger + indefinitely until it is deleted (value of 0) or only once (all + other values) + + return value (integer): returns a value of 0 on successful widget + addition; otherwise returns a value of -1 +*/ +{ + int widget; /* current widget's ID */ + + /* if no timer group for update interval exists, create one */ + if (!timer_group_exists(interval)) { + /* creation of new timer group failed, so signal failure by + returning a value of -1 */ + if (timer_add_group(interval) != 0) + return -1; + } + + /* try to minimize memory usage by looping through the widget + slots and looking for an inactive widget slot */ + for (widget = 0; widget < nTimerGroupWidgets; widget++) { + if (TimerGroupWidgets[widget].active == 0) { + /* we've just found one, so let's reuse it ("widget" holds its + ID) by breaking the loop */ break; + } } - /* none found, allocate a new slot */ - if (slot >= nSingleTimers) { - nSingleTimers++; - SingleTimers = realloc(SingleTimers, nSingleTimers * sizeof(*SingleTimers)); + /* no inactive widget slots (or none at all) found, so we have to + add a new widget slot */ + if (widget >= nTimerGroupWidgets) { + /* increment number of widget slots and (re-)allocate memory used + for storing the widget slots */ + nTimerGroupWidgets++; + TimerGroupWidgets = realloc(TimerGroupWidgets, nTimerGroupWidgets * sizeof(*TimerGroupWidgets)); + + /* make sure "widget" points to valid memory */ + widget = nTimerGroupWidgets - 1; + + /* realloc() has failed */ + if (TimerGroupWidgets == NULL) { + /* restore old number of widget slots */ + nTimerGroupWidgets--; + + /* signal unsuccessful creation of widget slot */ + return -1; + } } - /* fill slot with callback data */ - SingleTimers[slot].callback = callback; - SingleTimers[slot].data = data; - SingleTimers[slot].interval = interval; - SingleTimers[slot].one_shot = one_shot; - SingleTimers[slot].active = 1; + /* initialize widget slot */ + TimerGroupWidgets[widget].callback = callback; + TimerGroupWidgets[widget].data = data; + TimerGroupWidgets[widget].interval = interval; + TimerGroupWidgets[widget].one_shot = one_shot; + /* set widget slot to active so that it is processed and not + overwritten by the memory optimization routine above */ + TimerGroupWidgets[widget].active = 1; + + /* signal successful addition of widget slot */ return 0; } + int timer_remove_widget(void (*callback) (void *data), void *data) +/* Remove widget from the timer group with the specified update + interval (also removes corresponding timer group if empty). + + callback (void pointer): function of type void func(void *data); + here, it will be used to identify a specific widget + + data (void pointer): data which will be passed to the callback + function; here, it will be used to identify a specific widget + + return value (integer): returns a value of 0 on successful widget + removal; otherwise returns a value of -1 +*/ { - int slot, interval; - - interval = 0; - /* look for (active) widget with given callback function and data */ - for (slot = 0; slot < nSingleTimers; slot++) { - if (SingleTimers[slot].callback == callback && SingleTimers[slot].data == data && SingleTimers[slot].active) { - /* deactivate widget */ - SingleTimers[slot].active = 0; - interval = SingleTimers[slot].interval; + int widget; /* current widget's ID */ + int interval = -1; /* specified widget's triggering interval in + milliseconds */ + + /* loop through the widget slots and try to find the specified + widget slot by looking for its settings */ + for (widget = 0; widget < nTimerGroupWidgets; widget++) { + /* skip inactive (i.e. deleted) widget slots */ + if (TimerGroupWidgets[widget].active == 0) + continue; + + if (TimerGroupWidgets[widget].callback == callback && TimerGroupWidgets[widget].data == data) { + /* we have found the widget slot, so mark it as being + inactive; we will not actually delete the slot, so its + allocated memory may be re-used */ + TimerGroupWidgets[widget].active = 0; + + /* store the widget's triggering interval for later use and + break the loop */ + interval = TimerGroupWidgets[widget].interval; break; } } - /* signal an error if no matching widget was found */ - if (interval == 0) + /* if no matching widget was found, signal an error by returning + a value of -1 */ + if (interval < 0) return -1; - /* look for other widgets with given update interval */ - for (slot = 0; slot < nSingleTimers; slot++) { - if (SingleTimers[slot].active == 0) - continue; - /* at least one other widget with given update interval exists */ - if (SingleTimers[slot].interval == interval) - return 0; - } - - /* remove group with given update interval */ - return timer_remove_group(timer_process_group, interval); + /* if no other widgets with specified update interval exist, + remove corresponding timer group and signal success or + failure */ + return timer_remove_empty_group(interval); } + void timer_exit_group(void) +/* Release all timer groups and widgets and free the associated + memory blocks. + + return value: void +*/ { - int group; + int group; /* current timer group's ID */ + + /* loop through all timer groups and remove them one by one */ + for (group = 0; group < nTimerGroups; group++) { + /* remove generic timer */ + timer_remove(timer_process_group, TimerGroups[group].interval); - /* remove generic timer and free memory for callback data */ - for (group = 0; group < nGroupTimers; group++) { - timer_remove(GroupTimers[group].callback, GroupTimers[group].interval); - free(GroupTimers[group].interval); + /* free memory allocated for callback data (i.e. the group's + triggering interval in milliseconds) */ + free(TimerGroups[group].interval); } - /* free memory for groups */ - nGroupTimers = 0; + /* reset number of allocated timer groups */ + nTimerGroups = 0; - if (GroupTimers != NULL) { - free(GroupTimers);; - GroupTimers = NULL; + /* free allocated memory containing the timer group slots */ + if (TimerGroups != NULL) { + free(TimerGroups); + TimerGroups = NULL; } - /* free memory for widget callback data */ - nSingleTimers = 0; + /* reset number of allocated widget slots */ + nTimerGroupWidgets = 0; - if (SingleTimers != NULL) { - free(SingleTimers);; - SingleTimers = NULL; + /* free allocated memory containing the widget slots */ + if (TimerGroupWidgets != NULL) { + free(TimerGroupWidgets); + TimerGroupWidgets = NULL; } } diff --git a/timer_group.h b/timer_group.h index 36d9057..ab9b835 100644 --- a/timer_group.h +++ b/timer_group.h @@ -29,12 +29,13 @@ #ifndef _TIMER_GROUP_H_ #define _TIMER_GROUP_H_ -int timer_add_group(void (*callback) (void *data), const int interval); -int timer_remove_group(void (*callback) (void *data), const int interval); + void timer_process_group(void *data); + void timer_exit_group(void); int timer_add_widget(void (*callback) (void *data), void *data, const int interval, const int one_shot); + int timer_remove_widget(void (*callback) (void *data), void *data); #endif |