macosx.h 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. //
  2. // Created by Дмитрий Бахвалов on 13.07.15.
  3. // Copyright (c) 2015 Dmitry Bakhvalov. All rights reserved.
  4. //
  5. #ifndef __HIREDIS_MACOSX_H__
  6. #define __HIREDIS_MACOSX_H__
  7. #include <CoreFoundation/CoreFoundation.h>
  8. #include "../hiredis.h"
  9. #include "../async.h"
  10. typedef struct {
  11. redisAsyncContext *context;
  12. CFSocketRef socketRef;
  13. CFRunLoopSourceRef sourceRef;
  14. } RedisRunLoop;
  15. static int freeRedisRunLoop(RedisRunLoop* redisRunLoop) {
  16. if( redisRunLoop != NULL ) {
  17. if( redisRunLoop->sourceRef != NULL ) {
  18. CFRunLoopSourceInvalidate(redisRunLoop->sourceRef);
  19. CFRelease(redisRunLoop->sourceRef);
  20. }
  21. if( redisRunLoop->socketRef != NULL ) {
  22. CFSocketInvalidate(redisRunLoop->socketRef);
  23. CFRelease(redisRunLoop->socketRef);
  24. }
  25. free(redisRunLoop);
  26. }
  27. return REDIS_ERR;
  28. }
  29. static void redisMacOSAddRead(void *privdata) {
  30. RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
  31. CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
  32. }
  33. static void redisMacOSDelRead(void *privdata) {
  34. RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
  35. CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketReadCallBack);
  36. }
  37. static void redisMacOSAddWrite(void *privdata) {
  38. RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
  39. CFSocketEnableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
  40. }
  41. static void redisMacOSDelWrite(void *privdata) {
  42. RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
  43. CFSocketDisableCallBacks(redisRunLoop->socketRef, kCFSocketWriteCallBack);
  44. }
  45. static void redisMacOSCleanup(void *privdata) {
  46. RedisRunLoop *redisRunLoop = (RedisRunLoop*)privdata;
  47. freeRedisRunLoop(redisRunLoop);
  48. }
  49. static void redisMacOSAsyncCallback(CFSocketRef __unused s, CFSocketCallBackType callbackType, CFDataRef __unused address, const void __unused *data, void *info) {
  50. redisAsyncContext* context = (redisAsyncContext*) info;
  51. switch (callbackType) {
  52. case kCFSocketReadCallBack:
  53. redisAsyncHandleRead(context);
  54. break;
  55. case kCFSocketWriteCallBack:
  56. redisAsyncHandleWrite(context);
  57. break;
  58. default:
  59. break;
  60. }
  61. }
  62. static int redisMacOSAttach(redisAsyncContext *redisAsyncCtx, CFRunLoopRef runLoop) {
  63. redisContext *redisCtx = &(redisAsyncCtx->c);
  64. /* Nothing should be attached when something is already attached */
  65. if( redisAsyncCtx->ev.data != NULL ) return REDIS_ERR;
  66. RedisRunLoop* redisRunLoop = (RedisRunLoop*) calloc(1, sizeof(RedisRunLoop));
  67. if( !redisRunLoop ) return REDIS_ERR;
  68. /* Setup redis stuff */
  69. redisRunLoop->context = redisAsyncCtx;
  70. redisAsyncCtx->ev.addRead = redisMacOSAddRead;
  71. redisAsyncCtx->ev.delRead = redisMacOSDelRead;
  72. redisAsyncCtx->ev.addWrite = redisMacOSAddWrite;
  73. redisAsyncCtx->ev.delWrite = redisMacOSDelWrite;
  74. redisAsyncCtx->ev.cleanup = redisMacOSCleanup;
  75. redisAsyncCtx->ev.data = redisRunLoop;
  76. /* Initialize and install read/write events */
  77. CFSocketContext socketCtx = { 0, redisAsyncCtx, NULL, NULL, NULL };
  78. redisRunLoop->socketRef = CFSocketCreateWithNative(NULL, redisCtx->fd,
  79. kCFSocketReadCallBack | kCFSocketWriteCallBack,
  80. redisMacOSAsyncCallback,
  81. &socketCtx);
  82. if( !redisRunLoop->socketRef ) return freeRedisRunLoop(redisRunLoop);
  83. redisRunLoop->sourceRef = CFSocketCreateRunLoopSource(NULL, redisRunLoop->socketRef, 0);
  84. if( !redisRunLoop->sourceRef ) return freeRedisRunLoop(redisRunLoop);
  85. CFRunLoopAddSource(runLoop, redisRunLoop->sourceRef, kCFRunLoopDefaultMode);
  86. return REDIS_OK;
  87. }
  88. #endif