2009-06-06 17:43:50 +00:00
|
|
|
/*
|
|
|
|
* run_loop.c
|
|
|
|
*
|
|
|
|
* Created by Matthias Ringwald on 6/6/09.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "run_loop.h"
|
2009-07-13 21:51:42 +00:00
|
|
|
#include "linked_list.h"
|
|
|
|
|
2009-06-06 19:00:32 +00:00
|
|
|
#include <sys/select.h>
|
|
|
|
#include <stdlib.h>
|
2009-08-09 13:00:09 +00:00
|
|
|
#include <stdio.h>
|
2009-06-06 17:43:50 +00:00
|
|
|
|
|
|
|
// the run loop
|
2009-08-09 13:00:09 +00:00
|
|
|
static linked_list_t data_sources = NULL;
|
|
|
|
static linked_list_t timers = NULL;
|
|
|
|
|
|
|
|
// set timer
|
|
|
|
void run_loop_set_timer(timer_t *a, int timeout_in_seconds){
|
|
|
|
gettimeofday(&a->timeout, NULL);
|
|
|
|
a->timeout.tv_sec += timeout_in_seconds;
|
|
|
|
}
|
|
|
|
|
|
|
|
// compare timers - NULL is assumed to be before the Big Bang
|
|
|
|
int run_loop_timer_compare(timer_t *a, timer_t *b){
|
|
|
|
|
|
|
|
if (!a || !b) return 0;
|
|
|
|
if (!a) return -1;
|
|
|
|
if (!b) return 1;
|
|
|
|
|
|
|
|
if (a->timeout.tv_sec < b->timeout.tv_sec) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->timeout.tv_sec > b->timeout.tv_sec) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (a->timeout.tv_usec < b->timeout.tv_usec) {
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
if (a->timeout.tv_usec > b->timeout.tv_usec) {
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
2009-06-06 19:00:32 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Add data_source to run_loop
|
|
|
|
*/
|
2009-08-09 13:00:09 +00:00
|
|
|
void run_loop_add_data_source(data_source_t *ds){
|
|
|
|
linked_list_add(&data_sources, (linked_item_t *) ds);
|
2009-06-06 19:00:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove data_source from run loop
|
|
|
|
*/
|
2009-08-09 13:00:09 +00:00
|
|
|
int run_loop_remove_data_source(data_source_t *ds){
|
|
|
|
return linked_list_remove(&data_sources, (linked_item_t *) ds);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Add timer to run_loop (keep list sorted)
|
|
|
|
*/
|
|
|
|
void run_loop_add_timer(timer_t *ts){
|
|
|
|
linked_item_t *it;
|
|
|
|
for (it = (linked_item_t *) &timers; it ; it = it->next){
|
|
|
|
if ( run_loop_timer_compare( (timer_t *) it->next, ts) >= 0) {
|
|
|
|
ts->item.next = it->next;
|
|
|
|
it->next = (linked_item_t *) ts;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Remove timer from run loop
|
|
|
|
*/
|
|
|
|
int run_loop_remove_timer(timer_t *ts){
|
|
|
|
return linked_list_remove(&timers, (linked_item_t *) ts);
|
|
|
|
}
|
|
|
|
|
|
|
|
void run_loop_timer_dump(){
|
|
|
|
linked_item_t *it;
|
|
|
|
int i = 0;
|
|
|
|
for (it = (linked_item_t *) timers; it ; it = it->next){
|
|
|
|
timer_t *ts = (timer_t*) it;
|
|
|
|
printf("timer %u, timeout %u\n", i, ts->timeout.tv_sec);
|
|
|
|
}
|
2009-06-06 19:00:32 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Execute run_loop
|
|
|
|
*/
|
|
|
|
void run_loop_execute() {
|
|
|
|
fd_set descriptors;
|
|
|
|
data_source_t *ds;
|
2009-08-09 13:00:09 +00:00
|
|
|
timer_t *ts;
|
|
|
|
|
2009-06-06 19:00:32 +00:00
|
|
|
while (1) {
|
|
|
|
// collect FDs
|
|
|
|
FD_ZERO(&descriptors);
|
|
|
|
int highest_fd = 0;
|
2009-08-09 13:00:09 +00:00
|
|
|
for (ds = (data_source_t *) data_sources; ds ; ds = (data_source_t *) ds->item.next){
|
2009-06-06 19:00:32 +00:00
|
|
|
if (ds->fd) {
|
|
|
|
FD_SET(ds->fd, &descriptors);
|
|
|
|
if (ds->fd > highest_fd) {
|
|
|
|
highest_fd = ds->fd;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2009-08-09 13:00:09 +00:00
|
|
|
|
|
|
|
// get next timeout
|
|
|
|
// ..
|
|
|
|
|
2009-06-06 19:00:32 +00:00
|
|
|
// wait for ready FDs
|
2009-06-06 19:52:36 +00:00
|
|
|
select( highest_fd+1 , &descriptors, NULL, NULL, NULL);
|
2009-06-06 19:00:32 +00:00
|
|
|
|
2009-08-09 13:00:09 +00:00
|
|
|
// process data sources
|
2009-06-06 21:10:20 +00:00
|
|
|
data_source_t *next;
|
2009-08-09 13:00:09 +00:00
|
|
|
for (ds = (data_source_t *) data_sources; ds != NULL ; ds = next){
|
2009-07-13 21:51:42 +00:00
|
|
|
next = (data_source_t *) ds->item.next; // cache pointer to next data_source to allow data source to remove itself
|
2009-06-06 21:10:20 +00:00
|
|
|
if (FD_ISSET(ds->fd, &descriptors)) {
|
2009-08-09 13:00:09 +00:00
|
|
|
ds->process(ds);
|
2009-06-06 21:10:20 +00:00
|
|
|
}
|
2009-06-06 19:00:32 +00:00
|
|
|
}
|
2009-08-09 13:00:09 +00:00
|
|
|
|
|
|
|
// process timers
|
|
|
|
// ..
|
2009-06-06 19:00:32 +00:00
|
|
|
}
|
|
|
|
}
|
2009-06-06 17:43:50 +00:00
|
|
|
|
|
|
|
|
|
|
|
|