[IOMultiplexerV2] added CIOTimer class to c++ interface && added some features to...
authorpk910 <philipp@zoelle1.de>
Wed, 19 Mar 2014 01:15:48 +0000 (02:15 +0100)
committerpk910 <philipp@zoelle1.de>
Wed, 19 Mar 2014 01:15:48 +0000 (02:15 +0100)
configure.ac
src/IOHandler++/IOTimer.cpp [new file with mode: 0644]
src/IOHandler++/IOTimer.h [new file with mode: 0644]
src/IOHandler++/Makefile.am
src/IOHandler/IOTimer.c
src/IOHandler/IOTimer.h
src/IOHandler_test/Makefile.am
src/IOHandler_test/timer++/.gitignore [new file with mode: 0644]
src/IOHandler_test/timer++/Makefile.am [new file with mode: 0644]
src/IOHandler_test/timer++/iotest.cpp [new file with mode: 0644]

index 318b98b476dc710695024b0d2f19d7dfe7377e82..4275959d2caf16b73054236bb343d5bfcd31e588 100644 (file)
@@ -74,6 +74,7 @@ AC_CONFIG_FILES([
   src/IOHandler_test/client_ssl/Makefile
   src/IOHandler_test/server_ssl/Makefile
   src/IOHandler_test/timer/Makefile
   src/IOHandler_test/client_ssl/Makefile
   src/IOHandler_test/server_ssl/Makefile
   src/IOHandler_test/timer/Makefile
+  src/IOHandler_test/timer++/Makefile
   src/IOHandler_test/resolv/Makefile
 ])
 AC_OUTPUT
   src/IOHandler_test/resolv/Makefile
 ])
 AC_OUTPUT
diff --git a/src/IOHandler++/IOTimer.cpp b/src/IOHandler++/IOTimer.cpp
new file mode 100644 (file)
index 0000000..e6a2cd7
--- /dev/null
@@ -0,0 +1,140 @@
+/* IOTimer.cpp - IOMultiplexer v2
+ * Copyright (C) 2014  Philipp Kreil (pk910)
+ * 
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+extern "C" {
+       #include "../IOHandler/IOTimer.h"
+}
+#include "IOTimer.h"
+#include <cstdarg>
+#include <cstdio>
+#include <cstring>
+
+static IOTIMER_CALLBACK(c_timer_callback) {
+       CIOTimer *ciotimer = (CIOTimer *) iotimer->data;
+       ciotimer->timer_callback();
+}
+
+CIOTimer::CIOTimer() {
+       this->iotimer = iotimer_create(NULL);
+       this->iotimer->data = this;
+       iotimer_set_callback(this->iotimer, c_timer_callback);
+       iotimer_set_persistent(this->iotimer, 1);
+}
+
+CIOTimer::~CIOTimer() {
+       iotimer_destroy(this->iotimer);
+}
+
+void CIOTimer::setTimeout(timeval timeout) {
+       iotimer_set_timeout(this->iotimer, &timeout);
+}
+
+void CIOTimer::setRelativeTimeout(timeval timeout) {
+       timeval now;
+       gettimeofday(&now, NULL);
+       
+       timeout.tv_sec += now.tv_sec;
+       timeout.tv_usec += now.tv_usec;
+       while(timeout.tv_usec > 1000000) {
+               timeout.tv_usec -= 1000000;
+               timeout.tv_sec++;
+       }
+       
+       this->setTimeout(timeout);
+}
+
+void CIOTimer::setRelativeTimeout(timeval timeout, int auto_reload) {
+       this->setRelativeTimeout(timeout);
+       if(auto_reload)
+               this->setAutoReload(timeout);
+}
+
+void CIOTimer::setRelativeTimeoutSeconds(double seconds) {
+       this->setRelativeTimeoutSeconds(seconds, 0);
+}
+
+void CIOTimer::setRelativeTimeoutSeconds(double seconds, int auto_reload) {
+       timeval tout;
+       tout.tv_sec = (int) seconds;
+       tout.tv_usec = ((int) (seconds * 1000000)) % 1000000;
+       this->setRelativeTimeout(tout);
+       if(auto_reload)
+               this->setAutoReload(tout);
+}
+
+timeval CIOTimer::getTimeout() {
+       return iotimer_get_timeout(this->iotimer);
+}
+
+timeval CIOTimer::getRelativeTimeout() {
+       timeval tout, now;
+       gettimeofday(&now, NULL);
+       
+       tout = iotimer_get_timeout(this->iotimer);
+       
+       if(tout.tv_sec || tout.tv_usec) {
+               tout.tv_sec = tout.tv_sec - now.tv_sec;
+               tout.tv_usec = tout.tv_usec - now.tv_usec;
+               if(tout.tv_usec < 0) {
+                       tout.tv_usec += 1000000;
+                       tout.tv_sec--;
+               }
+       }
+       
+       return tout;
+}
+
+double CIOTimer::getRelativeTimeoutSeconds() {
+       timeval tout = this->getRelativeTimeout();
+       return tout.tv_sec + (tout.tv_usec / 1000000);
+}
+
+
+void CIOTimer::setAutoReload(timeval timeout) {
+       iotimer_set_autoreload(this->iotimer, &timeout);
+}
+
+void CIOTimer::clearAutoReload() {
+       iotimer_set_autoreload(this->iotimer, NULL);
+}
+
+timeval CIOTimer::getAutoReloadTime() {
+       return iotimer_get_autoreload(this->iotimer);
+}
+
+int CIOTimer::getAutoReloadState() {
+       timeval timeout = this->getAutoReloadTime();
+       if(timeout.tv_sec == 0 && timeout.tv_usec == 0)
+               return 0;
+       else
+               return 1;
+}
+
+void CIOTimer::setActive(int active) {
+       if(active)
+               iotimer_start(this->iotimer);
+       else
+               iotimer_stop(this->iotimer);
+}
+
+int CIOTimer::getActive() {
+       return iotimer_state(this->iotimer);
+}
+
+void CIOTimer::timer_callback() {
+       this->timeout();
+}
+
diff --git a/src/IOHandler++/IOTimer.h b/src/IOHandler++/IOTimer.h
new file mode 100644 (file)
index 0000000..df586a5
--- /dev/null
@@ -0,0 +1,57 @@
+/* IOTimer.h - IOMultiplexer v2
+ * Copyright (C) 2014  Philipp Kreil (pk910)
+ * 
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+#ifndef _IOTimer_cpp_h
+#define _IOTimer_cpp_h
+
+#include <iostream>
+#include <string>
+#include <sys/time.h>
+
+struct IOTimerDescriptor;
+
+class CIOTimer {
+public:
+       CIOTimer();
+       ~CIOTimer();
+       
+       void setTimeout(timeval timeout);
+       timeval getTimeout();
+       void setRelativeTimeout(timeval timeout);
+       void setRelativeTimeout(timeval timeout, int auto_reload);
+       timeval getRelativeTimeout();
+       void setRelativeTimeoutSeconds(double seconds);
+       void setRelativeTimeoutSeconds(double seconds, int auto_reload);
+       double getRelativeTimeoutSeconds();
+       
+       void setAutoReload(timeval timeout);
+       void clearAutoReload();
+       int getAutoReloadState();
+       timeval getAutoReloadTime();
+       
+       void setActive(int active);
+       int getActive();
+       
+       
+       void timer_callback();
+protected:
+       virtual void timeout() {};
+       
+private:
+       IOTimerDescriptor *iotimer;
+};
+
+#endif
index df2e17cd80c383a980d531a9a17dee5e45784a29..681f9fbc1b03e734bc2981b403a934d5ecb5dab3 100644 (file)
@@ -5,7 +5,8 @@ noinst_LTLIBRARIES = libiohandler.cpp.la
 
 libiohandler_cpp_la_LIBADD = ../IOHandler/libiohandler.la
 libiohandler_cpp_la_SOURCES = IOHandler.cpp \
 
 libiohandler_cpp_la_LIBADD = ../IOHandler/libiohandler.la
 libiohandler_cpp_la_SOURCES = IOHandler.cpp \
-IOSocket.cpp
+IOSocket.cpp \
+IOTimer.cpp
 
 all-local: libiohandler.cpp.la
        
\ No newline at end of file
 
 all-local: libiohandler.cpp.la
        
\ No newline at end of file
index 77648316a51718aa09eaabf4e9f3605a6550db92..784ab7649465c5622f794a33ae0e0524c7217075 100644 (file)
@@ -51,12 +51,37 @@ struct IOTimerDescriptor *iotimer_create(struct timeval *timeout) {
 void iotimer_start(struct IOTimerDescriptor *descriptor) {
        struct _IOTimerDescriptor *timer = descriptor->iotimer;
        if(timer == NULL) {
 void iotimer_start(struct IOTimerDescriptor *descriptor) {
        struct _IOTimerDescriptor *timer = descriptor->iotimer;
        if(timer == NULL) {
-               iolog_trigger(IOLOG_WARNING, "called iotimer_set_autoreload for destroyed IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
+               iolog_trigger(IOLOG_WARNING, "called iotimer_start for destroyed IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
                return;
        }
        timer->flags |= IOTIMERFLAG_ACTIVE;
                return;
        }
        timer->flags |= IOTIMERFLAG_ACTIVE;
-       if(!(timer->flags & IOTIMERFLAG_IN_LIST))
-               _trigger_timer(timer);
+       _rearrange_timer(timer);
+}
+
+void iotimer_stop(struct IOTimerDescriptor *descriptor) {
+       struct _IOTimerDescriptor *timer = descriptor->iotimer;
+       if(timer == NULL) {
+               iolog_trigger(IOLOG_WARNING, "called iotimer_stop for destroyed IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
+               return;
+       }
+       timer->flags &= ~IOTIMERFLAG_ACTIVE;
+       if((timer->flags & IOTIMERFLAG_PERSISTENT)) {
+               timer->flags &= ~IOTIMERFLAG_ACTIVE;
+               _rearrange_timer(timer);
+       } else
+               iotimer_destroy(descriptor);
+}
+
+int iotimer_state(struct IOTimerDescriptor *descriptor) {
+       struct _IOTimerDescriptor *timer = descriptor->iotimer;
+       if(timer == NULL) {
+               iolog_trigger(IOLOG_WARNING, "called iotimer_state for destroyed IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
+               return 0;
+       }
+       if((timer->flags & IOTIMERFLAG_ACTIVE))
+               return 1;
+       else
+               return 0;
 }
 
 void iotimer_set_autoreload(struct IOTimerDescriptor *descriptor, struct timeval *autoreload) {
 }
 
 void iotimer_set_autoreload(struct IOTimerDescriptor *descriptor, struct timeval *autoreload) {
@@ -69,7 +94,7 @@ void iotimer_set_autoreload(struct IOTimerDescriptor *descriptor, struct timeval
                timer->flags |= IOTIMERFLAG_PERIODIC;
                timer->autoreload = *autoreload;
                
                timer->flags |= IOTIMERFLAG_PERIODIC;
                timer->autoreload = *autoreload;
                
-               if(!(timer->flags & IOTIMERFLAG_IN_LIST)) {
+               if(timer->timeout.tv_sec == 0 && timer->timeout.tv_usec == 0) {
                        struct timeval now;
                        gettimeofday(&now, NULL);
                        timer->timeout = now;
                        struct timeval now;
                        gettimeofday(&now, NULL);
                        timer->timeout = now;
@@ -80,6 +105,25 @@ void iotimer_set_autoreload(struct IOTimerDescriptor *descriptor, struct timeval
        }
 }
 
        }
 }
 
+struct timeval iotimer_get_autoreload(struct IOTimerDescriptor *descriptor) {
+       struct _IOTimerDescriptor *timer = descriptor->iotimer;
+       if(timer == NULL) {
+               iolog_trigger(IOLOG_WARNING, "called iotimer_get_autoreload for destroyed IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
+               struct timeval tout;
+               tout.tv_sec = 0;
+               tout.tv_usec = 0;
+               return tout;
+       }
+       if((timer->flags & IOTIMERFLAG_PERIODIC))
+               return timer->autoreload;
+       else {
+               struct timeval tout;
+               tout.tv_sec = 0;
+               tout.tv_usec = 0;
+               return tout;
+       }
+}
+
 void iotimer_set_timeout(struct IOTimerDescriptor *descriptor, struct timeval *timeout) {
        struct _IOTimerDescriptor *timer = descriptor->iotimer;
        if(timer == NULL) {
 void iotimer_set_timeout(struct IOTimerDescriptor *descriptor, struct timeval *timeout) {
        struct _IOTimerDescriptor *timer = descriptor->iotimer;
        if(timer == NULL) {
@@ -94,10 +138,34 @@ void iotimer_set_timeout(struct IOTimerDescriptor *descriptor, struct timeval *t
        _rearrange_timer(timer);
 }
 
        _rearrange_timer(timer);
 }
 
+struct timeval iotimer_get_timeout(struct IOTimerDescriptor *descriptor) {
+       struct _IOTimerDescriptor *timer = descriptor->iotimer;
+       if(timer == NULL) {
+               iolog_trigger(IOLOG_WARNING, "called iotimer_get_timeout for destroyed IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
+               struct timeval tout;
+               tout.tv_sec = 0;
+               tout.tv_usec = 0;
+               return tout;
+       }
+       return timer->timeout;
+}
+
 void iotimer_set_callback(struct IOTimerDescriptor *descriptor, iotimer_callback *callback) {
        descriptor->callback = callback;
 }
 
 void iotimer_set_callback(struct IOTimerDescriptor *descriptor, iotimer_callback *callback) {
        descriptor->callback = callback;
 }
 
+void iotimer_set_persistent(struct IOTimerDescriptor *descriptor, int persistent) {
+       struct _IOTimerDescriptor *timer = descriptor->iotimer;
+       if(timer == NULL) {
+               iolog_trigger(IOLOG_WARNING, "called iotimer_set_persistent for destroyed IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
+               return;
+       }
+       if(persistent)
+               timer->flags |= IOTIMERFLAG_PERSISTENT;
+       else
+               timer->flags &= ~IOTIMERFLAG_PERSISTENT;
+}
+
 void iotimer_destroy(struct IOTimerDescriptor *descriptor) {
        struct _IOTimerDescriptor *timer = descriptor->iotimer;
        if(timer == NULL) {
 void iotimer_destroy(struct IOTimerDescriptor *descriptor) {
        struct _IOTimerDescriptor *timer = descriptor->iotimer;
        if(timer == NULL) {
@@ -121,10 +189,8 @@ struct _IOTimerDescriptor *_create_timer(struct timeval *timeout) {
                iolog_trigger(IOLOG_ERROR, "could not allocate memory for _IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
                return NULL;
        }
                iolog_trigger(IOLOG_ERROR, "could not allocate memory for _IOTimerDescriptor in %s:%d", __FILE__, __LINE__);
                return NULL;
        }
-       if(timeout) {
+       if(timeout)
                timer->timeout = *timeout;
                timer->timeout = *timeout;
-               _rearrange_timer(timer);
-       }
        return timer;
 }
 
        return timer;
 }
 
@@ -136,7 +202,10 @@ static void _rearrange_timer(struct _IOTimerDescriptor *timer) {
                        timer->prev->next = timer->next;
                if(timer->next != NULL)
                        timer->next->prev = timer->prev;
                        timer->prev->next = timer->next;
                if(timer->next != NULL)
                        timer->next->prev = timer->prev;
+               timer->flags &= ~IOTIMERFLAG_IN_LIST;
        }
        }
+       if(!(timer->flags & IOTIMERFLAG_ACTIVE))
+               return;
        struct _IOTimerDescriptor *ctimer;
        for(ctimer = iotimer_sorted_descriptors; ctimer; ctimer = ctimer->next) {
                if(timeval_is_bigger(ctimer->timeout, timer->timeout)) {
        struct _IOTimerDescriptor *ctimer;
        for(ctimer = iotimer_sorted_descriptors; ctimer; ctimer = ctimer->next) {
                if(timeval_is_bigger(ctimer->timeout, timer->timeout)) {
@@ -184,32 +253,32 @@ static void _autoreload_timer(struct _IOTimerDescriptor *timer) {
 
 void _trigger_timer() {
        struct timeval now;
 
 void _trigger_timer() {
        struct timeval now;
-       _trigger_timer_start:
-       gettimeofday(&now, NULL);
-       
-       struct _IOTimerDescriptor *timer = iotimer_sorted_descriptors;
-       if(!timer || timeval_is_bigger(timer->timeout, now)) {
-               return;
-       }
-       iotimer_sorted_descriptors = timer->next;
-       if(timer->next != NULL)
-               timer->next->prev = timer->prev;
-       timer->flags &= ~IOTIMERFLAG_IN_LIST;
-       
-       if((timer->flags & IOTIMERFLAG_PERIODIC))
-               _autoreload_timer(timer);
-       
-       if(timer->flags & IOTIMERFLAG_PARENT_PUBLIC) {
-               struct IOTimerDescriptor *descriptor = timer->parent;
-               if(descriptor->callback)
-                       descriptor->callback(descriptor);
-               if(!(timer->flags & IOTIMERFLAG_PERIODIC))
-                       iotimer_destroy(descriptor);
-       } else {
-               if(!(timer->flags & IOTIMERFLAG_PERIODIC))
-                       _destroy_timer(timer);
+       struct _IOTimerDescriptor *timer;
+       while(iotimer_sorted_descriptors) {
+               gettimeofday(&now, NULL);
+               
+               timer = iotimer_sorted_descriptors;
+               if(timeval_is_bigger(timer->timeout, now))
+                       break;
+               
+               iotimer_sorted_descriptors = timer->next;
+               if(timer->next != NULL)
+                       timer->next->prev = timer->prev;
+               timer->flags &= ~IOTIMERFLAG_IN_LIST;
+               
+               if((timer->flags & IOTIMERFLAG_PERIODIC))
+                       _autoreload_timer(timer);
+               
+               if(timer->flags & IOTIMERFLAG_PARENT_PUBLIC) {
+                       struct IOTimerDescriptor *descriptor = timer->parent;
+                       if(descriptor->callback)
+                               descriptor->callback(descriptor);
+                       if(!(timer->flags & IOTIMERFLAG_PERIODIC))
+                               iotimer_destroy(descriptor);
+               } else {
+                       if(!(timer->flags & IOTIMERFLAG_PERIODIC))
+                               _destroy_timer(timer);
+               }
        }
        }
-       
-       goto _trigger_timer_start;
 }
 
 }
 
index 1a42264601fa595cd9ab7538259860ba774114bb..e67ee6faec59d3b178d277a5f8299e1a0d8e535a 100644 (file)
@@ -27,6 +27,7 @@
 #define IOTIMERFLAG_IN_LIST        0x04
 #define IOTIMERFLAG_PARENT_PUBLIC  0x08
 #define IOTIMERFLAG_PARENT_SOCKET  0x10
 #define IOTIMERFLAG_IN_LIST        0x04
 #define IOTIMERFLAG_PARENT_PUBLIC  0x08
 #define IOTIMERFLAG_PARENT_SOCKET  0x10
+#define IOTIMERFLAG_PERSISTENT     0x20
 
 struct _IOTimerDescriptor;
 
 
 struct _IOTimerDescriptor;
 
@@ -63,9 +64,14 @@ struct IOTimerDescriptor {
 
 struct IOTimerDescriptor *iotimer_create(struct timeval *timeout);
 void iotimer_start(struct IOTimerDescriptor *iotimer);
 
 struct IOTimerDescriptor *iotimer_create(struct timeval *timeout);
 void iotimer_start(struct IOTimerDescriptor *iotimer);
+void iotimer_stop(struct IOTimerDescriptor *iotimer);
+int iotimer_state(struct IOTimerDescriptor *iotimer);
 void iotimer_set_autoreload(struct IOTimerDescriptor *iotimer, struct timeval *autoreload);
 void iotimer_set_autoreload(struct IOTimerDescriptor *iotimer, struct timeval *autoreload);
+struct timeval iotimer_get_autoreload(struct IOTimerDescriptor *iotimer);
 void iotimer_set_timeout(struct IOTimerDescriptor *iotimer, struct timeval *timeout);
 void iotimer_set_timeout(struct IOTimerDescriptor *iotimer, struct timeval *timeout);
+struct timeval iotimer_get_timeout(struct IOTimerDescriptor *iotimer);
 void iotimer_set_callback(struct IOTimerDescriptor *iotimer, iotimer_callback *callback);
 void iotimer_set_callback(struct IOTimerDescriptor *iotimer, iotimer_callback *callback);
+void iotimer_set_persistent(struct IOTimerDescriptor *iotimer, int persistent);
 void iotimer_destroy(struct IOTimerDescriptor *iotimer);
 
 #endif
 void iotimer_destroy(struct IOTimerDescriptor *iotimer);
 
 #endif
index e8c6698e216cf56e6cc32c6a2516b617e1d4e9bd..d8ca43d946728000a7e4407c5feff67bee86ba21 100644 (file)
@@ -1,3 +1,3 @@
 ##Process this file with automake to create Makefile.in
 ACLOCAL_AMFLAGS = -I m4
 ##Process this file with automake to create Makefile.in
 ACLOCAL_AMFLAGS = -I m4
-SUBDIRS = client client++ client_ssl server_ssl timer resolv
+SUBDIRS = client client++ client_ssl server_ssl timer timer++ resolv
diff --git a/src/IOHandler_test/timer++/.gitignore b/src/IOHandler_test/timer++/.gitignore
new file mode 100644 (file)
index 0000000..7af2f69
--- /dev/null
@@ -0,0 +1,7 @@
+.deps
+.libs
+*.o
+*.exe
+iotest
+Makefile
+Makefile.in
diff --git a/src/IOHandler_test/timer++/Makefile.am b/src/IOHandler_test/timer++/Makefile.am
new file mode 100644 (file)
index 0000000..0591fea
--- /dev/null
@@ -0,0 +1,7 @@
+##Process this file with automake to create Makefile.in
+ACLOCAL_AMFLAGS = -I m4
+
+noinst_PROGRAMS = iotest
+
+iotest_LDADD = ../../IOHandler++/libiohandler.cpp.la
+iotest_SOURCES = iotest.cpp
diff --git a/src/IOHandler_test/timer++/iotest.cpp b/src/IOHandler_test/timer++/iotest.cpp
new file mode 100644 (file)
index 0000000..6c6fd9b
--- /dev/null
@@ -0,0 +1,66 @@
+/* main.c - IOMultiplexer
+ * Copyright (C) 2012  Philipp Kreil (pk910)
+ * 
+ * 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 <http://www.gnu.org/licenses/>. 
+ */
+
+#include <stdio.h>
+#include "../../IOHandler++/IOHandler.h"
+#include "../../IOHandler++/IOTimer.h"
+
+class IOTestTimer : public CIOTimer {
+public:
+       IOTestTimer(int test_duration) : CIOTimer() {
+               this->tick_count = 0;
+               this->test_duration = test_duration;
+               gettimeofday(&this->test_clock1, NULL);
+               gettimeofday(&this->test_clock2, NULL);
+               
+               this->setRelativeTimeoutSeconds(this->test_duration / 1000.0, 1);
+               this->setActive(1);
+               
+               printf("[timer 0] %ld.%ld\n", test_clock1.tv_sec, test_clock1.tv_usec);
+       };
+       
+protected:
+       virtual void timeout() {
+               this->tick_count++;
+               this->tick();
+       };
+       
+private:
+       timeval test_clock1, test_clock2;
+       int tick_count, test_duration;
+       
+       void tick() {
+               timeval curr_time;
+               int diff1;
+               double diff2;
+               
+               gettimeofday(&curr_time, NULL);
+               diff1 = (curr_time.tv_sec - this->test_clock1.tv_sec) * 1000 + ((curr_time.tv_usec - this->test_clock1.tv_usec) / 1000);
+               diff2 = (curr_time.tv_sec - this->test_clock2.tv_sec) * 1000 + ((curr_time.tv_usec - this->test_clock2.tv_usec) / 1000.0);
+               diff2 -= (this->tick_count * this->test_duration);
+               gettimeofday(&this->test_clock1, NULL);
+               printf("[timer %03d] %ld.%06ld [%d ms]  accuracy: %f ms\n", this->tick_count, curr_time.tv_sec, curr_time.tv_usec, diff1, diff2);
+       };
+};
+
+
+int main(int argc, char *argv[]) {
+       CIOHandler *iohandler = new CIOHandler();
+       IOTestTimer *timer = new IOTestTimer(100);
+       
+       iohandler->start();
+}