From 7b22b9bc7d04f8e08e302ed46b8caae64ef7a16c Mon Sep 17 00:00:00 2001 From: "matthias.ringwald" Date: Sun, 9 Aug 2009 13:00:09 +0000 Subject: [PATCH] removed ready paramter from data_source callbacks, added timer management functions to run loop --- example/test.c | 3 +- src/hci_transport_h4.c | 10 ++--- src/run_loop.c | 89 ++++++++++++++++++++++++++++++++++++----- src/run_loop.h | 30 ++++++++++---- src/socket_connection.c | 14 +++---- 5 files changed, 116 insertions(+), 30 deletions(-) diff --git a/example/test.c b/example/test.c index 9f260aa12..950429a27 100644 --- a/example/test.c +++ b/example/test.c @@ -89,8 +89,7 @@ void event_handler(uint8_t *packet, uint16_t size){ exit(0); } } - - + int main (int argc, const char * argv[]){ bt_open(); bt_register_event_packet_handler(event_handler); diff --git a/src/hci_transport_h4.c b/src/hci_transport_h4.c index 64f269715..c7f516ee9 100644 --- a/src/hci_transport_h4.c +++ b/src/hci_transport_h4.c @@ -30,9 +30,9 @@ typedef struct hci_transport_h4 { // single instance static hci_transport_h4_t * hci_transport_h4 = NULL; -static int h4_process(struct data_source *ds, int ready); +static int h4_process(struct data_source *ds); static void dummy_handler(uint8_t *packet, int size); -static hci_uart_config_t *hci_uart_config; +static hci_uart_config_t *hci_uart_config; static void (*event_packet_handler)(uint8_t *packet, int size) = dummy_handler; static void (*acl_packet_handler) (uint8_t *packet, int size) = dummy_handler; @@ -110,7 +110,7 @@ static int h4_open(void *transport_config){ if (!hci_transport_h4) return -1; hci_transport_h4->ds->fd = fd; hci_transport_h4->ds->process = h4_process; - run_loop_add(hci_transport_h4->ds); + run_loop_add_data_source(hci_transport_h4->ds); // init state machine bytes_to_read = 1; @@ -122,7 +122,7 @@ static int h4_open(void *transport_config){ static int h4_close(){ // first remove run loop handler - run_loop_remove(hci_transport_h4->ds); + run_loop_remove_data_source(hci_transport_h4->ds); // close device close(hci_transport_h4->ds->fd); @@ -181,7 +181,7 @@ static void h4_register_acl_packet_handler (void (*handler)(uint8_t *packet, acl_packet_handler = handler; } -static int h4_process(struct data_source *ds, int ready) { +static int h4_process(struct data_source *ds) { if (hci_transport_h4->ds->fd == 0) return -1; // read up to bytes_to_read data in diff --git a/src/run_loop.c b/src/run_loop.c index 28a25ef1a..2ed1ccfdc 100644 --- a/src/run_loop.c +++ b/src/run_loop.c @@ -9,22 +9,84 @@ #include #include +#include // the run loop -static linked_list_t the_run_loop = NULL; +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; +} /** * Add data_source to run_loop */ -void run_loop_add(data_source_t *ds){ - linked_list_add(&the_run_loop, (linked_item_t *) ds); +void run_loop_add_data_source(data_source_t *ds){ + linked_list_add(&data_sources, (linked_item_t *) ds); } /** * Remove data_source from run loop */ -int run_loop_remove(data_source_t *ds){ - return linked_list_remove(&the_run_loop, (linked_item_t *) ds); +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); + } } /** @@ -33,11 +95,13 @@ int run_loop_remove(data_source_t *ds){ void run_loop_execute() { fd_set descriptors; data_source_t *ds; + timer_t *ts; + while (1) { // collect FDs FD_ZERO(&descriptors); int highest_fd = 0; - for (ds = (data_source_t *) the_run_loop; ds ; ds = (data_source_t *) ds->item.next){ + for (ds = (data_source_t *) data_sources; ds ; ds = (data_source_t *) ds->item.next){ if (ds->fd) { FD_SET(ds->fd, &descriptors); if (ds->fd > highest_fd) { @@ -45,17 +109,24 @@ void run_loop_execute() { } } } + + // get next timeout + // .. + // wait for ready FDs select( highest_fd+1 , &descriptors, NULL, NULL, NULL); - // process input + // process data sources data_source_t *next; - for (ds = (data_source_t *) the_run_loop; ds != NULL ; ds = next){ + for (ds = (data_source_t *) data_sources; ds != NULL ; ds = next){ next = (data_source_t *) ds->item.next; // cache pointer to next data_source to allow data source to remove itself if (FD_ISSET(ds->fd, &descriptors)) { - ds->process(ds, FD_ISSET(ds->fd, &descriptors)); + ds->process(ds); } } + + // process timers + // .. } } diff --git a/src/run_loop.h b/src/run_loop.h index d3b747aec..b58ea46d6 100644 --- a/src/run_loop.h +++ b/src/run_loop.h @@ -8,16 +8,32 @@ #include "linked_list.h" +#include + typedef struct data_source { linked_item_t item; int fd; // <-- file descriptors to watch or 0 - int (*process)(struct data_source *ds, int ready); // <-- do processing, @return: more to do + int (*process)(struct data_source *ds); // <-- do processing } data_source_t; -typedef struct timer_source { - struct timer_source *next; -} timer_source_t; +typedef struct timer { + linked_item_t item; + struct timeval timeout; // <-- next timeout + int (*process)(struct timer *ts); // <-- do processing +} timer_t; -void run_loop_add(data_source_t *dataSource); // <-- add DataSource to RunLoop -int run_loop_remove(data_source_t *dataSource); // <-- remove DataSource from RunLoop -void run_loop_execute(); // <-- execute configured RunLoop +// set timer based on current time +void run_loop_set_timer(timer_t *a, int 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); + +void run_loop_add_data_source(data_source_t *dataSource); // <-- add DataSource to RunLoop +int run_loop_remove_data_source(data_source_t *dataSource); // <-- remove DataSource from RunLoop + +void run_loop_add_timer(timer_t *timer); // <-- add Timer to RunLoop +int run_loop_remove_timer(timer_t *timer); // <-- remove Timer from RunLoop + +void run_loop_timer_dump(); // debug + +void run_loop_execute(); // <-- execute configured RunLoop diff --git a/src/socket_connection.c b/src/socket_connection.c index eb7bbb1d0..45cd2d7ae 100644 --- a/src/socket_connection.c +++ b/src/socket_connection.c @@ -25,7 +25,7 @@ #define DATA_BUF_SIZE 80 /** prototypes */ -static int socket_connection_hci_process(struct data_source *ds, int ready); +static int socket_connection_hci_process(struct data_source *ds); static int socket_connection_dummy_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t length); /** globals */ @@ -77,7 +77,7 @@ int socket_connection_set_non_blocking(int fd) void socket_connection_free_connection(connection_t *conn){ // remove from run_loop - run_loop_remove(&conn->ds); + run_loop_remove_data_source(&conn->ds); // and from connection list linked_list_remove(&connections, &conn->item); @@ -106,7 +106,7 @@ connection_t * socket_connection_register_new_connection(int fd){ socket_connection_init_statemachine(conn); // add this socket to the run_loop - run_loop_add( &conn->ds ); + run_loop_add_data_source( &conn->ds ); // and the connection list linked_list_add( &connections, &conn->item); @@ -114,7 +114,7 @@ connection_t * socket_connection_register_new_connection(int fd){ return conn; } -int socket_connection_hci_process(struct data_source *ds, int ready) { +int socket_connection_hci_process(struct data_source *ds) { connection_t *conn = (connection_t *) ds; int bytes_read = read(ds->fd, &conn->buffer[conn->bytes_read], conn->bytes_to_read); @@ -147,7 +147,7 @@ int socket_connection_hci_process(struct data_source *ds, int ready) { return 0; } -static int socket_connection_accept(struct data_source *socket_ds, int ready) { +static int socket_connection_accept(struct data_source *socket_ds) { /* New connection coming in! */ int fd = accept(socket_ds->fd, NULL, NULL); @@ -207,7 +207,7 @@ int socket_connection_create_tcp(int port){ return -1; } - run_loop_add(ds); + run_loop_add_data_source(ds); printf ("Server up and running ...\n"); return 0; @@ -290,7 +290,7 @@ connection_t * socket_connection_open_tcp(){ int socket_connection_close_tcp(connection_t * connection){ if (!connection) return -1; shutdown(connection->ds.fd, SHUT_RDWR); - run_loop_remove(&connection->ds); + run_loop_remove_data_source(&connection->ds); free( connection ); return 0; } \ No newline at end of file