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