rev 0.1.1 → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. data/README +45 -9
  2. data/doc/rdoc/classes/Rev.html +368 -0
  3. data/doc/rdoc/classes/Rev.src/M000001.html +28 -0
  4. data/doc/rdoc/classes/Rev.src/M000002.html +35 -0
  5. data/doc/rdoc/classes/Rev.src/M000003.html +24 -0
  6. data/doc/rdoc/classes/Rev.src/M000004.html +28 -0
  7. data/doc/rdoc/classes/Rev.src/M000005.html +27 -0
  8. data/doc/rdoc/classes/Rev.src/M000006.html +33 -0
  9. data/doc/rdoc/classes/Rev.src/M000007.html +43 -0
  10. data/doc/rdoc/classes/Rev.src/M000008.html +16 -0
  11. data/doc/rdoc/classes/Rev/Buffer.html +354 -0
  12. data/doc/rdoc/classes/Rev/Buffer.src/M000019.html +17 -0
  13. data/doc/rdoc/classes/Rev/Buffer.src/M000020.html +29 -0
  14. data/doc/rdoc/classes/Rev/Buffer.src/M000021.html +27 -0
  15. data/doc/rdoc/classes/Rev/Buffer.src/M000022.html +27 -0
  16. data/doc/rdoc/classes/Rev/Buffer.src/M000023.html +31 -0
  17. data/doc/rdoc/classes/Rev/Buffer.src/M000024.html +31 -0
  18. data/doc/rdoc/classes/Rev/Buffer.src/M000025.html +30 -0
  19. data/doc/rdoc/classes/Rev/Buffer.src/M000026.html +50 -0
  20. data/doc/rdoc/classes/Rev/Buffer.src/M000027.html +22 -0
  21. data/doc/rdoc/classes/Rev/Buffer.src/M000028.html +24 -0
  22. data/doc/rdoc/classes/Rev/Buffer.src/M000029.html +24 -0
  23. data/doc/rdoc/classes/Rev/BufferedIO.html +397 -0
  24. data/doc/rdoc/classes/Rev/BufferedIO.src/M000095.html +23 -0
  25. data/doc/rdoc/classes/Rev/BufferedIO.src/M000096.html +16 -0
  26. data/doc/rdoc/classes/Rev/BufferedIO.src/M000097.html +16 -0
  27. data/doc/rdoc/classes/Rev/BufferedIO.src/M000098.html +16 -0
  28. data/doc/rdoc/classes/Rev/BufferedIO.src/M000099.html +18 -0
  29. data/doc/rdoc/classes/Rev/BufferedIO.src/M000100.html +18 -0
  30. data/doc/rdoc/classes/Rev/BufferedIO.src/M000101.html +23 -0
  31. data/doc/rdoc/classes/Rev/BufferedIO.src/M000102.html +18 -0
  32. data/doc/rdoc/classes/Rev/BufferedIO.src/M000103.html +20 -0
  33. data/doc/rdoc/classes/Rev/BufferedIO.src/M000104.html +24 -0
  34. data/doc/rdoc/classes/Rev/BufferedIO.src/M000105.html +23 -0
  35. data/doc/rdoc/classes/Rev/BufferedIO.src/M000106.html +22 -0
  36. data/doc/rdoc/classes/Rev/BufferedIO.src/M000107.html +29 -0
  37. data/doc/rdoc/classes/Rev/BufferedIO/Writer.html +154 -0
  38. data/doc/rdoc/classes/Rev/BufferedIO/Writer.src/M000108.html +19 -0
  39. data/doc/rdoc/classes/Rev/BufferedIO/Writer.src/M000109.html +18 -0
  40. data/doc/rdoc/classes/Rev/DNSResolver.html +401 -0
  41. data/doc/rdoc/classes/Rev/DNSResolver.src/M000124.html +25 -0
  42. data/doc/rdoc/classes/Rev/DNSResolver.src/M000125.html +29 -0
  43. data/doc/rdoc/classes/Rev/DNSResolver.src/M000126.html +20 -0
  44. data/doc/rdoc/classes/Rev/DNSResolver.src/M000127.html +19 -0
  45. data/doc/rdoc/classes/Rev/DNSResolver.src/M000128.html +16 -0
  46. data/doc/rdoc/classes/Rev/DNSResolver.src/M000129.html +16 -0
  47. data/doc/rdoc/classes/Rev/DNSResolver.src/M000131.html +19 -0
  48. data/doc/rdoc/classes/Rev/DNSResolver.src/M000132.html +21 -0
  49. data/doc/rdoc/classes/Rev/DNSResolver.src/M000133.html +27 -0
  50. data/doc/rdoc/classes/Rev/DNSResolver.src/M000134.html +28 -0
  51. data/doc/rdoc/classes/Rev/DNSResolver.src/M000135.html +55 -0
  52. data/doc/rdoc/classes/Rev/DNSResolver/Timeout.html +154 -0
  53. data/doc/rdoc/classes/Rev/DNSResolver/Timeout.src/M000136.html +20 -0
  54. data/doc/rdoc/classes/Rev/DNSResolver/Timeout.src/M000137.html +22 -0
  55. data/doc/rdoc/classes/Rev/HttpChunkHeader.html +156 -0
  56. data/doc/rdoc/classes/Rev/HttpChunkHeader.src/M000031.html +19 -0
  57. data/doc/rdoc/classes/Rev/HttpClient.html +460 -0
  58. data/doc/rdoc/classes/Rev/HttpClient.src/M000042.html +18 -0
  59. data/doc/rdoc/classes/Rev/HttpClient.src/M000043.html +27 -0
  60. data/doc/rdoc/classes/Rev/HttpClient.src/M000044.html +24 -0
  61. data/doc/rdoc/classes/Rev/HttpClient.src/M000045.html +19 -0
  62. data/doc/rdoc/classes/Rev/HttpClient.src/M000046.html +17 -0
  63. data/doc/rdoc/classes/Rev/HttpClient.src/M000047.html +19 -0
  64. data/doc/rdoc/classes/Rev/HttpClient.src/M000048.html +18 -0
  65. data/doc/rdoc/classes/Rev/HttpClient.src/M000049.html +18 -0
  66. data/doc/rdoc/classes/Rev/HttpClient.src/M000050.html +19 -0
  67. data/doc/rdoc/classes/Rev/HttpClient.src/M000051.html +19 -0
  68. data/doc/rdoc/classes/Rev/HttpClient.src/M000052.html +19 -0
  69. data/doc/rdoc/classes/Rev/HttpClient.src/M000053.html +41 -0
  70. data/doc/rdoc/classes/Rev/HttpClient.src/M000054.html +18 -0
  71. data/doc/rdoc/classes/Rev/HttpClient.src/M000055.html +34 -0
  72. data/doc/rdoc/classes/Rev/HttpEncoding.html +310 -0
  73. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000009.html +20 -0
  74. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000010.html +20 -0
  75. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000011.html +18 -0
  76. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000012.html +18 -0
  77. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000013.html +18 -0
  78. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000014.html +19 -0
  79. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000015.html +18 -0
  80. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000016.html +18 -0
  81. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000017.html +22 -0
  82. data/doc/rdoc/classes/Rev/HttpEncoding.src/M000018.html +18 -0
  83. data/doc/rdoc/classes/Rev/HttpResponseHeader.html +219 -0
  84. data/doc/rdoc/classes/Rev/HttpResponseHeader.src/M000032.html +18 -0
  85. data/doc/rdoc/classes/Rev/HttpResponseHeader.src/M000033.html +18 -0
  86. data/doc/rdoc/classes/Rev/HttpResponseHeader.src/M000034.html +18 -0
  87. data/doc/rdoc/classes/Rev/IOWatcher.html +285 -0
  88. data/doc/rdoc/classes/Rev/IOWatcher.src/M000079.html +17 -0
  89. data/doc/rdoc/classes/Rev/IOWatcher.src/M000080.html +27 -0
  90. data/doc/rdoc/classes/Rev/IOWatcher.src/M000081.html +26 -0
  91. data/doc/rdoc/classes/Rev/IOWatcher.src/M000082.html +27 -0
  92. data/doc/rdoc/classes/Rev/IOWatcher.src/M000083.html +27 -0
  93. data/doc/rdoc/classes/Rev/IOWatcher.src/M000084.html +24 -0
  94. data/doc/rdoc/classes/Rev/IOWatcher.src/M000085.html +25 -0
  95. data/doc/rdoc/classes/Rev/Listener.html +207 -0
  96. data/doc/rdoc/classes/Rev/Listener.src/M000065.html +19 -0
  97. data/doc/rdoc/classes/Rev/Listener.src/M000066.html +19 -0
  98. data/doc/rdoc/classes/Rev/Listener.src/M000067.html +16 -0
  99. data/doc/rdoc/classes/Rev/Listener.src/M000068.html +18 -0
  100. data/doc/rdoc/classes/Rev/Loop.html +395 -0
  101. data/doc/rdoc/classes/Rev/Loop.src/M000070.html +25 -0
  102. data/doc/rdoc/classes/Rev/Loop.src/M000071.html +45 -0
  103. data/doc/rdoc/classes/Rev/Loop.src/M000072.html +18 -0
  104. data/doc/rdoc/classes/Rev/Loop.src/M000073.html +23 -0
  105. data/doc/rdoc/classes/Rev/Loop.src/M000074.html +19 -0
  106. data/doc/rdoc/classes/Rev/Loop.src/M000075.html +17 -0
  107. data/doc/rdoc/classes/Rev/Loop.src/M000076.html +27 -0
  108. data/doc/rdoc/classes/Rev/Loop.src/M000077.html +32 -0
  109. data/doc/rdoc/classes/Rev/Loop.src/M000078.html +32 -0
  110. data/doc/rdoc/classes/Rev/Server.html +164 -0
  111. data/doc/rdoc/classes/Rev/Server.src/M000121.html +32 -0
  112. data/doc/rdoc/classes/Rev/Server.src/M000122.html +20 -0
  113. data/doc/rdoc/classes/Rev/Socket.html +213 -0
  114. data/doc/rdoc/classes/Rev/Socket.src/M000035.html +21 -0
  115. data/doc/rdoc/classes/Rev/Socket.src/M000036.html +25 -0
  116. data/doc/rdoc/classes/Rev/Socket.src/M000037.html +16 -0
  117. data/doc/rdoc/classes/Rev/Socket.src/M000038.html +16 -0
  118. data/doc/rdoc/classes/Rev/Socket/Connector.html +154 -0
  119. data/doc/rdoc/classes/Rev/Socket/Connector.src/M000040.html +19 -0
  120. data/doc/rdoc/classes/Rev/Socket/Connector.src/M000041.html +28 -0
  121. data/doc/rdoc/classes/Rev/TCPListener.html +161 -0
  122. data/doc/rdoc/classes/Rev/TCPListener.src/M000069.html +23 -0
  123. data/doc/rdoc/classes/Rev/TCPServer.html +147 -0
  124. data/doc/rdoc/classes/Rev/TCPServer.src/M000123.html +20 -0
  125. data/doc/rdoc/classes/Rev/TCPSocket.html +233 -0
  126. data/doc/rdoc/classes/Rev/TCPSocket.src/M000056.html +20 -0
  127. data/doc/rdoc/classes/Rev/TCPSocket.src/M000057.html +34 -0
  128. data/doc/rdoc/classes/Rev/TCPSocket.src/M000058.html +24 -0
  129. data/doc/rdoc/classes/Rev/TCPSocket.src/M000059.html +18 -0
  130. data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectResolver.html +171 -0
  131. data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectResolver.src/M000060.html +19 -0
  132. data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectResolver.src/M000061.html +27 -0
  133. data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectResolver.src/M000062.html +23 -0
  134. data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectSocket.html +154 -0
  135. data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectSocket.src/M000063.html +25 -0
  136. data/doc/rdoc/classes/Rev/TCPSocket/TCPConnectSocket.src/M000064.html +23 -0
  137. data/doc/rdoc/classes/Rev/TimerWatcher.html +288 -0
  138. data/doc/rdoc/classes/Rev/TimerWatcher.src/M000086.html +17 -0
  139. data/doc/rdoc/classes/Rev/TimerWatcher.src/M000087.html +27 -0
  140. data/doc/rdoc/classes/Rev/TimerWatcher.src/M000088.html +26 -0
  141. data/doc/rdoc/classes/Rev/TimerWatcher.src/M000089.html +27 -0
  142. data/doc/rdoc/classes/Rev/TimerWatcher.src/M000090.html +27 -0
  143. data/doc/rdoc/classes/Rev/TimerWatcher.src/M000091.html +42 -0
  144. data/doc/rdoc/classes/Rev/TimerWatcher.src/M000092.html +24 -0
  145. data/doc/rdoc/classes/Rev/UNIXListener.html +147 -0
  146. data/doc/rdoc/classes/Rev/UNIXListener.src/M000120.html +18 -0
  147. data/doc/rdoc/classes/Rev/UNIXServer.html +147 -0
  148. data/doc/rdoc/classes/Rev/UNIXServer.src/M000030.html +18 -0
  149. data/doc/rdoc/classes/Rev/UNIXSocket.html +175 -0
  150. data/doc/rdoc/classes/Rev/UNIXSocket.src/M000093.html +18 -0
  151. data/doc/rdoc/classes/Rev/UNIXSocket.src/M000094.html +21 -0
  152. data/doc/rdoc/classes/Rev/Watcher.html +349 -0
  153. data/doc/rdoc/classes/Rev/Watcher.src/M000110.html +20 -0
  154. data/doc/rdoc/classes/Rev/Watcher.src/M000111.html +20 -0
  155. data/doc/rdoc/classes/Rev/Watcher.src/M000112.html +17 -0
  156. data/doc/rdoc/classes/Rev/Watcher.src/M000113.html +48 -0
  157. data/doc/rdoc/classes/Rev/Watcher.src/M000114.html +62 -0
  158. data/doc/rdoc/classes/Rev/Watcher.src/M000115.html +34 -0
  159. data/doc/rdoc/classes/Rev/Watcher.src/M000116.html +34 -0
  160. data/doc/rdoc/classes/Rev/Watcher.src/M000117.html +27 -0
  161. data/doc/rdoc/classes/Rev/Watcher.src/M000118.html +24 -0
  162. data/doc/rdoc/classes/Rev/Watcher.src/M000119.html +27 -0
  163. data/doc/rdoc/created.rid +1 -0
  164. data/doc/rdoc/files/LICENSE.html +165 -0
  165. data/doc/rdoc/files/README.html +297 -0
  166. data/doc/rdoc/files/ext/rev/rev_buffer_c.html +101 -0
  167. data/doc/rdoc/files/ext/rev/rev_ext_c.html +101 -0
  168. data/doc/rdoc/files/ext/rev/rev_io_watcher_c.html +101 -0
  169. data/doc/rdoc/files/ext/rev/rev_loop_c.html +101 -0
  170. data/doc/rdoc/files/ext/rev/rev_timer_watcher_c.html +101 -0
  171. data/doc/rdoc/files/ext/rev/rev_watcher_c.html +101 -0
  172. data/doc/rdoc/files/lib/rev/buffered_io_rb.html +101 -0
  173. data/doc/rdoc/files/lib/rev/dns_resolver_rb.html +101 -0
  174. data/doc/rdoc/files/lib/rev/http_client_rb.html +101 -0
  175. data/doc/rdoc/files/lib/rev/io_watcher_rb.html +101 -0
  176. data/doc/rdoc/files/lib/rev/listener_rb.html +108 -0
  177. data/doc/rdoc/files/lib/rev/loop_rb.html +101 -0
  178. data/doc/rdoc/files/lib/rev/server_rb.html +101 -0
  179. data/doc/rdoc/files/lib/rev/socket_rb.html +109 -0
  180. data/doc/rdoc/files/lib/rev/timer_watcher_rb.html +101 -0
  181. data/doc/rdoc/files/lib/rev/watcher_rb.html +101 -0
  182. data/doc/rdoc/files/lib/rev_rb.html +101 -0
  183. data/doc/rdoc/fr_class_index.html +52 -0
  184. data/doc/rdoc/fr_file_index.html +45 -0
  185. data/doc/rdoc/fr_method_index.html +163 -0
  186. data/doc/rdoc/index.html +24 -0
  187. data/doc/rdoc/rdoc-style.css +208 -0
  188. data/ext/rev/extconf.rb +1 -1
  189. data/ext/rev/rev.h +0 -1
  190. data/ext/rev/rev_buffer.c +606 -0
  191. data/ext/rev/rev_ext.c +1 -0
  192. data/ext/rev/rev_io_watcher.c +53 -19
  193. data/ext/rev/rev_loop.c +12 -35
  194. data/ext/rev/rev_timer_watcher.c +45 -3
  195. data/ext/rev/rev_watcher.c +13 -1
  196. data/lib/http11_client.bundle +0 -0
  197. data/lib/rev.rb +1 -1
  198. data/lib/rev/buffered_io.rb +25 -22
  199. data/lib/rev/dns_resolver.rb +31 -14
  200. data/lib/rev/http_client.rb +88 -91
  201. data/lib/rev/listener.rb +22 -5
  202. data/lib/rev/loop.rb +13 -0
  203. data/lib/rev/server.rb +10 -3
  204. data/lib/rev/socket.rb +30 -9
  205. data/lib/rev/watcher.rb +4 -2
  206. data/lib/rev_ext.bundle +0 -0
  207. metadata +230 -2
data/ext/rev/rev_ext.c CHANGED
@@ -26,4 +26,5 @@ void Init_rev_ext()
26
26
  Init_rev_watcher();
27
27
  Init_rev_io_watcher();
28
28
  Init_rev_timer_watcher();
29
+ Init_rev_buffer();
29
30
  }
@@ -32,6 +32,13 @@ static VALUE Rev_IOWatcher_on_writable(VALUE self);
32
32
  static void Rev_IOWatcher_libev_callback(struct ev_loop *ev_loop, struct ev_io *io, int revents);
33
33
  static void Rev_IOWatcher_dispatch_callback(VALUE self, int revents);
34
34
 
35
+ /*
36
+ * Rev::IOWatcher monitors Ruby IO objects for readability or writability.
37
+ * This allows your application to block while the kernel is writing out
38
+ * data and fill the read or write buffer whenever there is space available.
39
+ * It's used by the Rev::BufferedIO class to provide high performace I/O
40
+ * which is bound by the kernel's ability to read and write data.
41
+ */
35
42
  void Init_rev_io_watcher()
36
43
  {
37
44
  mRev = rb_define_module("Rev");
@@ -56,27 +63,27 @@ void Init_rev_io_watcher()
56
63
  */
57
64
  static VALUE Rev_IOWatcher_initialize(int argc, VALUE *argv, VALUE self)
58
65
  {
59
- VALUE io, flags;
60
- char *flags_str;
61
- int events;
66
+ VALUE io, flags;
67
+ char *flags_str;
68
+ int events;
62
69
  rb_io_t *fptr;
63
70
  struct Rev_Watcher *watcher_data;
64
71
 
65
- rb_scan_args(argc, argv, "11", &io, &flags);
66
-
67
- if(flags != Qnil)
68
- flags_str = RSTRING_PTR(rb_String(flags));
69
- else
70
- flags_str = "r";
71
-
72
- if(!strcmp(flags_str, "r"))
73
- events = EV_READ;
74
- else if(!strcmp(flags_str, "w"))
75
- events = EV_WRITE;
76
- else if(!strcmp(flags_str, "rw"))
77
- events = EV_READ | EV_WRITE;
78
- else
79
- rb_raise(rb_eArgError, "invalid event type: '%s' (must be 'r', 'w', or 'rw')", flags_str);
72
+ rb_scan_args(argc, argv, "11", &io, &flags);
73
+
74
+ if(flags != Qnil)
75
+ flags_str = RSTRING_PTR(rb_String(flags));
76
+ else
77
+ flags_str = "r";
78
+
79
+ if(!strcmp(flags_str, "r"))
80
+ events = EV_READ;
81
+ else if(!strcmp(flags_str, "w"))
82
+ events = EV_WRITE;
83
+ else if(!strcmp(flags_str, "rw"))
84
+ events = EV_READ | EV_WRITE;
85
+ else
86
+ rb_raise(rb_eArgError, "invalid event type: '%s' (must be 'r', 'w', or 'rw')", flags_str);
80
87
 
81
88
  GetOpenFile(rb_convert_type(io, T_FILE, "IO", "to_io"), fptr);
82
89
  Data_Get_Struct(self, struct Rev_Watcher, watcher_data);
@@ -85,9 +92,16 @@ static VALUE Rev_IOWatcher_initialize(int argc, VALUE *argv, VALUE self)
85
92
  ev_io_init(&watcher_data->event_types.ev_io, Rev_IOWatcher_libev_callback, fptr->fd, events);
86
93
  watcher_data->event_types.ev_io.data = (void *)self;
87
94
 
88
- return Qnil;
95
+ return Qnil;
89
96
  }
90
97
 
98
+ /**
99
+ * call-seq:
100
+ * Rev::IOWatcher.attach(loop) -> Rev::IOWatcher
101
+ *
102
+ * Attach the IO watcher to the given Rev::Loop. If the watcher is already attached
103
+ * to a loop, detach it from the old one and attach it to the new one.
104
+ */
91
105
  static VALUE Rev_IOWatcher_attach(VALUE self, VALUE loop)
92
106
  {
93
107
  Watcher_Attach(io, Rev_IOWatcher_detach, self, loop);
@@ -95,6 +109,12 @@ static VALUE Rev_IOWatcher_attach(VALUE self, VALUE loop)
95
109
  return self;
96
110
  }
97
111
 
112
+ /**
113
+ * call-seq:
114
+ * Rev::IOWatcher.detach -> Rev::IOWatcher
115
+ *
116
+ * Detach the IO watcher from its current Rev::Loop.
117
+ */
98
118
  static VALUE Rev_IOWatcher_detach(VALUE self)
99
119
  {
100
120
  Watcher_Detach(io, self);
@@ -102,6 +122,13 @@ static VALUE Rev_IOWatcher_detach(VALUE self)
102
122
  return self;
103
123
  }
104
124
 
125
+ /**
126
+ * call-seq:
127
+ * Rev::IOWatcher.enable -> Rev::IOWatcher
128
+ *
129
+ * Re-enable an IO watcher which has been temporarily disabled. See the
130
+ * disable method for a more thorough explanation.
131
+ */
105
132
  static VALUE Rev_IOWatcher_enable(VALUE self)
106
133
  {
107
134
  Watcher_Enable(io, self);
@@ -109,6 +136,13 @@ static VALUE Rev_IOWatcher_enable(VALUE self)
109
136
  return self;
110
137
  }
111
138
 
139
+ /**
140
+ * call-seq:
141
+ * Rev::IOWatcher.disable -> Rev::IOWatcher
142
+ *
143
+ * Temporarily disable an IO watcher which is attached to a loop.
144
+ * This is useful if you wish to toggle event monitoring on and off.
145
+ */
112
146
  static VALUE Rev_IOWatcher_disable(VALUE self)
113
147
  {
114
148
  Watcher_Disable(io, self);
data/ext/rev/rev_loop.c CHANGED
@@ -22,7 +22,7 @@ static void Rev_Loop_mark(struct Rev_Loop *loop);
22
22
  static void Rev_Loop_free(struct Rev_Loop *loop);
23
23
 
24
24
  /* Method implementations */
25
- static VALUE Rev_Loop_default(VALUE klass);
25
+ static VALUE Rev_Loop_initialize(VALUE self);
26
26
  static VALUE Rev_Loop_ev_loop_new(VALUE self, VALUE flags);
27
27
  static VALUE Rev_Loop_run_once(VALUE self);
28
28
  static VALUE Rev_Loop_run_once_blocking(void *ptr);
@@ -32,18 +32,22 @@ static void Rev_Loop_dispatch_events(struct Rev_Loop *loop_data);
32
32
 
33
33
  #define DEFAULT_EVENTBUF_SIZE 32
34
34
 
35
+ /*
36
+ * Rev::Loop represents an event loop. Event watchers can be attached and
37
+ * unattached. When an event loop is run, all currently attached watchers
38
+ * are monitored for events, and their respective callbacks are signaled
39
+ * whenever events occur.
40
+ */
35
41
  void Init_rev_loop()
36
42
  {
37
43
  mRev = rb_define_module("Rev");
38
44
  cRev_Loop = rb_define_class_under(mRev, "Loop", rb_cObject);
39
45
  rb_define_alloc_func(cRev_Loop, Rev_Loop_allocate);
40
- rb_define_singleton_method(cRev_Loop, "default", Rev_Loop_default, 0);
41
-
46
+
47
+ rb_define_method(cRev_Loop, "initialize", Rev_Loop_initialize, 0);
42
48
  rb_define_private_method(cRev_Loop, "ev_loop_new", Rev_Loop_ev_loop_new, 1);
43
49
  rb_define_method(cRev_Loop, "run_once", Rev_Loop_run_once, 0);
44
50
  rb_define_method(cRev_Loop, "run_nonblock", Rev_Loop_run_nonblock, 0);
45
-
46
- rb_cv_set(cRev_Loop, "@@default_loop", Qnil);
47
51
  }
48
52
 
49
53
  static VALUE Rev_Loop_allocate(VALUE klass)
@@ -51,7 +55,6 @@ static VALUE Rev_Loop_allocate(VALUE klass)
51
55
  struct Rev_Loop *loop = (struct Rev_Loop *)xmalloc(sizeof(struct Rev_Loop));
52
56
 
53
57
  loop->ev_loop = 0;
54
- loop->default_loop = 0;
55
58
 
56
59
  loop->events_received = 0;
57
60
  loop->eventbuf_size = DEFAULT_EVENTBUF_SIZE;
@@ -69,40 +72,15 @@ static void Rev_Loop_free(struct Rev_Loop *loop)
69
72
  if(!loop->ev_loop)
70
73
  return;
71
74
 
72
- if(loop->default_loop)
73
- ev_default_destroy();
74
- else
75
- ev_loop_destroy(loop->ev_loop);
75
+ ev_loop_destroy(loop->ev_loop);
76
76
 
77
77
  xfree(loop->eventbuf);
78
78
  xfree(loop);
79
79
  }
80
80
 
81
-
82
- /**
83
- * call-seq:
84
- * Rev::Loop.default -> Rev::Loop
85
- *
86
- * Retrieve a singleton instance of the default loop for the application
87
- */
88
- static VALUE Rev_Loop_default(VALUE klass)
81
+ static VALUE Rev_Loop_initialize(VALUE self)
89
82
  {
90
- struct Rev_Loop *loop_data;
91
- VALUE default_loop = rb_cv_get(klass, "@@default_loop");
92
-
93
- if(default_loop == Qnil) {
94
- default_loop = rb_obj_alloc(klass);
95
- Data_Get_Struct(default_loop, struct Rev_Loop, loop_data);
96
-
97
- loop_data->ev_loop = ev_default_loop(0);
98
- loop_data->default_loop = 1;
99
-
100
- rb_cv_set(klass, "@@default_loop", default_loop);
101
- rb_iv_set(default_loop, "@active_watchers", INT2NUM(0));
102
- rb_iv_set(default_loop, "@watchers", rb_ary_new());
103
- }
104
-
105
- return default_loop;
83
+ Rev_Loop_ev_loop_new(self, INT2NUM(0));
106
84
  }
107
85
 
108
86
  /* Wrapper for populating a Rev_Loop struct with a new event loop */
@@ -115,7 +93,6 @@ static VALUE Rev_Loop_ev_loop_new(VALUE self, VALUE flags)
115
93
  rb_raise(rb_eRuntimeError, "loop already initialized");
116
94
 
117
95
  loop_data->ev_loop = ev_loop_new(NUM2INT(flags));
118
- loop_data->default_loop = 0;
119
96
 
120
97
  return Qnil;
121
98
  }
@@ -31,6 +31,11 @@ static VALUE Rev_TimerWatcher_on_timer(VALUE self);
31
31
  static void Rev_TimerWatcher_libev_callback(struct ev_loop *ev_loop, struct ev_timer *timer, int revents);
32
32
  static void Rev_TimerWatcher_dispatch_callback(VALUE self, int revents);
33
33
 
34
+ /*
35
+ * Rev::TimerWatcher lets you create either one-shot or periodic timers which
36
+ * run within Rev's event loop. It's useful for creating timeouts or
37
+ * events which fire periodically.
38
+ */
34
39
  void Init_rev_timer_watcher()
35
40
  {
36
41
  mRev = rb_define_module("Rev");
@@ -51,7 +56,11 @@ void Init_rev_timer_watcher()
51
56
  * call-seq:
52
57
  * Rev::TimerWatcher.initialize(interval, repeating = false) -> Rev::TimerWatcher
53
58
  *
54
- * Create a new Rev::TimerWatcher for the given IO object and add it to the given Rev::Loop
59
+ * Create a new Rev::TimerWatcher for the given IO object and add it to the
60
+ * given Rev::Loop. Interval defines a duration in seconds to wait for events,
61
+ * and can be specified as an Integer or Float. Repeating is a boolean
62
+ * indicating whether the timer is one shot or should fire on the given
63
+ * interval.
55
64
  */
56
65
  static VALUE Rev_TimerWatcher_initialize(int argc, VALUE *argv, VALUE self)
57
66
  {
@@ -59,16 +68,29 @@ static VALUE Rev_TimerWatcher_initialize(int argc, VALUE *argv, VALUE self)
59
68
  struct Rev_Watcher *watcher_data;
60
69
 
61
70
  rb_scan_args(argc, argv, "11", &interval, &repeating);
62
-
71
+ interval = rb_convert_type(interval, T_FLOAT, "Float", "to_f");
72
+
63
73
  Data_Get_Struct(self, struct Rev_Watcher, watcher_data);
64
74
 
65
75
  watcher_data->dispatch_callback = Rev_TimerWatcher_dispatch_callback;
66
- ev_timer_init(&watcher_data->event_types.ev_timer, Rev_TimerWatcher_libev_callback, NUM2INT(interval), repeating == Qtrue);
76
+ ev_timer_init(
77
+ &watcher_data->event_types.ev_timer,
78
+ Rev_TimerWatcher_libev_callback,
79
+ RFLOAT_VALUE(interval),
80
+ repeating == Qtrue ? RFLOAT_VALUE(interval) : 0
81
+ );
67
82
  watcher_data->event_types.ev_timer.data = (void *)self;
68
83
 
69
84
  return Qnil;
70
85
  }
71
86
 
87
+ /**
88
+ * call-seq:
89
+ * Rev::TimerWatcher.attach(loop) -> Rev::TimerWatcher
90
+ *
91
+ * Attach the timer watcher to the given Rev::Loop. If the watcher is already
92
+ * attached to a loop, detach it from the old one and attach it to the new one.
93
+ */
72
94
  static VALUE Rev_TimerWatcher_attach(VALUE self, VALUE loop)
73
95
  {
74
96
  Watcher_Attach(timer, Rev_TimerWatcher_detach, self, loop);
@@ -76,6 +98,12 @@ static VALUE Rev_TimerWatcher_attach(VALUE self, VALUE loop)
76
98
  return self;
77
99
  }
78
100
 
101
+ /**
102
+ * call-seq:
103
+ * Rev::TimerWatcher.detach -> Rev::TimerWatcher
104
+ *
105
+ * Detach the timer watcher from its current Rev::Loop.
106
+ */
79
107
  static VALUE Rev_TimerWatcher_detach(VALUE self)
80
108
  {
81
109
  Watcher_Detach(timer, self);
@@ -83,6 +111,13 @@ static VALUE Rev_TimerWatcher_detach(VALUE self)
83
111
  return self;
84
112
  }
85
113
 
114
+ /**
115
+ * call-seq:
116
+ * Rev::TimerWatcher.enable -> Rev::TimerWatcher
117
+ *
118
+ * Re-enable a timer watcher which has been temporarily disabled. See the
119
+ * disable method for a more thorough explanation.
120
+ */
86
121
  static VALUE Rev_TimerWatcher_enable(VALUE self)
87
122
  {
88
123
  Watcher_Enable(timer, self);
@@ -90,6 +125,13 @@ static VALUE Rev_TimerWatcher_enable(VALUE self)
90
125
  return self;
91
126
  }
92
127
 
128
+ /**
129
+ * call-seq:
130
+ * Rev::TimerWatcher.disable -> Rev::TimerWatcher
131
+ *
132
+ * Temporarily disable a timer watcher which is attached to a loop.
133
+ * This is useful if you wish to toggle event monitoring on and off.
134
+ */
93
135
  static VALUE Rev_TimerWatcher_disable(VALUE self)
94
136
  {
95
137
  Watcher_Disable(timer, self);
@@ -30,6 +30,18 @@ static VALUE Rev_Watcher_evloop(VALUE self);
30
30
  static VALUE Rev_Watcher_attached(VALUE self);
31
31
  static VALUE Rev_Watcher_enabled(VALUE self);
32
32
 
33
+ /*
34
+ * Watchers are Rev's event observers. They contain a set of callback
35
+ * methods prefixed by on_* which fire whenever events occur.
36
+ *
37
+ * In order for a watcher to fire events it must be attached to a running
38
+ * loop. Every watcher has an attach and detach method to control which
39
+ * loop it's associated with.
40
+ *
41
+ * Watchers also have an enable and disable method. This allows a watcher
42
+ * to temporarily ignore certain events while remaining attached to a given
43
+ * loop. This is good for watchers which need to be toggled on and off.
44
+ */
33
45
  void Init_rev_watcher()
34
46
  {
35
47
  mRev = rb_define_module("Rev");
@@ -235,4 +247,4 @@ static VALUE Rev_Watcher_enabled(VALUE self)
235
247
  Data_Get_Struct(self, struct Rev_Watcher, watcher_data);
236
248
 
237
249
  return watcher_data->enabled ? Qtrue : Qfalse;
238
- }
250
+ }
Binary file
data/lib/rev.rb CHANGED
@@ -17,6 +17,6 @@ require File.dirname(__FILE__) + '/rev/server'
17
17
  require File.dirname(__FILE__) + '/rev/http_client'
18
18
 
19
19
  module Rev
20
- Rev::VERSION = '0.1.1' unless defined? Rev::VERSION
20
+ Rev::VERSION = '0.1.2' unless defined? Rev::VERSION
21
21
  def self.version() VERSION end
22
22
  end
@@ -7,13 +7,21 @@
7
7
  require File.dirname(__FILE__) + '/../rev'
8
8
 
9
9
  module Rev
10
+ # A buffered I/O class witch fits into the Rev Watcher framework.
11
+ # It provides both an observer which reads data as it's received
12
+ # from the wire and a buffered writer which stores data and writes
13
+ # it out each time the socket becomes writable.
14
+ #
15
+ # This class is primarily meant as a base class for other streams
16
+ # which need non-blocking writing, and is used to implement Rev's
17
+ # Socket class and its associated subclasses.
10
18
  class BufferedIO < IOWatcher
11
19
  # Maximum number of bytes to consume at once
12
20
  INPUT_SIZE = 16384
13
21
 
14
22
  def initialize(io)
15
23
  # Output buffer
16
- @write_buffer = ''
24
+ @write_buffer = Rev::Buffer.new
17
25
 
18
26
  # Coerce the argument into an IO object if possible
19
27
  @io = IO.try_convert(io)
@@ -23,7 +31,7 @@ module Rev
23
31
  #
24
32
  # Callbacks for asynchronous events
25
33
  #
26
-
34
+
27
35
  # Called whenever the IO object receives data
28
36
  def on_read(data); end
29
37
  event_callback :on_read
@@ -42,23 +50,7 @@ module Rev
42
50
 
43
51
  # Write data in a buffered, non-blocking manner
44
52
  def write(data)
45
- # Attempt a zero copy write
46
- if @write_buffer.empty?
47
- written = write_nonblock data
48
-
49
- # If we lucked out and wrote out the whole buffer, return
50
- if written == data.size
51
- on_write_complete
52
- return data.size
53
- end
54
-
55
- # Otherwise slice what we wrote out and begin buffered writing
56
- data.slice!(0, written) if written
57
- end
58
-
59
- @write_buffer << data
60
- schedule_write
61
- data.size
53
+ buffered_write data
62
54
  end
63
55
 
64
56
  # Number of bytes are currently in the output buffer
@@ -73,19 +65,30 @@ module Rev
73
65
  @io.close unless @io.closed?
74
66
 
75
67
  on_close
68
+ nil
69
+ end
70
+
71
+ # Is the IO object closed?
72
+ def closed?
73
+ @io.closed?
76
74
  end
77
75
 
78
76
  #########
79
77
  protected
80
78
  #########
81
79
 
80
+ # Buffered writer
81
+ def buffered_write(data)
82
+ @write_buffer << data
83
+ schedule_write
84
+ data.size
85
+ end
86
+
82
87
  # Attempt to write the contents of the output buffer
83
88
  def write_output_buffer
84
89
  return if @write_buffer.empty?
85
90
 
86
- written = write_nonblock @write_buffer
87
- @write_buffer.slice!(0, written) if written
88
-
91
+ @write_buffer.write_to(@io)
89
92
  return unless @write_buffer.empty?
90
93
 
91
94
  @writer.disable if @writer and @writer.enabled?
@@ -17,6 +17,17 @@ require File.dirname(__FILE__) + '/../rev'
17
17
  #++
18
18
 
19
19
  module Rev
20
+ # A non-blocking DNS resolver. It provides interfaces for querying both
21
+ # /etc/hosts and nameserves listed in /etc/resolv.conf, or nameservers of
22
+ # your choosing.
23
+ #
24
+ # Presently the client only supports UDP requests against your nameservers
25
+ # and cannot resolve anything with records larger than 512-bytes. Also,
26
+ # IPv6 is not presently supported.
27
+ #
28
+ # DNSResolver objects are one-shot. Once they resolve a domain name they
29
+ # automatically detach themselves from the event loop and cannot be used
30
+ # again.
20
31
  class DNSResolver < IOWatcher
21
32
  RESOLV_CONF = '/etc/resolv.conf'
22
33
  HOSTS = '/etc/hosts'
@@ -25,9 +36,10 @@ module Rev
25
36
  TIMEOUT = 3 # Retry timeout for each datagram sent
26
37
  RETRIES = 4 # Number of retries to attempt
27
38
 
28
- def self.hosts(host)
39
+ # Query /etc/hosts (or the specified hostfile) for the given host
40
+ def self.hosts(host, hostfile = HOSTS)
29
41
  hosts = {}
30
- File.open(HOSTS).each_line do |host_entry|
42
+ File.open(hostfile).each_line do |host_entry|
31
43
  entries = host_entry.gsub(/#.*$/, '').gsub(/\s+/, ' ').split(' ')
32
44
  addr = entries.shift
33
45
  entries.each { |e| hosts[e] ||= addr }
@@ -36,6 +48,10 @@ module Rev
36
48
  hosts[host]
37
49
  end
38
50
 
51
+ # Create a new Rev::Watcher descended object to resolve the
52
+ # given hostname. If you so desire you can also specify a
53
+ # list of nameservers to query. By default the resolver will
54
+ # use nameservers listed in /etc/resolv.conf
39
55
  def initialize(hostname, *nameservers)
40
56
  if nameservers.empty?
41
57
  nameservers = File.read(RESOLV_CONF).scan(/^\s*nameserver\s+([0-9.:]+)/).flatten
@@ -44,30 +60,26 @@ module Rev
44
60
 
45
61
  @nameservers = nameservers
46
62
  @question = request_question hostname
47
-
63
+
48
64
  @socket = UDPSocket.new
49
65
  @timer = Timeout.new(self)
50
66
 
51
67
  super(@socket)
52
68
  end
53
69
 
70
+ # Attach the DNSResolver to the given event loop
54
71
  def attach(evloop)
55
72
  send_request
56
73
  @timer.attach(evloop)
57
74
  super
58
75
  end
59
76
 
77
+ # Detach the DNSResolver from the given event loop
60
78
  def detach
61
79
  @timer.detach if @timer.attached?
62
80
  super
63
81
  end
64
82
 
65
- # Send a request to the DNS server
66
- def send_request
67
- @socket.connect @nameservers.first, DNS_PORT
68
- @socket.send request_message, 0
69
- end
70
-
71
83
  # Called when the name has successfully resolved to an address
72
84
  def on_success(address); end
73
85
  event_callback :on_success
@@ -76,14 +88,19 @@ module Rev
76
88
  def on_failure; end
77
89
  event_callback :on_failure
78
90
 
79
- # Called if we don't receive a response
80
- def on_timeout; end
81
- event_callback :on_timeout
91
+ # Called if we don't receive a response, defaults to on_failure
92
+ alias_method :on_timeout, :on_failure
82
93
 
83
94
  #########
84
95
  protected
85
96
  #########
86
97
 
98
+ # Send a request to the DNS server
99
+ def send_request
100
+ @socket.connect @nameservers.first, DNS_PORT
101
+ @socket.send request_message, 0
102
+ end
103
+
87
104
  # Called by the subclass when the DNS response is available
88
105
  def on_readable
89
106
  datagram = @socket.recvfrom_nonblock(DATAGRAM_SIZE).first
@@ -169,11 +186,11 @@ module Rev
169
186
 
170
187
  def on_timer
171
188
  @attempts += 1
172
- return @resolver.send_request if @attempts <= RETRIES
189
+ return @resolver.__send__(:send_request) if @attempts <= RETRIES
173
190
 
174
191
  @resolver.__send__(:on_timeout)
175
192
  @resolver.detach
176
193
  end
177
194
  end
178
195
  end
179
- end
196
+ end