xref: /redis-3.2.3/deps/hiredis/adapters/libuv.h (revision 28f32c99)
1 #ifndef __HIREDIS_LIBUV_H__
2 #define __HIREDIS_LIBUV_H__
3 #include <uv.h>
4 #include "../hiredis.h"
5 #include "../async.h"
6 #include <string.h>
7 
8 typedef struct redisLibuvEvents {
9   redisAsyncContext* context;
10   uv_poll_t          handle;
11   int                events;
12 } redisLibuvEvents;
13 
14 int redisLibuvAttach(redisAsyncContext*, uv_loop_t*);
15 
redisLibuvPoll(uv_poll_t * handle,int status,int events)16 static void redisLibuvPoll(uv_poll_t* handle, int status, int events) {
17   redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
18 
19   if (status != 0) {
20     return;
21   }
22 
23   if (events & UV_READABLE) {
24     redisAsyncHandleRead(p->context);
25   }
26   if (events & UV_WRITABLE) {
27     redisAsyncHandleWrite(p->context);
28   }
29 }
30 
31 
redisLibuvAddRead(void * privdata)32 static void redisLibuvAddRead(void *privdata) {
33   redisLibuvEvents* p = (redisLibuvEvents*)privdata;
34 
35   p->events |= UV_READABLE;
36 
37   uv_poll_start(&p->handle, p->events, redisLibuvPoll);
38 }
39 
40 
redisLibuvDelRead(void * privdata)41 static void redisLibuvDelRead(void *privdata) {
42   redisLibuvEvents* p = (redisLibuvEvents*)privdata;
43 
44   p->events &= ~UV_READABLE;
45 
46   if (p->events) {
47     uv_poll_start(&p->handle, p->events, redisLibuvPoll);
48   } else {
49     uv_poll_stop(&p->handle);
50   }
51 }
52 
53 
redisLibuvAddWrite(void * privdata)54 static void redisLibuvAddWrite(void *privdata) {
55   redisLibuvEvents* p = (redisLibuvEvents*)privdata;
56 
57   p->events |= UV_WRITABLE;
58 
59   uv_poll_start(&p->handle, p->events, redisLibuvPoll);
60 }
61 
62 
redisLibuvDelWrite(void * privdata)63 static void redisLibuvDelWrite(void *privdata) {
64   redisLibuvEvents* p = (redisLibuvEvents*)privdata;
65 
66   p->events &= ~UV_WRITABLE;
67 
68   if (p->events) {
69     uv_poll_start(&p->handle, p->events, redisLibuvPoll);
70   } else {
71     uv_poll_stop(&p->handle);
72   }
73 }
74 
75 
on_close(uv_handle_t * handle)76 static void on_close(uv_handle_t* handle) {
77   redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
78 
79   free(p);
80 }
81 
82 
redisLibuvCleanup(void * privdata)83 static void redisLibuvCleanup(void *privdata) {
84   redisLibuvEvents* p = (redisLibuvEvents*)privdata;
85 
86   uv_close((uv_handle_t*)&p->handle, on_close);
87 }
88 
89 
redisLibuvAttach(redisAsyncContext * ac,uv_loop_t * loop)90 static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {
91   redisContext *c = &(ac->c);
92 
93   if (ac->ev.data != NULL) {
94     return REDIS_ERR;
95   }
96 
97   ac->ev.addRead  = redisLibuvAddRead;
98   ac->ev.delRead  = redisLibuvDelRead;
99   ac->ev.addWrite = redisLibuvAddWrite;
100   ac->ev.delWrite = redisLibuvDelWrite;
101   ac->ev.cleanup  = redisLibuvCleanup;
102 
103   redisLibuvEvents* p = (redisLibuvEvents*)malloc(sizeof(*p));
104 
105   if (!p) {
106     return REDIS_ERR;
107   }
108 
109   memset(p, 0, sizeof(*p));
110 
111   if (uv_poll_init(loop, &p->handle, c->fd) != 0) {
112     return REDIS_ERR;
113   }
114 
115   ac->ev.data    = p;
116   p->handle.data = p;
117   p->context     = ac;
118 
119   return REDIS_OK;
120 }
121 #endif
122