소스 검색

open hloop.h

ithewei 6 년 전
부모
커밋
1773ad8ba4
24개의 변경된 파일546개의 추가작업 그리고 438개의 파일을 삭제
  1. 3 1
      base/RAII.cpp
  2. 3 13
      base/hbase.h
  3. 1 0
      base/hbuf.h
  4. 17 6
      base/hdef.h
  5. 3 3
      base/hproc.h
  6. 1 0
      base/hsocket.h
  7. 1 1
      base/hthreadpool.h
  8. 70 0
      event/hevent.c
  9. 105 1
      event/hevent.h
  10. 0 15
      event/hio.h
  11. 88 78
      event/hloop.c
  12. 66 139
      event/hloop.h
  13. 17 8
      event/nio.c
  14. 14 11
      event/nlog.c
  15. 14 13
      event/nmap.cpp
  16. 17 7
      event/overlapio.c
  17. 16 15
      examples/loop.c
  18. 22 25
      examples/nc.c
  19. 18 16
      examples/tcp.c
  20. 21 21
      examples/timer.c
  21. 13 11
      examples/udp.c
  22. 0 20
      h.h
  23. 4 4
      http/server/HttpHandler.h
  24. 32 30
      http/server/http_server.cpp

+ 3 - 1
base/RAII.cpp

@@ -45,7 +45,9 @@ static CurlRAII s_curl;
 class OpensslRAII {
 public:
     OpensslRAII() {
-        OPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, NULL);
+        //OPENSSL_init_ssl(OPENSSL_INIT_SSL_DEFAULT, NULL);
+        SSL_load_error_strings();
+        SSL_library_init();
     }
 
     ~OpensslRAII() {

+ 3 - 13
base/hbase.h

@@ -4,20 +4,8 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#ifdef _MSC_VER
-    #define strcasecmp stricmp
-    #define strncasecmp strnicmp
-#else
-    #include <strings.h>
-    #define stricmp     strcasecmp
-    #define strnicmp    strncasecmp
-#endif
 
-#ifdef PRINT_DEBUG
-#define printd printf
-#else
-#define printd(...)
-#endif
+#include "hdef.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -32,6 +20,7 @@ void* safe_realloc(void* oldptr, size_t newsize, size_t oldsize);
 void* safe_calloc(size_t nmemb, size_t size);
 void* safe_zalloc(size_t size);
 
+#undef  SAFE_ALLOC
 #define SAFE_ALLOC(ptr, size)\
     do {\
         void** pptr = (void**)&(ptr);\
@@ -41,6 +30,7 @@ void* safe_zalloc(size_t size);
 
 #define SAFE_ALLOC_SIZEOF(ptr)  SAFE_ALLOC(ptr, sizeof(*(ptr)))
 
+#undef  SAFE_FREE
 #define SAFE_FREE(ptr)\
     do {\
         if (ptr) {\

+ 1 - 0
base/hbuf.h

@@ -6,6 +6,7 @@
 #include <string.h>
 
 #include "hdef.h"
+#include "hbase.h"
 
 typedef struct hbuf_s {
     char*  base;

+ 17 - 6
base/hdef.h

@@ -2,7 +2,6 @@
 #define HW_DEF_H_
 
 #include "hplatform.h"
-#include "hbase.h"
 
 typedef float               float32;
 typedef double              float64;
@@ -23,14 +22,26 @@ typedef union {
     void*       ptr;
 } var;
 
+typedef int (*method_t)(void* userdata);
+typedef void (*procedure_t)(void* userdata);
+
 #ifdef _MSC_VER
-typedef int pid_t;
-typedef int gid_t;
-typedef int uid_t;
+    typedef int pid_t;
+    typedef int gid_t;
+    typedef int uid_t;
+    #define strcasecmp stricmp
+    #define strncasecmp strnicmp
+#else
+    #include <strings.h>
+    #define stricmp     strcasecmp
+    #define strnicmp    strncasecmp
 #endif
 
-typedef int (*method_t)(void* userdata);
-typedef void (*procedure_t)(void* userdata);
+#ifdef PRINT_DEBUG
+#define printd printf
+#else
+#define printd(...)
+#endif
 
 #ifndef MAX_PATH
 #define MAX_PATH          260

+ 3 - 3
base/hproc.h

@@ -1,5 +1,5 @@
-#ifndef H_PROC_H_
-#define H_PROC_H_
+#ifndef HW_PROC_H_
+#define HW_PROC_H_
 
 #include "hplatform.h"
 #include "hdef.h"
@@ -65,4 +65,4 @@ static inline int spawn_proc(proc_ctx_t* ctx) {
 }
 #endif
 
-#endif // H_PROC_H_
+#endif // HW_PROC_H_

+ 1 - 0
base/hsocket.h

@@ -3,6 +3,7 @@
 
 #include "hplatform.h"
 #include "hdef.h"
+#include "hbase.h"
 
 #ifdef _MSC_VER
 #pragma comment(lib, "ws2_32.lib")

+ 1 - 1
base/hthreadpool.h

@@ -126,8 +126,8 @@ public:
         PAUSE,
     };
     int                 pool_size;
-    std::atomic<Status> status;
     std::atomic<int>    idle_num;
+    std::atomic<Status> status;
     std::vector<std::thread>    workers;
     std::queue<Task>            tasks;
 

+ 70 - 0
event/hevent.c

@@ -0,0 +1,70 @@
+#include "hevent.h"
+
+int hio_fd(hio_t* io) {
+    return io->fd;
+}
+
+hio_type_e hio_type(hio_t* io) {
+    return io->io_type;
+}
+
+int hio_error(hio_t* io) {
+    return io->error;
+}
+
+struct sockaddr* hio_localaddr(hio_t* io) {
+    return io->localaddr;
+}
+
+struct sockaddr* hio_peeraddr(hio_t* io) {
+    return io->peeraddr;
+}
+
+void hio_set_readbuf(hio_t* io, void* buf, size_t len) {
+    io->readbuf.base = buf;
+    io->readbuf.len = len;
+}
+
+int hio_enable_ssl(hio_t* io) {
+    printd("ssl fd=%d\n", io->fd);
+    io->io_type = HIO_TYPE_SSL;
+    return 0;
+}
+
+void hio_setcb_accept   (hio_t* io, haccept_cb  accept_cb) {
+    io->accept_cb = accept_cb;
+}
+
+void hio_setcb_connect  (hio_t* io, hconnect_cb connect_cb) {
+    io->connect_cb = connect_cb;
+}
+
+void hio_setcb_read     (hio_t* io, hread_cb    read_cb) {
+    io->read_cb = read_cb;
+}
+
+void hio_setcb_write    (hio_t* io, hwrite_cb   write_cb) {
+    io->write_cb = write_cb;
+}
+
+void hio_setcb_close    (hio_t* io, hclose_cb   close_cb) {
+    io->close_cb = close_cb;
+}
+
+void hio_set_type(hio_t* io, hio_type_e type) {
+    io->io_type = type;
+}
+
+void hio_set_localaddr(hio_t* io, struct sockaddr* addr, int addrlen) {
+    if (io->localaddr == NULL) {
+        SAFE_ALLOC(io->localaddr, sizeof(struct sockaddr_in6));
+    }
+    memcpy(io->localaddr, addr, addrlen);
+}
+
+void hio_set_peeraddr (hio_t* io, struct sockaddr* addr, int addrlen) {
+    if (io->peeraddr == NULL) {
+        SAFE_ALLOC(io->peeraddr, sizeof(struct sockaddr_in6));
+    }
+    memcpy(io->peeraddr, addr, addrlen);
+}

+ 105 - 1
event/hevent.h

@@ -1,9 +1,113 @@
 #ifndef HW_EVENT_H_
 #define HW_EVENT_H_
 
+#include "array.h"
+#include "list.h"
+#include "heap.h"
+#include "queue.h"
+
 #include "hloop.h"
+#include "hbuf.h"
+
+typedef enum {
+    HLOOP_STATUS_STOP,
+    HLOOP_STATUS_RUNNING,
+    HLOOP_STATUS_PAUSE
+} hloop_status_e;
+
+ARRAY_DECL(hio_t*, io_array);
+
+struct hloop_s {
+    uint32_t    flags;
+    hloop_status_e status;
+    time_t      start_time; // s
+    uint64_t    start_hrtime; // us
+    uint64_t    end_hrtime;
+    uint64_t    cur_hrtime;
+    uint64_t    loop_cnt;
+    void*       userdata;
+//private:
+    // events
+    uint64_t                    event_counter;
+    uint32_t                    nactives;
+    uint32_t                    npendings;
+    // pendings: with priority as array.index
+    hevent_t*                   pendings[HEVENT_PRIORITY_SIZE];
+    // idles
+    struct list_head            idles;
+    uint32_t                    nidles;
+    // timers
+    struct heap                 timers;
+    uint32_t                    ntimers;
+    // ios: with fd as array.index
+    struct io_array             ios;
+    uint32_t                    nios;
+    void*                       iowatcher;
+};
+
+struct hidle_s {
+    HEVENT_FIELDS
+    uint32_t    repeat;
+//private:
+    struct list_node node;
+};
+
+#define HTIMER_FIELDS                   \
+    HEVENT_FIELDS                       \
+    uint32_t    repeat;                 \
+    uint64_t    next_timeout;           \
+    struct heap_node node;
+
+struct htimer_s {
+    HTIMER_FIELDS
+};
+
+struct htimeout_s {
+    HTIMER_FIELDS
+    uint32_t    timeout;                \
+};
+
+struct hperiod_s {
+    HTIMER_FIELDS
+    int8_t      minute;
+    int8_t      hour;
+    int8_t      day;
+    int8_t      week;
+    int8_t      month;
+};
 
-#include "hdef.h"
+QUEUE_DECL(offset_buf_t, write_queue);
+struct hio_s {
+    HEVENT_FIELDS
+    unsigned    ready       :1;
+    unsigned    closed      :1;
+    unsigned    accept      :1;
+    unsigned    connect     :1;
+    unsigned    connectex   :1; // for ConnectEx/DisconnectEx
+    unsigned    recv        :1;
+    unsigned    send        :1;
+    unsigned    recvfrom    :1;
+    unsigned    sendto      :1;
+    int         fd;
+    hio_type_e  io_type;
+    int         error;
+    int         events;
+    int         revents;
+    struct sockaddr*    localaddr;
+    struct sockaddr*    peeraddr;
+    hbuf_t              readbuf;        // for hread
+    struct write_queue  write_queue;    // for hwrite
+    // callbacks
+    hread_cb    read_cb;
+    hwrite_cb   write_cb;
+    hclose_cb   close_cb;
+    haccept_cb  accept_cb;
+    hconnect_cb connect_cb;
+//private:
+    int         event_index[2]; // for poll,kqueue
+    void*       hovlp;          // for iocp/overlapio
+    void*       ssl;            // for SSL
+};
 
 #define EVENT_ENTRY(p)          container_of(p, hevent_t, pending_node)
 #define IDLE_ENTRY(p)           container_of(p, hidle_t,  node)

+ 0 - 15
event/hio.h

@@ -1,15 +0,0 @@
-#ifndef HW_HIO_H_
-#define HW_HIO_H_
-
-#include "hloop.h"
-
-//int hio_read (hio_t* io, void* buf, size_t len);
-//@see io->readbuf
-int hio_read (hio_t* io);
-int hio_write(hio_t* io, const void* buf, size_t len);
-int hio_close(hio_t* io);
-
-int hio_accept (hio_t* io);
-int hio_connect(hio_t* io);
-
-#endif // HW_HIO_H_

+ 88 - 78
event/hloop.c

@@ -1,11 +1,12 @@
 #include "hloop.h"
 #include "hevent.h"
-#include "hio.h"
 #include "iowatcher.h"
 
 #include "hdef.h"
+#include "hbase.h"
 #include "hlog.h"
 #include "hmath.h"
+#include "htime.h"
 #include "hsocket.h"
 
 #define PAUSE_TIME              10          // ms
@@ -157,8 +158,7 @@ process_timers:
     return ncbs;
 }
 
-int hloop_init(hloop_t* loop) {
-    memset(loop, 0, sizeof(hloop_t));
+static void hloop_init(hloop_t* loop) {
     loop->status = HLOOP_STATUS_STOP;
     // idles
     list_init(&loop->idles);
@@ -171,10 +171,9 @@ int hloop_init(hloop_t* loop) {
     // NOTE: init start_time here, because htimer_add use it.
     time(&loop->start_time);
     loop->start_hrtime = loop->cur_hrtime = gethrtime();
-    return 0;
 }
 
-void hloop_cleanup(hloop_t* loop) {
+static void hloop_cleanup(hloop_t* loop) {
     // pendings
     printd("cleanup pendings...\n");
     for (int i = 0; i < HEVENT_PRIORITY_SIZE; ++i) {
@@ -205,7 +204,7 @@ void hloop_cleanup(hloop_t* loop) {
         hio_t* io = loop->ios.ptr[i];
         if (io) {
             if ((!(io->io_type&HIO_TYPE_STDIO)) && io->active) {
-                hclose(io);
+                hio_close(io);
             }
             hio_free(io);
         }
@@ -215,8 +214,24 @@ void hloop_cleanup(hloop_t* loop) {
     iowatcher_cleanup(loop);
 }
 
+hloop_t* hloop_new(int flags) {
+    hloop_t* loop;
+    SAFE_ALLOC_SIZEOF(loop);
+    memset(loop, 0, sizeof(hloop_t));
+    hloop_init(loop);
+    loop->flags |= flags;
+    return loop;
+}
+
+void hloop_free(hloop_t** pp) {
+    if (pp && *pp) {
+        hloop_cleanup(*pp);
+        SAFE_FREE(*pp);
+        *pp = NULL;
+    }
+}
+
 int hloop_run(hloop_t* loop) {
-    loop->loop_cnt = 0;
     loop->status = HLOOP_STATUS_RUNNING;
     while (loop->status != HLOOP_STATUS_STOP) {
         if (loop->status == HLOOP_STATUS_PAUSE) {
@@ -227,10 +242,16 @@ int hloop_run(hloop_t* loop) {
         ++loop->loop_cnt;
         if (loop->nactives == 0) break;
         hloop_process_events(loop);
+        if (loop->flags & HLOOP_FLAG_RUN_ONCE) {
+            break;
+        }
     }
     loop->status = HLOOP_STATUS_STOP;
     loop->end_hrtime = gethrtime();
-    hloop_cleanup(loop);
+    if (loop->flags & HLOOP_FLAG_AUTO_FREE) {
+        hloop_cleanup(loop);
+        SAFE_FREE(loop);
+    }
     return 0;
 }
 
@@ -253,6 +274,26 @@ int hloop_resume(hloop_t* loop) {
     return 0;
 }
 
+void hloop_update_time(hloop_t* loop) {
+    loop->cur_hrtime = gethrtime();
+}
+
+time_t hloop_now(hloop_t* loop) {
+    return loop->start_time + (loop->cur_hrtime - loop->start_hrtime) / 1000000;
+}
+
+uint64_t hloop_now_hrtime(hloop_t* loop) {
+    return loop->start_time*1e6 + (loop->cur_hrtime - loop->start_hrtime);
+}
+
+void  hloop_set_userdata(hloop_t* loop, void* userdata) {
+    loop->userdata = userdata;
+}
+
+void* hloop_userdata(hloop_t* loop) {
+    return loop->userdata;
+}
+
 hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat) {
     hidle_t* idle;
     SAFE_ALLOC_SIZEOF(idle);
@@ -508,20 +549,6 @@ int hio_del(hio_t* io, int events) {
     return 0;
 }
 
-void hio_setlocaladdr(hio_t* io, struct sockaddr* addr, int addrlen) {
-    if (io->localaddr == NULL) {
-        SAFE_ALLOC(io->localaddr, sizeof(struct sockaddr_in6));
-    }
-    memcpy(io->localaddr, addr, addrlen);
-}
-
-void hio_setpeeraddr (hio_t* io, struct sockaddr* addr, int addrlen) {
-    if (io->peeraddr == NULL) {
-        SAFE_ALLOC(io->peeraddr, sizeof(struct sockaddr_in6));
-    }
-    memcpy(io->peeraddr, addr, addrlen);
-}
-
 hio_t* hread(hloop_t* loop, int fd, void* buf, size_t len, hread_cb read_cb) {
     hio_t* io = hio_get(loop, fd);
     if (io == NULL) return NULL;
@@ -544,19 +571,6 @@ hio_t* hwrite(hloop_t* loop, int fd, const void* buf, size_t len, hwrite_cb writ
     return io;
 }
 
-void hclose(hio_t* io) {
-    printd("close fd=%d\n", io->fd);
-    if (io->closed) return;
-    io->closed = 1;
-    hio_del(io, ALL_EVENTS);
-    hio_close(io);
-    if (io->close_cb) {
-        printd("close_cb------\n");
-        io->close_cb(io);
-        printd("close_cb======\n");
-    }
-}
-
 hio_t* haccept(hloop_t* loop, int listenfd, haccept_cb accept_cb) {
     hio_t* io = hio_get(loop, listenfd);
     if (io == NULL) return NULL;
@@ -579,6 +593,42 @@ hio_t* hconnect (hloop_t* loop, int connfd, hconnect_cb connect_cb) {
     return io;
 }
 
+hio_t* hrecv (hloop_t* loop, int connfd, void* buf, size_t len, hread_cb read_cb) {
+    //hio_t* io = hio_get(loop, connfd);
+    //if (io == NULL) return NULL;
+    //io->recv = 1;
+    //if (io->io_type != HIO_TYPE_SSL) {
+        //io->io_type = HIO_TYPE_TCP;
+    //}
+    return hread(loop, connfd, buf, len, read_cb);
+}
+
+hio_t* hsend (hloop_t* loop, int connfd, const void* buf, size_t len, hwrite_cb write_cb) {
+    //hio_t* io = hio_get(loop, connfd);
+    //if (io == NULL) return NULL;
+    //io->send = 1;
+    //if (io->io_type != HIO_TYPE_SSL) {
+        //io->io_type = HIO_TYPE_TCP;
+    //}
+    return hwrite(loop, connfd, buf, len, write_cb);
+}
+
+hio_t* hrecvfrom (hloop_t* loop, int sockfd, void* buf, size_t len, hread_cb read_cb) {
+    //hio_t* io = hio_get(loop, sockfd);
+    //if (io == NULL) return NULL;
+    //io->recvfrom = 1;
+    //io->io_type = HIO_TYPE_UDP;
+    return hread(loop, sockfd, buf, len, read_cb);
+}
+
+hio_t* hsendto (hloop_t* loop, int sockfd, const void* buf, size_t len, hwrite_cb write_cb) {
+    //hio_t* io = hio_get(loop, sockfd);
+    //if (io == NULL) return NULL;
+    //io->sendto = 1;
+    //io->io_type = HIO_TYPE_UDP;
+    return hwrite(loop, sockfd, buf, len, write_cb);
+}
+
 hio_t* create_tcp_server (hloop_t* loop, int port, haccept_cb accept_cb) {
     int listenfd = Listen(port);
     if (listenfd < 0) {
@@ -606,46 +656,11 @@ hio_t* create_tcp_client (hloop_t* loop, const char* host, int port, hconnect_cb
     }
     hio_t* io = hio_get(loop, connfd);
     if (io == NULL) return NULL;
-    hio_setpeeraddr(io, (struct sockaddr*)&addr, addrlen);
+    hio_set_peeraddr(io, (struct sockaddr*)&addr, addrlen);
     hconnect(loop, connfd, connect_cb);
     return io;
 }
 
-hio_t* hrecv (hloop_t* loop, int connfd, void* buf, size_t len, hread_cb read_cb) {
-    hio_t* io = hio_get(loop, connfd);
-    if (io == NULL) return NULL;
-    io->recv = 1;
-    if (io->io_type != HIO_TYPE_SSL) {
-        io->io_type = HIO_TYPE_TCP;
-    }
-    return hread(loop, connfd, buf, len, read_cb);
-}
-
-hio_t* hsend (hloop_t* loop, int connfd, const void* buf, size_t len, hwrite_cb write_cb) {
-    hio_t* io = hio_get(loop, connfd);
-    if (io == NULL) return NULL;
-    io->send = 1;
-    if (io->io_type != HIO_TYPE_SSL) {
-        io->io_type = HIO_TYPE_TCP;
-    }
-    return hwrite(loop, connfd, buf, len, write_cb);
-}
-
-hio_t* hrecvfrom (hloop_t* loop, int sockfd, void* buf, size_t len, hread_cb read_cb) {
-    hio_t* io = hio_get(loop, sockfd);
-    if (io == NULL) return NULL;
-    io->recvfrom = 1;
-    io->io_type = HIO_TYPE_UDP;
-    return hread(loop, sockfd, buf, len, read_cb);
-}
-
-hio_t* hsendto (hloop_t* loop, int sockfd, const void* buf, size_t len, hwrite_cb write_cb) {
-    hio_t* io = hio_get(loop, sockfd);
-    if (io == NULL) return NULL;
-    io->sendto = 1;
-    io->io_type = HIO_TYPE_UDP;
-    return hwrite(loop, sockfd, buf, len, write_cb);
-}
 
 // @server: socket -> bind -> hrecvfrom
 hio_t* create_udp_server(hloop_t* loop, int port) {
@@ -656,7 +671,7 @@ hio_t* create_udp_server(hloop_t* loop, int port) {
     return hio_get(loop, bindfd);
 }
 
-// @client: Resolver -> socket -> hio_get -> hio_setpeeraddr
+// @client: Resolver -> socket -> hio_get -> hio_set_peeraddr
 hio_t* create_udp_client(hloop_t* loop, const char* host, int port) {
     // IPv4
     struct sockaddr_in peeraddr;
@@ -675,12 +690,7 @@ hio_t* create_udp_client(hloop_t* loop, const char* host, int port) {
 
     hio_t* io = hio_get(loop, sockfd);
     if (io == NULL) return NULL;
-    hio_setpeeraddr(io, (struct sockaddr*)&peeraddr, addrlen);
+    hio_set_peeraddr(io, (struct sockaddr*)&peeraddr, addrlen);
     return io;
 }
 
-int hio_enable_ssl(hio_t* io) {
-    printd("ssl fd=%d\n", io->fd);
-    io->io_type = HIO_TYPE_SSL;
-    return 0;
-}

+ 66 - 139
event/hloop.h

@@ -4,17 +4,7 @@
 #include "hdef.h"
 
 BEGIN_EXTERN_C
-
-#include "htime.h"
-#include "array.h"
-#include "list.h"
-#include "heap.h"
-#include "queue.h"
-#include "hbuf.h"
-
-typedef struct hloop_s  hloop_t;
-typedef struct hevent_s hevent_t;
-
+typedef struct hloop_s  hloop_t; typedef struct hevent_s hevent_t; 
 typedef struct hidle_s      hidle_t;
 typedef struct htimer_s     htimer_t;
 typedef struct htimeout_s   htimeout_t;
@@ -68,38 +58,14 @@ struct hevent_s {
     HEVENT_FIELDS
 };
 
-struct hidle_s {
-    HEVENT_FIELDS
-    uint32_t    repeat;
-//private:
-    struct list_node node;
-};
-
-#define HTIMER_FIELDS                   \
-    HEVENT_FIELDS                       \
-    uint32_t    repeat;                 \
-    uint64_t    next_timeout;           \
-    struct heap_node node;
-
-struct htimer_s {
-    HTIMER_FIELDS
-};
-
-struct htimeout_s {
-    HTIMER_FIELDS
-    uint32_t    timeout;                \
-};
-
-struct hperiod_s {
-    HTIMER_FIELDS
-    int8_t      minute;
-    int8_t      hour;
-    int8_t      day;
-    int8_t      week;
-    int8_t      month;
-};
+#define hevent_set_priority(ev, prio)   ((hevent_t*)(ev))->priority = prio
+#define hevent_set_userdata(ev, udata)  ((hevent_t*)(ev))->userdata = (void*)udata
 
-QUEUE_DECL(offset_buf_t, write_queue);
+#define hevent_loop(ev)         (((hevent_t*)(ev))->loop)
+#define hevent_type(ev)         (((hevent_t*)(ev))->event_type)
+#define hevent_id(ev)           (((hevent_t*)(ev))->event_id)
+#define hevent_priority(ev)     (((hevent_t*)(ev))->priority)
+#define hevent_userdata(ev)     (((hevent_t*)(ev))->userdata)
 
 typedef enum {
     HIO_TYPE_UNKNOWN = 0,
@@ -117,94 +83,24 @@ typedef enum {
     HIO_TYPE_SOCKET  = 0x00FFFF00,
 } hio_type_e;
 
-struct hio_s {
-    HEVENT_FIELDS
-    unsigned    ready       :1;
-    unsigned    closed      :1;
-    unsigned    accept      :1;
-    unsigned    connect     :1;
-    unsigned    connectex   :1; // for ConnectEx/DisconnectEx
-    unsigned    recv        :1;
-    unsigned    send        :1;
-    unsigned    recvfrom    :1;
-    unsigned    sendto      :1;
-    int         fd;
-    hio_type_e  io_type;
-    int         error;
-    int         events;
-    int         revents;
-    struct sockaddr*    localaddr;
-    struct sockaddr*    peeraddr;
-    hbuf_t              readbuf;        // for hread
-    struct write_queue  write_queue;    // for hwrite
-    // callbacks
-    hread_cb    read_cb;
-    hwrite_cb   write_cb;
-    hclose_cb   close_cb;
-    haccept_cb  accept_cb;
-    hconnect_cb connect_cb;
-//private:
-    int         event_index[2]; // for poll,kqueue
-    void*       hovlp;          // for iocp/overlapio
-    void*       ssl;            // for SSL
-};
-
-typedef enum {
-    HLOOP_STATUS_STOP,
-    HLOOP_STATUS_RUNNING,
-    HLOOP_STATUS_PAUSE
-} hloop_status_e;
-
-ARRAY_DECL(hio_t*, io_array);
-
-struct hloop_s {
-    hloop_status_e status;
-    time_t      start_time;
-    // hrtime: us
-    uint64_t    start_hrtime;
-    uint64_t    end_hrtime;
-    uint64_t    cur_hrtime;
-    uint64_t    loop_cnt;
-    void*       userdata;
-//private:
-    // events
-    uint64_t                    event_counter;
-    uint32_t                    nactives;
-    uint32_t                    npendings;
-    // pendings: with priority as array.index
-    hevent_t*                   pendings[HEVENT_PRIORITY_SIZE];
-    // idles
-    struct list_head            idles;
-    uint32_t                    nidles;
-    // timers
-    struct heap                 timers;
-    uint32_t                    ntimers;
-    // ios: with fd as array.index
-    struct io_array             ios;
-    uint32_t                    nios;
-    void*                       iowatcher;
-};
-
 // loop
-int hloop_init(hloop_t* loop);
-//void hloop_cleanup(hloop_t* loop);
+#define HLOOP_FLAG_RUN_ONCE    0x00000001
+#define HLOOP_FLAG_AUTO_FREE   0x00000002
+hloop_t* hloop_new(int flags DEFAULT(HLOOP_FLAG_AUTO_FREE));
+// WARN: Not allow to call hloop_free when HLOOP_INIT_FLAG_AUTO_FREE set.
+void hloop_free(hloop_t** pp);
 // NOTE: when no active events, loop will quit.
 int hloop_run(hloop_t* loop);
 int hloop_stop(hloop_t* loop);
 int hloop_pause(hloop_t* loop);
 int hloop_resume(hloop_t* loop);
 
-static inline void hloop_update_time(hloop_t* loop) {
-    loop->cur_hrtime = gethrtime();
-}
+void     hloop_update_time(hloop_t* loop);
+time_t   hloop_now(hloop_t* loop); // s
+uint64_t hloop_now_hrtime(hloop_t* loop); // us
 
-static inline time_t hloop_now(hloop_t* loop) {
-    return loop->start_time + (loop->cur_hrtime - loop->start_hrtime) / 1000000;
-}
-
-static inline uint64_t hloop_now_hrtime(hloop_t* loop) {
-    return loop->start_time*1e6 + (loop->cur_hrtime - loop->start_hrtime);
-}
+void  hloop_set_userdata(hloop_t* loop, void* userdata);
+void* hloop_userdata(hloop_t* loop);
 
 // idle
 hidle_t*    hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
@@ -229,7 +125,7 @@ void        htimer_del(htimer_t* timer);
 void        htimer_reset(htimer_t* timer);
 
 // io
-// low-level api
+//-----------------------low-level apis---------------------------------------
 #define READ_EVENT  0x0001
 #define WRITE_EVENT 0x0004
 #define ALL_EVENTS  READ_EVENT|WRITE_EVENT
@@ -237,37 +133,68 @@ hio_t* hio_get(hloop_t* loop, int fd);
 int    hio_add(hio_t* io, hio_cb cb, int events DEFAULT(READ_EVENT));
 int    hio_del(hio_t* io, int events DEFAULT(ALL_EVENTS));
 
-void hio_setlocaladdr(hio_t* io, struct sockaddr* addr, int addrlen);
-void hio_setpeeraddr (hio_t* io, struct sockaddr* addr, int addrlen);
+int hio_fd    (hio_t* io);
+int hio_error (hio_t* io);
+hio_type_e hio_type(hio_t* io);
+struct sockaddr* hio_localaddr(hio_t* io);
+struct sockaddr* hio_peeraddr (hio_t* io);
 
-// high-level api
+void hio_set_readbuf(hio_t* io, void* buf, size_t len);
+// ssl
+int  hio_enable_ssl(hio_t* io);
+
+void hio_setcb_accept   (hio_t* io, haccept_cb  accept_cb);
+void hio_setcb_connect  (hio_t* io, hconnect_cb connect_cb);
+void hio_setcb_read     (hio_t* io, hread_cb    read_cb);
+void hio_setcb_write    (hio_t* io, hwrite_cb   write_cb);
+void hio_setcb_close    (hio_t* io, hclose_cb   close_cb);
+
+// NOTE: don't forget to call hio_set_readbuf
+int hio_read   (hio_t* io);
+int hio_write  (hio_t* io, const void* buf, size_t len);
+int hio_close  (hio_t* io);
+int hio_accept (hio_t* io);
+int hio_connect(hio_t* io);
+
+//------------------high-level apis-------------------------------------------
+// hio_get -> hio_set_readbuf -> hio_setcb_read -> hio_read
 hio_t* hread    (hloop_t* loop, int fd, void* buf, size_t len, hread_cb read_cb);
+// hio_get -> hio_setcb_write -> hio_write
 hio_t* hwrite   (hloop_t* loop, int fd, const void* buf, size_t len, hwrite_cb write_cb DEFAULT(NULL));
-void   hclose   (hio_t* io);
+// hio_get -> hio_close
+void   hclose   (hloop_t* loop, int fd);
 
 // tcp
+// hio_get -> hio_setcb_accept -> hio_accept
 hio_t* haccept  (hloop_t* loop, int listenfd, haccept_cb accept_cb);
+// hio_get -> hio_setcb_connect -> hio_connect
 hio_t* hconnect (hloop_t* loop, int connfd,   hconnect_cb connect_cb);
+// hio_get -> hio_set_readbuf -> hio_setcb_read -> hio_read
 hio_t* hrecv    (hloop_t* loop, int connfd, void* buf, size_t len, hread_cb read_cb);
+// hio_get -> hio_setcb_write -> hio_write
 hio_t* hsend    (hloop_t* loop, int connfd, const void* buf, size_t len, hwrite_cb write_cb DEFAULT(NULL));
 
-// @tcp_server: socket -> bind -> listen -> haccept
-hio_t* create_tcp_server (hloop_t* loop, int port, haccept_cb accept_cb);
-// @tcp_client: resolver -> socket -> hio_get -> hio_setpeeraddr -> hconnect
-hio_t* create_tcp_client (hloop_t* loop, const char* host, int port, hconnect_cb connect_cb);
-
 // udp/ip
-// NOTE: recvfrom/sendto struct sockaddr* addr save in io->peeraddr
+// for HIO_TYPE_IP
+void hio_set_type(hio_t* io, hio_type_e type);
+void hio_set_localaddr(hio_t* io, struct sockaddr* addr, int addrlen);
+void hio_set_peeraddr (hio_t* io, struct sockaddr* addr, int addrlen);
+// NOTE: must call hio_set_peeraddr before hrecvfrom/hsendto
+// hio_get -> hio_set_readbuf -> hio_setcb_read -> hio_read
 hio_t* hrecvfrom (hloop_t* loop, int sockfd, void* buf, size_t len, hread_cb read_cb);
+// hio_get -> hio_setcb_write -> hio_write
 hio_t* hsendto   (hloop_t* loop, int sockfd, const void* buf, size_t len, hwrite_cb write_cb DEFAULT(NULL));
 
-// @udp_server: socket -> bind -> hio_get
-hio_t* create_udp_server(hloop_t* loop, int port);
-// @udp_client: resolver -> socket -> hio_get -> hio_setpeeraddr
-hio_t* create_udp_client(hloop_t* loop, const char* host, int port);
+//----------------- top-level apis---------------------------------------------
+// @tcp_server: socket -> bind -> listen -> haccept
+hio_t* create_tcp_server (hloop_t* loop, int port, haccept_cb accept_cb);
+// @tcp_client: resolver -> socket -> hio_get -> hio_set_peeraddr -> hconnect
+hio_t* create_tcp_client (hloop_t* loop, const char* host, int port, hconnect_cb connect_cb);
 
-// ssl
-int hio_enable_ssl(hio_t* io);
+// @udp_server: socket -> bind -> hio_get
+hio_t* create_udp_server (hloop_t* loop, int port);
+// @udp_client: resolver -> socket -> hio_get -> hio_set_peeraddr
+hio_t* create_udp_client (hloop_t* loop, const char* host, int port);
 
 END_EXTERN_C
 

+ 17 - 8
event/nio.c

@@ -1,6 +1,6 @@
 #include "iowatcher.h"
 #ifndef EVENT_IOCP
-#include "hio.h"
+#include "hevent.h"
 #include "hsocket.h"
 #include "hlog.h"
 
@@ -35,7 +35,7 @@ static void ssl_do_handshark(hio_t* io) {
         }
         else {
             hloge("ssl handshake failed: %d", errcode);
-            hclose(io);
+            hio_close(io);
         }
     }
 }
@@ -98,7 +98,7 @@ accept:
     goto accept;
 
 accept_error:
-    hclose(io);
+    hio_close(io);
 }
 
 static void nio_connect(hio_t* io) {
@@ -144,7 +144,7 @@ static void nio_connect(hio_t* io) {
     }
 
 connect_failed:
-    hclose(io);
+    hio_close(io);
 }
 
 static void nio_read(hio_t* io) {
@@ -205,7 +205,7 @@ read:
     return;
 read_error:
 disconnect:
-    hclose(io);
+    hio_close(io);
 }
 
 static void nio_write(hio_t* io) {
@@ -269,7 +269,7 @@ write:
     return;
 write_error:
 disconnect:
-    hclose(io);
+    hio_close(io);
 }
 
 static void hio_handle_events(hio_t* io) {
@@ -316,7 +316,7 @@ int hio_connect(hio_t* io) {
     if (ret < 0 && socket_errno() != EINPROGRESS) {
 #endif
         perror("connect");
-        hclose(io);
+        hio_close(io);
         return ret;
     }
     if (ret == 0) {
@@ -401,11 +401,15 @@ enqueue:
     return nwrite;
 write_error:
 disconnect:
-    hclose(io);
+    hio_close(io);
     return nwrite;
 }
 
 int hio_close (hio_t* io) {
+    printd("close fd=%d\n", io->fd);
+    if (io->closed) return 0;
+    io->closed = 1;
+    hio_del(io, ALL_EVENTS);
 #ifdef OS_UNIX
     close(io->fd);
 #else
@@ -416,6 +420,11 @@ int hio_close (hio_t* io) {
         SSL_free((SSL*)io->ssl);
     }
 #endif
+    if (io->close_cb) {
+        printd("close_cb------\n");
+        io->close_cb(io);
+        printd("close_cb======\n");
+    }
     return 0;
 }
 #endif

+ 14 - 11
event/nlog.c

@@ -2,6 +2,7 @@
 
 #include "list.h"
 #include "hdef.h"
+#include "hbase.h"
 #include "hsocket.h"
 
 typedef struct network_logger_s {
@@ -18,7 +19,7 @@ typedef struct nlog_client {
 static network_logger_t s_logger = {0};
 
 static void on_close(hio_t* io) {
-    printd("on_close fd=%d error=%d\n", io->fd, io->error);
+    printd("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
     struct list_node* next = s_logger.clients.next;
     nlog_client* client;
     while (next != &s_logger.clients) {
@@ -33,27 +34,29 @@ static void on_close(hio_t* io) {
 }
 
 static void on_read(hio_t* io, void* buf, int readbytes) {
-    printd("on_read fd=%d readbytes=%d\n", io->fd, readbytes);
+    printd("on_read fd=%d readbytes=%d\n", hio_fd(io), readbytes);
     printd("< %s\n", buf);
     // nothing to do
 }
 
-static void on_accept(hio_t* io, int connfd) {
-    printd("on_accept listenfd=%d connfd=%d\n", io->fd, connfd);
+static void on_accept(hio_t* io) {
+    printd("on_accept connfd=%d\n", hio_fd(io));
     char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
     char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
-    printd("accept listenfd=%d connfd=%d [%s] <= [%s]\n", io->fd, connfd,
-            sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
-            sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
+    printd("accept connfd=%d [%s] <= [%s]\n", hio_fd(io),
+            sockaddr_snprintf(hio_localaddr(io), localaddrstr, sizeof(localaddrstr)),
+            sockaddr_snprintf(hio_peeraddr(io), peeraddrstr, sizeof(peeraddrstr)));
 
     static char s_readbuf[256] = {0};
-    hio_t* connio = hread(io->loop, connfd, s_readbuf, sizeof(s_readbuf), on_read);
-    connio->close_cb = on_close;
+    hio_set_readbuf(io, s_readbuf, sizeof(s_readbuf));
+    hio_setcb_read(io, on_read);
+    hio_setcb_close(io, on_close);
+    hio_read(io);
 
     // free on_close
     nlog_client* client;
     SAFE_ALLOC_SIZEOF(client);
-    client->io = connio;
+    client->io = io;
     list_add(&client->node, &s_logger.clients);
 }
 
@@ -62,7 +65,7 @@ void network_logger(int loglevel, const char* buf, int len) {
     nlog_client* client;
     list_for_each (node, &s_logger.clients) {
         client = list_entry(node, nlog_client, node);
-        hwrite(s_logger.loop, client->io->fd, buf, len, NULL);
+        hio_write(client->io, buf, len);
     }
 }
 

+ 14 - 13
event/nmap.cpp

@@ -1,7 +1,8 @@
 #include "nmap.h"
 #include "hloop.h"
-#include "netinet.h"
+#include "hevent.h"
 #include "hstring.h"
+#include "netinet.h"
 
 #define MAX_RECVFROM_TIMEOUT    5000 // ms
 #define MAX_SENDTO_PERSOCKET    1024
@@ -52,9 +53,8 @@ static void on_recvfrom(hio_t* io, void* buf, int readbytes) {
 }
 
 int nmap_discovery(Nmap* nmap) {
-    hloop_t loop;
-    hloop_init(&loop);
-    uint64_t start_hrtime = hloop_now_hrtime(&loop);
+    hloop_t* loop = hloop_new(0);
+    uint64_t start_hrtime = hloop_now_hrtime(loop);
 
     nmap_udata_t udata;
     udata.nmap = nmap;
@@ -62,7 +62,7 @@ int nmap_discovery(Nmap* nmap) {
     udata.recv_cnt = 0;
     udata.up_cnt = 0;
     udata.idle_cnt = 0;
-    loop.userdata = &udata;
+    loop->userdata = &udata;
 
     char recvbuf[128];
     // icmp
@@ -93,15 +93,15 @@ int nmap_discovery(Nmap* nmap) {
             socklen_t optlen = sizeof(len);
             setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, (const char*)&len, optlen);
 
-            io = hio_get(&loop, sockfd);
+            io = hio_get(loop, sockfd);
             if (io == NULL) return -1;
             io->io_type = HIO_TYPE_IP;
             struct sockaddr_in localaddr;
             socklen_t addrlen = sizeof(localaddr);
             memset(&localaddr, 0, addrlen);
             localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
-            hio_setlocaladdr(io, (struct sockaddr*)&localaddr, addrlen);
-            hrecvfrom(&loop, sockfd, recvbuf, sizeof(recvbuf), on_recvfrom);
+            hio_set_localaddr(io, (struct sockaddr*)&localaddr, addrlen);
+            hrecvfrom(loop, sockfd, recvbuf, sizeof(recvbuf), on_recvfrom);
         }
         icmp_req->icmp_seq = iter->first;
         icmp_req->icmp_cksum = 0;
@@ -110,16 +110,17 @@ int nmap_discovery(Nmap* nmap) {
         memset(&peeraddr, 0, addrlen);
         peeraddr.sin_family = AF_INET;
         peeraddr.sin_addr.s_addr = iter->first;
-        hio_setpeeraddr(io, (struct sockaddr*)&peeraddr, addrlen);
+        hio_set_peeraddr(io, (struct sockaddr*)&peeraddr, addrlen);
         hsendto(io->loop, io->fd, sendbuf, sizeof(sendbuf), NULL);
         ++udata.send_cnt;
     }
 
-    htimer_add(&loop, on_timer, MAX_RECVFROM_TIMEOUT, 1);
-    hidle_add(&loop, on_idle, 3);
+    htimer_add(loop, on_timer, MAX_RECVFROM_TIMEOUT, 1);
+    hidle_add(loop, on_idle, 3);
 
-    hloop_run(&loop);
-    uint64_t end_hrtime = hloop_now_hrtime(&loop);
+    hloop_run(loop);
+    uint64_t end_hrtime = hloop_now_hrtime(loop);
+    hloop_free(&loop);
 
     // print result
     char ip[INET_ADDRSTRLEN];

+ 17 - 7
event/overlapio.c

@@ -3,6 +3,7 @@
 
 #ifdef EVENT_IOCP
 #include "overlapio.h"
+#include "hevent.h"
 
 #define ACCEPTEX_NUM    10
 
@@ -130,7 +131,7 @@ static void on_connectex_complete(hio_t* io) {
     io->error = hovlp->error;
     SAFE_FREE(io->hovlp);
     if (io->error != 0) {
-        hclose(io);
+        hio_close(io);
         return;
     }
     if (io->connect_cb) {
@@ -155,7 +156,7 @@ static void on_wsarecv_complete(hio_t* io) {
     hoverlapped_t* hovlp = (hoverlapped_t*)io->hovlp;
     if (hovlp->bytes == 0) {
         io->error = WSAGetLastError();
-        hclose(io);
+        hio_close(io);
         return;
     }
 
@@ -189,7 +190,7 @@ static void on_wsasend_complete(hio_t* io) {
     hoverlapped_t* hovlp = (hoverlapped_t*)io->hovlp;
     if (hovlp->bytes == 0) {
         io->error = WSAGetLastError();
-        hclose(io);
+        hio_close(io);
         goto end;
     }
     if (io->write_cb) {
@@ -282,7 +283,7 @@ int hio_connect (hio_t* io) {
     }
     return hio_add(io, hio_handle_events, WRITE_EVENT);
 error:
-    hclose(io);
+    hio_close(io);
     return 0;
 };
 
@@ -366,12 +367,15 @@ WSASend:
     }
 write_error:
 disconnect:
-    hclose(io);
+    hio_close(io);
     return 0;
 }
 
-void hio_close (hio_t* io) {
-    //printd("close fd=%d\n", io->fd);
+int hio_close (hio_t* io) {
+    printd("close fd=%d\n", io->fd);
+    if (io->closed) return 0;
+    io->closed = 1;
+    hio_del(io, ALL_EVENTS);
 #ifdef USE_DISCONNECTEX
     // DisconnectEx reuse socket
     if (io->connectex) {
@@ -399,6 +403,12 @@ void hio_close (hio_t* io) {
         SAFE_FREE(hovlp->addr);
         SAFE_FREE(io->hovlp);
     }
+    if (io->close_cb) {
+        printd("close_cb------\n");
+        io->close_cb(io);
+        printd("close_cb======\n");
+    }
+    return 0;
 }
 
 #endif

+ 16 - 15
examples/loop.c

@@ -15,12 +15,13 @@ void mylogger(int loglevel, const char* buf, int len) {
 }
 
 void on_idle(hidle_t* idle) {
-    printf("on_idle: event_id=%lu\tpriority=%d\tuserdata=%ld\n", idle->event_id, idle->priority, (long)idle->userdata);
+    printf("on_idle: event_id=%lu\tpriority=%d\tuserdata=%ld\n", hevent_id(idle), hevent_priority(idle), (long)(hevent_userdata(idle)));
 }
 
 void on_timer(htimer_t* timer) {
+    hloop_t* loop = hevent_loop(timer);
     printf("on_timer: event_id=%lu\tpriority=%d\tuserdata=%ld\ttime=%lus\thrtime=%luus\n",
-        timer->event_id, timer->priority, (long)timer->userdata, hloop_now(timer->loop), timer->loop->cur_hrtime);
+        hevent_id(timer), hevent_priority(timer), (long)(hevent_userdata(timer)), hloop_now(loop), hloop_now_hrtime(loop));
 }
 
 void cron_hourly(htimer_t* timer) {
@@ -37,10 +38,10 @@ void timer_write_log(htimer_t* timer) {
 }
 
 void on_stdin(hio_t* io, void* buf, int readbytes) {
-    printf("on_stdin fd=%d readbytes=%d\n", io->fd, readbytes);
+    printf("on_stdin fd=%d readbytes=%d\n", hio_fd(io), readbytes);
     printf("> %s\n", buf);
     if (strncmp((char*)buf, "quit", 4) == 0) {
-        hloop_stop(io->loop);
+        hloop_stop(hevent_loop(io));
     }
 }
 
@@ -48,36 +49,36 @@ int main() {
     // memcheck atexit
     MEMCHECK;
 
-    hloop_t loop;
-    hloop_init(&loop);
+    hloop_t* loop = hloop_new(0);
 
     // test idle and priority
     for (int i = HEVENT_LOWEST_PRIORITY; i <= HEVENT_HIGHEST_PRIORITY; ++i) {
-        hidle_t* idle = hidle_add(&loop, on_idle, 10);
-        idle->priority = i;
+        hidle_t* idle = hidle_add(loop, on_idle, 10);
+        hevent_set_priority(idle, i);
     }
 
     // test timer timeout
     for (int i = 1; i <= 10; ++i) {
-        htimer_t* timer = htimer_add(&loop, on_timer, i*1000, 3);
-        timer->userdata = (void*)i;
+        htimer_t* timer = htimer_add(loop, on_timer, i*1000, 3);
+        hevent_set_userdata(timer, i);
     }
 
     // test timer period
     int minute = time(NULL)%3600/60;
-    htimer_add_period(&loop, cron_hourly, minute+1, -1, -1, -1, -1, INFINITE);
+    htimer_add_period(loop, cron_hourly, minute+1, -1, -1, -1, -1, INFINITE);
 
     // test network_logger
-    htimer_add(&loop, timer_write_log, 1000, INFINITE);
+    htimer_add(loop, timer_write_log, 1000, INFINITE);
     hlog_set_logger(mylogger);
     hlog_set_file("loop.log");
-    nlog_listen(&loop, DEFAULT_LOG_PORT);
+    nlog_listen(loop, DEFAULT_LOG_PORT);
 
     // test nonblock stdin
     printf("input 'quit' to quit loop\n");
     char buf[64];
-    hread(&loop, STDIN_FILENO, buf, sizeof(buf), on_stdin);
+    hread(loop, STDIN_FILENO, buf, sizeof(buf), on_stdin);
 
-    hloop_run(&loop);
+    hloop_run(loop);
+    hloop_free(&loop);
     return 0;
 }

+ 22 - 25
examples/nc.c

@@ -18,47 +18,41 @@ hio_t*      sockio = NULL;
 int verbose = 0;
 
 void on_recv(hio_t* io, void* buf, int readbytes) {
-    //printf("on_recv fd=%d readbytes=%d\n", io->fd, readbytes);
+    //printf("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
     if (verbose) {
         char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
         char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
         printf("[%s] <=> [%s]\n",
-                sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
-                sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
+                sockaddr_snprintf(hio_localaddr(io), localaddrstr, sizeof(localaddrstr)),
+                sockaddr_snprintf(hio_peeraddr(io), peeraddrstr, sizeof(peeraddrstr)));
     }
     printf("%s", (char*)buf);
     fflush(stdout);
 }
 
 void on_stdin(hio_t* io, void* buf, int readbytes) {
-    //printf("on_stdin fd=%d readbytes=%d\n", io->fd, readbytes);
+    //printf("on_stdin fd=%d readbytes=%d\n", hio_fd(io), readbytes);
     //printf("> %s\n", buf);
 
-    if (protocol == 1) {
-        hsend(sockio->loop, sockio->fd, buf, readbytes, NULL);
-    }
-    else if (protocol == 2) {
-        hsendto(sockio->loop, sockio->fd, buf, readbytes, NULL);
-        hrecvfrom(sockio->loop, sockio->fd, recvbuf, RECV_BUFSIZE, on_recv);
-    }
+    hio_write(sockio, buf, readbytes);
 }
 
 void on_close(hio_t* io) {
-    //printf("on_close fd=%d error=%d\n", io->fd, io->error);
+    //printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
     hio_del(stdinio, READ_EVENT);
 }
 
 void on_connect(hio_t* io) {
-    //printf("on_connect fd=%d\n", io->fd, state);
+    //printf("on_connect fd=%d\n", hio_fd(io));
     if (verbose) {
         char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
         char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
-        printf("connect connfd=%d [%s] => [%s]\n", io->fd,
-                sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
-                sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
+        printf("connect connfd=%d [%s] => [%s]\n", hio_fd(io),
+                sockaddr_snprintf(hio_localaddr(io), localaddrstr, sizeof(localaddrstr)),
+                sockaddr_snprintf(hio_peeraddr(io), peeraddrstr, sizeof(peeraddrstr)));
     }
 
-    hrecv(io->loop, io->fd, recvbuf, RECV_BUFSIZE, on_recv);
+    hio_read(io);
 }
 
 int main(int argc, char** argv) {
@@ -94,11 +88,10 @@ Examples: nc 127.0.0.1 80\n\
 
     MEMCHECK;
 
-    hloop_t loop;
-    hloop_init(&loop);
+    hloop_t* loop = hloop_new(0);
 
     // stdin
-    stdinio = hread(&loop, 0, recvbuf, RECV_BUFSIZE, on_stdin);
+    stdinio = hread(loop, 0, recvbuf, RECV_BUFSIZE, on_stdin);
     if (stdinio == NULL) {
         return -20;
     }
@@ -106,19 +99,23 @@ Examples: nc 127.0.0.1 80\n\
     // socket
     if (protocol == 1) {
         // tcp
-        sockio = create_tcp_client(&loop, host, port, on_connect);
+        sockio = create_tcp_client(loop, host, port, on_connect);
     }
     else if (protocol == 2) {
         // udp
-        sockio = create_udp_client(&loop, host, port);
+        sockio = create_udp_client(loop, host, port);
+        hio_read(sockio);
     }
     if (sockio == NULL) {
         return -20;
     }
-    //printf("sockfd=%d\n", sockio->fd);
-    sockio->close_cb = on_close;
+    //printf("sockfd=%d\n", hio_fd(sockio));
+    hio_setcb_close(sockio, on_close);
+    hio_setcb_read(sockio, on_recv);
+    hio_set_readbuf(sockio, recvbuf, RECV_BUFSIZE);
 
-    hloop_run(&loop);
+    hloop_run(loop);
+    hloop_free(&loop);
 
     return 0;
 }

+ 18 - 16
examples/tcp.c

@@ -5,32 +5,34 @@
 static char recvbuf[RECV_BUFSIZE];
 
 void on_close(hio_t* io) {
-    printf("on_close fd=%d error=%d\n", io->fd, io->error);
+    printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
 }
 
 void on_recv(hio_t* io, void* buf, int readbytes) {
-    printf("on_recv fd=%d readbytes=%d\n", io->fd, readbytes);
+    printf("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
     char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
     char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
     printf("[%s] <=> [%s]\n",
-            sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
-            sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
+            sockaddr_snprintf(hio_localaddr(io), localaddrstr, sizeof(localaddrstr)),
+            sockaddr_snprintf(hio_peeraddr(io), peeraddrstr, sizeof(peeraddrstr)));
     printf("< %s\n", buf);
     // echo
     printf("> %s\n", buf);
-    hsend(io->loop, io->fd, buf, readbytes, NULL);
+    hio_write(io, buf, readbytes);
 }
 
 void on_accept(hio_t* io) {
-    printf("on_accept connfd=%d\n", io->fd);
+    printf("on_accept connfd=%d\n", hio_fd(io));
     char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
     char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
-    printf("accept connfd=%d [%s] <= [%s]\n", io->fd,
-            sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
-            sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
+    printf("accept connfd=%d [%s] <= [%s]\n", hio_fd(io),
+            sockaddr_snprintf(hio_localaddr(io), localaddrstr, sizeof(localaddrstr)),
+            sockaddr_snprintf(hio_peeraddr(io), peeraddrstr, sizeof(peeraddrstr)));
 
-    hrecv(io->loop, io->fd, recvbuf, RECV_BUFSIZE, on_recv);
-    io->close_cb = on_close;
+    hio_setcb_close(io, on_close);
+    hio_setcb_read(io, on_recv);
+    hio_set_readbuf(io, recvbuf, RECV_BUFSIZE);
+    hio_read(io);
 }
 
 int main(int argc, char** argv) {
@@ -40,13 +42,13 @@ int main(int argc, char** argv) {
     }
     int port = atoi(argv[1]);
 
-    hloop_t loop;
-    hloop_init(&loop);
-    hio_t* listenio = create_tcp_server(&loop, port, on_accept);
+    hloop_t* loop = hloop_new(0);
+    hio_t* listenio = create_tcp_server(loop, port, on_accept);
     if (listenio == NULL) {
         return -20;
     }
-    printf("listenfd=%d\n", listenio->fd);
-    hloop_run(&loop);
+    printf("listenfd=%d\n", hio_fd(listenio));
+    hloop_run(loop);
+    hloop_free(&loop);
     return 0;
 }

+ 21 - 21
examples/timer.c

@@ -2,59 +2,59 @@
 #include "hbase.h"
 
 void on_timer(htimer_t* timer) {
-    printf("time=%lus on_timer\n", hloop_now(timer->loop));
+    printf("time=%lus on_timer\n", hloop_now(hevent_loop(timer)));
 }
 
 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);
+    printf("time=%lus on_timer_add\n", hloop_now(hevent_loop(timer)));
+    htimer_add(hevent_loop(timer), on_timer_add, 1000, 1);
 }
 
 void on_timer_del(htimer_t* timer) {
-    printf("time=%lus on_timer_del\n", hloop_now(timer->loop));
+    printf("time=%lus on_timer_del\n", hloop_now(hevent_loop(timer)));
     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);
+    printf("time=%lus on_timer_reset\n", hloop_now(hevent_loop(timer)));
+    htimer_reset((htimer_t*)hevent_userdata(timer));
 }
 
 void on_timer_quit(htimer_t* timer) {
-    printf("time=%lus on_timer_quit\n", hloop_now(timer->loop));
-    hloop_stop(timer->loop);
+    printf("time=%lus on_timer_quit\n", hloop_now(hevent_loop(timer)));
+    hloop_stop(hevent_loop(timer));
 }
 
 void cron_hourly(htimer_t* timer) {
     time_t tt;
     time(&tt);
-    printf("time=%lus cron_hourly: %s\n", hloop_now(timer->loop), ctime(&tt));
+    printf("time=%lus cron_hourly: %s\n", hloop_now(hevent_loop(timer)), ctime(&tt));
 }
 
 int main() {
     MEMCHECK;
-    hloop_t loop;
-    hloop_init(&loop);
+    hloop_t* loop = hloop_new(0);
 
     // on_timer_add triggered forever
-    htimer_add(&loop, on_timer_add, 1000, 1);
+    htimer_add(loop, on_timer_add, 1000, 1);
     // on_timer_del triggered just once
-    htimer_add(&loop, on_timer_del, 1000, 10);
+    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;
+    htimer_t* reseted = htimer_add(loop, on_timer, 5000, 1);
+    htimer_t* reset = htimer_add(loop, on_timer_reset, 1000, 5);
+    hevent_set_userdata(reset, 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);
+    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);
+    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));
+    printf("time=%lus begin\n", hloop_now(loop));
+    hloop_run(loop);
+    printf("time=%lus stop\n", hloop_now(loop));
+    hloop_free(&loop);
     return 0;
 }

+ 13 - 11
examples/udp.c

@@ -5,20 +5,20 @@
 static char recvbuf[RECV_BUFSIZE];
 
 void on_close(hio_t* io) {
-    printf("on_close fd=%d error=%d\n", io->fd, io->error);
+    printf("on_close fd=%d error=%d\n", hio_fd(io), hio_error(io));
 }
 
 void on_recvfrom(hio_t* io, void* buf, int readbytes) {
-    printf("on_recvfrom fd=%d readbytes=%d\n", io->fd, readbytes);
+    printf("on_recvfrom fd=%d readbytes=%d\n", hio_fd(io), readbytes);
     char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
     char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
     printf("[%s] <=> [%s]\n",
-            sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
-            sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
+            sockaddr_snprintf(hio_localaddr(io), localaddrstr, sizeof(localaddrstr)),
+            sockaddr_snprintf(hio_peeraddr(io), peeraddrstr, sizeof(peeraddrstr)));
     printf("< %s\n", buf);
     // echo
     printf("> %s\n", buf);
-    hsendto(io->loop, io->fd, buf, readbytes, NULL);
+    hio_write(io, buf, readbytes);
 }
 
 int main(int argc, char** argv) {
@@ -28,14 +28,16 @@ int main(int argc, char** argv) {
     }
     int port = atoi(argv[1]);
 
-    hloop_t loop;
-    hloop_init(&loop);
-    hio_t* io = create_udp_server(&loop, port);
+    hloop_t* loop = hloop_new(0);
+    hio_t* io = create_udp_server(loop, port);
     if (io == NULL) {
         return -20;
     }
-    io->close_cb = on_close;
-    hrecvfrom(&loop, io->fd, recvbuf, RECV_BUFSIZE, on_recvfrom);
-    hloop_run(&loop);
+    hio_setcb_close(io, on_close);
+    hio_setcb_read(io, on_recvfrom);
+    hio_set_readbuf(io, recvbuf, RECV_BUFSIZE);
+    hio_read(io);
+    hloop_run(loop);
+    hloop_free(&loop);
     return 0;
 }

+ 0 - 20
h.h

@@ -5,7 +5,6 @@
  * @copyright 2018 HeWei, all rights reserved.
  */
 
-//-------------------base---------------------------
 // platform
 #include "hplatform.h"
 #include "hdef.h"
@@ -36,23 +35,4 @@
 #include "hthreadpool.h"
 #endif
 
-//--------------------utils-----------------------------
-#ifdef WITH_HW_UTILS
-#include "md5.h"
-#include "base64.h"
-#include "hbytearray.h"
-#include "hframe.h"
-#include "ifconfig.h"
-#include "iniparser.h"
-#include "json.hpp"
-#include "singleton.h"
-#include "htask.h"
-#include "task_queue.h"
-#endif
-
-//--------------------misc------------------------------
-#ifdef WITH_HW_MISC
-#include "win32_getopt.h"
-#endif
-
 #endif  // HW_H_

+ 4 - 4
http/server/HttpHandler.h

@@ -10,8 +10,8 @@
 #define HTTP_KEEPALIVE_TIMEOUT  75 // s
 
 static inline void on_keepalive_timeout(htimer_t* timer) {
-    hio_t* io = (hio_t*)timer->userdata;
-    hclose(io);
+    hio_t* io = (hio_t*)hevent_userdata(timer);
+    hio_close(io);
 }
 
 class HttpHandler {
@@ -55,8 +55,8 @@ public:
 
     void keepalive() {
         if (keepalive_timer == NULL) {
-            keepalive_timer = htimer_add(io->loop, on_keepalive_timeout, HTTP_KEEPALIVE_TIMEOUT*1000, 1);
-            keepalive_timer->userdata = io;
+            keepalive_timer = htimer_add(hevent_loop(io), on_keepalive_timeout, HTTP_KEEPALIVE_TIMEOUT*1000, 1);
+            hevent_set_userdata(keepalive_timer, io);
         }
         else {
             htimer_reset(keepalive_timer);

+ 32 - 30
http/server/http_server.cpp

@@ -37,14 +37,14 @@ static void worker_init(void* userdata) {
 }
 
 static void on_recv(hio_t* io, void* buf, int readbytes) {
-    //printf("on_recv fd=%d readbytes=%d\n", io->fd, readbytes);
-    HttpHandler* handler = (HttpHandler*)io->userdata;
+    //printf("on_recv fd=%d readbytes=%d\n", hio_fd(io), readbytes);
+    HttpHandler* handler = (HttpHandler*)hevent_userdata(io);
     HttpParser* parser = &handler->parser;
     // recv -> HttpParser -> HttpRequest -> handle_request -> HttpResponse -> send
     int nparse = parser->execute((char*)buf, readbytes);
     if (nparse != readbytes || parser->get_errno() != HPE_OK) {
         hloge("[%s:%d] http parser error: %s", handler->srcip, handler->srcport, http_errno_description(parser->get_errno()));
-        hclose(io);
+        hio_close(io);
         return;
     }
     if (parser->get_state() == HP_MESSAGE_COMPLETE) {
@@ -90,10 +90,10 @@ static void on_recv(hio_t* io, void* buf, int readbytes) {
             sendbuf.len = header.size();
         }
         // send header/body
-        hsend(io->loop, io->fd, sendbuf.base, sendbuf.len);
+        hio_write(io, sendbuf.base, sendbuf.len);
         if (send_in_one_packet == false) {
             // send body
-            hsend(io->loop, io->fd, handler->res.body.data(), handler->res.body.size());
+            hio_write(io, handler->res.body.data(), handler->res.body.size());
         }
 
         hlogi("[%s:%d][%s %s]=>[%d %s]",
@@ -106,45 +106,47 @@ static void on_recv(hio_t* io, void* buf, int readbytes) {
             handler->keepalive();
         }
         else {
-            hclose(io);
+            hio_close(io);
         }
     }
 }
 
 static void on_close(hio_t* io) {
-    HttpHandler* handler = (HttpHandler*)io->userdata;
+    HttpHandler* handler = (HttpHandler*)hevent_userdata(io);
     if (handler) {
         delete handler;
-        io->userdata = NULL;
+        hevent_set_userdata(io, NULL);
     }
 }
 
 static void on_accept(hio_t* io) {
-    //printf("on_accept connfd=%d\n", io->fd);
+    //printf("on_accept connfd=%d\n", hio_fd(io));
     /*
     char localaddrstr[INET6_ADDRSTRLEN+16] = {0};
     char peeraddrstr[INET6_ADDRSTRLEN+16] = {0};
-    printf("accept connfd=%d [%s] <= [%s]\n", io->fd,
-            sockaddr_snprintf(io->localaddr, localaddrstr, sizeof(localaddrstr)),
-            sockaddr_snprintf(io->peeraddr, peeraddrstr, sizeof(peeraddrstr)));
+    printf("accept connfd=%d [%s] <= [%s]\n", hio_fd(io),
+            sockaddr_snprintf(hio_localaddr(io), localaddrstr, sizeof(localaddrstr)),
+            sockaddr_snprintf(hio_peeraddr(io), peeraddrstr, sizeof(peeraddrstr)));
     */
 
-    HBuf* buf = (HBuf*)io->loop->userdata;
-    hrecv(io->loop, io->fd, buf->base, buf->len, on_recv);
-    io->close_cb = on_close;
+    HBuf* buf = (HBuf*)hloop_userdata(hevent_loop(io));
+    hio_setcb_close(io, on_close);
+    hio_setcb_read(io, on_recv);
+    hio_set_readbuf(io, buf->base, buf->len);
+    hio_read(io);
     // new HttpHandler
     // delete on_close
     HttpHandler* handler = new HttpHandler;
-    handler->service = (HttpService*)io->userdata;
+    handler->service = (HttpService*)hevent_userdata(io);
     handler->files = &s_filecache;
-    sockaddr_ntop(io->peeraddr, handler->srcip, sizeof(handler->srcip));
-    handler->srcport = sockaddr_htons(io->peeraddr);
+    sockaddr_ntop(hio_peeraddr(io), handler->srcip, sizeof(handler->srcip));
+    handler->srcport = sockaddr_htons(hio_peeraddr(io));
     handler->io = io;
-    io->userdata = handler;
+    hevent_set_userdata(io, handler);
 }
 
 static void handle_cached_files(htimer_t* timer) {
-    FileCache* pfc = (FileCache*)timer->userdata;
+    FileCache* pfc = (FileCache*)hevent_userdata(timer);
     if (pfc == NULL) {
         htimer_del(timer);
         return;
@@ -174,25 +176,25 @@ static hloop_t* s_loop = NULL;
 static void worker_proc(void* userdata) {
     http_server_t* server = (http_server_t*)userdata;
     int listenfd = server->listenfd;
-    hloop_t loop;
-    s_loop = &loop;
-    hloop_init(&loop);
+    hloop_t* loop = hloop_new(0);
+    s_loop = loop;
     // one loop one readbuf.
     HBuf readbuf;
     readbuf.resize(RECV_BUFSIZE);
-    loop.userdata = &readbuf;
-    hio_t* listenio = haccept(&loop, listenfd, on_accept);
-    listenio->userdata = server->service;
+    hloop_set_userdata(loop, &readbuf);
+    hio_t* listenio = haccept(loop, listenfd, on_accept);
+    hevent_set_userdata(listenio, server->service);
     if (server->ssl) {
         hio_enable_ssl(listenio);
     }
     // fflush logfile when idle
     hlog_set_fflush(0);
-    hidle_add(&loop, fflush_log, INFINITE);
+    hidle_add(loop, fflush_log, INFINITE);
     // timer handle_cached_files
-    htimer_t* timer = htimer_add(&loop, handle_cached_files, s_filecache.file_cached_time*1000);
-    timer->userdata = &s_filecache;
-    hloop_run(&loop);
+    htimer_t* timer = htimer_add(loop, handle_cached_files, s_filecache.file_cached_time*1000);
+    hevent_set_userdata(timer, &s_filecache);
+    hloop_run(loop);
+    hloop_free(&loop);
 }
 
 int http_server_run(http_server_t* server, int wait) {