summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile7
-rw-r--r--adapters/glib.h153
-rw-r--r--examples/example-glib.c73
3 files changed, 232 insertions, 1 deletions
diff --git a/Makefile b/Makefile
index ddcc4e4..09a6ef5 100644
--- a/Makefile
+++ b/Makefile
@@ -4,7 +4,7 @@
# This file is released under the BSD license, see the COPYING file
OBJ=net.o hiredis.o sds.o async.o
-EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev
+EXAMPLES=hiredis-example hiredis-example-libevent hiredis-example-libev hiredis-example-glib
TESTS=hiredis-test
LIBNAME=libhiredis
@@ -79,6 +79,9 @@ hiredis-example-libevent: examples/example-libevent.c adapters/libevent.h $(STLI
hiredis-example-libev: examples/example-libev.c adapters/libev.h $(STLIBNAME)
$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -lev $(STLIBNAME)
+hiredis-example-glib: examples/example-glib.c adapters/glib.h $(STLIBNAME)
+ $(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) $(shell pkg-config --cflags --libs glib-2.0) -I. $< $(STLIBNAME)
+
ifndef AE_DIR
hiredis-example-ae:
@echo "Please specify AE_DIR (e.g. <redis repository>/src)"
@@ -103,6 +106,8 @@ hiredis-example: examples/example.c $(STLIBNAME)
examples: $(EXAMPLES)
hiredis-test: test.o $(STLIBNAME)
+
+hiredis-%: %.o $(STLIBNAME)
$(CC) -o $@ $(REAL_LDFLAGS) $< $(STLIBNAME)
test: hiredis-test
diff --git a/adapters/glib.h b/adapters/glib.h
new file mode 100644
index 0000000..e13eee7
--- /dev/null
+++ b/adapters/glib.h
@@ -0,0 +1,153 @@
+#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 = data;
+ g_return_if_fail(source);
+ source->poll_fd.events |= G_IO_IN;
+ g_main_context_wakeup(g_source_get_context(data));
+}
+
+static void
+redis_source_del_read (gpointer data)
+{
+ RedisSource *source = data;
+ g_return_if_fail(source);
+ source->poll_fd.events &= ~G_IO_IN;
+ g_main_context_wakeup(g_source_get_context(data));
+}
+
+static void
+redis_source_add_write (gpointer data)
+{
+ RedisSource *source = data;
+ g_return_if_fail(source);
+ source->poll_fd.events |= G_IO_OUT;
+ g_main_context_wakeup(g_source_get_context(data));
+}
+
+static void
+redis_source_del_write (gpointer data)
+{
+ RedisSource *source = data;
+ g_return_if_fail(source);
+ source->poll_fd.events &= ~G_IO_OUT;
+ g_main_context_wakeup(g_source_get_context(data));
+}
+
+static void
+redis_source_cleanup (gpointer data)
+{
+ RedisSource *source = 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(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);
+ 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/examples/example-glib.c b/examples/example-glib.c
new file mode 100644
index 0000000..d6e10f8
--- /dev/null
+++ b/examples/example-glib.c
@@ -0,0 +1,73 @@
+#include <stdlib.h>
+
+#include <hiredis.h>
+#include <async.h>
+#include <adapters/glib.h>
+
+static GMainLoop *mainloop;
+
+static void
+connect_cb (const redisAsyncContext *ac G_GNUC_UNUSED,
+ int status)
+{
+ if (status != REDIS_OK) {
+ g_printerr("Failed to connect: %s\n", ac->errstr);
+ g_main_loop_quit(mainloop);
+ } else {
+ g_printerr("Connected...\n");
+ }
+}
+
+static void
+disconnect_cb (const redisAsyncContext *ac G_GNUC_UNUSED,
+ int status)
+{
+ if (status != REDIS_OK) {
+ g_error("Failed to disconnect: %s", ac->errstr);
+ } else {
+ g_printerr("Disconnected...\n");
+ g_main_loop_quit(mainloop);
+ }
+}
+
+static void
+command_cb(redisAsyncContext *ac,
+ gpointer r,
+ gpointer user_data G_GNUC_UNUSED)
+{
+ redisReply *reply = r;
+
+ if (reply) {
+ g_print("REPLY: %s\n", reply->str);
+ }
+
+ redisAsyncDisconnect(ac);
+}
+
+gint
+main (gint argc G_GNUC_UNUSED,
+ gchar *argv[] G_GNUC_UNUSED)
+{
+ redisAsyncContext *ac;
+ GMainContext *context = NULL;
+ GSource *source;
+
+ ac = redisAsyncConnect("127.0.0.1", 6379);
+ if (ac->err) {
+ g_printerr("%s\n", ac->errstr);
+ exit(EXIT_FAILURE);
+ }
+
+ source = redis_source_new(ac);
+ mainloop = g_main_loop_new(context, FALSE);
+ g_source_attach(source, context);
+
+ redisAsyncSetConnectCallback(ac, connect_cb);
+ redisAsyncSetDisconnectCallback(ac, disconnect_cb);
+ redisAsyncCommand(ac, command_cb, NULL, "SET key 1234");
+ redisAsyncCommand(ac, command_cb, NULL, "GET key");
+
+ g_main_loop_run(mainloop);
+
+ return EXIT_SUCCESS;
+}