ithewei 6 anos atrás
pai
commit
b95123e229
6 arquivos alterados com 135 adições e 42 exclusões
  1. 7 2
      Makefile
  2. 2 0
      README.md
  3. 12 8
      event/hevent.h
  4. 54 31
      event/hloop.c
  5. 0 1
      examples/nmap.cpp
  6. 60 0
      examples/timer.c

+ 7 - 2
Makefile

@@ -3,7 +3,7 @@ TMPDIR=tmp
 
 default: all
 
-all: test ping loop tcp udp nc nmap httpd
+all: test ping timer loop tcp udp nc nmap httpd
 
 clean:
 	$(MAKEF) clean SRCDIRS=". base utils event http http/client http/server examples $(TMPDIR)"
@@ -20,6 +20,11 @@ ping:
 	-rm base/hsocket.o
 	$(MAKEF) TARGET=$@ SRCDIRS="" SRCS="examples/ping.c base/hsocket.c base/htime.c base/RAII.cpp" INCDIRS=". base" DEFINES="PRINT_DEBUG"
 
+timer: prepare
+	-rm $(TMPDIR)/*.o $(TMPDIR)/*.h $(TMPDIR)/*.c $(TMPDIR)/*.cpp
+	cp examples/timer.c $(TMPDIR)
+	$(MAKEF) TARGET=$@ SRCDIRS=". base event $(TMPDIR)"
+
 loop: prepare
 	-rm $(TMPDIR)/*.o $(TMPDIR)/*.h $(TMPDIR)/*.c $(TMPDIR)/*.cpp
 	cp examples/loop.c $(TMPDIR)
@@ -65,4 +70,4 @@ CURL_SRCS    += examples/curl.cpp base/hstring.cpp base/hbase.c
 curl:
 	$(MAKEF) TARGET=$@ SRCDIRS="$(CURL_SRCDIRS)" INCDIRS="$(CURL_INCDIRS)" SRCS="$(CURL_SRCS)" DEFINES="CURL_STATICLIB" LIBS="curl"
 
-.PHONY: clean prepare test ping loop tcp udp nc nmap httpd webbench curl
+.PHONY: clean prepare test ping timer loop tcp udp nc nmap httpd webbench curl

+ 2 - 0
README.md

@@ -60,10 +60,12 @@ hw 是一套跨平台c/c++基础组件,函数名/类名以h/H开头
 
 - make all
 - make test: 服务端master-workers model
+- make timer: 定时器测试
 - make loop: 事件循环(包含timer、io、idle)
 - make tcp:  tcp server
 - make udp:  udp server
 - make nc:   network client
+- make nmap: host discovery
 - make httpd: http服务(包含web service和api service)
 - make curl: 基于libcurl封装http客户端
 - make webbench: http服务压力测试程序

+ 12 - 8
event/hevent.h

@@ -18,7 +18,6 @@
 #define EVENT_INACTIVE(ev) \
     if (ev->active) {\
         ev->active = 0;\
-        ev->pending = 0; \
         ev->loop->nactives--;\
     }\
 
@@ -28,12 +27,8 @@
             ev->pending = 1;\
             ev->loop->npendings++;\
             hevent_t** phead = &ev->loop->pendings[HEVENT_PRIORITY_INDEX(ev->priority)];\
-            if (*phead == NULL) {\
-                *phead = (hevent_t*)ev;\
-            } else {\
-                ev->pending_next = *phead;\
-                *phead = (hevent_t*)ev;\
-            }\
+            ev->pending_next = *phead;\
+            *phead = (hevent_t*)ev;\
         }\
     } while(0)
 
@@ -48,7 +43,16 @@
 #define EVENT_DEL(ev) \
     do {\
         EVENT_INACTIVE(ev);\
-        ev->destroy = 1;\
+        if (!ev->pending) {\
+            SAFE_FREE(ev);\
+        }\
+    } while(0)
+
+#define EVENT_RESET(ev) \
+    do {\
+        ev->destroy = 0;\
+        ev->active  = 1;\
+        ev->pending = 0;\
     } while(0)
 
 #endif // HW_EVENT_H_

+ 54 - 31
event/hloop.c

@@ -17,6 +17,9 @@ static void hio_ready(hio_t* io);
 static void hio_done(hio_t* io);
 static void hio_free(hio_t* io);
 
+static void __hidle_del(hidle_t* idle);
+static void __htimer_del(htimer_t* timer);
+
 static int timers_compare(const struct heap_node* lhs, const struct heap_node* rhs) {
     return TIMER_ENTRY(lhs)->next_timeout < TIMER_ENTRY(rhs)->next_timeout;
 }
@@ -27,18 +30,15 @@ static int hloop_process_idles(hloop_t* loop) {
     hidle_t* idle = NULL;
     while (node != &loop->idles) {
         idle = IDLE_ENTRY(node);
+        node = node->next;
         if (idle->repeat != INFINITE) {
             --idle->repeat;
         }
         if (idle->repeat == 0) {
-            hidle_del(idle);
+            __hidle_del(idle);
         }
         EVENT_PENDING(idle);
         ++nidles;
-        node = node->next;
-        if (!idle->active) {
-            list_del(node->prev);
-        }
     }
     return nidles;
 }
@@ -56,14 +56,14 @@ static int hloop_process_timers(hloop_t* loop) {
             --timer->repeat;
         }
         if (timer->repeat == 0) {
-            htimer_del(timer);
+            __htimer_del(timer);
         }
-        EVENT_PENDING(timer);
-        ++ntimers;
-        heap_dequeue(&loop->timers);
-        if (timer->active) {
+        else {
+            heap_dequeue(&loop->timers);
             if (timer->event_type == HEVENT_TYPE_TIMEOUT) {
-                timer->next_timeout += ((htimeout_t*)timer)->timeout*1000;
+                while (timer->next_timeout <= now_hrtime) {
+                    timer->next_timeout += ((htimeout_t*)timer)->timeout*1000;
+                }
             }
             else if (timer->event_type == HEVENT_TYPE_PERIOD) {
                 hperiod_t* period = (hperiod_t*)timer;
@@ -72,6 +72,8 @@ static int hloop_process_timers(hloop_t* loop) {
             }
             heap_insert(&loop->timers, &timer->node);
         }
+        EVENT_PENDING(timer);
+        ++ntimers;
     }
     return ntimers;
 }
@@ -87,23 +89,24 @@ static int hloop_process_ios(hloop_t* loop, int timeout) {
 static int hloop_process_pendings(hloop_t* loop) {
     if (loop->npendings == 0) return 0;
 
-    hevent_t* prev = NULL;
+    hevent_t* cur = NULL;
     hevent_t* next = NULL;
     int ncbs = 0;
     for (int i = HEVENT_PRIORITY_SIZE-1; i >= 0; --i) {
-        next = loop->pendings[i];
-        while (next) {
-            if (next->pending && next->cb) {
-                next->cb(next);
-                ++ncbs;
-            }
-            prev = next;
-            next = next->pending_next;
-            prev->pending = 0;
-            prev->pending_next = NULL;
-            if (prev->destroy) {
-                SAFE_FREE(prev);
+        cur = loop->pendings[i];
+        while (cur) {
+            next = cur->pending_next;
+            if (cur->pending) {
+                if (cur->active && cur->cb) {
+                    cur->cb(cur);
+                    ++ncbs;
+                }
+                cur->pending = 0;
+                if (cur->destroy) {
+                    EVENT_DEL(cur);
+                }
             }
+            cur = next;
         }
         loop->pendings[i] = NULL;
     }
@@ -148,7 +151,7 @@ process_timers:
     }
     int ncbs = hloop_process_pendings(loop);
     //printd("blocktime=%d nios=%d/%u ntimers=%d/%u nidles=%d/%u nactives=%d npendings=%d ncbs=%d\n",
-            //blocktime, nios/loop->nios, loop->nios, ntimers, loop->ntimers, nidles, loop->nidles,
+            //blocktime, nios, loop->nios, ntimers, loop->ntimers, nidles, loop->nidles,
             //loop->nactives, npendings, ncbs);
     return ncbs;
 }
@@ -261,10 +264,17 @@ hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat) {
     return idle;
 }
 
+static void __hidle_del(hidle_t* idle) {
+    if (idle->destroy) return;
+    idle->destroy = 1;
+    list_del(&idle->node);
+    idle->loop->nidles--;
+}
+
 void hidle_del(hidle_t* idle) {
     if (!idle->active) return;
-    idle->loop->nidles--;
     EVENT_DEL(idle);
+    __hidle_del(idle);
 }
 
 htimer_t* htimer_add(hloop_t* loop, htimer_cb cb, uint64_t timeout, uint32_t repeat) {
@@ -284,14 +294,22 @@ htimer_t* htimer_add(hloop_t* loop, htimer_cb cb, uint64_t timeout, uint32_t rep
 }
 
 void htimer_reset(htimer_t* timer) {
-    if (timer->event_type != HEVENT_TYPE_TIMEOUT || timer->pending) {
+    if (timer->event_type != HEVENT_TYPE_TIMEOUT) {
         return;
     }
     hloop_t* loop = timer->loop;
     htimeout_t* timeout = (htimeout_t*)timer;
-    heap_remove(&loop->timers, &timer->node);
+    if (timer->pending) {
+        if (timer->repeat == 0) {
+            timer->repeat = 1;
+        }
+    }
+    else {
+        heap_remove(&loop->timers, &timer->node);
+    }
     timer->next_timeout = hloop_now_hrtime(loop) + timeout->timeout*1000;
     heap_insert(&loop->timers, &timer->node);
+    EVENT_RESET(timer);
 }
 
 htimer_t* htimer_add_period(hloop_t* loop, htimer_cb cb,
@@ -317,12 +335,17 @@ htimer_t* htimer_add_period(hloop_t* loop, htimer_cb cb,
     return (htimer_t*)timer;
 }
 
+static void __htimer_del(htimer_t* timer) {
+    if (timer->destroy) return;
+    heap_remove(&timer->loop->timers, &timer->node);
+    timer->loop->ntimers--;
+    timer->destroy = 1;
+}
+
 void htimer_del(htimer_t* timer) {
     if (!timer->active) return;
-    timer->loop->ntimers--;
+    __htimer_del(timer);
     EVENT_DEL(timer);
-    // NOTE: set timer->next_timeout to handle at next loop
-    timer->next_timeout = hloop_now_hrtime(timer->loop);
 }
 
 void hio_init(hio_t* io) {

+ 0 - 1
examples/nmap.cpp

@@ -6,7 +6,6 @@
 
 int host_discovery_task(std::string segment, void* nmap) {
     Nmap* hosts= (Nmap*)nmap;
-    printf("%p %s------------------------------------------------\n", nmap, segment.c_str());
     return host_discovery(segment.c_str(), hosts);
 }
 

+ 60 - 0
examples/timer.c

@@ -0,0 +1,60 @@
+#include "hloop.h"
+#include "hbase.h"
+
+void on_timer(htimer_t* timer) {
+    printf("time=%lus on_timer\n", hloop_now(timer->loop));
+}
+
+void on_timer_add(htimer_t* timer) {
+    printf("time=%lus on_timer_add\n", hloop_now(timer->loop));
+    htimer_add(timer->loop, on_timer_add, 1000, 1);
+}
+
+void on_timer_del(htimer_t* timer) {
+    printf("time=%lus on_timer_del\n", hloop_now(timer->loop));
+    htimer_del(timer);
+}
+
+void on_timer_reset(htimer_t* timer) {
+    printf("time=%lus on_timer_reset\n", hloop_now(timer->loop));
+    htimer_reset((htimer_t*)timer->userdata);
+}
+
+void on_timer_quit(htimer_t* timer) {
+    printf("time=%lus on_timer_quit\n", hloop_now(timer->loop));
+    hloop_stop(timer->loop);
+}
+
+void cron_hourly(htimer_t* timer) {
+    time_t tt;
+    time(&tt);
+    printf("time=%lus cron_hourly: %s\n", hloop_now(timer->loop), ctime(&tt));
+}
+
+int main() {
+    MEMCHECK;
+    hloop_t loop;
+    hloop_init(&loop);
+
+    // on_timer_add triggered forever
+    htimer_add(&loop, on_timer_add, 1000, 1);
+    // on_timer_del triggered just once
+    htimer_add(&loop, on_timer_del, 1000, 10);
+
+    // on_timer triggered after 10s
+    htimer_t* reseted = htimer_add(&loop, on_timer, 5000, 1);
+    htimer_t* reset = htimer_add(&loop, on_timer_reset, 1000, 5);
+    reset->userdata = reseted;
+
+    // cron_hourly next triggered in one minute
+    int minute = time(NULL)%3600/60;
+    htimer_add_period(&loop, cron_hourly, minute+1, -1, -1, -1, -1, INFINITE);
+
+    // quit application after 1 min
+    htimer_add(&loop, on_timer_quit, 60000, 1);
+
+    printf("time=%lus begin\n", hloop_now(&loop));
+    hloop_run(&loop);
+    printf("time=%lus stop\n", hloop_now(&loop));
+    return 0;
+}