summaryrefslogtreecommitdiff
path: root/examples/redis-unstable/deps/hiredis/adapters
diff options
context:
space:
mode:
authorMitja Felicijan <mitja.felicijan@gmail.com>2026-01-21 22:40:55 +0100
committerMitja Felicijan <mitja.felicijan@gmail.com>2026-01-21 22:40:55 +0100
commit5d8dfe892a2ea89f706ee140c3bdcfd89fe03fda (patch)
tree1acdfa5220cd13b7be43a2a01368e80d306473ca /examples/redis-unstable/deps/hiredis/adapters
parentc7ab12bba64d9c20ccd79b132dac475f7bc3923e (diff)
downloadcrep-5d8dfe892a2ea89f706ee140c3bdcfd89fe03fda.tar.gz
Add Redis source code for testing
Diffstat (limited to 'examples/redis-unstable/deps/hiredis/adapters')
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/ae.h130
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/glib.h156
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/ivykis.h84
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/libev.h188
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/libevent.h175
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/libhv.h123
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/libsdevent.h177
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/libuv.h171
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/macosx.h115
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/poll.h197
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/qt.h135
-rw-r--r--examples/redis-unstable/deps/hiredis/adapters/redismoduleapi.h144
12 files changed, 1795 insertions, 0 deletions
diff --git a/examples/redis-unstable/deps/hiredis/adapters/ae.h b/examples/redis-unstable/deps/hiredis/adapters/ae.h
new file mode 100644
index 0000000..660d82e
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/ae.h
@@ -0,0 +1,130 @@
1/*
2 * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of Redis nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without
16 * specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef __HIREDIS_AE_H__
32#define __HIREDIS_AE_H__
33#include <sys/types.h>
34#include <ae.h>
35#include "../hiredis.h"
36#include "../async.h"
37
38typedef struct redisAeEvents {
39 redisAsyncContext *context;
40 aeEventLoop *loop;
41 int fd;
42 int reading, writing;
43} redisAeEvents;
44
45static void redisAeReadEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
46 ((void)el); ((void)fd); ((void)mask);
47
48 redisAeEvents *e = (redisAeEvents*)privdata;
49 redisAsyncHandleRead(e->context);
50}
51
52static void redisAeWriteEvent(aeEventLoop *el, int fd, void *privdata, int mask) {
53 ((void)el); ((void)fd); ((void)mask);
54
55 redisAeEvents *e = (redisAeEvents*)privdata;
56 redisAsyncHandleWrite(e->context);
57}
58
59static void redisAeAddRead(void *privdata) {
60 redisAeEvents *e = (redisAeEvents*)privdata;
61 aeEventLoop *loop = e->loop;
62 if (!e->reading) {
63 e->reading = 1;
64 aeCreateFileEvent(loop,e->fd,AE_READABLE,redisAeReadEvent,e);
65 }
66}
67
68static void redisAeDelRead(void *privdata) {
69 redisAeEvents *e = (redisAeEvents*)privdata;
70 aeEventLoop *loop = e->loop;
71 if (e->reading) {
72 e->reading = 0;
73 aeDeleteFileEvent(loop,e->fd,AE_READABLE);
74 }
75}
76
77static void redisAeAddWrite(void *privdata) {
78 redisAeEvents *e = (redisAeEvents*)privdata;
79 aeEventLoop *loop = e->loop;
80 if (!e->writing) {
81 e->writing = 1;
82 aeCreateFileEvent(loop,e->fd,AE_WRITABLE,redisAeWriteEvent,e);
83 }
84}
85
86static void redisAeDelWrite(void *privdata) {
87 redisAeEvents *e = (redisAeEvents*)privdata;
88 aeEventLoop *loop = e->loop;
89 if (e->writing) {
90 e->writing = 0;
91 aeDeleteFileEvent(loop,e->fd,AE_WRITABLE);
92 }
93}
94
95static void redisAeCleanup(void *privdata) {
96 redisAeEvents *e = (redisAeEvents*)privdata;
97 redisAeDelRead(privdata);
98 redisAeDelWrite(privdata);
99 hi_free(e);
100}
101
102static int redisAeAttach(aeEventLoop *loop, redisAsyncContext *ac) {
103 redisContext *c = &(ac->c);
104 redisAeEvents *e;
105
106 /* Nothing should be attached when something is already attached */
107 if (ac->ev.data != NULL)
108 return REDIS_ERR;
109
110 /* Create container for context and r/w events */
111 e = (redisAeEvents*)hi_malloc(sizeof(*e));
112 if (e == NULL)
113 return REDIS_ERR;
114
115 e->context = ac;
116 e->loop = loop;
117 e->fd = c->fd;
118 e->reading = e->writing = 0;
119
120 /* Register functions to start/stop listening for events */
121 ac->ev.addRead = redisAeAddRead;
122 ac->ev.delRead = redisAeDelRead;
123 ac->ev.addWrite = redisAeAddWrite;
124 ac->ev.delWrite = redisAeDelWrite;
125 ac->ev.cleanup = redisAeCleanup;
126 ac->ev.data = e;
127
128 return REDIS_OK;
129}
130#endif
diff --git a/examples/redis-unstable/deps/hiredis/adapters/glib.h b/examples/redis-unstable/deps/hiredis/adapters/glib.h
new file mode 100644
index 0000000..ad59dd1
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/glib.h
@@ -0,0 +1,156 @@
1#ifndef __HIREDIS_GLIB_H__
2#define __HIREDIS_GLIB_H__
3
4#include <glib.h>
5
6#include "../hiredis.h"
7#include "../async.h"
8
9typedef struct
10{
11 GSource source;
12 redisAsyncContext *ac;
13 GPollFD poll_fd;
14} RedisSource;
15
16static void
17redis_source_add_read (gpointer data)
18{
19 RedisSource *source = (RedisSource *)data;
20 g_return_if_fail(source);
21 source->poll_fd.events |= G_IO_IN;
22 g_main_context_wakeup(g_source_get_context((GSource *)data));
23}
24
25static void
26redis_source_del_read (gpointer data)
27{
28 RedisSource *source = (RedisSource *)data;
29 g_return_if_fail(source);
30 source->poll_fd.events &= ~G_IO_IN;
31 g_main_context_wakeup(g_source_get_context((GSource *)data));
32}
33
34static void
35redis_source_add_write (gpointer data)
36{
37 RedisSource *source = (RedisSource *)data;
38 g_return_if_fail(source);
39 source->poll_fd.events |= G_IO_OUT;
40 g_main_context_wakeup(g_source_get_context((GSource *)data));
41}
42
43static void
44redis_source_del_write (gpointer data)
45{
46 RedisSource *source = (RedisSource *)data;
47 g_return_if_fail(source);
48 source->poll_fd.events &= ~G_IO_OUT;
49 g_main_context_wakeup(g_source_get_context((GSource *)data));
50}
51
52static void
53redis_source_cleanup (gpointer data)
54{
55 RedisSource *source = (RedisSource *)data;
56
57 g_return_if_fail(source);
58
59 redis_source_del_read(source);
60 redis_source_del_write(source);
61 /*
62 * It is not our responsibility to remove ourself from the
63 * current main loop. However, we will remove the GPollFD.
64 */
65 if (source->poll_fd.fd >= 0) {
66 g_source_remove_poll((GSource *)data, &source->poll_fd);
67 source->poll_fd.fd = -1;
68 }
69}
70
71static gboolean
72redis_source_prepare (GSource *source,
73 gint *timeout_)
74{
75 RedisSource *redis = (RedisSource *)source;
76 *timeout_ = -1;
77 return !!(redis->poll_fd.events & redis->poll_fd.revents);
78}
79
80static gboolean
81redis_source_check (GSource *source)
82{
83 RedisSource *redis = (RedisSource *)source;
84 return !!(redis->poll_fd.events & redis->poll_fd.revents);
85}
86
87static gboolean
88redis_source_dispatch (GSource *source,
89 GSourceFunc callback,
90 gpointer user_data)
91{
92 RedisSource *redis = (RedisSource *)source;
93
94 if ((redis->poll_fd.revents & G_IO_OUT)) {
95 redisAsyncHandleWrite(redis->ac);
96 redis->poll_fd.revents &= ~G_IO_OUT;
97 }
98
99 if ((redis->poll_fd.revents & G_IO_IN)) {
100 redisAsyncHandleRead(redis->ac);
101 redis->poll_fd.revents &= ~G_IO_IN;
102 }
103
104 if (callback) {
105 return callback(user_data);
106 }
107
108 return TRUE;
109}
110
111static void
112redis_source_finalize (GSource *source)
113{
114 RedisSource *redis = (RedisSource *)source;
115
116 if (redis->poll_fd.fd >= 0) {
117 g_source_remove_poll(source, &redis->poll_fd);
118 redis->poll_fd.fd = -1;
119 }
120}
121
122static GSource *
123redis_source_new (redisAsyncContext *ac)
124{
125 static GSourceFuncs source_funcs = {
126 .prepare = redis_source_prepare,
127 .check = redis_source_check,
128 .dispatch = redis_source_dispatch,
129 .finalize = redis_source_finalize,
130 };
131 redisContext *c = &ac->c;
132 RedisSource *source;
133
134 g_return_val_if_fail(ac != NULL, NULL);
135
136 source = (RedisSource *)g_source_new(&source_funcs, sizeof *source);
137 if (source == NULL)
138 return NULL;
139
140 source->ac = ac;
141 source->poll_fd.fd = c->fd;
142 source->poll_fd.events = 0;
143 source->poll_fd.revents = 0;
144 g_source_add_poll((GSource *)source, &source->poll_fd);
145
146 ac->ev.addRead = redis_source_add_read;
147 ac->ev.delRead = redis_source_del_read;
148 ac->ev.addWrite = redis_source_add_write;
149 ac->ev.delWrite = redis_source_del_write;
150 ac->ev.cleanup = redis_source_cleanup;
151 ac->ev.data = source;
152
153 return (GSource *)source;
154}
155
156#endif /* __HIREDIS_GLIB_H__ */
diff --git a/examples/redis-unstable/deps/hiredis/adapters/ivykis.h b/examples/redis-unstable/deps/hiredis/adapters/ivykis.h
new file mode 100644
index 0000000..179f6ab
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/ivykis.h
@@ -0,0 +1,84 @@
1#ifndef __HIREDIS_IVYKIS_H__
2#define __HIREDIS_IVYKIS_H__
3#include <iv.h>
4#include "../hiredis.h"
5#include "../async.h"
6
7typedef struct redisIvykisEvents {
8 redisAsyncContext *context;
9 struct iv_fd fd;
10} redisIvykisEvents;
11
12static void redisIvykisReadEvent(void *arg) {
13 redisAsyncContext *context = (redisAsyncContext *)arg;
14 redisAsyncHandleRead(context);
15}
16
17static void redisIvykisWriteEvent(void *arg) {
18 redisAsyncContext *context = (redisAsyncContext *)arg;
19 redisAsyncHandleWrite(context);
20}
21
22static void redisIvykisAddRead(void *privdata) {
23 redisIvykisEvents *e = (redisIvykisEvents*)privdata;
24 iv_fd_set_handler_in(&e->fd, redisIvykisReadEvent);
25}
26
27static void redisIvykisDelRead(void *privdata) {
28 redisIvykisEvents *e = (redisIvykisEvents*)privdata;
29 iv_fd_set_handler_in(&e->fd, NULL);
30}
31
32static void redisIvykisAddWrite(void *privdata) {
33 redisIvykisEvents *e = (redisIvykisEvents*)privdata;
34 iv_fd_set_handler_out(&e->fd, redisIvykisWriteEvent);
35}
36
37static void redisIvykisDelWrite(void *privdata) {
38 redisIvykisEvents *e = (redisIvykisEvents*)privdata;
39 iv_fd_set_handler_out(&e->fd, NULL);
40}
41
42static void redisIvykisCleanup(void *privdata) {
43 redisIvykisEvents *e = (redisIvykisEvents*)privdata;
44
45 iv_fd_unregister(&e->fd);
46 hi_free(e);
47}
48
49static int redisIvykisAttach(redisAsyncContext *ac) {
50 redisContext *c = &(ac->c);
51 redisIvykisEvents *e;
52
53 /* Nothing should be attached when something is already attached */
54 if (ac->ev.data != NULL)
55 return REDIS_ERR;
56
57 /* Create container for context and r/w events */
58 e = (redisIvykisEvents*)hi_malloc(sizeof(*e));
59 if (e == NULL)
60 return REDIS_ERR;
61
62 e->context = ac;
63
64 /* Register functions to start/stop listening for events */
65 ac->ev.addRead = redisIvykisAddRead;
66 ac->ev.delRead = redisIvykisDelRead;
67 ac->ev.addWrite = redisIvykisAddWrite;
68 ac->ev.delWrite = redisIvykisDelWrite;
69 ac->ev.cleanup = redisIvykisCleanup;
70 ac->ev.data = e;
71
72 /* Initialize and install read/write events */
73 IV_FD_INIT(&e->fd);
74 e->fd.fd = c->fd;
75 e->fd.handler_in = redisIvykisReadEvent;
76 e->fd.handler_out = redisIvykisWriteEvent;
77 e->fd.handler_err = NULL;
78 e->fd.cookie = e->context;
79
80 iv_fd_register(&e->fd);
81
82 return REDIS_OK;
83}
84#endif
diff --git a/examples/redis-unstable/deps/hiredis/adapters/libev.h b/examples/redis-unstable/deps/hiredis/adapters/libev.h
new file mode 100644
index 0000000..c59d3da
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/libev.h
@@ -0,0 +1,188 @@
1/*
2 * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of Redis nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without
16 * specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef __HIREDIS_LIBEV_H__
32#define __HIREDIS_LIBEV_H__
33#include <stdlib.h>
34#include <sys/types.h>
35#include <ev.h>
36#include "../hiredis.h"
37#include "../async.h"
38
39typedef struct redisLibevEvents {
40 redisAsyncContext *context;
41 struct ev_loop *loop;
42 int reading, writing;
43 ev_io rev, wev;
44 ev_timer timer;
45} redisLibevEvents;
46
47static void redisLibevReadEvent(EV_P_ ev_io *watcher, int revents) {
48#if EV_MULTIPLICITY
49 ((void)EV_A);
50#endif
51 ((void)revents);
52
53 redisLibevEvents *e = (redisLibevEvents*)watcher->data;
54 redisAsyncHandleRead(e->context);
55}
56
57static void redisLibevWriteEvent(EV_P_ ev_io *watcher, int revents) {
58#if EV_MULTIPLICITY
59 ((void)EV_A);
60#endif
61 ((void)revents);
62
63 redisLibevEvents *e = (redisLibevEvents*)watcher->data;
64 redisAsyncHandleWrite(e->context);
65}
66
67static void redisLibevAddRead(void *privdata) {
68 redisLibevEvents *e = (redisLibevEvents*)privdata;
69#if EV_MULTIPLICITY
70 struct ev_loop *loop = e->loop;
71#endif
72 if (!e->reading) {
73 e->reading = 1;
74 ev_io_start(EV_A_ &e->rev);
75 }
76}
77
78static void redisLibevDelRead(void *privdata) {
79 redisLibevEvents *e = (redisLibevEvents*)privdata;
80#if EV_MULTIPLICITY
81 struct ev_loop *loop = e->loop;
82#endif
83 if (e->reading) {
84 e->reading = 0;
85 ev_io_stop(EV_A_ &e->rev);
86 }
87}
88
89static void redisLibevAddWrite(void *privdata) {
90 redisLibevEvents *e = (redisLibevEvents*)privdata;
91#if EV_MULTIPLICITY
92 struct ev_loop *loop = e->loop;
93#endif
94 if (!e->writing) {
95 e->writing = 1;
96 ev_io_start(EV_A_ &e->wev);
97 }
98}
99
100static void redisLibevDelWrite(void *privdata) {
101 redisLibevEvents *e = (redisLibevEvents*)privdata;
102#if EV_MULTIPLICITY
103 struct ev_loop *loop = e->loop;
104#endif
105 if (e->writing) {
106 e->writing = 0;
107 ev_io_stop(EV_A_ &e->wev);
108 }
109}
110
111static void redisLibevStopTimer(void *privdata) {
112 redisLibevEvents *e = (redisLibevEvents*)privdata;
113#if EV_MULTIPLICITY
114 struct ev_loop *loop = e->loop;
115#endif
116 ev_timer_stop(EV_A_ &e->timer);
117}
118
119static void redisLibevCleanup(void *privdata) {
120 redisLibevEvents *e = (redisLibevEvents*)privdata;
121 redisLibevDelRead(privdata);
122 redisLibevDelWrite(privdata);
123 redisLibevStopTimer(privdata);
124 hi_free(e);
125}
126
127static void redisLibevTimeout(EV_P_ ev_timer *timer, int revents) {
128#if EV_MULTIPLICITY
129 ((void)EV_A);
130#endif
131 ((void)revents);
132 redisLibevEvents *e = (redisLibevEvents*)timer->data;
133 redisAsyncHandleTimeout(e->context);
134}
135
136static void redisLibevSetTimeout(void *privdata, struct timeval tv) {
137 redisLibevEvents *e = (redisLibevEvents*)privdata;
138#if EV_MULTIPLICITY
139 struct ev_loop *loop = e->loop;
140#endif
141
142 if (!ev_is_active(&e->timer)) {
143 ev_init(&e->timer, redisLibevTimeout);
144 e->timer.data = e;
145 }
146
147 e->timer.repeat = tv.tv_sec + tv.tv_usec / 1000000.00;
148 ev_timer_again(EV_A_ &e->timer);
149}
150
151static int redisLibevAttach(EV_P_ redisAsyncContext *ac) {
152 redisContext *c = &(ac->c);
153 redisLibevEvents *e;
154
155 /* Nothing should be attached when something is already attached */
156 if (ac->ev.data != NULL)
157 return REDIS_ERR;
158
159 /* Create container for context and r/w events */
160 e = (redisLibevEvents*)hi_calloc(1, sizeof(*e));
161 if (e == NULL)
162 return REDIS_ERR;
163
164 e->context = ac;
165#if EV_MULTIPLICITY
166 e->loop = EV_A;
167#else
168 e->loop = NULL;
169#endif
170 e->rev.data = e;
171 e->wev.data = e;
172
173 /* Register functions to start/stop listening for events */
174 ac->ev.addRead = redisLibevAddRead;
175 ac->ev.delRead = redisLibevDelRead;
176 ac->ev.addWrite = redisLibevAddWrite;
177 ac->ev.delWrite = redisLibevDelWrite;
178 ac->ev.cleanup = redisLibevCleanup;
179 ac->ev.scheduleTimer = redisLibevSetTimeout;
180 ac->ev.data = e;
181
182 /* Initialize read/write events */
183 ev_io_init(&e->rev,redisLibevReadEvent,c->fd,EV_READ);
184 ev_io_init(&e->wev,redisLibevWriteEvent,c->fd,EV_WRITE);
185 return REDIS_OK;
186}
187
188#endif
diff --git a/examples/redis-unstable/deps/hiredis/adapters/libevent.h b/examples/redis-unstable/deps/hiredis/adapters/libevent.h
new file mode 100644
index 0000000..73bb8ed
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/libevent.h
@@ -0,0 +1,175 @@
1/*
2 * Copyright (c) 2010-2011, Pieter Noordhuis <pcnoordhuis at gmail dot com>
3 *
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
8 *
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * * Neither the name of Redis nor the names of its contributors may be used
15 * to endorse or promote products derived from this software without
16 * specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 */
30
31#ifndef __HIREDIS_LIBEVENT_H__
32#define __HIREDIS_LIBEVENT_H__
33#include <event2/event.h>
34#include "../hiredis.h"
35#include "../async.h"
36
37#define REDIS_LIBEVENT_DELETED 0x01
38#define REDIS_LIBEVENT_ENTERED 0x02
39
40typedef struct redisLibeventEvents {
41 redisAsyncContext *context;
42 struct event *ev;
43 struct event_base *base;
44 struct timeval tv;
45 short flags;
46 short state;
47} redisLibeventEvents;
48
49static void redisLibeventDestroy(redisLibeventEvents *e) {
50 hi_free(e);
51}
52
53static void redisLibeventHandler(evutil_socket_t fd, short event, void *arg) {
54 ((void)fd);
55 redisLibeventEvents *e = (redisLibeventEvents*)arg;
56 e->state |= REDIS_LIBEVENT_ENTERED;
57
58 #define CHECK_DELETED() if (e->state & REDIS_LIBEVENT_DELETED) {\
59 redisLibeventDestroy(e);\
60 return; \
61 }
62
63 if ((event & EV_TIMEOUT) && (e->state & REDIS_LIBEVENT_DELETED) == 0) {
64 redisAsyncHandleTimeout(e->context);
65 CHECK_DELETED();
66 }
67
68 if ((event & EV_READ) && e->context && (e->state & REDIS_LIBEVENT_DELETED) == 0) {
69 redisAsyncHandleRead(e->context);
70 CHECK_DELETED();
71 }
72
73 if ((event & EV_WRITE) && e->context && (e->state & REDIS_LIBEVENT_DELETED) == 0) {
74 redisAsyncHandleWrite(e->context);
75 CHECK_DELETED();
76 }
77
78 e->state &= ~REDIS_LIBEVENT_ENTERED;
79 #undef CHECK_DELETED
80}
81
82static void redisLibeventUpdate(void *privdata, short flag, int isRemove) {
83 redisLibeventEvents *e = (redisLibeventEvents *)privdata;
84 const struct timeval *tv = e->tv.tv_sec || e->tv.tv_usec ? &e->tv : NULL;
85
86 if (isRemove) {
87 if ((e->flags & flag) == 0) {
88 return;
89 } else {
90 e->flags &= ~flag;
91 }
92 } else {
93 if (e->flags & flag) {
94 return;
95 } else {
96 e->flags |= flag;
97 }
98 }
99
100 event_del(e->ev);
101 event_assign(e->ev, e->base, e->context->c.fd, e->flags | EV_PERSIST,
102 redisLibeventHandler, privdata);
103 event_add(e->ev, tv);
104}
105
106static void redisLibeventAddRead(void *privdata) {
107 redisLibeventUpdate(privdata, EV_READ, 0);
108}
109
110static void redisLibeventDelRead(void *privdata) {
111 redisLibeventUpdate(privdata, EV_READ, 1);
112}
113
114static void redisLibeventAddWrite(void *privdata) {
115 redisLibeventUpdate(privdata, EV_WRITE, 0);
116}
117
118static void redisLibeventDelWrite(void *privdata) {
119 redisLibeventUpdate(privdata, EV_WRITE, 1);
120}
121
122static void redisLibeventCleanup(void *privdata) {
123 redisLibeventEvents *e = (redisLibeventEvents*)privdata;
124 if (!e) {
125 return;
126 }
127 event_del(e->ev);
128 event_free(e->ev);
129 e->ev = NULL;
130
131 if (e->state & REDIS_LIBEVENT_ENTERED) {
132 e->state |= REDIS_LIBEVENT_DELETED;
133 } else {
134 redisLibeventDestroy(e);
135 }
136}
137
138static void redisLibeventSetTimeout(void *privdata, struct timeval tv) {
139 redisLibeventEvents *e = (redisLibeventEvents *)privdata;
140 short flags = e->flags;
141 e->flags = 0;
142 e->tv = tv;
143 redisLibeventUpdate(e, flags, 0);
144}
145
146static int redisLibeventAttach(redisAsyncContext *ac, struct event_base *base) {
147 redisContext *c = &(ac->c);
148 redisLibeventEvents *e;
149
150 /* Nothing should be attached when something is already attached */
151 if (ac->ev.data != NULL)
152 return REDIS_ERR;
153
154 /* Create container for context and r/w events */
155 e = (redisLibeventEvents*)hi_calloc(1, sizeof(*e));
156 if (e == NULL)
157 return REDIS_ERR;
158
159 e->context = ac;
160
161 /* Register functions to start/stop listening for events */
162 ac->ev.addRead = redisLibeventAddRead;
163 ac->ev.delRead = redisLibeventDelRead;
164 ac->ev.addWrite = redisLibeventAddWrite;
165 ac->ev.delWrite = redisLibeventDelWrite;
166 ac->ev.cleanup = redisLibeventCleanup;
167 ac->ev.scheduleTimer = redisLibeventSetTimeout;
168 ac->ev.data = e;
169
170 /* Initialize and install read/write events */
171 e->ev = event_new(base, c->fd, EV_READ | EV_WRITE, redisLibeventHandler, e);
172 e->base = base;
173 return REDIS_OK;
174}
175#endif
diff --git a/examples/redis-unstable/deps/hiredis/adapters/libhv.h b/examples/redis-unstable/deps/hiredis/adapters/libhv.h
new file mode 100644
index 0000000..3b54c70
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/libhv.h
@@ -0,0 +1,123 @@
1#ifndef __HIREDIS_LIBHV_H__
2#define __HIREDIS_LIBHV_H__
3
4#include <hv/hloop.h>
5#include "../hiredis.h"
6#include "../async.h"
7
8typedef struct redisLibhvEvents {
9 hio_t *io;
10 htimer_t *timer;
11} redisLibhvEvents;
12
13static void redisLibhvHandleEvents(hio_t* io) {
14 redisAsyncContext* context = (redisAsyncContext*)hevent_userdata(io);
15 int events = hio_events(io);
16 int revents = hio_revents(io);
17 if (context && (events & HV_READ) && (revents & HV_READ)) {
18 redisAsyncHandleRead(context);
19 }
20 if (context && (events & HV_WRITE) && (revents & HV_WRITE)) {
21 redisAsyncHandleWrite(context);
22 }
23}
24
25static void redisLibhvAddRead(void *privdata) {
26 redisLibhvEvents* events = (redisLibhvEvents*)privdata;
27 hio_add(events->io, redisLibhvHandleEvents, HV_READ);
28}
29
30static void redisLibhvDelRead(void *privdata) {
31 redisLibhvEvents* events = (redisLibhvEvents*)privdata;
32 hio_del(events->io, HV_READ);
33}
34
35static void redisLibhvAddWrite(void *privdata) {
36 redisLibhvEvents* events = (redisLibhvEvents*)privdata;
37 hio_add(events->io, redisLibhvHandleEvents, HV_WRITE);
38}
39
40static void redisLibhvDelWrite(void *privdata) {
41 redisLibhvEvents* events = (redisLibhvEvents*)privdata;
42 hio_del(events->io, HV_WRITE);
43}
44
45static void redisLibhvCleanup(void *privdata) {
46 redisLibhvEvents* events = (redisLibhvEvents*)privdata;
47
48 if (events->timer)
49 htimer_del(events->timer);
50
51 hio_close(events->io);
52 hevent_set_userdata(events->io, NULL);
53
54 hi_free(events);
55}
56
57static void redisLibhvTimeout(htimer_t* timer) {
58 hio_t* io = (hio_t*)hevent_userdata(timer);
59 redisAsyncHandleTimeout((redisAsyncContext*)hevent_userdata(io));
60}
61
62static void redisLibhvSetTimeout(void *privdata, struct timeval tv) {
63 redisLibhvEvents* events;
64 uint32_t millis;
65 hloop_t* loop;
66
67 events = (redisLibhvEvents*)privdata;
68 millis = tv.tv_sec * 1000 + tv.tv_usec / 1000;
69
70 if (millis == 0) {
71 /* Libhv disallows zero'd timers so treat this as a delete or NO OP */
72 if (events->timer) {
73 htimer_del(events->timer);
74 events->timer = NULL;
75 }
76 } else if (events->timer == NULL) {
77 /* Add new timer */
78 loop = hevent_loop(events->io);
79 events->timer = htimer_add(loop, redisLibhvTimeout, millis, 1);
80 hevent_set_userdata(events->timer, events->io);
81 } else {
82 /* Update existing timer */
83 htimer_reset(events->timer, millis);
84 }
85}
86
87static int redisLibhvAttach(redisAsyncContext* ac, hloop_t* loop) {
88 redisContext *c = &(ac->c);
89 redisLibhvEvents *events;
90 hio_t* io = NULL;
91
92 if (ac->ev.data != NULL) {
93 return REDIS_ERR;
94 }
95
96 /* Create container struct to keep track of our io and any timer */
97 events = (redisLibhvEvents*)hi_malloc(sizeof(*events));
98 if (events == NULL) {
99 return REDIS_ERR;
100 }
101
102 io = hio_get(loop, c->fd);
103 if (io == NULL) {
104 hi_free(events);
105 return REDIS_ERR;
106 }
107
108 hevent_set_userdata(io, ac);
109
110 events->io = io;
111 events->timer = NULL;
112
113 ac->ev.addRead = redisLibhvAddRead;
114 ac->ev.delRead = redisLibhvDelRead;
115 ac->ev.addWrite = redisLibhvAddWrite;
116 ac->ev.delWrite = redisLibhvDelWrite;
117 ac->ev.cleanup = redisLibhvCleanup;
118 ac->ev.scheduleTimer = redisLibhvSetTimeout;
119 ac->ev.data = events;
120
121 return REDIS_OK;
122}
123#endif
diff --git a/examples/redis-unstable/deps/hiredis/adapters/libsdevent.h b/examples/redis-unstable/deps/hiredis/adapters/libsdevent.h
new file mode 100644
index 0000000..1268ed9
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/libsdevent.h
@@ -0,0 +1,177 @@
1#ifndef HIREDIS_LIBSDEVENT_H
2#define HIREDIS_LIBSDEVENT_H
3#include <systemd/sd-event.h>
4#include "../hiredis.h"
5#include "../async.h"
6
7#define REDIS_LIBSDEVENT_DELETED 0x01
8#define REDIS_LIBSDEVENT_ENTERED 0x02
9
10typedef struct redisLibsdeventEvents {
11 redisAsyncContext *context;
12 struct sd_event *event;
13 struct sd_event_source *fdSource;
14 struct sd_event_source *timerSource;
15 int fd;
16 short flags;
17 short state;
18} redisLibsdeventEvents;
19
20static void redisLibsdeventDestroy(redisLibsdeventEvents *e) {
21 if (e->fdSource) {
22 e->fdSource = sd_event_source_disable_unref(e->fdSource);
23 }
24 if (e->timerSource) {
25 e->timerSource = sd_event_source_disable_unref(e->timerSource);
26 }
27 sd_event_unref(e->event);
28 hi_free(e);
29}
30
31static int redisLibsdeventTimeoutHandler(sd_event_source *s, uint64_t usec, void *userdata) {
32 ((void)s);
33 ((void)usec);
34 redisLibsdeventEvents *e = (redisLibsdeventEvents*)userdata;
35 redisAsyncHandleTimeout(e->context);
36 return 0;
37}
38
39static int redisLibsdeventHandler(sd_event_source *s, int fd, uint32_t event, void *userdata) {
40 ((void)s);
41 ((void)fd);
42 redisLibsdeventEvents *e = (redisLibsdeventEvents*)userdata;
43 e->state |= REDIS_LIBSDEVENT_ENTERED;
44
45#define CHECK_DELETED() if (e->state & REDIS_LIBSDEVENT_DELETED) {\
46 redisLibsdeventDestroy(e);\
47 return 0; \
48 }
49
50 if ((event & EPOLLIN) && e->context && (e->state & REDIS_LIBSDEVENT_DELETED) == 0) {
51 redisAsyncHandleRead(e->context);
52 CHECK_DELETED();
53 }
54
55 if ((event & EPOLLOUT) && e->context && (e->state & REDIS_LIBSDEVENT_DELETED) == 0) {
56 redisAsyncHandleWrite(e->context);
57 CHECK_DELETED();
58 }
59
60 e->state &= ~REDIS_LIBSDEVENT_ENTERED;
61#undef CHECK_DELETED
62
63 return 0;
64}
65
66static void redisLibsdeventAddRead(void *userdata) {
67 redisLibsdeventEvents *e = (redisLibsdeventEvents*)userdata;
68
69 if (e->flags & EPOLLIN) {
70 return;
71 }
72
73 e->flags |= EPOLLIN;
74
75 if (e->flags & EPOLLOUT) {
76 sd_event_source_set_io_events(e->fdSource, e->flags);
77 } else {
78 sd_event_add_io(e->event, &e->fdSource, e->fd, e->flags, redisLibsdeventHandler, e);
79 }
80}
81
82static void redisLibsdeventDelRead(void *userdata) {
83 redisLibsdeventEvents *e = (redisLibsdeventEvents*)userdata;
84
85 e->flags &= ~EPOLLIN;
86
87 if (e->flags) {
88 sd_event_source_set_io_events(e->fdSource, e->flags);
89 } else {
90 e->fdSource = sd_event_source_disable_unref(e->fdSource);
91 }
92}
93
94static void redisLibsdeventAddWrite(void *userdata) {
95 redisLibsdeventEvents *e = (redisLibsdeventEvents*)userdata;
96
97 if (e->flags & EPOLLOUT) {
98 return;
99 }
100
101 e->flags |= EPOLLOUT;
102
103 if (e->flags & EPOLLIN) {
104 sd_event_source_set_io_events(e->fdSource, e->flags);
105 } else {
106 sd_event_add_io(e->event, &e->fdSource, e->fd, e->flags, redisLibsdeventHandler, e);
107 }
108}
109
110static void redisLibsdeventDelWrite(void *userdata) {
111 redisLibsdeventEvents *e = (redisLibsdeventEvents*)userdata;
112
113 e->flags &= ~EPOLLOUT;
114
115 if (e->flags) {
116 sd_event_source_set_io_events(e->fdSource, e->flags);
117 } else {
118 e->fdSource = sd_event_source_disable_unref(e->fdSource);
119 }
120}
121
122static void redisLibsdeventCleanup(void *userdata) {
123 redisLibsdeventEvents *e = (redisLibsdeventEvents*)userdata;
124
125 if (!e) {
126 return;
127 }
128
129 if (e->state & REDIS_LIBSDEVENT_ENTERED) {
130 e->state |= REDIS_LIBSDEVENT_DELETED;
131 } else {
132 redisLibsdeventDestroy(e);
133 }
134}
135
136static void redisLibsdeventSetTimeout(void *userdata, struct timeval tv) {
137 redisLibsdeventEvents *e = (redisLibsdeventEvents *)userdata;
138
139 uint64_t usec = tv.tv_sec * 1000000 + tv.tv_usec;
140 if (!e->timerSource) {
141 sd_event_add_time_relative(e->event, &e->timerSource, CLOCK_MONOTONIC, usec, 1, redisLibsdeventTimeoutHandler, e);
142 } else {
143 sd_event_source_set_time_relative(e->timerSource, usec);
144 }
145}
146
147static int redisLibsdeventAttach(redisAsyncContext *ac, struct sd_event *event) {
148 redisContext *c = &(ac->c);
149 redisLibsdeventEvents *e;
150
151 /* Nothing should be attached when something is already attached */
152 if (ac->ev.data != NULL)
153 return REDIS_ERR;
154
155 /* Create container for context and r/w events */
156 e = (redisLibsdeventEvents*)hi_calloc(1, sizeof(*e));
157 if (e == NULL)
158 return REDIS_ERR;
159
160 /* Initialize and increase event refcount */
161 e->context = ac;
162 e->event = event;
163 e->fd = c->fd;
164 sd_event_ref(event);
165
166 /* Register functions to start/stop listening for events */
167 ac->ev.addRead = redisLibsdeventAddRead;
168 ac->ev.delRead = redisLibsdeventDelRead;
169 ac->ev.addWrite = redisLibsdeventAddWrite;
170 ac->ev.delWrite = redisLibsdeventDelWrite;
171 ac->ev.cleanup = redisLibsdeventCleanup;
172 ac->ev.scheduleTimer = redisLibsdeventSetTimeout;
173 ac->ev.data = e;
174
175 return REDIS_OK;
176}
177#endif
diff --git a/examples/redis-unstable/deps/hiredis/adapters/libuv.h b/examples/redis-unstable/deps/hiredis/adapters/libuv.h
new file mode 100644
index 0000000..268edab
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/libuv.h
@@ -0,0 +1,171 @@
1#ifndef __HIREDIS_LIBUV_H__
2#define __HIREDIS_LIBUV_H__
3#include <stdlib.h>
4#include <uv.h>
5#include "../hiredis.h"
6#include "../async.h"
7#include <string.h>
8
9typedef struct redisLibuvEvents {
10 redisAsyncContext* context;
11 uv_poll_t handle;
12 uv_timer_t timer;
13 int events;
14} redisLibuvEvents;
15
16
17static void redisLibuvPoll(uv_poll_t* handle, int status, int events) {
18 redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
19 int ev = (status ? p->events : events);
20
21 if (p->context != NULL && (ev & UV_READABLE)) {
22 redisAsyncHandleRead(p->context);
23 }
24 if (p->context != NULL && (ev & UV_WRITABLE)) {
25 redisAsyncHandleWrite(p->context);
26 }
27}
28
29
30static void redisLibuvAddRead(void *privdata) {
31 redisLibuvEvents* p = (redisLibuvEvents*)privdata;
32
33 if (p->events & UV_READABLE) {
34 return;
35 }
36
37 p->events |= UV_READABLE;
38
39 uv_poll_start(&p->handle, p->events, redisLibuvPoll);
40}
41
42
43static void redisLibuvDelRead(void *privdata) {
44 redisLibuvEvents* p = (redisLibuvEvents*)privdata;
45
46 p->events &= ~UV_READABLE;
47
48 if (p->events) {
49 uv_poll_start(&p->handle, p->events, redisLibuvPoll);
50 } else {
51 uv_poll_stop(&p->handle);
52 }
53}
54
55
56static void redisLibuvAddWrite(void *privdata) {
57 redisLibuvEvents* p = (redisLibuvEvents*)privdata;
58
59 if (p->events & UV_WRITABLE) {
60 return;
61 }
62
63 p->events |= UV_WRITABLE;
64
65 uv_poll_start(&p->handle, p->events, redisLibuvPoll);
66}
67
68
69static void redisLibuvDelWrite(void *privdata) {
70 redisLibuvEvents* p = (redisLibuvEvents*)privdata;
71
72 p->events &= ~UV_WRITABLE;
73
74 if (p->events) {
75 uv_poll_start(&p->handle, p->events, redisLibuvPoll);
76 } else {
77 uv_poll_stop(&p->handle);
78 }
79}
80
81static void on_timer_close(uv_handle_t *handle) {
82 redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
83 p->timer.data = NULL;
84 if (!p->handle.data) {
85 // both timer and handle are closed
86 hi_free(p);
87 }
88 // else, wait for `on_handle_close`
89}
90
91static void on_handle_close(uv_handle_t *handle) {
92 redisLibuvEvents* p = (redisLibuvEvents*)handle->data;
93 p->handle.data = NULL;
94 if (!p->timer.data) {
95 // timer never started, or timer already destroyed
96 hi_free(p);
97 }
98 // else, wait for `on_timer_close`
99}
100
101// libuv removed `status` parameter since v0.11.23
102// see: https://github.com/libuv/libuv/blob/v0.11.23/include/uv.h
103#if (UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR < 11) || \
104 (UV_VERSION_MAJOR == 0 && UV_VERSION_MINOR == 11 && UV_VERSION_PATCH < 23)
105static void redisLibuvTimeout(uv_timer_t *timer, int status) {
106 (void)status; // unused
107#else
108static void redisLibuvTimeout(uv_timer_t *timer) {
109#endif
110 redisLibuvEvents *e = (redisLibuvEvents*)timer->data;
111 redisAsyncHandleTimeout(e->context);
112}
113
114static void redisLibuvSetTimeout(void *privdata, struct timeval tv) {
115 redisLibuvEvents* p = (redisLibuvEvents*)privdata;
116
117 uint64_t millsec = tv.tv_sec * 1000 + tv.tv_usec / 1000.0;
118 if (!p->timer.data) {
119 // timer is uninitialized
120 if (uv_timer_init(p->handle.loop, &p->timer) != 0) {
121 return;
122 }
123 p->timer.data = p;
124 }
125 // updates the timeout if the timer has already started
126 // or start the timer
127 uv_timer_start(&p->timer, redisLibuvTimeout, millsec, 0);
128}
129
130static void redisLibuvCleanup(void *privdata) {
131 redisLibuvEvents* p = (redisLibuvEvents*)privdata;
132
133 p->context = NULL; // indicate that context might no longer exist
134 if (p->timer.data) {
135 uv_close((uv_handle_t*)&p->timer, on_timer_close);
136 }
137 uv_close((uv_handle_t*)&p->handle, on_handle_close);
138}
139
140
141static int redisLibuvAttach(redisAsyncContext* ac, uv_loop_t* loop) {
142 redisContext *c = &(ac->c);
143
144 if (ac->ev.data != NULL) {
145 return REDIS_ERR;
146 }
147
148 ac->ev.addRead = redisLibuvAddRead;
149 ac->ev.delRead = redisLibuvDelRead;
150 ac->ev.addWrite = redisLibuvAddWrite;
151 ac->ev.delWrite = redisLibuvDelWrite;
152 ac->ev.cleanup = redisLibuvCleanup;
153 ac->ev.scheduleTimer = redisLibuvSetTimeout;
154
155 redisLibuvEvents* p = (redisLibuvEvents*)hi_malloc(sizeof(*p));
156 if (p == NULL)
157 return REDIS_ERR;
158
159 memset(p, 0, sizeof(*p));
160
161 if (uv_poll_init_socket(loop, &p->handle, c->fd) != 0) {
162 return REDIS_ERR;
163 }
164
165 ac->ev.data = p;
166 p->handle.data = p;
167 p->context = ac;
168
169 return REDIS_OK;
170}
171#endif
diff --git a/examples/redis-unstable/deps/hiredis/adapters/macosx.h b/examples/redis-unstable/deps/hiredis/adapters/macosx.h
new file mode 100644
index 0000000..3c87f1b
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/macosx.h
@@ -0,0 +1,115 @@
1//
2// Created by Дмитрий Бахвалов on 13.07.15.
3// Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
4//
5
6#ifndef __HIREDIS_MACOSX_H__
7#define __HIREDIS_MACOSX_H__
8
9#include <CoreFoundation/CoreFoundation.h>
10
11#include "../hiredis.h"
12#include "../async.h"
13
14typedef struct {
15 redisAsyncContext *context;
16 CFSocketRef socketRef;
17 CFRunLoopSourceRef sourceRef;
18} RedisRunLoop;
19
20static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) {
21 if( redisRunLoop != NULL ) {
22 if( redisRunLoop->sourceRef != NULL ) {
23 CFRunLoopSourceInvalidate(redisRunLoop->sourceRef);
24 CFRelease(redisRunLoop->sourceRef);
25 }
26 if( redisRunLoop->socketRef != NULL ) {
27 CFSocketInvalidate(redisRunLoop->socketRef);
28 CFRelease(redisRunLoop->socketRef);
29 }
30 hi_free(redisRunLoop);
31 }
32 return REDIS_ERR;
33}
34
35static void redisMacOSAddRead(void *privdata) {
36 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
37 CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
38}
39
40static void redisMacOSDelRead(void *privdata) {
41 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
42 CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
43}
44
45static void redisMacOSAddWrite(void *privdata) {
46 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
47 CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
48}
49
50static void redisMacOSDelWrite(void *privdata) {
51 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
52 CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
53}
54
55static void redisMacOSCleanup(void *privdata) {
56 RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
57 freeRedisRunLoop(redisRunLoop);
58}
59
60static void redisMacOSAsyncCallback(CFSocketRef __unused s, CFSocketCallBackType callbackType, CFDataRef __unused address, const void __unused *data, void *info) {
61 redisAsyncContext* context = (redisAsyncContext*) info;
62
63 switch (callbackType) {
64 case kCFSocketReadCallBack:
65 redisAsyncHandleRead(context);
66 break;
67
68 case kCFSocketWriteCallBack:
69 redisAsyncHandleWrite(context);
70 break;
71
72 default:
73 break;
74 }
75}
76
77static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef runLoop) {
78 redisContext *redisCtx = &(redisAsyncCtx->c);
79
80 /* Nothing should be attached when something is already attached */
81 if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR;
82
83 RedisRunLoop* redisRunLoop = (RedisRunLoop*) hi_calloc(1, sizeof(RedisRunLoop));
84 if (redisRunLoop == NULL)
85 return REDIS_ERR;
86
87 /* Setup redis stuff */
88 redisRunLoop->context = redisAsyncCtx;
89
90 redisAsyncCtx->ev.addRead = redisMacOSAddRead;
91 redisAsyncCtx->ev.delRead = redisMacOSDelRead;
92 redisAsyncCtx->ev.addWrite = redisMacOSAddWrite;
93 redisAsyncCtx->ev.delWrite = redisMacOSDelWrite;
94 redisAsyncCtx->ev.cleanup = redisMacOSCleanup;
95 redisAsyncCtx->ev.data = redisRunLoop;
96
97 /* Initialize and install read/write events */
98 CFSocketContext socketCtx = { 0, redisAsyncCtx, NULL, NULL, NULL };
99
100 redisRunLoop->socketRef = CFSocketCreateWithNative(NULL, redisCtx->fd,
101 kCFSocketReadCallBack | kCFSocketWriteCallBack,
102 redisMacOSAsyncCallback,
103 &socketCtx);
104 if( !redisRunLoop->socketRef ) return freeRedisRunLoop(redisRunLoop);
105
106 redisRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, redisRunLoop->socketRef, 0);
107 if( !redisRunLoop->sourceRef ) return freeRedisRunLoop(redisRunLoop);
108
109 CFRunLoopAddSource(runLoop, redisRunLoop->sourceRef, kCFRunLoopDefaultMode);
110
111 return REDIS_OK;
112}
113
114#endif
115
diff --git a/examples/redis-unstable/deps/hiredis/adapters/poll.h b/examples/redis-unstable/deps/hiredis/adapters/poll.h
new file mode 100644
index 0000000..f138650
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/poll.h
@@ -0,0 +1,197 @@
1
2#ifndef HIREDIS_POLL_H
3#define HIREDIS_POLL_H
4
5#include "../async.h"
6#include "../sockcompat.h"
7#include <string.h> // for memset
8#include <errno.h>
9
10/* Values to return from redisPollTick */
11#define REDIS_POLL_HANDLED_READ 1
12#define REDIS_POLL_HANDLED_WRITE 2
13#define REDIS_POLL_HANDLED_TIMEOUT 4
14
15/* An adapter to allow manual polling of the async context by checking the state
16 * of the underlying file descriptor. Useful in cases where there is no formal
17 * IO event loop but regular ticking can be used, such as in game engines. */
18
19typedef struct redisPollEvents {
20 redisAsyncContext *context;
21 redisFD fd;
22 char reading, writing;
23 char in_tick;
24 char deleted;
25 double deadline;
26} redisPollEvents;
27
28static double redisPollTimevalToDouble(struct timeval *tv) {
29 if (tv == NULL)
30 return 0.0;
31 return tv->tv_sec + tv->tv_usec / 1000000.00;
32}
33
34static double redisPollGetNow(void) {
35#ifndef _MSC_VER
36 struct timeval tv;
37 gettimeofday(&tv,NULL);
38 return redisPollTimevalToDouble(&tv);
39#else
40 FILETIME ft;
41 ULARGE_INTEGER li;
42 GetSystemTimeAsFileTime(&ft);
43 li.HighPart = ft.dwHighDateTime;
44 li.LowPart = ft.dwLowDateTime;
45 return (double)li.QuadPart * 1e-7;
46#endif
47}
48
49/* Poll for io, handling any pending callbacks. The timeout argument can be
50 * positive to wait for a maximum given time for IO, zero to poll, or negative
51 * to wait forever */
52static int redisPollTick(redisAsyncContext *ac, double timeout) {
53 int reading, writing;
54 struct pollfd pfd;
55 int handled;
56 int ns;
57 int itimeout;
58
59 redisPollEvents *e = (redisPollEvents*)ac->ev.data;
60 if (!e)
61 return 0;
62
63 /* local flags, won't get changed during callbacks */
64 reading = e->reading;
65 writing = e->writing;
66 if (!reading && !writing)
67 return 0;
68
69 pfd.fd = e->fd;
70 pfd.events = 0;
71 if (reading)
72 pfd.events = POLLIN;
73 if (writing)
74 pfd.events |= POLLOUT;
75
76 if (timeout >= 0.0) {
77 itimeout = (int)(timeout * 1000.0);
78 } else {
79 itimeout = -1;
80 }
81
82 ns = poll(&pfd, 1, itimeout);
83 if (ns < 0) {
84 /* ignore the EINTR error */
85 if (errno != EINTR)
86 return ns;
87 ns = 0;
88 }
89
90 handled = 0;
91 e->in_tick = 1;
92 if (ns) {
93 if (reading && (pfd.revents & POLLIN)) {
94 redisAsyncHandleRead(ac);
95 handled |= REDIS_POLL_HANDLED_READ;
96 }
97 /* on Windows, connection failure is indicated with the Exception fdset.
98 * handle it the same as writable. */
99 if (writing && (pfd.revents & (POLLOUT | POLLERR))) {
100 /* context Read callback may have caused context to be deleted, e.g.
101 by doing an redisAsyncDisconnect() */
102 if (!e->deleted) {
103 redisAsyncHandleWrite(ac);
104 handled |= REDIS_POLL_HANDLED_WRITE;
105 }
106 }
107 }
108
109 /* perform timeouts */
110 if (!e->deleted && e->deadline != 0.0) {
111 double now = redisPollGetNow();
112 if (now >= e->deadline) {
113 /* deadline has passed. disable timeout and perform callback */
114 e->deadline = 0.0;
115 redisAsyncHandleTimeout(ac);
116 handled |= REDIS_POLL_HANDLED_TIMEOUT;
117 }
118 }
119
120 /* do a delayed cleanup if required */
121 if (e->deleted)
122 hi_free(e);
123 else
124 e->in_tick = 0;
125
126 return handled;
127}
128
129static void redisPollAddRead(void *data) {
130 redisPollEvents *e = (redisPollEvents*)data;
131 e->reading = 1;
132}
133
134static void redisPollDelRead(void *data) {
135 redisPollEvents *e = (redisPollEvents*)data;
136 e->reading = 0;
137}
138
139static void redisPollAddWrite(void *data) {
140 redisPollEvents *e = (redisPollEvents*)data;
141 e->writing = 1;
142}
143
144static void redisPollDelWrite(void *data) {
145 redisPollEvents *e = (redisPollEvents*)data;
146 e->writing = 0;
147}
148
149static void redisPollCleanup(void *data) {
150 redisPollEvents *e = (redisPollEvents*)data;
151
152 /* if we are currently processing a tick, postpone deletion */
153 if (e->in_tick)
154 e->deleted = 1;
155 else
156 hi_free(e);
157}
158
159static void redisPollScheduleTimer(void *data, struct timeval tv)
160{
161 redisPollEvents *e = (redisPollEvents*)data;
162 double now = redisPollGetNow();
163 e->deadline = now + redisPollTimevalToDouble(&tv);
164}
165
166static int redisPollAttach(redisAsyncContext *ac) {
167 redisContext *c = &(ac->c);
168 redisPollEvents *e;
169
170 /* Nothing should be attached when something is already attached */
171 if (ac->ev.data != NULL)
172 return REDIS_ERR;
173
174 /* Create container for context and r/w events */
175 e = (redisPollEvents*)hi_malloc(sizeof(*e));
176 if (e == NULL)
177 return REDIS_ERR;
178 memset(e, 0, sizeof(*e));
179
180 e->context = ac;
181 e->fd = c->fd;
182 e->reading = e->writing = 0;
183 e->in_tick = e->deleted = 0;
184 e->deadline = 0.0;
185
186 /* Register functions to start/stop listening for events */
187 ac->ev.addRead = redisPollAddRead;
188 ac->ev.delRead = redisPollDelRead;
189 ac->ev.addWrite = redisPollAddWrite;
190 ac->ev.delWrite = redisPollDelWrite;
191 ac->ev.scheduleTimer = redisPollScheduleTimer;
192 ac->ev.cleanup = redisPollCleanup;
193 ac->ev.data = e;
194
195 return REDIS_OK;
196}
197#endif /* HIREDIS_POLL_H */
diff --git a/examples/redis-unstable/deps/hiredis/adapters/qt.h b/examples/redis-unstable/deps/hiredis/adapters/qt.h
new file mode 100644
index 0000000..5cc02e6
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/qt.h
@@ -0,0 +1,135 @@
1/*-
2 * Copyright (C) 2014 Pietro Cerutti <gahr@gahr.ch>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#ifndef __HIREDIS_QT_H__
27#define __HIREDIS_QT_H__
28#include <QSocketNotifier>
29#include "../async.h"
30
31static void RedisQtAddRead(void *);
32static void RedisQtDelRead(void *);
33static void RedisQtAddWrite(void *);
34static void RedisQtDelWrite(void *);
35static void RedisQtCleanup(void *);
36
37class RedisQtAdapter : public QObject {
38
39 Q_OBJECT
40
41 friend
42 void RedisQtAddRead(void * adapter) {
43 RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
44 a->addRead();
45 }
46
47 friend
48 void RedisQtDelRead(void * adapter) {
49 RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
50 a->delRead();
51 }
52
53 friend
54 void RedisQtAddWrite(void * adapter) {
55 RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
56 a->addWrite();
57 }
58
59 friend
60 void RedisQtDelWrite(void * adapter) {
61 RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
62 a->delWrite();
63 }
64
65 friend
66 void RedisQtCleanup(void * adapter) {
67 RedisQtAdapter * a = static_cast<RedisQtAdapter *>(adapter);
68 a->cleanup();
69 }
70
71 public:
72 RedisQtAdapter(QObject * parent = 0)
73 : QObject(parent), m_ctx(0), m_read(0), m_write(0) { }
74
75 ~RedisQtAdapter() {
76 if (m_ctx != 0) {
77 m_ctx->ev.data = NULL;
78 }
79 }
80
81 int setContext(redisAsyncContext * ac) {
82 if (ac->ev.data != NULL) {
83 return REDIS_ERR;
84 }
85 m_ctx = ac;
86 m_ctx->ev.data = this;
87 m_ctx->ev.addRead = RedisQtAddRead;
88 m_ctx->ev.delRead = RedisQtDelRead;
89 m_ctx->ev.addWrite = RedisQtAddWrite;
90 m_ctx->ev.delWrite = RedisQtDelWrite;
91 m_ctx->ev.cleanup = RedisQtCleanup;
92 return REDIS_OK;
93 }
94
95 private:
96 void addRead() {
97 if (m_read) return;
98 m_read = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Read, 0);
99 connect(m_read, SIGNAL(activated(int)), this, SLOT(read()));
100 }
101
102 void delRead() {
103 if (!m_read) return;
104 delete m_read;
105 m_read = 0;
106 }
107
108 void addWrite() {
109 if (m_write) return;
110 m_write = new QSocketNotifier(m_ctx->c.fd, QSocketNotifier::Write, 0);
111 connect(m_write, SIGNAL(activated(int)), this, SLOT(write()));
112 }
113
114 void delWrite() {
115 if (!m_write) return;
116 delete m_write;
117 m_write = 0;
118 }
119
120 void cleanup() {
121 delRead();
122 delWrite();
123 }
124
125 private slots:
126 void read() { redisAsyncHandleRead(m_ctx); }
127 void write() { redisAsyncHandleWrite(m_ctx); }
128
129 private:
130 redisAsyncContext * m_ctx;
131 QSocketNotifier * m_read;
132 QSocketNotifier * m_write;
133};
134
135#endif /* !__HIREDIS_QT_H__ */
diff --git a/examples/redis-unstable/deps/hiredis/adapters/redismoduleapi.h b/examples/redis-unstable/deps/hiredis/adapters/redismoduleapi.h
new file mode 100644
index 0000000..8a076fe
--- /dev/null
+++ b/examples/redis-unstable/deps/hiredis/adapters/redismoduleapi.h
@@ -0,0 +1,144 @@
1#ifndef __HIREDIS_REDISMODULEAPI_H__
2#define __HIREDIS_REDISMODULEAPI_H__
3
4#include "redismodule.h"
5
6#include "../async.h"
7#include "../hiredis.h"
8
9#include <sys/types.h>
10
11typedef struct redisModuleEvents {
12 redisAsyncContext *context;
13 RedisModuleCtx *module_ctx;
14 int fd;
15 int reading, writing;
16 int timer_active;
17 RedisModuleTimerID timer_id;
18} redisModuleEvents;
19
20static inline void redisModuleReadEvent(int fd, void *privdata, int mask) {
21 (void) fd;
22 (void) mask;
23
24 redisModuleEvents *e = (redisModuleEvents*)privdata;
25 redisAsyncHandleRead(e->context);
26}
27
28static inline void redisModuleWriteEvent(int fd, void *privdata, int mask) {
29 (void) fd;
30 (void) mask;
31
32 redisModuleEvents *e = (redisModuleEvents*)privdata;
33 redisAsyncHandleWrite(e->context);
34}
35
36static inline void redisModuleAddRead(void *privdata) {
37 redisModuleEvents *e = (redisModuleEvents*)privdata;
38 if (!e->reading) {
39 e->reading = 1;
40 RedisModule_EventLoopAdd(e->fd, REDISMODULE_EVENTLOOP_READABLE, redisModuleReadEvent, e);
41 }
42}
43
44static inline void redisModuleDelRead(void *privdata) {
45 redisModuleEvents *e = (redisModuleEvents*)privdata;
46 if (e->reading) {
47 e->reading = 0;
48 RedisModule_EventLoopDel(e->fd, REDISMODULE_EVENTLOOP_READABLE);
49 }
50}
51
52static inline void redisModuleAddWrite(void *privdata) {
53 redisModuleEvents *e = (redisModuleEvents*)privdata;
54 if (!e->writing) {
55 e->writing = 1;
56 RedisModule_EventLoopAdd(e->fd, REDISMODULE_EVENTLOOP_WRITABLE, redisModuleWriteEvent, e);
57 }
58}
59
60static inline void redisModuleDelWrite(void *privdata) {
61 redisModuleEvents *e = (redisModuleEvents*)privdata;
62 if (e->writing) {
63 e->writing = 0;
64 RedisModule_EventLoopDel(e->fd, REDISMODULE_EVENTLOOP_WRITABLE);
65 }
66}
67
68static inline void redisModuleStopTimer(void *privdata) {
69 redisModuleEvents *e = (redisModuleEvents*)privdata;
70 if (e->timer_active) {
71 RedisModule_StopTimer(e->module_ctx, e->timer_id, NULL);
72 }
73 e->timer_active = 0;
74}
75
76static inline void redisModuleCleanup(void *privdata) {
77 redisModuleEvents *e = (redisModuleEvents*)privdata;
78 redisModuleDelRead(privdata);
79 redisModuleDelWrite(privdata);
80 redisModuleStopTimer(privdata);
81 hi_free(e);
82}
83
84static inline void redisModuleTimeout(RedisModuleCtx *ctx, void *privdata) {
85 (void) ctx;
86
87 redisModuleEvents *e = (redisModuleEvents*)privdata;
88 e->timer_active = 0;
89 redisAsyncHandleTimeout(e->context);
90}
91
92static inline void redisModuleSetTimeout(void *privdata, struct timeval tv) {
93 redisModuleEvents* e = (redisModuleEvents*)privdata;
94
95 redisModuleStopTimer(privdata);
96
97 mstime_t millis = tv.tv_sec * 1000 + tv.tv_usec / 1000.0;
98 e->timer_id = RedisModule_CreateTimer(e->module_ctx, millis, redisModuleTimeout, e);
99 e->timer_active = 1;
100}
101
102/* Check if Redis version is compatible with the adapter. */
103static inline int redisModuleCompatibilityCheck(void) {
104 if (!RedisModule_EventLoopAdd ||
105 !RedisModule_EventLoopDel ||
106 !RedisModule_CreateTimer ||
107 !RedisModule_StopTimer) {
108 return REDIS_ERR;
109 }
110 return REDIS_OK;
111}
112
113static inline int redisModuleAttach(redisAsyncContext *ac, RedisModuleCtx *module_ctx) {
114 redisContext *c = &(ac->c);
115 redisModuleEvents *e;
116
117 /* Nothing should be attached when something is already attached */
118 if (ac->ev.data != NULL)
119 return REDIS_ERR;
120
121 /* Create container for context and r/w events */
122 e = (redisModuleEvents*)hi_malloc(sizeof(*e));
123 if (e == NULL)
124 return REDIS_ERR;
125
126 e->context = ac;
127 e->module_ctx = module_ctx;
128 e->fd = c->fd;
129 e->reading = e->writing = 0;
130 e->timer_active = 0;
131
132 /* Register functions to start/stop listening for events */
133 ac->ev.addRead = redisModuleAddRead;
134 ac->ev.delRead = redisModuleDelRead;
135 ac->ev.addWrite = redisModuleAddWrite;
136 ac->ev.delWrite = redisModuleDelWrite;
137 ac->ev.cleanup = redisModuleCleanup;
138 ac->ev.scheduleTimer = redisModuleSetTimeout;
139 ac->ev.data = e;
140
141 return REDIS_OK;
142}
143
144#endif