add support for Cocoa CoreFoundation run loop - not fully implemented but usable by clients, use ms instead of s for run_loop_set_timer function

This commit is contained in:
matthias.ringwald 2009-10-07 20:17:19 +00:00
parent 1a0f3836c2
commit e29adc1159
14 changed files with 293 additions and 84 deletions

View File

@ -5,13 +5,6 @@ Last change: use single packet handler on client side
NEXT:
- support Cocoa CFRunLoop in addition to POSIX select run loop
- define struct run_loop_t
- run_loop_posix.c: run_loop_t * BTstack_run_loop = run_loop_posix;
- convert all run_loop calls to use (*BTstack_run_loop->functionX)(..)
- new btstack_open(RUN_LOOP_MODE mode) allows to choose between both
- implement missing functions in run_loop_cocoa: remove data source and timer functions
- prepare WiiMoteDemo for release
- update to current stack version
- add inquiry code

View File

@ -11,7 +11,7 @@ AC_ARG_WITH(uart-device, [AS_HELP_STRING([--with-uart-device=uartDevice], [Speci
AC_ARG_WITH(uart-speed, [AS_HELP_STRING([--with-uart-speed=uartSpeed], [Specify BT UART speed to use])], UART_SPEED=$withval, UART_SPEED="115200")
AC_ARG_ENABLE(bluetool, [AS_HELP_STRING([--disable-bluetool],[Disable init of Bluetooth module by BlueTool])], USE_BLUETOOL=$enableval, USE_BLUETOOL="DEFAULT")
AC_ARG_ENABLE(springboard, [AS_HELP_STRING([--disable-springboard],[Disable display of BTstack status in SpringBoard])], USE_SPRINGBOARD=$enableval, USE_SPRINGBOARD="DEFAULT")
AC_ARG_ENABLE(launchd, [AS_HELP_STRING([--enable-launchd],[Compiles BTdaemon for use by launchd])], USE_LAUNCHD=$enableval, USE_LAUNCHD="NO")
AC_ARG_ENABLE(launchd, [AS_HELP_STRING([--enable-launchd],[Compiles BTdaemon for use by launchd])], USE_LAUNCHD=$enableval, USE_LAUNCHD="no")
AC_ARG_WITH(iphone-ip, [AS_HELP_STRING([--with-iphone-ip=192.168.1.5], [Specify IP address used by iPhone for installation (not supported yet)])], IPHONE_IP=$withval, IPHONE_IP="")
AC_ARG_WITH(vendor-id, [AS_HELP_STRING([--with-vendor-id=vendorID], [Specify USB BT Dongle vendorID])], USB_VENDOR_ID=$withval, USB_VENDOR_ID="")
AC_ARG_WITH(product-id, [AS_HELP_STRING([--with-product-id=productID], [Specify USB BT Dongle productID])], USB_PRODUCT_ID=$withval, USB_PRODUCT_ID="")
@ -58,10 +58,21 @@ if test "x$HCI_TRANSPORT" = xUSB; then
fi
AM_CONDITIONAL(HAVE_LIBUSB, [test "x$HAVE_LIBUSB" == "xyes"])
echo
echo "BTstack configured for HCI $HCI_TRANSPORT Transport"
RUN_LOOP_SOURCES=run_loop_posix.c
case "$host_os" in
darwin*)
RUN_LOOP_SOURCES="$RUN_LOOP_SOURCES run_loop_cocoa.m"
LDFLAGS="$LDFLAGS -framework CoreFoundation"
USE_COCOA_RUN_LOOP="yes"
;;
*)
USE_COCOA_RUN_LOOP="no"
;;
esac
# iPhone/iPod touch cross-compilation for darwin
DEVELOPER_PATH="/Developer/Platforms/iPhoneOS.platform/Developer"
SDK_VERSION="2.0"
@ -96,12 +107,10 @@ if test "x$target" = xiphone; then
USE_BLUETOOL="yes"
echo "USE_BLUETOOL: $USE_BLUETOOL"
fi
if test "x$USE_SPRINGBOARD" = xDEFAULT ; then
USE_SPRINGBOARD="yes"
echo "USE_SPRINGBOARD: $USE_SPRINGBOARD"
SPRINGBOARD_ACCESS_SOURCES="../SpringBoardAccess/SpringBoardAccess.c"
fi
echo "USE_LAUNCHD: $USE_LAUNCHD"
if test "x$USE_LDID" = xyes ; then
USE_LDID=""
@ -110,13 +119,16 @@ if test "x$target" = xiphone; then
USE_LDID="#"
echo "USE_LDID: no"
fi
else
USE_LDID="#"
if test "x$UART_DEVICE" = xDEFAULT ; then
UART_DEVICE=/dev/ttyS0
fi
if test "x$USE_SPRINGBOARD" = xDEFAULT ; then
USE_SPRINGBOARD="no"
fi
fi
AM_CONDITIONAL(USE_SPRINGBOARD, [test "x$USE_SPRINGBOARD" == "xyes"])
# summary
@ -126,9 +138,14 @@ if test "x$HCI_TRANSPORT" = xUSB; then
echo "LIBUSB_CFLAGS: $LIBUSB_CFLAGS"
echo "LIBUSB_LIBS: $LIBUSB_LIBS"
else
echo "UART_DEVICE: $UART_DEVICE"
echo "UART_SPEED: $UART_SPEED"
echo "UART_DEVICE: $UART_DEVICE"
echo "UART_SPEED: $UART_SPEED"
fi
echo "USE_LAUNCHD: $USE_LAUNCHD"
echo "USE_SPRINGBOARD: $USE_SPRINGBOARD"
echo "USE_COCOA_RUN_LOOP: $USE_COCOA_RUN_LOOP"
echo
echo
# create config.h
@ -144,16 +161,21 @@ else
if test "x$USE_BLUETOOL" = xyes; then
echo "#define USE_BLUETOOL" >> config.h
fi
if test "x$USE_SPRINGBOARD" = xyes; then
echo "#define USE_SPRINGBOARD" >> config.h
fi
if test "x$USE_LAUNCHD" = xyes; then
echo "#define USE_LAUNCHD" >> config.h
fi
fi
if test "x$USE_SPRINGBOARD" = xyes; then
SPRINGBOARD_ACCESS_SOURCES="../SpringBoardAccess/SpringBoardAccess.c"
echo "#define USE_SPRINGBOARD" >> config.h
fi
if test "x$USE_LAUNCHD" = xyes; then
echo "#define USE_LAUNCHD" >> config.h
fi
if test "x$USE_COCOA_RUN_LOOP" = xyes; then
echo "#define USE_COCOA_RUN_LOOP" >> config.h
fi
AC_SUBST(IPHONE_IP)
AC_SUBST(HAVE_LIBUSB)
AC_SUBST(USE_LDID)
AC_SUBST(SPRINGBOARD_ACCESS_SOURCES)
AC_SUBST(RUN_LOOP_SOURCES)
AC_OUTPUT(Makefile src/Makefile example/Makefile SpringBoardAccess/Makefile)

View File

@ -222,6 +222,7 @@ int main (int argc, const char * argv[]){
}
// start stack
run_loop_init(RUN_LOOP_POSIX);
int err = bt_open();
if (err) {
printf("Failed to open connection to BTdaemon\n");

View File

@ -127,6 +127,7 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
}
int main (int argc, const char * argv[]){
run_loop_init(RUN_LOOP_POSIX);
int err = bt_open();
if (err) {
printf("Failed to open connection to BTdaemon\n");

View File

@ -117,6 +117,7 @@ void packet_handler(uint8_t packet_type, uint8_t *packet, uint16_t size){
}
int main (int argc, const char * argv[]){
run_loop_init(RUN_LOOP_POSIX);
int err = bt_open();
if (err) {
printf("Failed to open connection to BTdaemon\n");

View File

@ -10,6 +10,11 @@
#include <sys/time.h>
typedef enum {
RUN_LOOP_POSIX = 1,
RUN_LOOP_COCOA
} RUN_LOOP_TYPE;
typedef struct data_source {
linked_item_t item;
int fd; // <-- file descriptors to watch or 0
@ -22,8 +27,11 @@ typedef struct timer {
void (*process)(struct timer *ts); // <-- do processing
} timer_t;
// init must be called before any other run_loop call
void run_loop_init(RUN_LOOP_TYPE type);
// set timer based on current time
void run_loop_set_timer(timer_t *a, int timeout_in_seconds);
void run_loop_set_timer(timer_t *a, int timeout_in_ms);
// compare timeval or timers - NULL is assumed to be before the Big Bang
int run_loop_timeval_compare(struct timeval *a, struct timeval *b);
@ -35,6 +43,18 @@ int run_loop_remove_data_source(data_source_t *dataSource); // <-- remove Data
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_execute(); // <-- execute configured RunLoop
void run_loop_timer_dump(); // debug
void run_loop_execute(); // <-- execute configured RunLoop
// internal use only
typedef struct {
void (*init)();
void (*add_data_source)(data_source_t *dataSource);
int (*remove_data_source)(data_source_t *dataSource);
void (*add_timer)(timer_t *timer);
int (*remove_timer)(timer_t *timer);
void (*execute)();
void (*dump_timer)();
} run_loop_t;

View File

@ -13,6 +13,9 @@
9C00F86410191097008DAB17 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F86210191097008DAB17 /* utils.c */; };
9C00F86510191097008DAB17 /* utils.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F86210191097008DAB17 /* utils.c */; };
9C00F87410191130008DAB17 /* l2cap_signaling.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F87210191130008DAB17 /* l2cap_signaling.c */; };
9C04B826107D1CED002A63D0 /* run_loop.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C04B825107D1CED002A63D0 /* run_loop.c */; };
9C04B876107D2B7C002A63D0 /* run_loop_cocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CEB4DAA10753B4B00DD5720 /* run_loop_cocoa.m */; };
9C04B87A107D2BA7002A63D0 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9C04B879107D2BA7002A63D0 /* CoreFoundation.framework */; };
9C05FC971020D3F300255261 /* socket_connection.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C00F7301017ACC3008DAB17 /* socket_connection.c */; };
9C2071F310014D3200A07EA4 /* hci_transport_usb.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C2071F210014D3200A07EA4 /* hci_transport_usb.c */; };
9C46FC3A0FA906F700ABEF05 /* hci_transport_h4.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC360FA906F700ABEF05 /* hci_transport_h4.c */; };
@ -27,8 +30,7 @@
9CC813A20FFC0774002816F9 /* btstack.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC813A10FFC0774002816F9 /* btstack.c */; };
9CC813A50FFC0A51002816F9 /* daemon.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CC813A40FFC0A51002816F9 /* daemon.c */; };
9CCE6CEA1025BD0000FCE9F4 /* hci.c in Sources */ = {isa = PBXBuildFile; fileRef = 9C46FC340FA906F700ABEF05 /* hci.c */; };
9CEB4DAB10753B4B00DD5720 /* run_loop_cocoa.m in Sources */ = {isa = PBXBuildFile; fileRef = 9CEB4DAA10753B4B00DD5720 /* run_loop_cocoa.m */; };
9CEB4DAD10753BE600DD5720 /* run_loop_posix.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CEB4DAC10753BE600DD5720 /* run_loop_posix.c */; };
9CEB4F17107AAAEF00DD5720 /* run_loop_posix.c in Sources */ = {isa = PBXBuildFile; fileRef = 9CEB4DAC10753BE600DD5720 /* run_loop_posix.c */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@ -51,6 +53,8 @@
9C00F86210191097008DAB17 /* utils.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = utils.c; path = src/utils.c; sourceTree = "<group>"; };
9C00F87110191130008DAB17 /* l2cap_signaling.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = l2cap_signaling.h; path = src/l2cap_signaling.h; sourceTree = "<group>"; };
9C00F87210191130008DAB17 /* l2cap_signaling.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = l2cap_signaling.c; path = src/l2cap_signaling.c; sourceTree = "<group>"; };
9C04B825107D1CED002A63D0 /* run_loop.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = run_loop.c; path = src/run_loop.c; sourceTree = "<group>"; };
9C04B879107D2BA7002A63D0 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = /System/Library/Frameworks/CoreFoundation.framework; sourceTree = "<absolute>"; };
9C1813F71042FCCA00C68F09 /* mitm.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = mitm.c; path = example/mitm.c; sourceTree = "<group>"; };
9C2071F210014D3200A07EA4 /* hci_transport_usb.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = hci_transport_usb.c; path = src/hci_transport_usb.c; sourceTree = "<group>"; };
9C46FC340FA906F700ABEF05 /* hci.c */ = {isa = PBXFileReference; fileEncoding = 5; lastKnownFileType = sourcecode.c.c; name = hci.c; path = src/hci.c; sourceTree = "<group>"; };
@ -106,6 +110,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
9C04B87A107D2BA7002A63D0 /* CoreFoundation.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -132,6 +137,7 @@
1AB674ADFE9D54B511CA2CBB /* Products */,
9CC152C61009052100223347 /* config.h */,
9CA3C0900FB8B3C4005F48DE /* TODO.txt */,
9C04B879107D2BA7002A63D0 /* CoreFoundation.framework */,
);
name = project;
sourceTree = "<group>";
@ -160,6 +166,7 @@
9C00F87110191130008DAB17 /* l2cap_signaling.h */,
9C00F87210191130008DAB17 /* l2cap_signaling.c */,
9C7B5ABF100BD3340065D87E /* linked_list.c */,
9C04B825107D1CED002A63D0 /* run_loop.c */,
9CEB4DAA10753B4B00DD5720 /* run_loop_cocoa.m */,
9CEB4DAC10753BE600DD5720 /* run_loop_posix.c */,
9C00F7301017ACC3008DAB17 /* socket_connection.c */,
@ -320,8 +327,9 @@
9C00F87410191130008DAB17 /* l2cap_signaling.c in Sources */,
9CCE6CEA1025BD0000FCE9F4 /* hci.c in Sources */,
9C77E79210667F0600F39DCF /* platform_iphone.c in Sources */,
9CEB4DAB10753B4B00DD5720 /* run_loop_cocoa.m in Sources */,
9CEB4DAD10753BE600DD5720 /* run_loop_posix.c in Sources */,
9CEB4F17107AAAEF00DD5720 /* run_loop_posix.c in Sources */,
9C04B826107D1CED002A63D0 /* run_loop.c in Sources */,
9C04B876107D2B7C002A63D0 /* run_loop_cocoa.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@ -5,7 +5,7 @@ prefix = @prefix@
springboard_access_sources = @SPRINGBOARD_ACCESS_SOURCES@
libBTstack_SOURCES = btstack.c hci_cmds.c linked_list.c run_loop_posix.c socket_connection.c utils.c
libBTstack_SOURCES = btstack.c hci_cmds.c linked_list.c run_loop.c run_loop_posix.c run_loop_cocoa.m socket_connection.c utils.c
BTdaemon_SOURCES = $(libBTstack_SOURCES) \
bt_control_iphone.c \
@ -37,7 +37,8 @@ clean:
rm -f libBTstack* BTdaemon *.o
install:
echo "installing BTdaemon in $(prefix)"
echo "installing BTdaemon in $(prefix)..."
mkdir -p $(prefix)/lib $(prefix)/include
cp libBTstack.a libBTstack.dylib $(prefix)/lib/
cp BTdaemon $(prefix)/bin/
cp -r ../include/btstack $(prefix)/include

View File

@ -56,6 +56,7 @@ int bt_send_cmd(hci_cmd_t *cmd, ...){
}
int btstack_packet_handler(connection_t *connection, uint16_t packet_type, uint16_t channel, uint8_t *data, uint16_t size){
// printf("BTstack client handler: packet type %u, data[0] %x\n", packet_type, data[0]);
(*client_packet_handler)(packet_type, data, size);
return 0;
}

View File

@ -39,7 +39,7 @@
#include "hci_transport_usb.h"
#endif
#define DAEMON_NO_CONNECTION_TIMEOUT 60
#define DAEMON_NO_CONNECTION_TIMEOUT 60000
static hci_transport_t * transport;
static hci_uart_config_t config;
@ -211,6 +211,8 @@ int main (int argc, const char * argv[]){
bluetooth_status_handler = platform_iphone_status_handler;
#endif
run_loop_init(RUN_LOOP_POSIX);
// @TODO: allow configuration per HCI CMD
// use logger: format HCI_DUMP_PACKETLOGGER, HCI_DUMP_BLUEZ or HCI_DUMP_STDOUT

View File

@ -15,7 +15,7 @@
// temp
#include "l2cap.h"
#define HCI_CONNECTION_TIMEOUT 10
#define HCI_CONNECTION_TIMEOUT 10000
// the STACK is here
static hci_stack_t hci_stack;
@ -303,7 +303,6 @@ int hci_power_control(HCI_POWER_MODE power_mode){
}
void hci_run(){
uint8_t micro_packet;
switch (hci_stack.state){
case HCI_STATE_INITIALIZING:
if (hci_stack.substate % 2) {

144
src/run_loop.c Normal file
View File

@ -0,0 +1,144 @@
/*
* run_loop.c
*
* Created by Matthias Ringwald on 6/6/09.
*/
#include <btstack/run_loop.h>
#include <stdio.h>
#include <stdlib.h> // exit()
#include "../config.h"
static run_loop_t * the_run_loop = NULL;
extern run_loop_t run_loop_posix;
#ifdef USE_COCOA_RUN_LOOP
extern run_loop_t run_loop_cocoa;
#endif
// assert run loop initialized
void run_loop_assert(){
if (!the_run_loop){
fprintf(stderr, "ERROR: run_loop function called before run_loop_init!\n");
exit(10);
}
}
/**
* Add data_source to run_loop
*/
void run_loop_add_data_source(data_source_t *ds){
run_loop_assert();
the_run_loop->add_data_source(ds);
}
/**
* Remove data_source from run loop
*/
int run_loop_remove_data_source(data_source_t *ds){
run_loop_assert();
return the_run_loop->remove_data_source(ds);
}
/**
* Add timer to run_loop (keep list sorted)
*/
void run_loop_add_timer(timer_t *ts){
run_loop_assert();
the_run_loop->add_timer(ts);
}
/**
* Remove timer from run loop
*/
int run_loop_remove_timer(timer_t *ts){
run_loop_assert();
return the_run_loop->remove_timer(ts);
}
void run_loop_timer_dump(){
run_loop_assert();
return the_run_loop->dump_timer();
}
/**
* Execute run_loop
*/
void run_loop_execute() {
run_loop_assert();
the_run_loop->execute();
}
// init must be called before any other run_loop call
void run_loop_init(RUN_LOOP_TYPE type){
if (the_run_loop){
fprintf(stderr, "ERROR: run loop initialized twice!\n");
exit(10);
}
switch (type) {
case RUN_LOOP_POSIX:
the_run_loop = &run_loop_posix;
break;
#ifdef USE_COCOA_RUN_LOOP
case RUN_LOOP_COCOA:
the_run_loop = &run_loop_cocoa;
break;
#endif
default:
fprintf(stderr, "ERROR: invalid run loop type %u selected!\n", type);
exit(10);
break;
}
the_run_loop->init();
}
// set timer
void run_loop_set_timer(timer_t *a, int timeout_in_ms){
gettimeofday(&a->timeout, NULL);
a->timeout.tv_sec += timeout_in_ms / 1000;
a->timeout.tv_usec += (timeout_in_ms % 1000) * 1000;
if (a->timeout.tv_usec > 1000000) {
a->timeout.tv_usec -= 1000000;
a->timeout.tv_sec++;
}
}
// compare timers - NULL is assumed to be before the Big Bang
// pre: 0 <= tv_usec < 1000000
int run_loop_timeval_compare(struct timeval *a, struct timeval *b){
if (!a || !b) return 0;
if (!a) return -1;
if (!b) return 1;
if (a->tv_sec < b->tv_sec) {
return -1;
}
if (a->tv_sec > b->tv_sec) {
return 1;
}
if (a->tv_usec < b->tv_usec) {
return -1;
}
if (a->tv_usec > b->tv_usec) {
return 1;
}
return 0;
}
// compare timers - NULL is assumed to be before the Big Bang
// pre: 0 <= tv_usec < 1000000
int run_loop_timer_compare(timer_t *a, timer_t *b){
if (!a || !b) return 0;
if (!a) return -1;
if (!b) return 1;
return run_loop_timeval_compare(&a->timeout, &b->timeout);
}

View File

@ -9,6 +9,9 @@
#import <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#include <stdio.h>
#include <stdlib.h>
static void socketDataCallback (
CFSocketRef s,
CFSocketCallBackType callbackType,
@ -20,7 +23,7 @@ static void socketDataCallback (
ds->process(ds);
}
void run_loop_add_data_source(data_source_t *dataSource){
void cocoa_add_data_source(data_source_t *dataSource){
// add fd as CF "socket"
@ -43,8 +46,49 @@ void run_loop_add_data_source(data_source_t *dataSource){
CFRunLoopAddSource( CFRunLoopGetCurrent(), socketRunLoop, kCFRunLoopDefaultMode);
}
int run_loop_remove_data_source(data_source_t *dataSource){
int cocoa_remove_data_source(data_source_t *dataSource){
// not needed yet
fprintf(stderr, "WARNING: run_loop_remove_data_source not implemented yet!");
// warning never the less
return 0;
}
void cocoa_add_timer(timer_t * ts){
// not needed yet
fprintf(stderr, "WARNING: run_loop_add_timer not implemented yet!");
// warning never the less
}
int cocoa_remove_timer(timer_t * ts){
// not needed yet
fprintf(stderr, "WARNING: run_loop_remove_timer not implemented yet!");
// warning never the less
return 0;
}
void cocoa_init(){
}
void cocoa_execute(){
// not needed yet
fprintf(stderr, "WARNING: execute not available for RUN_LOOP_COCOA!");
// warning never the less
exit(10);
}
void cocoa_dump_timer(){
// not needed yet
fprintf(stderr, "WARNING: run_loop_dump_timer not implemented yet!");
// warning never the less
return;
}
const run_loop_t run_loop_cocoa = {
&cocoa_init,
&cocoa_add_data_source,
&cocoa_remove_data_source,
&cocoa_add_timer,
&cocoa_remove_timer,
&cocoa_execute,
&cocoa_dump_timer
};

View File

@ -12,67 +12,27 @@
#include <stdio.h>
// the run loop
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
// pre: 0 <= tv_usec < 1000000
int run_loop_timeval_compare(struct timeval *a, struct timeval *b){
if (!a || !b) return 0;
if (!a) return -1;
if (!b) return 1;
if (a->tv_sec < b->tv_sec) {
return -1;
}
if (a->tv_sec > b->tv_sec) {
return 1;
}
if (a->tv_usec < b->tv_usec) {
return -1;
}
if (a->tv_usec > b->tv_usec) {
return 1;
}
return 0;
}
// compare timers - NULL is assumed to be before the Big Bang
// pre: 0 <= tv_usec < 1000000
int run_loop_timer_compare(timer_t *a, timer_t *b){
if (!a || !b) return 0;
if (!a) return -1;
if (!b) return 1;
return run_loop_timeval_compare(&a->timeout, &b->timeout);
}
static linked_list_t data_sources;
static linked_list_t timers;
/**
* Add data_source to run_loop
*/
void run_loop_add_data_source(data_source_t *ds){
void posix_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(data_source_t *ds){
int posix_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){
void posix_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) {
@ -86,23 +46,23 @@ void run_loop_add_timer(timer_t *ts){
/**
* Remove timer from run loop
*/
int run_loop_remove_timer(timer_t *ts){
int posix_remove_timer(timer_t *ts){
return linked_list_remove(&timers, (linked_item_t *) ts);
}
void run_loop_timer_dump(){
void posix_dump_timer(){
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);
printf("timer %u, timeout %u\n", i, (unsigned int) ts->timeout.tv_sec);
}
}
/**
* Execute run_loop
*/
void run_loop_execute() {
void posix_execute() {
fd_set descriptors;
data_source_t *ds;
timer_t *ts;
@ -166,5 +126,17 @@ void run_loop_execute() {
}
}
void posix_init(){
data_sources = NULL;
timers = NULL;
}
const run_loop_t run_loop_posix = {
&posix_init,
&posix_add_data_source,
&posix_remove_data_source,
&posix_add_timer,
&posix_remove_timer,
&posix_execute,
&posix_dump_timer
};