diff options
| author | Dmitry Bakhvalov <dizzus@gmail.com> | 2015-07-13 20:26:41 +0300 | 
|---|---|---|
| committer | Jan-Erik Rediger <janerik@fnordig.de> | 2015-07-27 23:19:14 +0200 | 
| commit | c18a5648181801aa6fddd1856940b7dd20cdf74a (patch) | |
| tree | abd8b01a55c461dd5936c282fce466ed6cd78070 | |
| parent | 4a632a6038f37b4d72c52f580d6a396c5ee3fe12 (diff) | |
| download | hiredict-c18a5648181801aa6fddd1856940b7dd20cdf74a.tar.xz | |
Added MacOS X addapter and corresponding example.
Added MacOS X support via CoreFoundation run loop.
| -rw-r--r-- | Makefile | 3 | ||||
| -rw-r--r-- | adapters/macosx.h | 114 | ||||
| -rw-r--r-- | examples/example-macosx.c | 66 | 
3 files changed, 183 insertions, 0 deletions
@@ -99,6 +99,9 @@ hiredis-example-glib: examples/example-glib.c adapters/glib.h $(STLIBNAME)  hiredis-example-ivykis: examples/example-ivykis.c adapters/ivykis.h $(STLIBNAME)  	$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -livykis $(STLIBNAME) +hiredis-example-macosx: examples/example-macosx.c adapters/macosx.h $(STLIBNAME) +	$(CC) -o examples/$@ $(REAL_CFLAGS) $(REAL_LDFLAGS) -I. $< -framework CoreFoundation $(STLIBNAME) +  ifndef AE_DIR  hiredis-example-ae:  	@echo "Please specify AE_DIR (e.g. <redis repository>/src)" diff --git a/adapters/macosx.h b/adapters/macosx.h new file mode 100644 index 0000000..72121f6 --- /dev/null +++ b/adapters/macosx.h @@ -0,0 +1,114 @@ +// +//  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); +        } +        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*) calloc(1, sizeof(RedisRunLoop)); +    if( !redisRunLoop ) 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/examples/example-macosx.c b/examples/example-macosx.c new file mode 100644 index 0000000..1b9ef3e --- /dev/null +++ b/examples/example-macosx.c @@ -0,0 +1,66 @@ +// +//  Created by Дмитрий Бахвалов on 13.07.15. +//  Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved. +// + +#include <stdio.h> + +#include <hiredis.h> +#include <async.h> +#include <adapters/macosx.h> + +void getCallback(redisAsyncContext *c, void *r, void *privdata) { +    redisReply *reply = r; +    if (reply == NULL) return; +    printf("argv[%s]: %s\n", (char*)privdata, reply->str); +     +    /* Disconnect after receiving the reply to GET */ +    redisAsyncDisconnect(c); +} + +void connectCallback(const redisAsyncContext *c, int status) { +    if (status != REDIS_OK) { +        printf("Error: %s\n", c->errstr); +        return; +    } +    printf("Connected...\n"); +} + +void disconnectCallback(const redisAsyncContext *c, int status) { +    if (status != REDIS_OK) { +        printf("Error: %s\n", c->errstr); +        return; +    } +    CFRunLoopStop(CFRunLoopGetCurrent()); +    printf("Disconnected...\n"); +} + +int main (int argc, char **argv) { +    signal(SIGPIPE, SIG_IGN); +     +    CFRunLoopRef loop = CFRunLoopGetCurrent(); +    if( !loop ) { +        printf("Error: Cannot get current run lopp\n"); +        return 1; +    } +     +    redisAsyncContext *c = redisAsyncConnect("127.0.0.1", 6379); +    if (c->err) { +        /* Let *c leak for now... */ +        printf("Error: %s\n", c->errstr); +        return 1; +    } +     +    redisMacOSAttach(c, loop); +     +    redisAsyncSetConnectCallback(c,connectCallback); +    redisAsyncSetDisconnectCallback(c,disconnectCallback); + +    redisAsyncCommand(c, NULL, NULL, "SET key %b", argv[argc-1], strlen(argv[argc-1])); +    redisAsyncCommand(c, getCallback, (char*)"end-1", "GET key"); +     +    CFRunLoopRun(); +     +    return 0; +} +  | 
