*fix* use another timer implementation, coz *BSD does not support timerfd :(
git-svn-id: http://tint2.googlecode.com/svn/trunk@296 121b4492-b84c-0410-8b4c-0d4edfb3f3cc
This commit is contained in:
@@ -3,7 +3,7 @@ SUBDIRS = tint2conf
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
AM_CFLAGS += @PANGOCAIRO_CFLAGS@ @PANGO_CFLAGS@ @CAIRO_CFLAGS@ @GLIB2_CFLAGS@ @GOBJECT2_CFLAGS@ @X11_CFLAGS@ @XINERAMA_CFLAGS@ @IMLIB2_CFLAGS@
|
AM_CFLAGS += @PANGOCAIRO_CFLAGS@ @PANGO_CFLAGS@ @CAIRO_CFLAGS@ @GLIB2_CFLAGS@ @GOBJECT2_CFLAGS@ @X11_CFLAGS@ @XINERAMA_CFLAGS@ @IMLIB2_CFLAGS@
|
||||||
LIBS = @PANGOCAIRO_LIBS@ @PANGO_LIBS@ @CAIRO_LIBS@ @GLIB2_LIBS@ @GOBJECT2_LIBS@ @X11_LIBS@ @XINERAMA_LIBS@ @IMLIB2_LIBS@
|
LIBS = @PANGOCAIRO_LIBS@ @PANGO_LIBS@ @CAIRO_LIBS@ @GLIB2_LIBS@ @GOBJECT2_LIBS@ @X11_LIBS@ @XINERAMA_LIBS@ @IMLIB2_LIBS@ -lrt
|
||||||
INCLUDES = -Iutil -Iclock -Itaskbar -Isystray -Itooltip
|
INCLUDES = -Iutil -Iclock -Itaskbar -Isystray -Itooltip
|
||||||
|
|
||||||
bin_PROGRAMS = tint2
|
bin_PROGRAMS = tint2
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ PangoFontDescription *bat1_font_desc=0;
|
|||||||
PangoFontDescription *bat2_font_desc=0;
|
PangoFontDescription *bat2_font_desc=0;
|
||||||
struct batstate battery_state;
|
struct batstate battery_state;
|
||||||
int battery_enabled;
|
int battery_enabled;
|
||||||
|
static const struct timeout* battery_timeout=0;
|
||||||
|
|
||||||
static char buf_bat_percentage[10];
|
static char buf_bat_percentage[10];
|
||||||
static char buf_bat_time[20];
|
static char buf_bat_time[20];
|
||||||
@@ -131,8 +132,8 @@ void init_battery()
|
|||||||
g_free(path1);
|
g_free(path1);
|
||||||
g_free(battery_dir);
|
g_free(battery_dir);
|
||||||
|
|
||||||
if (battery_enabled)
|
if (battery_enabled && battery_timeout==0)
|
||||||
install_timer(0, 1000000, 5, 0, update_batterys);
|
battery_timeout = add_timeout(10, 5000, update_batterys);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ static char buf_time[40];
|
|||||||
static char buf_date[40];
|
static char buf_date[40];
|
||||||
static char buf_tooltip[40];
|
static char buf_tooltip[40];
|
||||||
int clock_enabled;
|
int clock_enabled;
|
||||||
|
static const struct timeout* clock_timeout=0;
|
||||||
|
|
||||||
|
|
||||||
void update_clocks()
|
void update_clocks()
|
||||||
@@ -69,10 +70,11 @@ const char* clock_get_tooltip(void* obj)
|
|||||||
|
|
||||||
void init_clock()
|
void init_clock()
|
||||||
{
|
{
|
||||||
if(time1_format) {
|
if(time1_format && clock_timeout==0) {
|
||||||
if (strchr(time1_format, 'S') || strchr(time1_format, 'T') || strchr(time1_format, 'r'))
|
if (strchr(time1_format, 'S') || strchr(time1_format, 'T') || strchr(time1_format, 'r'))
|
||||||
install_timer(0, 1000000, 1, 0, update_clocks);
|
clock_timeout = add_timeout(10, 1000, update_clocks);
|
||||||
else install_timer(0, 1000000, 60, 0, update_clocks);
|
else
|
||||||
|
clock_timeout = add_timeout(10, 60000, update_clocks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
17
src/config.c
17
src/config.c
@@ -75,7 +75,6 @@ void init_config()
|
|||||||
list_back = g_slist_append(0, calloc(1, sizeof(Area)));
|
list_back = g_slist_append(0, calloc(1, sizeof(Area)));
|
||||||
|
|
||||||
// tint2 could reload config, so we cleanup objects
|
// tint2 could reload config, so we cleanup objects
|
||||||
uninstall_all_timer();
|
|
||||||
cleanup_systray();
|
cleanup_systray();
|
||||||
#ifdef ENABLE_BATTERY
|
#ifdef ENABLE_BATTERY
|
||||||
cleanup_battery();
|
cleanup_battery();
|
||||||
@@ -526,20 +525,12 @@ void add_entry (char *key, char *value)
|
|||||||
else if (strcmp (key, "tooltip") == 0)
|
else if (strcmp (key, "tooltip") == 0)
|
||||||
g_tooltip.enabled = atoi(value);
|
g_tooltip.enabled = atoi(value);
|
||||||
else if (strcmp (key, "tooltip_show_timeout") == 0) {
|
else if (strcmp (key, "tooltip_show_timeout") == 0) {
|
||||||
double timeout = atof(value);
|
int timeout_msec = 1000*atof(value);
|
||||||
int sec = (int)timeout;
|
g_tooltip.show_timeout_msec = timeout_msec;
|
||||||
int nsec = (timeout-sec)*1e9;
|
|
||||||
if (nsec < 0) // can happen because of double is not precise such that (sec > timeout)==TRUE
|
|
||||||
nsec = 0;
|
|
||||||
g_tooltip.show_timeout = (struct timespec){.tv_sec=sec, .tv_nsec=nsec};
|
|
||||||
}
|
}
|
||||||
else if (strcmp (key, "tooltip_hide_timeout") == 0) {
|
else if (strcmp (key, "tooltip_hide_timeout") == 0) {
|
||||||
double timeout = atof(value);
|
int timeout_msec = 1000*atof(value);
|
||||||
int sec = (int)timeout;
|
g_tooltip.hide_timeout_msec = timeout_msec;
|
||||||
int nsec = (timeout-sec)*1e9;
|
|
||||||
if (nsec < 0) // can happen because of double is not precise such that (sec > timeout)==TRUE
|
|
||||||
nsec = 0;
|
|
||||||
g_tooltip.hide_timeout = (struct timespec){.tv_sec=sec, .tv_nsec=nsec};
|
|
||||||
}
|
}
|
||||||
else if (strcmp (key, "tooltip_padding") == 0) {
|
else if (strcmp (key, "tooltip_padding") == 0) {
|
||||||
extract_values(value, &value1, &value2, &value3);
|
extract_values(value, &value1, &value2, &value3);
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
static int urgent_timer = 0;
|
static const struct timeout* urgent_timeout = 0;
|
||||||
|
|
||||||
const char* task_get_tooltip(void* obj)
|
const char* task_get_tooltip(void* obj)
|
||||||
{
|
{
|
||||||
@@ -99,6 +99,8 @@ Task *add_task (Window win)
|
|||||||
//printf("add_task panel %d, desktop %d, task %s\n", i, j, new_tsk2->title);
|
//printf("add_task panel %d, desktop %d, task %s\n", i, j, new_tsk2->title);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (window_is_urgent(win))
|
||||||
|
add_urgent(new_tsk2);
|
||||||
return new_tsk2;
|
return new_tsk2;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -503,10 +505,8 @@ void add_urgent(Task *tsk)
|
|||||||
t->tick = 0;
|
t->tick = 0;
|
||||||
urgent_list = g_slist_prepend(urgent_list, t);
|
urgent_list = g_slist_prepend(urgent_list, t);
|
||||||
|
|
||||||
if (urgent_timer == 0)
|
if (urgent_timeout == 0)
|
||||||
urgent_timer = install_timer(0, 1000000, 1, 0, blink_urgent);
|
urgent_timeout = add_timeout(10, 1000, blink_urgent);
|
||||||
else
|
|
||||||
reset_timer(urgent_timer, 0, 1000000, 1, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -518,8 +518,10 @@ void del_urgent(Task *tsk)
|
|||||||
if (t->tsk == tsk) {
|
if (t->tsk == tsk) {
|
||||||
urgent_list = g_slist_remove(urgent_list, t);
|
urgent_list = g_slist_remove(urgent_list, t);
|
||||||
free(t);
|
free(t);
|
||||||
if (!urgent_list)
|
if (!urgent_list) {
|
||||||
reset_timer(urgent_timer, 0, 0, 0, 0);
|
stop_timeout(urgent_timeout);
|
||||||
|
urgent_timeout = 0;
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
urgent_task = urgent_task->next;
|
urgent_task = urgent_task->next;
|
||||||
@@ -528,6 +530,8 @@ void del_urgent(Task *tsk)
|
|||||||
|
|
||||||
int is_urgent(Task *tsk)
|
int is_urgent(Task *tsk)
|
||||||
{
|
{
|
||||||
|
if (!tsk)
|
||||||
|
return;
|
||||||
GSList* urgent_task = urgent_list;
|
GSList* urgent_task = urgent_list;
|
||||||
while (urgent_task) {
|
while (urgent_task) {
|
||||||
Task_urgent* t = urgent_task->data;
|
Task_urgent* t = urgent_task->data;
|
||||||
|
|||||||
35
src/tint.c
35
src/tint.c
@@ -635,8 +635,7 @@ int main (int argc, char *argv[])
|
|||||||
int x11_fd, i;
|
int x11_fd, i;
|
||||||
Panel *panel;
|
Panel *panel;
|
||||||
GSList *it;
|
GSList *it;
|
||||||
GSList* timer_iter;
|
const struct timespec* timeout;
|
||||||
struct timer* timer;
|
|
||||||
|
|
||||||
init (argc, argv);
|
init (argc, argv);
|
||||||
|
|
||||||
@@ -695,33 +694,17 @@ int main (int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
|
|
||||||
// thanks to AngryLlama for the timer
|
// thanks to AngryLlama for the timer
|
||||||
// Create a File Description Set containing x11_fd, and every timer_fd
|
// Create a File Description Set containing x11_fd
|
||||||
FD_ZERO (&fdset);
|
FD_ZERO (&fdset);
|
||||||
FD_SET (x11_fd, &fdset);
|
FD_SET (x11_fd, &fdset);
|
||||||
int max_fd = x11_fd;
|
update_next_timeout();
|
||||||
timer_iter = timer_list;
|
if (next_timeout.tv_sec >= 0 && next_timeout.tv_nsec >= 0)
|
||||||
while (timer_iter) {
|
timeout = &next_timeout;
|
||||||
timer = timer_iter->data;
|
else
|
||||||
max_fd = timer->id > max_fd ? timer->id : max_fd;
|
timeout = 0;
|
||||||
FD_SET(timer->id, &fdset);
|
|
||||||
timer_iter = timer_iter->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait for X Event or a Timer
|
// Wait for X Event or a Timer
|
||||||
if (pselect(max_fd+1, &fdset, 0, 0, 0, &empty_mask) > 0) {
|
if (pselect(x11_fd+1, &fdset, 0, 0, timeout, &empty_mask) > 0) {
|
||||||
// we need to iterate over the whole timer list, since fd_set can only be checked with the
|
|
||||||
// brute force method FD_ISSET for every possible timer
|
|
||||||
timer_iter = timer_list;
|
|
||||||
while (timer_iter) {
|
|
||||||
timer = timer_iter->data;
|
|
||||||
if (FD_ISSET(timer->id, &fdset)) {
|
|
||||||
uint64_t dummy;
|
|
||||||
if ( -1 != read(timer->id, &dummy, sizeof(uint64_t)) )
|
|
||||||
timer->_callback();
|
|
||||||
}
|
|
||||||
timer_iter = timer_iter->next;
|
|
||||||
}
|
|
||||||
|
|
||||||
while (XPending (server.dsp)) {
|
while (XPending (server.dsp)) {
|
||||||
XNextEvent(server.dsp, &e);
|
XNextEvent(server.dsp, &e);
|
||||||
|
|
||||||
@@ -800,6 +783,8 @@ int main (int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
callback_timeout_expired();
|
||||||
|
|
||||||
switch (signal_pending) {
|
switch (signal_pending) {
|
||||||
case SIGUSR1: // reload config file
|
case SIGUSR1: // reload config file
|
||||||
signal_pending = 0;
|
signal_pending = 0;
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ static int x, y, width, height;
|
|||||||
// the next functions are helper functions for tooltip handling
|
// the next functions are helper functions for tooltip handling
|
||||||
void start_show_timeout();
|
void start_show_timeout();
|
||||||
void start_hide_timeout();
|
void start_hide_timeout();
|
||||||
void stop_timeouts();
|
void stop_tooltip_timeout();
|
||||||
void tooltip_copy_text(Area* area);
|
void tooltip_copy_text(Area* area);
|
||||||
|
|
||||||
// give the tooltip some reasonable default values
|
// give the tooltip some reasonable default values
|
||||||
@@ -41,8 +41,8 @@ Tooltip g_tooltip = {
|
|||||||
.area = 0,
|
.area = 0,
|
||||||
.panel = 0,
|
.panel = 0,
|
||||||
.window = 0,
|
.window = 0,
|
||||||
.show_timeout = { 0, 0 },
|
.show_timeout_msec = 0,
|
||||||
.hide_timeout = { 0, 0 },
|
.hide_timeout_msec = 0,
|
||||||
.enabled = False,
|
.enabled = False,
|
||||||
.mapped = False,
|
.mapped = False,
|
||||||
.paddingx = 0,
|
.paddingx = 0,
|
||||||
@@ -51,8 +51,7 @@ Tooltip g_tooltip = {
|
|||||||
.background_color = { .color={0.5, 0.4, 0.5}, .alpha=1 },
|
.background_color = { .color={0.5, 0.4, 0.5}, .alpha=1 },
|
||||||
.border = { .color={0, 0, 0}, .alpha=1, .width=1, .rounded=0 },
|
.border = { .color={0, 0, 0}, .alpha=1, .width=1, .rounded=0 },
|
||||||
.font_desc = 0,
|
.font_desc = 0,
|
||||||
.show_timer_id = 0,
|
.timeout = 0
|
||||||
.hide_timer_id = 0
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void init_tooltip()
|
void init_tooltip()
|
||||||
@@ -60,9 +59,6 @@ void init_tooltip()
|
|||||||
if (!g_tooltip.font_desc)
|
if (!g_tooltip.font_desc)
|
||||||
g_tooltip.font_desc = pango_font_description_from_string("sans 10");
|
g_tooltip.font_desc = pango_font_description_from_string("sans 10");
|
||||||
|
|
||||||
g_tooltip.show_timer_id = install_timer(0, 0, 0, 0, tooltip_show);
|
|
||||||
g_tooltip.hide_timer_id = install_timer(0, 0, 0, 0, tooltip_hide);
|
|
||||||
|
|
||||||
XSetWindowAttributes attr;
|
XSetWindowAttributes attr;
|
||||||
attr.override_redirect = True;
|
attr.override_redirect = True;
|
||||||
attr.event_mask = StructureNotifyMask;
|
attr.event_mask = StructureNotifyMask;
|
||||||
@@ -73,7 +69,7 @@ void init_tooltip()
|
|||||||
|
|
||||||
void cleanup_tooltip()
|
void cleanup_tooltip()
|
||||||
{
|
{
|
||||||
stop_timeouts();
|
stop_tooltip_timeout();
|
||||||
tooltip_hide();
|
tooltip_hide();
|
||||||
g_tooltip.enabled = False;
|
g_tooltip.enabled = False;
|
||||||
tooltip_copy_text(0);
|
tooltip_copy_text(0);
|
||||||
@@ -96,7 +92,7 @@ void tooltip_trigger_show(Area* area, Panel* p, int x_root, int y_root)
|
|||||||
if (g_tooltip.mapped && g_tooltip.area != area) {
|
if (g_tooltip.mapped && g_tooltip.area != area) {
|
||||||
tooltip_copy_text(area);
|
tooltip_copy_text(area);
|
||||||
tooltip_update();
|
tooltip_update();
|
||||||
stop_timeouts();
|
stop_tooltip_timeout();
|
||||||
}
|
}
|
||||||
else if (!g_tooltip.mapped) {
|
else if (!g_tooltip.mapped) {
|
||||||
start_show_timeout();
|
start_show_timeout();
|
||||||
@@ -110,7 +106,7 @@ void tooltip_show()
|
|||||||
Window w;
|
Window w;
|
||||||
XTranslateCoordinates( server.dsp, server.root_win, g_tooltip.panel->main_win, x, y, &mx, &my, &w);
|
XTranslateCoordinates( server.dsp, server.root_win, g_tooltip.panel->main_win, x, y, &mx, &my, &w);
|
||||||
Area* area = click_area(g_tooltip.panel, mx, my);
|
Area* area = click_area(g_tooltip.panel, mx, my);
|
||||||
stop_timeouts();
|
stop_tooltip_timeout();
|
||||||
if (!g_tooltip.mapped && area->_get_tooltip_text) {
|
if (!g_tooltip.mapped && area->_get_tooltip_text) {
|
||||||
tooltip_copy_text(area);
|
tooltip_copy_text(area);
|
||||||
g_tooltip.mapped = True;
|
g_tooltip.mapped = True;
|
||||||
@@ -204,7 +200,6 @@ void tooltip_update()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("tooltip_update\n");
|
|
||||||
tooltip_update_geometry();
|
tooltip_update_geometry();
|
||||||
tooltip_adjust_geometry();
|
tooltip_adjust_geometry();
|
||||||
XMoveResizeWindow(server.dsp, g_tooltip.window, x, y, width, height);
|
XMoveResizeWindow(server.dsp, g_tooltip.window, x, y, width, height);
|
||||||
@@ -253,14 +248,14 @@ void tooltip_trigger_hide(Tooltip* tooltip)
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// tooltip not visible yet, but maybe a timeout is still pending
|
// tooltip not visible yet, but maybe a timeout is still pending
|
||||||
stop_timeouts();
|
stop_tooltip_timeout();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void tooltip_hide()
|
void tooltip_hide()
|
||||||
{
|
{
|
||||||
stop_timeouts();
|
stop_tooltip_timeout();
|
||||||
if (g_tooltip.mapped) {
|
if (g_tooltip.mapped) {
|
||||||
g_tooltip.mapped = False;
|
g_tooltip.mapped = False;
|
||||||
XUnmapWindow(server.dsp, g_tooltip.window);
|
XUnmapWindow(server.dsp, g_tooltip.window);
|
||||||
@@ -271,31 +266,28 @@ void tooltip_hide()
|
|||||||
|
|
||||||
void start_show_timeout()
|
void start_show_timeout()
|
||||||
{
|
{
|
||||||
reset_timer(g_tooltip.hide_timer_id, 0, 0, 0, 0);
|
if (g_tooltip.timeout)
|
||||||
struct timespec t = g_tooltip.show_timeout;
|
change_timeout(g_tooltip.timeout, g_tooltip.show_timeout_msec, 0, tooltip_show);
|
||||||
if (t.tv_sec == 0 && t.tv_nsec == 0) {
|
else
|
||||||
tooltip_show();
|
g_tooltip.timeout = add_timeout(g_tooltip.show_timeout_msec, 0, tooltip_show);
|
||||||
}
|
|
||||||
else {
|
|
||||||
reset_timer(g_tooltip.show_timer_id, t.tv_sec, t.tv_nsec, 0, 0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void start_hide_timeout()
|
void start_hide_timeout()
|
||||||
{
|
{
|
||||||
reset_timer(g_tooltip.show_timer_id, 0, 0, 0, 0);
|
if (g_tooltip.timeout)
|
||||||
struct timespec t = g_tooltip.hide_timeout;
|
change_timeout(g_tooltip.timeout, g_tooltip.hide_timeout_msec, 0, tooltip_hide);
|
||||||
if (t.tv_sec == 0 && t.tv_nsec == 0)
|
|
||||||
tooltip_hide();
|
|
||||||
else
|
else
|
||||||
reset_timer(g_tooltip.hide_timer_id, t.tv_sec, t.tv_nsec, 0, 0);
|
g_tooltip.timeout = add_timeout(g_tooltip.hide_timeout_msec, 0, tooltip_hide);
|
||||||
}
|
}
|
||||||
|
|
||||||
void stop_timeouts()
|
|
||||||
|
void stop_tooltip_timeout()
|
||||||
{
|
{
|
||||||
reset_timer(g_tooltip.show_timer_id, 0, 0, 0, 0);
|
if (g_tooltip.timeout) {
|
||||||
reset_timer(g_tooltip.hide_timer_id, 0, 0, 0, 0);
|
stop_timeout(g_tooltip.timeout);
|
||||||
|
g_tooltip.timeout = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,10 +18,9 @@
|
|||||||
#ifndef TOOLTIP_H
|
#ifndef TOOLTIP_H
|
||||||
#define TOOLTIP_H
|
#define TOOLTIP_H
|
||||||
|
|
||||||
#include <sys/time.h>
|
|
||||||
|
|
||||||
#include "task.h"
|
#include "task.h"
|
||||||
#include "panel.h"
|
#include "panel.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@@ -29,8 +28,8 @@ typedef struct {
|
|||||||
char* tooltip_text;
|
char* tooltip_text;
|
||||||
Panel* panel;
|
Panel* panel;
|
||||||
Window window;
|
Window window;
|
||||||
struct timespec show_timeout;
|
int show_timeout_msec;
|
||||||
struct timespec hide_timeout;
|
int hide_timeout_msec;
|
||||||
Bool enabled;
|
Bool enabled;
|
||||||
Bool mapped;
|
Bool mapped;
|
||||||
int paddingx;
|
int paddingx;
|
||||||
@@ -39,8 +38,7 @@ typedef struct {
|
|||||||
config_color font_color;
|
config_color font_color;
|
||||||
Color background_color;
|
Color background_color;
|
||||||
Border border;
|
Border border;
|
||||||
int show_timer_id;
|
const struct timeout* timeout;
|
||||||
int hide_timer_id;
|
|
||||||
} Tooltip;
|
} Tooltip;
|
||||||
|
|
||||||
extern Tooltip g_tooltip;
|
extern Tooltip g_tooltip;
|
||||||
|
|||||||
170
src/util/timer.c
170
src/util/timer.c
@@ -15,68 +15,152 @@
|
|||||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
#include <sys/timerfd.h>
|
#include <time.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
|
||||||
#include <fcntl.h>
|
|
||||||
|
|
||||||
#include "timer.h"
|
#include "timer.h"
|
||||||
|
|
||||||
GSList* timer_list = 0;
|
GSList* timeout_list = 0;
|
||||||
|
struct timespec next_timeout;
|
||||||
|
|
||||||
int install_timer(int value_sec, int value_nsec, int interval_sec, int interval_nsec, void (*_callback)())
|
void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(), struct timeout* t);
|
||||||
|
gint compare_timeouts(gconstpointer t1, gconstpointer t2);
|
||||||
|
gint compare_timespecs(const struct timespec* t1, const struct timespec* t2);
|
||||||
|
int timespec_subtract(struct timespec* result, struct timespec* x, struct timespec* y);
|
||||||
|
|
||||||
|
|
||||||
|
const struct timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)())
|
||||||
{
|
{
|
||||||
if ( value_sec < 0 || interval_sec < 0 || _callback == 0 )
|
struct timeout* t = malloc(sizeof(struct timeout));
|
||||||
return -1;
|
add_timeout_intern(value_msec, interval_msec, _callback, t);
|
||||||
|
return t;
|
||||||
int timer_fd;
|
|
||||||
struct itimerspec timer;
|
|
||||||
timer.it_value = (struct timespec){ .tv_sec=value_sec, .tv_nsec=value_nsec };
|
|
||||||
timer.it_interval = (struct timespec){ .tv_sec=interval_sec, .tv_nsec=interval_nsec };
|
|
||||||
timer_fd = timerfd_create(CLOCK_MONOTONIC, 0);
|
|
||||||
timerfd_settime(timer_fd, 0, &timer, 0);
|
|
||||||
struct timer* t = malloc(sizeof(struct timer));
|
|
||||||
t->id=timer_fd;
|
|
||||||
t->_callback = _callback;
|
|
||||||
timer_list = g_slist_prepend(timer_list, t);
|
|
||||||
|
|
||||||
int flags = fcntl( timer_fd, F_GETFL, 0 );
|
|
||||||
if( flags != -1 )
|
|
||||||
fcntl( timer_fd, F_SETFL, flags | O_NONBLOCK );
|
|
||||||
|
|
||||||
return timer_fd;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void reset_timer(int id, int value_sec, int value_nsec, int interval_sec, int interval_nsec)
|
void change_timeout(const struct timeout *t, int value_msec, int interval_msec, void(*_callback)())
|
||||||
{
|
{
|
||||||
struct itimerspec timer;
|
timeout_list = g_slist_remove(timeout_list, t);
|
||||||
timer.it_value = (struct timespec){ .tv_sec=value_sec, .tv_nsec=value_nsec };
|
add_timeout_intern(value_msec, interval_msec, _callback, (struct timeout*)t);
|
||||||
timer.it_interval = (struct timespec){ .tv_sec=interval_sec, .tv_nsec=interval_nsec };
|
|
||||||
timerfd_settime(id, 0, &timer, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uninstall_timer(int id)
|
void update_next_timeout()
|
||||||
{
|
{
|
||||||
close(id);
|
if (timeout_list) {
|
||||||
GSList* timer_iter = timer_list;
|
struct timeout* t = timeout_list->data;
|
||||||
while (timer_iter) {
|
struct timespec cur_time;
|
||||||
struct timer* t = timer_iter->data;
|
clock_gettime(CLOCK_MONOTONIC, &cur_time);
|
||||||
if (t->id == id) {
|
if (timespec_subtract(&next_timeout, &t->timeout_expires, &cur_time)) {
|
||||||
timer_list = g_slist_remove(timer_list, t);
|
next_timeout.tv_sec = 0;
|
||||||
free(t);
|
next_timeout.tv_nsec = 0;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
timer_iter = timer_iter->next;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
next_timeout.tv_sec = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void uninstall_all_timer()
|
void callback_timeout_expired()
|
||||||
{
|
{
|
||||||
while (timer_list) {
|
struct timespec cur_time;
|
||||||
struct timer* t = timer_list->data;
|
struct timeout* t;
|
||||||
uninstall_timer(t->id);
|
while (timeout_list) {
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &cur_time);
|
||||||
|
t = timeout_list->data;
|
||||||
|
if (compare_timespecs(&t->timeout_expires, &cur_time) <= 0) {
|
||||||
|
// it's time for the callback function
|
||||||
|
t->_callback();
|
||||||
|
if (g_slist_find(timeout_list, t)) {
|
||||||
|
// if _callback() calls stop_timeout(t) the timeout 't' does not exist anymore
|
||||||
|
timeout_list = g_slist_remove(timeout_list, t);
|
||||||
|
if (t->interval_msec > 0)
|
||||||
|
add_timeout_intern(t->interval_msec, t->interval_msec, t->_callback, t);
|
||||||
|
else
|
||||||
|
free(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void stop_timeout(const struct timeout* t)
|
||||||
|
{
|
||||||
|
if (g_slist_find(timeout_list, t)) {
|
||||||
|
timeout_list = g_slist_remove(timeout_list, t);
|
||||||
|
free((void*)t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void stop_all_timeouts()
|
||||||
|
{
|
||||||
|
while (timeout_list) {
|
||||||
|
free(timeout_list->data);
|
||||||
|
timeout_list = g_slist_remove(timeout_list, timeout_list->data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void add_timeout_intern(int value_msec, int interval_msec, void(*_callback)(), struct timeout *t)
|
||||||
|
{
|
||||||
|
t->interval_msec = interval_msec;
|
||||||
|
t->_callback = _callback;
|
||||||
|
struct timespec expire;
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &expire);
|
||||||
|
expire.tv_sec += value_msec / 1000;
|
||||||
|
expire.tv_nsec += (value_msec % 1000)*1000000;
|
||||||
|
if (expire.tv_nsec >= 1000000000) { // 10^9
|
||||||
|
expire.tv_sec++;
|
||||||
|
expire.tv_nsec -= 1000000000;
|
||||||
|
}
|
||||||
|
t->timeout_expires = expire;
|
||||||
|
timeout_list = g_slist_insert_sorted(timeout_list, t, compare_timeouts);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gint compare_timeouts(gconstpointer t1, gconstpointer t2)
|
||||||
|
{
|
||||||
|
return compare_timespecs(&((const struct timeout*)t1)->timeout_expires,
|
||||||
|
&((const struct timeout*)t2)->timeout_expires);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
gint compare_timespecs(const struct timespec* t1, const struct timespec* t2)
|
||||||
|
{
|
||||||
|
if (t1->tv_sec < t2->tv_sec)
|
||||||
|
return -1;
|
||||||
|
else if (t1->tv_sec == t2->tv_sec) {
|
||||||
|
if (t1->tv_nsec < t2->tv_nsec)
|
||||||
|
return -1;
|
||||||
|
else if (t1->tv_nsec == t2->tv_nsec)
|
||||||
|
return 0;
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int timespec_subtract(struct timespec* result, struct timespec* x, struct timespec* y)
|
||||||
|
{
|
||||||
|
/* Perform the carry for the later subtraction by updating y. */
|
||||||
|
if (x->tv_nsec < y->tv_nsec) {
|
||||||
|
int nsec = (y->tv_nsec - x->tv_nsec) / 1000000000 + 1;
|
||||||
|
y->tv_nsec -= 1000000000 * nsec;
|
||||||
|
y->tv_sec += nsec;
|
||||||
|
}
|
||||||
|
if (x->tv_nsec - y->tv_nsec > 1000000000) {
|
||||||
|
int nsec = (x->tv_nsec - y->tv_nsec) / 1000000000;
|
||||||
|
y->tv_nsec += 1000000000 * nsec;
|
||||||
|
y->tv_sec -= nsec;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute the time remaining to wait. tv_nsec is certainly positive. */
|
||||||
|
result->tv_sec = x->tv_sec - y->tv_sec;
|
||||||
|
result->tv_nsec = x->tv_nsec - y->tv_nsec;
|
||||||
|
|
||||||
|
/* Return 1 if result is negative. */
|
||||||
|
return x->tv_sec < y->tv_sec;
|
||||||
|
}
|
||||||
|
|||||||
@@ -21,31 +21,32 @@
|
|||||||
|
|
||||||
#include <glib.h>
|
#include <glib.h>
|
||||||
|
|
||||||
extern GSList* timer_list;
|
extern GSList* timeout_list;
|
||||||
|
extern struct timespec next_timeout;
|
||||||
|
|
||||||
|
|
||||||
struct timer {
|
struct timeout {
|
||||||
int id;
|
int interval_msec;
|
||||||
|
struct timespec timeout_expires;
|
||||||
void (*_callback)();
|
void (*_callback)();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
// timer functions
|
// timer functions
|
||||||
/** installs a timer with the first timeout 'value_sec' and then a periodic timeout with interval_sec
|
/** installs a timeout with the first timeout of 'value_msec' and then a periodic timeout with
|
||||||
* '_callback' is the callback function when the timer reaches the timeout.
|
* 'interval_msec'. '_callback' is the callback function when the timer reaches the timeout.
|
||||||
* If 'value_sec' == 0 then the timer is disabled (but not uninstalled)
|
* returns a pointer to the timeout, which is needed for stopping it again **/
|
||||||
* If 'interval_sec' == 0 the timer is a single shot timer, ie. no periodic timeout occur
|
const struct timeout* add_timeout(int value_msec, int interval_msec, void (*_callback)());
|
||||||
* returns the 'id' of the timer, which is needed for uninstalling the timer **/
|
|
||||||
int install_timer(int value_sec, int value_nsec, int interval_sec, int interval_nsec, void (*_callback)());
|
|
||||||
|
|
||||||
/** resets a timer to the new values. If 'id' does not exist nothing happens.
|
void change_timeout(const struct timeout* t, int value_msec, int interval_msec, void (*_callback)());
|
||||||
* If value_sec == 0 the timer is stopped **/
|
|
||||||
void reset_timer(int id, int value_sec, int value_nsec, int interval_sec, int interval_nsec);
|
|
||||||
|
|
||||||
/** uninstalls a timer with the given 'id'. If no timer is installed with this id nothing happens **/
|
/** stops the timeout 't' **/
|
||||||
void uninstall_timer(int id);
|
void stop_timeout(const struct timeout* t);
|
||||||
|
|
||||||
/** uninstalls all timer. Calls uninstall_timer for all available id's **/
|
/** stops all timeouts **/
|
||||||
void uninstall_all_timer();
|
void stop_all_timeouts();
|
||||||
|
|
||||||
|
void update_next_timeout();
|
||||||
|
void callback_timeout_expired();
|
||||||
|
|
||||||
#endif // TIMER_H
|
#endif // TIMER_H
|
||||||
|
|||||||
Reference in New Issue
Block a user