| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294 |
- #ifndef HV_LOOP_H_
- #define HV_LOOP_H_
- #include "hexport.h"
- #include "hplatform.h"
- #include "hdef.h"
- typedef struct hloop_s hloop_t;
- typedef struct hevent_s hevent_t;
- // NOTE: The following structures are subclasses of hevent_t,
- // inheriting hevent_t data members and function members.
- typedef struct hidle_s hidle_t;
- typedef struct htimer_s htimer_t;
- typedef struct htimeout_s htimeout_t;
- typedef struct hperiod_s hperiod_t;
- typedef struct hio_s hio_t;
- typedef void (*hevent_cb) (hevent_t* ev);
- typedef void (*hidle_cb) (hidle_t* idle);
- typedef void (*htimer_cb) (htimer_t* timer);
- typedef void (*hio_cb) (hio_t* io);
- typedef void (*haccept_cb) (hio_t* io);
- typedef void (*hconnect_cb) (hio_t* io);
- typedef void (*hread_cb) (hio_t* io, void* buf, int readbytes);
- typedef void (*hwrite_cb) (hio_t* io, const void* buf, int writebytes);
- typedef void (*hclose_cb) (hio_t* io);
- typedef enum {
- HEVENT_TYPE_NONE = 0,
- HEVENT_TYPE_IO = 0x00000001,
- HEVENT_TYPE_TIMEOUT = 0x00000010,
- HEVENT_TYPE_PERIOD = 0x00000020,
- HEVENT_TYPE_TIMER = HEVENT_TYPE_TIMEOUT|HEVENT_TYPE_PERIOD,
- HEVENT_TYPE_IDLE = 0x00000100,
- HEVENT_TYPE_CUSTOM = 0x00000400, // 1024
- } hevent_type_e;
- #define HEVENT_LOWEST_PRIORITY (-5)
- #define HEVENT_LOW_PRIORITY (-3)
- #define HEVENT_NORMAL_PRIORITY 0
- #define HEVENT_HIGH_PRIORITY 3
- #define HEVENT_HIGHEST_PRIORITY 5
- #define HEVENT_PRIORITY_SIZE (HEVENT_HIGHEST_PRIORITY-HEVENT_LOWEST_PRIORITY+1)
- #define HEVENT_PRIORITY_INDEX(priority) (priority-HEVENT_LOWEST_PRIORITY)
- #define HEVENT_FLAGS \
- unsigned destroy :1; \
- unsigned active :1; \
- unsigned pending :1;
- #define HEVENT_FIELDS \
- hloop_t* loop; \
- hevent_type_e event_type; \
- uint64_t event_id; \
- hevent_cb cb; \
- void* userdata; \
- void* privdata; \
- int priority; \
- struct hevent_s* pending_next; \
- HEVENT_FLAGS
- struct hevent_s {
- HEVENT_FIELDS
- };
- #define hevent_set_priority(ev, prio) ((hevent_t*)(ev))->priority = prio
- #define hevent_set_userdata(ev, udata) ((hevent_t*)(ev))->userdata = (void*)udata
- #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,
- HIO_TYPE_STDIN = 0x00000001,
- HIO_TYPE_STDOUT = 0x00000002,
- HIO_TYPE_STDERR = 0x00000004,
- HIO_TYPE_STDIO = 0x0000000F,
- HIO_TYPE_FILE = 0x00000010,
- HIO_TYPE_IP = 0x00000100,
- HIO_TYPE_UDP = 0x00001000,
- HIO_TYPE_TCP = 0x00010000,
- HIO_TYPE_SSL = 0x00020000,
- HIO_TYPE_SOCKET = 0x00FFFF00,
- } hio_type_e;
- #define HIO_DEFAULT_CONNECT_TIMEOUT 5000 // ms
- #define HIO_DEFAULT_CLOSE_TIMEOUT 60000 // ms
- #define HIO_DEFAULT_KEEPALIVE_TIMEOUT 75000 // ms
- #define HIO_DEFAULT_HEARTBEAT_INTERVAL 3000 // ms
- BEGIN_EXTERN_C
- // loop
- #define HLOOP_FLAG_RUN_ONCE 0x00000001
- #define HLOOP_FLAG_AUTO_FREE 0x00000002
- #define HLOOP_FLAG_QUIT_WHEN_NO_ACTIVE_EVENTS 0x00000004
- HV_EXPORT hloop_t* hloop_new(int flags DEFAULT(HLOOP_FLAG_AUTO_FREE));
- // WARN: Forbid to call hloop_free if HLOOP_FLAG_AUTO_FREE set.
- HV_EXPORT void hloop_free(hloop_t** pp);
- // NOTE: when no active events, loop will quit if HLOOP_FLAG_QUIT_WHEN_NO_ACTIVE_EVENTS set.
- HV_EXPORT int hloop_run(hloop_t* loop);
- // NOTE: hloop_stop called in loop-thread just set flag to quit in next loop,
- // if called in other thread, it will wakeup loop-thread from blocking poll system call,
- // then you should join loop thread to safely exit loop thread.
- HV_EXPORT int hloop_stop(hloop_t* loop);
- HV_EXPORT int hloop_pause(hloop_t* loop);
- HV_EXPORT int hloop_resume(hloop_t* loop);
- HV_EXPORT int hloop_wakeup(hloop_t* loop);
- HV_EXPORT void hloop_update_time(hloop_t* loop);
- HV_EXPORT uint64_t hloop_now(hloop_t* loop); // s
- HV_EXPORT uint64_t hloop_now_ms(hloop_t* loop); // ms
- HV_EXPORT uint64_t hloop_now_hrtime(hloop_t* loop); // us
- #define hloop_now_us hloop_now_hrtime
- // @return pid of hloop_run
- HV_EXPORT long hloop_pid(hloop_t* loop);
- // @return tid of hloop_run
- HV_EXPORT long hloop_tid(hloop_t* loop);
- // userdata
- HV_EXPORT void hloop_set_userdata(hloop_t* loop, void* userdata);
- HV_EXPORT void* hloop_userdata(hloop_t* loop);
- // custom_event
- /*
- * hevent_t ev;
- * memset(&ev, 0, sizeof(hevent_t));
- * ev.event_type = (hevent_type_e)(HEVENT_TYPE_CUSTOM + 1);
- * ev.cb = custom_event_cb;
- * ev.userdata = userdata;
- * hloop_post_event(loop, &ev);
- */
- // NOTE: hloop_post_event is thread-safe
- HV_EXPORT void hloop_post_event(hloop_t* loop, hevent_t* ev);
- // idle
- HV_EXPORT hidle_t* hidle_add(hloop_t* loop, hidle_cb cb, uint32_t repeat DEFAULT(INFINITE));
- HV_EXPORT void hidle_del(hidle_t* idle);
- // timer
- // @param timeout: unit(ms)
- HV_EXPORT htimer_t* htimer_add(hloop_t* loop, htimer_cb cb, uint32_t timeout, uint32_t repeat DEFAULT(INFINITE));
- /*
- * minute hour day week month cb
- * 0~59 0~23 1~31 0~6 1~12
- * 30 -1 -1 -1 -1 cron.hourly
- * 30 1 -1 -1 -1 cron.daily
- * 30 1 15 -1 -1 cron.monthly
- * 30 1 -1 5 -1 cron.weekly
- * 30 1 1 -1 10 cron.yearly
- */
- HV_EXPORT htimer_t* htimer_add_period(hloop_t* loop, htimer_cb cb,
- int8_t minute DEFAULT(0), int8_t hour DEFAULT(-1), int8_t day DEFAULT(-1),
- int8_t week DEFAULT(-1), int8_t month DEFAULT(-1), uint32_t repeat DEFAULT(INFINITE));
- HV_EXPORT void htimer_del(htimer_t* timer);
- HV_EXPORT void htimer_reset(htimer_t* timer);
- // io
- //-----------------------low-level apis---------------------------------------
- #define HV_READ 0x0001
- #define HV_WRITE 0x0004
- #define HV_RDWR (HV_READ|HV_WRITE)
- /*
- const char* hio_engine() {
- #ifdef EVENT_SELECT
- return "select";
- #elif defined(EVENT_POLL)
- return "poll";
- #elif defined(EVENT_EPOLL)
- return "epoll";
- #elif defined(EVENT_KQUEUE)
- return "kqueue";
- #elif defined(EVENT_IOCP)
- return "iocp";
- #elif defined(EVENT_PORT)
- return "evport";
- #else
- return "noevent";
- #endif
- }
- */
- HV_EXPORT const char* hio_engine();
- HV_EXPORT hio_t* hio_get(hloop_t* loop, int fd);
- HV_EXPORT int hio_add(hio_t* io, hio_cb cb, int events DEFAULT(HV_READ));
- HV_EXPORT int hio_del(hio_t* io, int events DEFAULT(HV_RDWR));
- // hio_t fields
- HV_EXPORT int hio_fd (hio_t* io);
- HV_EXPORT int hio_error (hio_t* io);
- HV_EXPORT hio_type_e hio_type(hio_t* io);
- HV_EXPORT struct sockaddr* hio_localaddr(hio_t* io);
- HV_EXPORT struct sockaddr* hio_peeraddr (hio_t* io);
- // set callbacks
- HV_EXPORT void hio_setcb_accept (hio_t* io, haccept_cb accept_cb);
- HV_EXPORT void hio_setcb_connect (hio_t* io, hconnect_cb connect_cb);
- HV_EXPORT void hio_setcb_read (hio_t* io, hread_cb read_cb);
- HV_EXPORT void hio_setcb_write (hio_t* io, hwrite_cb write_cb);
- HV_EXPORT void hio_setcb_close (hio_t* io, hclose_cb close_cb);
- // some useful settings
- // Enable SSL/TLS is so easy :)
- HV_EXPORT int hio_enable_ssl(hio_t* io);
- // TODO: One loop per thread, one readbuf per loop.
- // But you can pass in your own readbuf instead of the default readbuf to avoid memcopy.
- HV_EXPORT void hio_set_readbuf(hio_t* io, void* buf, size_t len);
- // connect timeout => hclose_cb
- HV_EXPORT void hio_set_connect_timeout(hio_t* io, int timeout_ms DEFAULT(HIO_DEFAULT_CONNECT_TIMEOUT));
- // close timeout => hclose_cb
- HV_EXPORT void hio_set_close_timeout(hio_t* io, int timeout_ms DEFAULT(HIO_DEFAULT_CLOSE_TIMEOUT));
- // keepalive timeout => hclose_cb
- HV_EXPORT void hio_set_keepalive_timeout(hio_t* io, int timeout_ms DEFAULT(HIO_DEFAULT_KEEPALIVE_TIMEOUT));
- /*
- void send_heartbeat(hio_t* io) {
- static char buf[] = "PING\r\n";
- hio_write(io, buf, 6);
- }
- hio_set_heartbeat(io, 3000, send_heartbeat);
- */
- typedef void (*hio_send_heartbeat_fn)(hio_t* io);
- // heartbeat interval => hio_send_heartbeat_fn
- HV_EXPORT void hio_set_heartbeat(hio_t* io, int interval_ms, hio_send_heartbeat_fn fn);
- // Nonblocking, poll IO events in the loop to call corresponding callback.
- // hio_add(io, HV_READ) => accept => haccept_cb
- HV_EXPORT int hio_accept (hio_t* io);
- // connect => hio_add(io, HV_WRITE) => hconnect_cb
- HV_EXPORT int hio_connect(hio_t* io);
- // hio_add(io, HV_READ) => read => hread_cb
- HV_EXPORT int hio_read (hio_t* io);
- #define hio_read_start(io) hio_read(io)
- #define hio_read_stop(io) hio_del(io, HV_READ)
- // hio_try_write => hio_add(io, HV_WRITE) => write => hwrite_cb
- HV_EXPORT int hio_write (hio_t* io, const void* buf, size_t len);
- // hio_del(io, HV_RDWR) => close => hclose_cb
- HV_EXPORT int hio_close (hio_t* io);
- //------------------high-level apis-------------------------------------------
- // hio_get -> hio_set_readbuf -> hio_setcb_read -> hio_read
- HV_EXPORT hio_t* hread (hloop_t* loop, int fd, void* buf, size_t len, hread_cb read_cb);
- // hio_get -> hio_setcb_write -> hio_write
- HV_EXPORT hio_t* hwrite (hloop_t* loop, int fd, const void* buf, size_t len, hwrite_cb write_cb DEFAULT(NULL));
- // hio_get -> hio_close
- HV_EXPORT void hclose (hloop_t* loop, int fd);
- // tcp
- // hio_get -> hio_setcb_accept -> hio_accept
- HV_EXPORT hio_t* haccept (hloop_t* loop, int listenfd, haccept_cb accept_cb);
- // hio_get -> hio_setcb_connect -> hio_connect
- HV_EXPORT hio_t* hconnect (hloop_t* loop, int connfd, hconnect_cb connect_cb);
- // hio_get -> hio_set_readbuf -> hio_setcb_read -> hio_read
- HV_EXPORT hio_t* hrecv (hloop_t* loop, int connfd, void* buf, size_t len, hread_cb read_cb);
- // hio_get -> hio_setcb_write -> hio_write
- HV_EXPORT hio_t* hsend (hloop_t* loop, int connfd, const void* buf, size_t len, hwrite_cb write_cb DEFAULT(NULL));
- // udp
- HV_EXPORT void hio_set_type(hio_t* io, hio_type_e type);
- HV_EXPORT void hio_set_localaddr(hio_t* io, struct sockaddr* addr, int addrlen);
- HV_EXPORT 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
- HV_EXPORT hio_t* hrecvfrom (hloop_t* loop, int sockfd, void* buf, size_t len, hread_cb read_cb);
- // hio_get -> hio_setcb_write -> hio_write
- HV_EXPORT hio_t* hsendto (hloop_t* loop, int sockfd, const void* buf, size_t len, hwrite_cb write_cb DEFAULT(NULL));
- //----------------- top-level apis---------------------------------------------
- // @tcp_server: socket -> bind -> listen -> haccept
- // @see examples/tcp.c
- HV_EXPORT hio_t* hloop_create_tcp_server (hloop_t* loop, const char* host, int port, haccept_cb accept_cb);
- // @tcp_client: resolver -> socket -> hio_get -> hio_set_peeraddr -> hconnect
- // @see examples/nc.c
- HV_EXPORT hio_t* hloop_create_tcp_client (hloop_t* loop, const char* host, int port, hconnect_cb connect_cb);
- // @udp_server: socket -> bind -> hio_get
- // @see examples/udp.c
- HV_EXPORT hio_t* hloop_create_udp_server (hloop_t* loop, const char* host, int port);
- // @udp_client: resolver -> socket -> hio_get -> hio_set_peeraddr
- // @see examples/nc.c
- HV_EXPORT hio_t* hloop_create_udp_client (hloop_t* loop, const char* host, int port);
- END_EXTERN_C
- #endif // HV_LOOP_H_
|