diff --git a/GNUmakefile b/GNUmakefile index d9cefa5..f713ce2 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -141,6 +141,7 @@ libuhub_SOURCES := \ src/util/log.c \ src/util/memory.c \ src/util/misc.c \ + src/util/timeout.c \ src/core/netevent.c \ src/network/connection.c \ src/network/network.c \ diff --git a/src/util/timeout.c b/src/util/timeout.c new file mode 100644 index 0000000..58bfad5 --- /dev/null +++ b/src/util/timeout.c @@ -0,0 +1,121 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2009, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along wtimeout_evtith this program. If not, see . + * + */ + +#include "uhub.h" +#include "util/timeout.h" + +void timeout_evt_initialize(struct timeout_evt* t, timeout_evt_cb cb, void* ptr) +{ + t->callback = cb; + t->ptr = ptr; + t->prev = 0; + t->next = 0; +} + +void timeout_evt_reset(struct timeout_evt* t) +{ + t->prev = 0; + t->next = 0; +} + +int timeout_evt_is_scheduled(struct timeout_evt* t) +{ + return !!t->prev; +} + +void timeout_queue_initialize(struct timeout_queue* t, time_t now, size_t max) +{ + t->last = now; + t->max = max; + t->events = hub_malloc_zero(max * sizeof(struct timeout_evt*)); +} + +void timeout_queue_shutdown(struct timeout_queue* t) +{ + hub_free(t->events); + t->events = 0; + t->max = 0; +} + +size_t timeout_queue_process(struct timeout_queue* t, time_t now) +{ + size_t pos; + size_t events = 0; + struct timeout_evt* evt = 0; + for (pos = t->last; pos < now; pos++) + { + while ((evt = t->events[pos % t->max])) + { + timeout_queue_remove(t, evt); + timeout_evt_reset(evt); + evt->callback(evt); + events++; + } + } + t->last = now; + return events; +} + +void timeout_queue_insert(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds) +{ + struct timeout_evt* first; + size_t pos = ((t->last + seconds) % t->max); + evt->timestamp = t->last + seconds; + evt->next = 0; + + first = t->events[pos]; + + if (!first) + { + t->events[pos] = evt; + evt->prev = evt; + } + else + { + evt->prev = first->prev; + first->prev = evt; + } +} + +void timeout_queue_remove(struct timeout_queue* t, struct timeout_evt* evt) +{ + size_t pos = (evt->timestamp % t->max); + struct timeout_evt* first = t->events[pos]; + + if (first == evt) + { + first->next->prev = first->prev; + t->events[pos] = first->next; + } + else + { + evt->prev->next = evt->next; + if (evt->next) + evt->next->prev = evt->prev; + else + first->prev = evt->prev; + } +} + +void timeout_queue_reschedule(struct timeout_queue* t, struct timeout_evt* evt, size_t seconds) +{ + if (timeout_evt_is_scheduled(evt)) + timeout_queue_remove(t, evt); + timeout_queue_insert(t, evt, seconds); +} \ No newline at end of file diff --git a/src/util/timeout.h b/src/util/timeout.h new file mode 100644 index 0000000..b86e222 --- /dev/null +++ b/src/util/timeout.h @@ -0,0 +1,56 @@ +/* + * uhub - A tiny ADC p2p connection hub + * Copyright (C) 2007-2009, Jan Vidar Krey + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +#ifndef HAVE_UHUB_TIMEOUT_HANDLER_H +#define HAVE_UHUB_TIMEOUT_HANDLER_H + +struct timeout_evt; +struct timeout_queue; + +typedef void (*timeout_evt_cb)(struct timeout_evt*); + +struct timeout_evt +{ + time_t timestamp; + timeout_evt_cb callback; + void* ptr; + struct timeout_evt* prev; + struct timeout_evt* next; +}; + +void timeout_evt_initialize(struct timeout_evt*, timeout_evt_cb, void* ptr); +void timeout_evt_reset(struct timeout_evt*); +int timeout_evt_is_scheduled(struct timeout_evt*); + + +struct timeout_queue +{ + time_t last; + size_t max; + struct timeout_evt** events; +}; + +void timeout_queue_initialize(struct timeout_queue*, time_t now, size_t max); +void timeout_queue_shutdown(struct timeout_queue*); +size_t timeout_queue_process(struct timeout_queue*, time_t now); +void timeout_queue_insert(struct timeout_queue*, struct timeout_evt*, size_t seconds); +void timeout_queue_remove(struct timeout_queue*, struct timeout_evt*); +void timeout_queue_reschedule(struct timeout_queue*, struct timeout_evt*, size_t seconds); + +#endif /* HAVE_UHUB_TIMEOUT_HANDLER_H */