Use separate timers for each schedule slot
This commit is contained in:
parent
87bd264900
commit
4f37276414
2 changed files with 101 additions and 82 deletions
|
@ -17,18 +17,18 @@ typedef struct _hexagram_schedule_slot {
|
||||||
hexagram_schedule_handler handler;
|
hexagram_schedule_handler handler;
|
||||||
} hexagram_schedule_slot;
|
} hexagram_schedule_slot;
|
||||||
|
|
||||||
typedef struct _hexagram_schedule {
|
typedef struct _hexagram_schedule_timer {
|
||||||
|
timer_t id;
|
||||||
struct sigevent ev;
|
struct sigevent ev;
|
||||||
struct itimerspec ts;
|
struct itimerspec ts;
|
||||||
timer_t timer;
|
hexagram_schedule_slot *slot;
|
||||||
|
|
||||||
size_t current,
|
|
||||||
count;
|
|
||||||
|
|
||||||
hexagram_schedule_slot *table;
|
|
||||||
|
|
||||||
void *ctx;
|
void *ctx;
|
||||||
int error;
|
int error;
|
||||||
|
} hexagram_schedule_timer;
|
||||||
|
|
||||||
|
typedef struct _hexagram_schedule {
|
||||||
|
hexagram_schedule_slot *table;
|
||||||
|
size_t count;
|
||||||
} hexagram_schedule;
|
} hexagram_schedule;
|
||||||
|
|
||||||
hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table,
|
hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table,
|
||||||
|
@ -37,8 +37,6 @@ hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table,
|
||||||
|
|
||||||
void hexagram_schedule_destroy(hexagram_schedule *schedule);
|
void hexagram_schedule_destroy(hexagram_schedule *schedule);
|
||||||
|
|
||||||
void hexagram_schedule_reset(hexagram_schedule *schedule);
|
|
||||||
|
|
||||||
int hexagram_schedule_run(hexagram_schedule *schedule);
|
int hexagram_schedule_run(hexagram_schedule *schedule);
|
||||||
|
|
||||||
int hexagram_schedule_stop(hexagram_schedule *schedule);
|
int hexagram_schedule_stop(hexagram_schedule *schedule);
|
||||||
|
|
161
src/schedule.c
161
src/schedule.c
|
@ -5,63 +5,40 @@
|
||||||
|
|
||||||
#include <hexagram/schedule.h>
|
#include <hexagram/schedule.h>
|
||||||
|
|
||||||
static int _slot_cmp(const void *item_a, const void *item_b) {
|
static inline hexagram_schedule_timer *_timer(hexagram_schedule *schedule, size_t i) {
|
||||||
hexagram_schedule_slot *a = (hexagram_schedule_slot *)item_a,
|
return &((hexagram_schedule_timer *)(schedule + 1))[i];
|
||||||
*b = (hexagram_schedule_slot *)item_b;
|
|
||||||
|
|
||||||
return a->interval_us < b->interval_us? -1:
|
|
||||||
a->interval_us > b->interval_us? 1: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline hexagram_schedule_slot *_slot(hexagram_schedule *schedule, size_t i) {
|
|
||||||
return ((hexagram_schedule_slot **)(schedule + 1))[i];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline time_t _slot_interval_ns(hexagram_schedule *schedule, size_t i) {
|
static int _timer_cmp(const void *item_a, const void *item_b) {
|
||||||
return 1000 * _slot(schedule, i)->interval_us;
|
hexagram_schedule_timer *a = (hexagram_schedule_timer *)item_a,
|
||||||
|
*b = (hexagram_schedule_timer *)item_b;
|
||||||
|
|
||||||
|
return a->slot->interval_us < b->slot->interval_us? -1:
|
||||||
|
a->slot->interval_us > b->slot->interval_us? 1: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int _set_interval(hexagram_schedule *schedule, time_t int_nsec) {
|
static inline int _timer_set(hexagram_schedule_timer *timer, time_t nsec) {
|
||||||
schedule->ts.it_value.tv_sec = 0;
|
timer->ts.it_value.tv_sec = 0;
|
||||||
schedule->ts.it_value.tv_nsec = int_nsec;
|
timer->ts.it_value.tv_nsec = nsec;
|
||||||
schedule->ts.it_interval.tv_sec = 0;
|
timer->ts.it_interval.tv_sec = 0;
|
||||||
schedule->ts.it_interval.tv_nsec = int_nsec;
|
timer->ts.it_interval.tv_nsec = nsec;
|
||||||
|
|
||||||
return timer_settime(schedule->timer, 0, &schedule->ts, NULL);
|
return timer_settime(timer->id, 0, &timer->ts, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int _slot_set_interval(hexagram_schedule *schedule, size_t i) {
|
static inline int _timer_stop(hexagram_schedule_timer *timer) {
|
||||||
return _set_interval(schedule, _slot_interval_ns(schedule, i));
|
return _timer_set(timer, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void _ev_notify(union sigval sv) {
|
static void _ev_notify(union sigval sv) {
|
||||||
hexagram_schedule *schedule = sv.sival_ptr;
|
hexagram_schedule_timer *timer = sv.sival_ptr;
|
||||||
time_t last = -1;
|
hexagram_schedule_slot *slot = timer->slot;
|
||||||
|
|
||||||
while (schedule->current < schedule->count) {
|
if (slot->handler(&slot->frame, timer->ctx) < 0) {
|
||||||
hexagram_schedule_slot *slot = _slot(schedule, schedule->current);
|
timer->error = errno;
|
||||||
time_t delay = slot->interval_us;
|
|
||||||
|
|
||||||
if (slot->handler(&slot->frame, schedule->ctx) < 0) {
|
_timer_stop(timer);
|
||||||
schedule->error = errno;
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
schedule->current++;
|
|
||||||
|
|
||||||
if (last >= 0 && last != delay) {
|
|
||||||
_slot_set_interval(schedule, schedule->current);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
last = delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
schedule->current = 0;
|
|
||||||
|
|
||||||
_slot_set_interval(schedule, schedule->current);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table,
|
hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table,
|
||||||
|
@ -70,35 +47,42 @@ hexagram_schedule *hexagram_schedule_create(hexagram_schedule_slot *table,
|
||||||
hexagram_schedule *schedule;
|
hexagram_schedule *schedule;
|
||||||
size_t i;
|
size_t i;
|
||||||
|
|
||||||
if ((schedule = malloc(sizeof(*schedule) + count * sizeof(void *))) == 0) {
|
if ((schedule = malloc(sizeof(*schedule) + count * sizeof(hexagram_schedule_timer))) == 0) {
|
||||||
goto error_malloc_schedule;
|
goto error_malloc_schedule;
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&schedule->ev, '\0', sizeof(struct sigevent));
|
|
||||||
|
|
||||||
schedule->ev.sigev_notify = SIGEV_THREAD;
|
|
||||||
schedule->ev.sigev_notify_function = _ev_notify;
|
|
||||||
schedule->ev.sigev_value.sival_ptr = schedule;
|
|
||||||
|
|
||||||
schedule->current = 0;
|
|
||||||
schedule->count = count;
|
|
||||||
schedule->table = table;
|
schedule->table = table;
|
||||||
schedule->ctx = ctx;
|
schedule->count = count;
|
||||||
schedule->error = 0;
|
|
||||||
|
|
||||||
if (timer_create(CLOCK_REALTIME, &schedule->ev, &schedule->timer) < 0) {
|
|
||||||
goto error_timer_create;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i=0; i<count; i++) {
|
for (i=0; i<count; i++) {
|
||||||
((hexagram_schedule_slot **)(schedule + 1))[i] = &table[i];
|
hexagram_schedule_timer *timer = _timer(schedule, i);
|
||||||
|
|
||||||
|
memset(&timer->ev, '\0', sizeof(struct sigevent));
|
||||||
|
|
||||||
|
timer->ev.sigev_notify = SIGEV_THREAD;
|
||||||
|
timer->ev.sigev_notify_function = _ev_notify;
|
||||||
|
timer->ev.sigev_value.sival_ptr = timer;
|
||||||
|
|
||||||
|
timer->slot = &table[i];
|
||||||
|
timer->ctx = ctx;
|
||||||
|
timer->error = 0;
|
||||||
|
|
||||||
|
if (timer_create(CLOCK_REALTIME, &timer->ev, &timer->id) < 0) {
|
||||||
|
goto error_timer_create;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
qsort(schedule + 1, count, sizeof(hexagram_schedule_slot *), _slot_cmp);
|
qsort(schedule + 1, count, sizeof(hexagram_schedule_timer), _timer_cmp);
|
||||||
|
|
||||||
return schedule;
|
return schedule;
|
||||||
|
|
||||||
error_timer_create:
|
error_timer_create:
|
||||||
|
while (--i) {
|
||||||
|
hexagram_schedule_timer *timer = _timer(schedule, i);
|
||||||
|
|
||||||
|
timer_delete(timer->id);
|
||||||
|
}
|
||||||
|
|
||||||
free(schedule);
|
free(schedule);
|
||||||
|
|
||||||
error_malloc_schedule:
|
error_malloc_schedule:
|
||||||
|
@ -106,26 +90,63 @@ error_malloc_schedule:
|
||||||
}
|
}
|
||||||
|
|
||||||
void hexagram_schedule_destroy(hexagram_schedule *schedule) {
|
void hexagram_schedule_destroy(hexagram_schedule *schedule) {
|
||||||
if (schedule->timer) {
|
size_t i;
|
||||||
timer_delete(schedule->timer);
|
|
||||||
|
for (i=0; i<schedule->count; i++) {
|
||||||
|
hexagram_schedule_timer *timer = _timer(schedule, i);
|
||||||
|
|
||||||
|
_timer_stop(timer);
|
||||||
|
|
||||||
|
timer_delete(timer->id);
|
||||||
}
|
}
|
||||||
|
|
||||||
free(schedule);
|
free(schedule);
|
||||||
}
|
}
|
||||||
|
|
||||||
void hexagram_schedule_reset(hexagram_schedule *schedule) {
|
int hexagram_schedule_run(hexagram_schedule *schedule) {
|
||||||
schedule->current = 0;
|
size_t i;
|
||||||
schedule->error = 0;
|
|
||||||
|
for (i=0; i<schedule->count; i++) {
|
||||||
|
hexagram_schedule_timer *timer = _timer(schedule, i);
|
||||||
|
|
||||||
|
if (_timer_set(timer, 1000 * timer->slot->interval_us) < 0) {
|
||||||
|
goto error_timer_set;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int hexagram_schedule_run(hexagram_schedule *schedule) {
|
return 0;
|
||||||
return _slot_set_interval(schedule, schedule->current);
|
|
||||||
|
error_timer_set:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hexagram_schedule_stop(hexagram_schedule *schedule) {
|
int hexagram_schedule_stop(hexagram_schedule *schedule) {
|
||||||
return _set_interval(schedule, 0);
|
size_t i;
|
||||||
|
|
||||||
|
for (i=0; i<schedule->count; i++) {
|
||||||
|
hexagram_schedule_timer *timer = _timer(schedule, i);
|
||||||
|
|
||||||
|
if (_timer_stop(timer) < 0) {
|
||||||
|
goto error_timer_stop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
error_timer_stop:
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int hexagram_schedule_error(hexagram_schedule *schedule) {
|
int hexagram_schedule_error(hexagram_schedule *schedule) {
|
||||||
return schedule->error;
|
size_t i;
|
||||||
|
|
||||||
|
for (i=0; i<schedule->count; i++) {
|
||||||
|
hexagram_schedule_timer *timer = _timer(schedule, i);
|
||||||
|
|
||||||
|
if (timer->error != 0) {
|
||||||
|
return timer->error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue