glib.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. #ifndef __HIREDIS_GLIB_H__
  2. #define __HIREDIS_GLIB_H__
  3. #include <glib.h>
  4. #include "../hiredis.h"
  5. #include "../async.h"
  6. typedef struct
  7. {
  8. GSource source;
  9. redisAsyncContext *ac;
  10. GPollFD poll_fd;
  11. } RedisSource;
  12. static void
  13. redis_source_add_read (gpointer data)
  14. {
  15. RedisSource *source = (RedisSource *)data;
  16. g_return_if_fail(source);
  17. source->poll_fd.events |= G_IO_IN;
  18. g_main_context_wakeup(g_source_get_context((GSource *)data));
  19. }
  20. static void
  21. redis_source_del_read (gpointer data)
  22. {
  23. RedisSource *source = (RedisSource *)data;
  24. g_return_if_fail(source);
  25. source->poll_fd.events &= ~G_IO_IN;
  26. g_main_context_wakeup(g_source_get_context((GSource *)data));
  27. }
  28. static void
  29. redis_source_add_write (gpointer data)
  30. {
  31. RedisSource *source = (RedisSource *)data;
  32. g_return_if_fail(source);
  33. source->poll_fd.events |= G_IO_OUT;
  34. g_main_context_wakeup(g_source_get_context((GSource *)data));
  35. }
  36. static void
  37. redis_source_del_write (gpointer data)
  38. {
  39. RedisSource *source = (RedisSource *)data;
  40. g_return_if_fail(source);
  41. source->poll_fd.events &= ~G_IO_OUT;
  42. g_main_context_wakeup(g_source_get_context((GSource *)data));
  43. }
  44. static void
  45. redis_source_cleanup (gpointer data)
  46. {
  47. RedisSource *source = (RedisSource *)data;
  48. g_return_if_fail(source);
  49. redis_source_del_read(source);
  50. redis_source_del_write(source);
  51. /*
  52. * It is not our responsibility to remove ourself from the
  53. * current main loop. However, we will remove the GPollFD.
  54. */
  55. if (source->poll_fd.fd >= 0) {
  56. g_source_remove_poll((GSource *)data, &source->poll_fd);
  57. source->poll_fd.fd = -1;
  58. }
  59. }
  60. static gboolean
  61. redis_source_prepare (GSource *source,
  62. gint *timeout_)
  63. {
  64. RedisSource *redis = (RedisSource *)source;
  65. *timeout_ = -1;
  66. return !!(redis->poll_fd.events & redis->poll_fd.revents);
  67. }
  68. static gboolean
  69. redis_source_check (GSource *source)
  70. {
  71. RedisSource *redis = (RedisSource *)source;
  72. return !!(redis->poll_fd.events & redis->poll_fd.revents);
  73. }
  74. static gboolean
  75. redis_source_dispatch (GSource *source,
  76. GSourceFunc callback,
  77. gpointer user_data)
  78. {
  79. RedisSource *redis = (RedisSource *)source;
  80. if ((redis->poll_fd.revents & G_IO_OUT)) {
  81. redisAsyncHandleWrite(redis->ac);
  82. redis->poll_fd.revents &= ~G_IO_OUT;
  83. }
  84. if ((redis->poll_fd.revents & G_IO_IN)) {
  85. redisAsyncHandleRead(redis->ac);
  86. redis->poll_fd.revents &= ~G_IO_IN;
  87. }
  88. if (callback) {
  89. return callback(user_data);
  90. }
  91. return TRUE;
  92. }
  93. static void
  94. redis_source_finalize (GSource *source)
  95. {
  96. RedisSource *redis = (RedisSource *)source;
  97. if (redis->poll_fd.fd >= 0) {
  98. g_source_remove_poll(source, &redis->poll_fd);
  99. redis->poll_fd.fd = -1;
  100. }
  101. }
  102. static GSource *
  103. redis_source_new (redisAsyncContext *ac)
  104. {
  105. static GSourceFuncs source_funcs = {
  106. .prepare = redis_source_prepare,
  107. .check = redis_source_check,
  108. .dispatch = redis_source_dispatch,
  109. .finalize = redis_source_finalize,
  110. };
  111. redisContext *c = &ac->c;
  112. RedisSource *source;
  113. g_return_val_if_fail(ac != NULL, NULL);
  114. source = (RedisSource *)g_source_new(&source_funcs, sizeof *source);
  115. source->ac = ac;
  116. source->poll_fd.fd = c->fd;
  117. source->poll_fd.events = 0;
  118. source->poll_fd.revents = 0;
  119. g_source_add_poll((GSource *)source, &source->poll_fd);
  120. ac->ev.addRead = redis_source_add_read;
  121. ac->ev.delRead = redis_source_del_read;
  122. ac->ev.addWrite = redis_source_add_write;
  123. ac->ev.delWrite = redis_source_del_write;
  124. ac->ev.cleanup = redis_source_cleanup;
  125. ac->ev.data = source;
  126. return (GSource *)source;
  127. }
  128. #endif /* __HIREDIS_GLIB_H__ */