1 
2 
3 #ifndef __LIBGSOCKET_SELECT_H__
4 #define __LIBGSOCKET_SELECT_H__ 1
5 
6 
7 struct _gs_sel_item
8 {
9 	int (*func)(void *ctx, int fd, void *cb_arg, int cb_val);
10 	void *cb_arg;
11 	int cb_val;
12 };
13 
14 enum bfunc_state {GS_CALLREAD = 0x01, GS_CALLWRITE = 0x02};
15 typedef struct _gs_select_ctx
16 {
17 	int max_fd;
18 	fd_set *rfd;
19 	fd_set *wfd;
20 	fd_set *r;
21 	fd_set *w;
22 	struct timeval tv;
23 	struct timeval *tv_now;
24 
25 	struct _gs_sel_item mgr_r[FD_SETSIZE];
26 	struct _gs_sel_item mgr_w[FD_SETSIZE];
27 
28 	enum bfunc_state blocking_func[FD_SETSIZE];
29 	int saved_rw_state[FD_SETSIZE];		/* 0 == not saved. 1 = READ, 2 = WRITE, 3 = R&W */
30 	int is_rw_state_saved[FD_SETSIZE];
31 	int want_io_write[FD_SETSIZE];
32 	int want_io_read[FD_SETSIZE];
33 
34 	int rdata_pending[FD_SETSIZE];
35 	int rdata_pending_count;
36 
37 	GS_EVENT_MGR emgr; // Event Manager (for Heartbeat)
38 	GS_EVENT hb;       // Heatbeat timeout; return control to caller
39 } GS_SELECT_CTX;
40 
41 typedef int (*gselect_cb_t)(GS_SELECT_CTX *ctx, int fd, void *arg, int val);
42 
43 int GS_SELECT_CTX_init(GS_SELECT_CTX *ctx, fd_set *rfd, fd_set *wfd, fd_set *r, fd_set *w, struct timeval *tv_now, int frequency);
44 int GS_select(GS_SELECT_CTX *ctx);
45 void GS_SELECT_add_cb_r(GS_SELECT_CTX *ctx, gselect_cb_t func, int fd, void *arg, int val);
46 void GS_SELECT_add_cb_w(GS_SELECT_CTX *ctx, gselect_cb_t func, int fd, void *arg, int val);
47 void GS_SELECT_add_cb(GS_SELECT_CTX *ctx, gselect_cb_t func_r, gselect_cb_t func_w, int fd, void *arg, int val);
48 void GS_SELECT_add_cb_callagain(GS_SELECT_CTX *ctx, gselect_cb_t func_r, gselect_cb_t func_w, int fd, void *arg, int val);
49 void GS_SELECT_del_cb(GS_SELECT_CTX *ctx, int fd);
50 void GS_SELECT_del_cb_callagain(GS_SELECT_CTX *ctx, int fd);
51 
52 #define GS_SELECT_FD_CLR_R(ctx, fd)	do { \
53 	if ((ctx)->is_rw_state_saved[fd]) { ctx->saved_rw_state[fd] &= ~0x01; } \
54 	FD_CLR(fd, (ctx)->rfd); \
55 } while (0)
56 
57 #define GS_SELECT_FD_CLR_W(ctx, fd)	do { \
58 	if ((ctx)->is_rw_state_saved[fd]) { ctx->saved_rw_state[fd] &= ~0x02; } \
59 	FD_CLR(fd, (ctx)->wfd); \
60 } while (0)
61 
62 #define GS_SELECT_FD_SET_R(ctx, fd) do { \
63 	if ((ctx)->is_rw_state_saved[fd]) { \
64 		ctx->saved_rw_state[fd] |= 0x01; \
65 	} else { \
66 		XFD_SET(fd, (ctx)->rfd); \
67 	} \
68 } while (0)
69 
70 #define GS_SUCCESS			(0x00)
71 #define GS_ECALLAGAIN		(0x01)	// Return Error Likes to be calleda gain
72 #define GS_ERR_WAITING		-1		// Waiting for I/O
73 #define GS_ERR_FATAL		-2		// must exit (?)
74 #define GS_ERR_EOF			-3
75 #define GS_ERROR			-4
76 
77 #endif /* !__LIBGSOCKET_SELECT_H__ */
78