diff options
| author | Christian Hergert <chris@dronelabs.com> | 2012-02-08 03:07:48 -0800 | 
|---|---|---|
| committer | Matt Stancliff <matt@genges.com> | 2015-01-05 16:39:30 -0500 | 
| commit | 0c9ff5bb030fd07706c39b3d4f28cef618dd8794 (patch) | |
| tree | 1e4d4e48292511bffa7ee546e071044f6f852a72 | |
| parent | e30c96ebdec4e8612f4102f9cd99d36488c66e5c (diff) | |
| download | hiredict-0c9ff5bb030fd07706c39b3d4f28cef618dd8794.tar.xz | |
Add GLib 2.0 adapter
[Cleaned up Makefile and header includes.  Didn't change crazy
coding style because it's the convention for GLib systems.]
Closes #83
Closes #71
| -rw-r--r-- | Makefile | 7 | ||||
| -rw-r--r-- | adapters/glib.h | 153 | ||||
| -rw-r--r-- | examples/example-glib.c | 73 | 
3 files changed, 232 insertions, 1 deletions
| @@ -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; +} | 
