eventmachine-maglev- 0.12.10 → 1.0.0.beta.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (174) hide show
  1. data/.gitignore +7 -0
  2. data/.yardopts +7 -0
  3. data/Gemfile +3 -0
  4. data/README.md +109 -0
  5. data/Rakefile +14 -368
  6. data/docs/DocumentationGuidesIndex.md +27 -0
  7. data/docs/GettingStarted.md +521 -0
  8. data/docs/old/DEFERRABLES +246 -0
  9. data/docs/{KEYBOARD → old/KEYBOARD} +15 -11
  10. data/docs/old/LIGHTWEIGHT_CONCURRENCY +130 -0
  11. data/docs/old/SMTP +4 -0
  12. data/docs/old/SPAWNED_PROCESSES +148 -0
  13. data/eventmachine.gemspec +20 -26
  14. data/examples/guides/getting_started/01_eventmachine_echo_server.rb +18 -0
  15. data/examples/guides/getting_started/02_eventmachine_echo_server_that_recognizes_exit_command.rb +22 -0
  16. data/examples/guides/getting_started/03_simple_chat_server.rb +149 -0
  17. data/examples/guides/getting_started/04_simple_chat_server_step_one.rb +27 -0
  18. data/examples/guides/getting_started/05_simple_chat_server_step_two.rb +43 -0
  19. data/examples/guides/getting_started/06_simple_chat_server_step_three.rb +98 -0
  20. data/examples/guides/getting_started/07_simple_chat_server_step_four.rb +121 -0
  21. data/examples/guides/getting_started/08_simple_chat_server_step_five.rb +141 -0
  22. data/examples/{ex_channel.rb → old/ex_channel.rb} +3 -3
  23. data/examples/old/ex_tick_loop_array.rb +15 -0
  24. data/examples/old/ex_tick_loop_counter.rb +32 -0
  25. data/ext/binder.cpp +0 -1
  26. data/ext/cmain.cpp +40 -29
  27. data/ext/ed.cpp +189 -134
  28. data/ext/ed.h +34 -40
  29. data/ext/em.cpp +388 -340
  30. data/ext/em.h +29 -32
  31. data/ext/eventmachine.h +7 -6
  32. data/ext/extconf.rb +57 -48
  33. data/ext/fastfilereader/extconf.rb +5 -3
  34. data/ext/fastfilereader/mapper.cpp +1 -1
  35. data/ext/fastfilereader/rubymain.cpp +0 -1
  36. data/ext/kb.cpp +1 -3
  37. data/ext/pipe.cpp +9 -11
  38. data/ext/project.h +12 -8
  39. data/ext/rubymain.cpp +158 -112
  40. data/java/src/com/rubyeventmachine/EmReactor.java +3 -2
  41. data/lib/em/buftok.rb +35 -63
  42. data/lib/em/callback.rb +43 -11
  43. data/lib/em/channel.rb +22 -15
  44. data/lib/em/completion.rb +303 -0
  45. data/lib/em/connection.rb +341 -208
  46. data/lib/em/deferrable/pool.rb +2 -0
  47. data/lib/em/deferrable.rb +20 -2
  48. data/lib/em/file_watch.rb +37 -18
  49. data/lib/em/iterator.rb +270 -0
  50. data/lib/em/pool.rb +146 -0
  51. data/lib/em/process_watch.rb +5 -4
  52. data/lib/em/processes.rb +8 -4
  53. data/lib/em/protocols/httpclient.rb +27 -11
  54. data/lib/em/protocols/httpclient2.rb +15 -5
  55. data/lib/em/protocols/line_protocol.rb +29 -0
  56. data/lib/em/protocols/memcache.rb +17 -9
  57. data/lib/em/protocols/object_protocol.rb +2 -1
  58. data/lib/em/protocols/postgres3.rb +2 -1
  59. data/lib/em/protocols/smtpclient.rb +19 -11
  60. data/lib/em/protocols/smtpserver.rb +101 -8
  61. data/lib/em/protocols/stomp.rb +9 -7
  62. data/lib/em/protocols/tcptest.rb +3 -2
  63. data/lib/em/protocols.rb +1 -1
  64. data/lib/{pr_eventmachine.rb → em/pure_ruby.rb} +188 -205
  65. data/lib/em/queue.rb +23 -13
  66. data/lib/em/resolver.rb +192 -0
  67. data/lib/em/spawnable.rb +9 -10
  68. data/lib/em/streamer.rb +34 -46
  69. data/lib/em/threaded_resource.rb +90 -0
  70. data/lib/em/tick_loop.rb +85 -0
  71. data/lib/em/timers.rb +8 -3
  72. data/lib/em/version.rb +1 -1
  73. data/lib/eventmachine.rb +582 -686
  74. data/lib/jeventmachine.rb +25 -3
  75. data/tasks/package.rake +98 -0
  76. data/tasks/test.rake +8 -0
  77. data/tests/em_test_helper.rb +64 -0
  78. data/tests/test_attach.rb +56 -56
  79. data/tests/test_basic.rb +111 -168
  80. data/tests/test_channel.rb +5 -6
  81. data/tests/test_completion.rb +177 -0
  82. data/tests/test_connection_count.rb +1 -3
  83. data/tests/test_defer.rb +3 -32
  84. data/tests/test_deferrable.rb +35 -0
  85. data/tests/test_epoll.rb +27 -57
  86. data/tests/test_error_handler.rb +10 -7
  87. data/tests/test_exc.rb +6 -33
  88. data/tests/test_file_watch.rb +51 -35
  89. data/tests/test_futures.rb +10 -38
  90. data/tests/test_get_sock_opt.rb +27 -20
  91. data/tests/test_handler_check.rb +1 -3
  92. data/tests/test_hc.rb +49 -112
  93. data/tests/test_httpclient.rb +34 -62
  94. data/tests/test_httpclient2.rb +14 -39
  95. data/tests/test_inactivity_timeout.rb +44 -40
  96. data/tests/test_kb.rb +26 -52
  97. data/tests/test_ltp.rb +27 -71
  98. data/tests/test_ltp2.rb +1 -30
  99. data/tests/test_next_tick.rb +2 -31
  100. data/tests/test_object_protocol.rb +8 -9
  101. data/tests/test_pause.rb +45 -37
  102. data/tests/test_pending_connect_timeout.rb +42 -38
  103. data/tests/test_pool.rb +128 -0
  104. data/tests/test_process_watch.rb +37 -37
  105. data/tests/test_processes.rb +92 -110
  106. data/tests/test_proxy_connection.rb +137 -61
  107. data/tests/test_pure.rb +30 -67
  108. data/tests/test_queue.rb +10 -4
  109. data/tests/test_resolver.rb +55 -0
  110. data/tests/test_running.rb +1 -29
  111. data/tests/test_sasl.rb +8 -33
  112. data/tests/test_send_file.rb +163 -188
  113. data/tests/test_servers.rb +12 -55
  114. data/tests/test_shutdown_hooks.rb +23 -0
  115. data/tests/test_smtpclient.rb +1 -29
  116. data/tests/test_smtpserver.rb +1 -29
  117. data/tests/test_spawn.rb +2 -31
  118. data/tests/test_ssl_args.rb +9 -10
  119. data/tests/test_ssl_methods.rb +1 -3
  120. data/tests/test_ssl_verify.rb +63 -63
  121. data/tests/test_threaded_resource.rb +53 -0
  122. data/tests/test_tick_loop.rb +59 -0
  123. data/tests/test_timers.rb +52 -91
  124. data/tests/test_ud.rb +1 -29
  125. data/tests/test_unbind_reason.rb +31 -0
  126. metadata +113 -70
  127. data/README +0 -82
  128. data/docs/DEFERRABLES +0 -133
  129. data/docs/LIGHTWEIGHT_CONCURRENCY +0 -70
  130. data/docs/SMTP +0 -2
  131. data/docs/SPAWNED_PROCESSES +0 -89
  132. data/ext/cplusplus.cpp +0 -202
  133. data/ext/emwin.cpp +0 -300
  134. data/ext/emwin.h +0 -94
  135. data/ext/epoll.cpp +0 -26
  136. data/ext/epoll.h +0 -25
  137. data/ext/eventmachine_cpp.h +0 -96
  138. data/ext/files.cpp +0 -94
  139. data/ext/files.h +0 -65
  140. data/ext/sigs.cpp +0 -89
  141. data/ext/sigs.h +0 -32
  142. data/java/src/com/rubyeventmachine/application/Application.java +0 -194
  143. data/java/src/com/rubyeventmachine/application/Connection.java +0 -74
  144. data/java/src/com/rubyeventmachine/application/ConnectionFactory.java +0 -37
  145. data/java/src/com/rubyeventmachine/application/DefaultConnectionFactory.java +0 -46
  146. data/java/src/com/rubyeventmachine/application/PeriodicTimer.java +0 -38
  147. data/java/src/com/rubyeventmachine/application/Timer.java +0 -54
  148. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +0 -109
  149. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +0 -148
  150. data/java/src/com/rubyeventmachine/tests/EMTest.java +0 -80
  151. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +0 -53
  152. data/java/src/com/rubyeventmachine/tests/TestServers.java +0 -75
  153. data/java/src/com/rubyeventmachine/tests/TestTimers.java +0 -90
  154. data/lib/evma/callback.rb +0 -32
  155. data/lib/evma/container.rb +0 -75
  156. data/lib/evma/factory.rb +0 -77
  157. data/lib/evma/protocol.rb +0 -87
  158. data/lib/evma/reactor.rb +0 -48
  159. data/lib/evma.rb +0 -32
  160. data/setup.rb +0 -1585
  161. data/tests/test_errors.rb +0 -82
  162. data/tests/testem.rb +0 -31
  163. data/web/whatis +0 -7
  164. /data/{docs/GNU → GNU} +0 -0
  165. /data/{docs/COPYING → LICENSE} +0 -0
  166. /data/docs/{ChangeLog → old/ChangeLog} +0 -0
  167. /data/docs/{EPOLL → old/EPOLL} +0 -0
  168. /data/docs/{INSTALL → old/INSTALL} +0 -0
  169. /data/docs/{LEGAL → old/LEGAL} +0 -0
  170. /data/docs/{PURE_RUBY → old/PURE_RUBY} +0 -0
  171. /data/docs/{RELEASE_NOTES → old/RELEASE_NOTES} +0 -0
  172. /data/docs/{TODO → old/TODO} +0 -0
  173. /data/examples/{ex_queue.rb → old/ex_queue.rb} +0 -0
  174. /data/examples/{helper.rb → old/helper.rb} +0 -0
@@ -3,7 +3,7 @@
3
3
  # Author:: Francis Cianfrocca (gmail: blackhedd)
4
4
  # Homepage:: http://rubyeventmachine.com
5
5
  # Date:: 8 Apr 2006
6
- #
6
+ #
7
7
  # See EventMachine and EventMachine::Connection for documentation and
8
8
  # usage examples.
9
9
  #
@@ -11,17 +11,17 @@
11
11
  #
12
12
  # Copyright (C) 2006-07 by Francis Cianfrocca. All Rights Reserved.
13
13
  # Gmail: blackhedd
14
- #
14
+ #
15
15
  # This program is free software; you can redistribute it and/or modify
16
16
  # it under the terms of either: 1) the GNU General Public License
17
17
  # as published by the Free Software Foundation; either version 2 of the
18
18
  # License, or (at your option) any later version; or 2) Ruby's License.
19
- #
19
+ #
20
20
  # See the file COPYING for complete licensing information.
21
21
  #
22
22
  #-------------------------------------------------------------------
23
23
  #
24
- #
24
+ #
25
25
 
26
26
  # TODO List:
27
27
  # TCP-connects currently assume non-blocking connect is available- need to
@@ -34,330 +34,318 @@ require 'socket'
34
34
  require 'fcntl'
35
35
  require 'set'
36
36
 
37
-
37
+ # @private
38
38
  module EventMachine
39
-
40
-
41
39
  class << self
42
40
  # This is mostly useful for automated tests.
43
41
  # Return a distinctive symbol so the caller knows whether he's dealing
44
42
  # with an extension or with a pure-Ruby library.
43
+ # @private
45
44
  def library_type
46
45
  :pure_ruby
47
46
  end
48
47
 
49
- # #initialize_event_machine
48
+ # @private
50
49
  def initialize_event_machine
51
50
  Reactor.instance.initialize_for_run
52
51
  end
53
52
 
54
- # #add_oneshot_timer
55
- #--
56
53
  # Changed 04Oct06: intervals from the caller are now in milliseconds, but our native-ruby
57
54
  # processor still wants them in seconds.
55
+ # @private
58
56
  def add_oneshot_timer interval
59
57
  Reactor.instance.install_oneshot_timer(interval / 1000)
60
58
  end
61
59
 
62
- # run_machine
60
+ # @private
63
61
  def run_machine
64
62
  Reactor.instance.run
65
63
  end
66
64
 
67
- # release_machine. Probably a no-op.
65
+ # @private
68
66
  def release_machine
69
67
  end
70
68
 
71
- # #stop
69
+ # @private
72
70
  def stop
73
71
  Reactor.instance.stop
74
72
  end
75
73
 
76
- # #connect_server. Return a connection descriptor to the caller.
77
- # TODO, what do we return here if we can't connect?
74
+ # @private
78
75
  def connect_server host, port
79
76
  bind_connect_server nil, nil, host, port
80
77
  end
81
78
 
79
+ # @private
82
80
  def bind_connect_server bind_addr, bind_port, host, port
83
81
  EvmaTCPClient.connect(bind_addr, bind_port, host, port).uuid
84
82
  end
85
83
 
86
- # #send_data
84
+ # @private
87
85
  def send_data target, data, datalength
88
86
  selectable = Reactor.instance.get_selectable( target ) or raise "unknown send_data target"
89
87
  selectable.send_data data
90
88
  end
91
89
 
92
- # #close_connection
90
+
93
91
  # The extension version does NOT raise any kind of an error if an attempt is made
94
92
  # to close a non-existent connection. Not sure whether we should. For now, we'll
95
93
  # raise an error here in that case.
94
+ # @private
96
95
  def close_connection target, after_writing
97
96
  selectable = Reactor.instance.get_selectable( target ) or raise "unknown close_connection target"
98
97
  selectable.schedule_close after_writing
99
98
  end
100
99
 
101
- # #start_tcp_server
100
+ # @private
102
101
  def start_tcp_server host, port
103
102
  (s = EvmaTCPServer.start_server host, port) or raise "no acceptor"
104
103
  s.uuid
105
104
  end
106
105
 
107
- # #stop_tcp_server
106
+ # @private
108
107
  def stop_tcp_server sig
109
108
  s = Reactor.instance.get_selectable(sig)
110
109
  s.schedule_close
111
110
  end
112
111
 
113
- # #start_unix_server
112
+ # @private
114
113
  def start_unix_server chain
115
114
  (s = EvmaUNIXServer.start_server chain) or raise "no acceptor"
116
115
  s.uuid
117
116
  end
118
117
 
119
- # #connect_unix_server
118
+ # @private
120
119
  def connect_unix_server chain
121
120
  EvmaUNIXClient.connect(chain).uuid
122
121
  end
123
122
 
124
- # #signal_loopbreak
123
+ # @private
125
124
  def signal_loopbreak
126
125
  Reactor.instance.signal_loopbreak
127
126
  end
128
127
 
129
- # #get_peername
128
+ # @private
130
129
  def get_peername sig
131
130
  selectable = Reactor.instance.get_selectable( sig ) or raise "unknown get_peername target"
132
131
  selectable.get_peername
133
132
  end
134
133
 
135
- # #open_udp_socket
134
+ # @private
136
135
  def open_udp_socket host, port
137
136
  EvmaUDPSocket.create(host, port).uuid
138
137
  end
139
138
 
140
- # #send_datagram. This is currently only for UDP!
139
+ # This is currently only for UDP!
141
140
  # We need to make it work with unix-domain sockets as well.
141
+ # @private
142
142
  def send_datagram target, data, datalength, host, port
143
143
  selectable = Reactor.instance.get_selectable( target ) or raise "unknown send_data target"
144
144
  selectable.send_datagram data, Socket::pack_sockaddr_in(port, host)
145
145
  end
146
146
 
147
147
 
148
- # #set_timer_quantum in milliseconds. The underlying Reactor function wants a (possibly
148
+ # Sets reactor quantum in milliseconds. The underlying Reactor function wants a (possibly
149
149
  # fractional) number of seconds.
150
+ # @private
150
151
  def set_timer_quantum interval
151
152
  Reactor.instance.set_timer_quantum(( 1.0 * interval) / 1000.0)
152
153
  end
153
154
 
154
- # #epoll is a harmless no-op in the pure-Ruby implementation. This is intended to ensure
155
+ # This method is a harmless no-op in the pure-Ruby implementation. This is intended to ensure
155
156
  # that user code behaves properly across different EM implementations.
157
+ # @private
156
158
  def epoll
157
159
  end
158
160
 
159
- # #ssl? is not implemented for pure-Ruby implementation
161
+ # This method is not implemented for pure-Ruby implementation
162
+ # @private
160
163
  def ssl?
161
164
  false
162
165
  end
163
166
 
164
- # #set_rlimit_nofile is a no-op in the pure-Ruby implementation. We simply return Ruby's built-in
167
+ # This method is a no-op in the pure-Ruby implementation. We simply return Ruby's built-in
165
168
  # per-process file-descriptor limit.
169
+ # @private
166
170
  def set_rlimit_nofile n
167
171
  1024
168
172
  end
169
173
 
170
- # #set_max_timer_count is a harmless no-op in pure Ruby, which doesn't have a built-in limit
174
+ # This method is a harmless no-op in pure Ruby, which doesn't have a built-in limit
171
175
  # on the number of available timers.
176
+ # @private
172
177
  def set_max_timer_count n
173
178
  end
174
179
 
175
- # #send_file_data
180
+ # @private
176
181
  def send_file_data sig, filename
177
182
  sz = File.size(filename)
178
183
  raise "file too large" if sz > 32*1024
179
184
  data =
180
- begin
181
- File.read filename
182
- rescue
183
- ""
184
- end
185
+ begin
186
+ File.read filename
187
+ rescue
188
+ ""
189
+ end
185
190
  send_data sig, data, data.length
186
191
  end
187
192
 
188
- # #get_outbound_data_size
189
- #
193
+ # @private
190
194
  def get_outbound_data_size sig
191
195
  r = Reactor.instance.get_selectable( sig ) or raise "unknown get_outbound_data_size target"
192
196
  r.get_outbound_data_size
193
197
  end
194
198
 
195
- # #read_keyboard
196
- #
199
+ # @private
197
200
  def read_keyboard
198
201
  EvmaKeyboard.open.uuid
199
202
  end
200
203
 
201
- # #set_comm_inactivity_timeout
202
- #
204
+ # @private
203
205
  def set_comm_inactivity_timeout sig, tm
204
206
  r = Reactor.instance.get_selectable( sig ) or raise "unknown set_comm_inactivity_timeout target"
205
207
  r.set_inactivity_timeout tm
206
208
  end
207
209
  end
208
-
209
210
  end
210
211
 
211
212
 
212
- #-----------------------------------------------------------------
213
-
214
213
  module EventMachine
215
-
214
+ # @private
216
215
  class Error < Exception; end
217
-
218
216
  end
219
217
 
220
- #-----------------------------------------------------------------
221
-
222
218
  module EventMachine
219
+ # @private
223
220
  class Connection
221
+ # @private
224
222
  def get_outbound_data_size
225
223
  EventMachine::get_outbound_data_size @signature
226
224
  end
227
225
  end
228
226
  end
229
227
 
230
- #-----------------------------------------------------------------
231
-
232
228
  module EventMachine
233
229
 
234
230
  # Factored out so we can substitute other implementations
235
231
  # here if desired, such as the one in ActiveRBAC.
232
+ # @private
236
233
  module UuidGenerator
237
-
238
234
  def self.generate
239
- if @ix and @ix >= 10000
240
- @ix = nil
241
- @seed = nil
242
- end
243
-
244
- @seed ||= `uuidgen`.chomp.gsub(/-/,"")
245
235
  @ix ||= 0
246
-
247
- "#{@seed}#{@ix += 1}"
236
+ @ix += 1
248
237
  end
249
-
250
238
  end
251
-
252
239
  end
253
240
 
254
- #-----------------------------------------------------------------
255
241
 
256
242
  module EventMachine
257
-
243
+ # @private
258
244
  TimerFired = 100
245
+ # @private
259
246
  ConnectionData = 101
247
+ # @private
260
248
  ConnectionUnbound = 102
249
+ # @private
261
250
  ConnectionAccepted = 103
251
+ # @private
262
252
  ConnectionCompleted = 104
253
+ # @private
263
254
  LoopbreakSignalled = 105
264
-
265
255
  end
266
256
 
267
- #-----------------------------------------------------------------
268
-
269
257
  module EventMachine
270
- class Reactor
271
- include Singleton
258
+ # @private
259
+ class Reactor
260
+ include Singleton
272
261
 
273
- HeartbeatInterval = 2
262
+ HeartbeatInterval = 2
274
263
 
275
- attr_reader :current_loop_time
264
+ attr_reader :current_loop_time
276
265
 
277
- def initialize
278
- initialize_for_run
279
- end
266
+ def initialize
267
+ initialize_for_run
268
+ end
280
269
 
281
- #--
282
- # Replaced original implementation 05Dec07, was way too slow because of the sort.
283
- def install_oneshot_timer interval
284
- uuid = UuidGenerator::generate
285
- #@timers << [Time.now + interval, uuid]
286
- #@timers.sort! {|a,b| a.first <=> b.first}
287
- @timers.add([Time.now + interval, uuid])
288
- uuid
289
- end
270
+ def install_oneshot_timer interval
271
+ uuid = UuidGenerator::generate
272
+ #@timers << [Time.now + interval, uuid]
273
+ #@timers.sort! {|a,b| a.first <=> b.first}
274
+ @timers.add([Time.now + interval, uuid])
275
+ uuid
276
+ end
290
277
 
291
- # Called before run, this is a good place to clear out arrays
292
- # with cruft that may be left over from a previous run.
293
- def initialize_for_run
294
- @running = false
295
- @stop_scheduled = false
296
- @selectables ||= {}; @selectables.clear
297
- @timers = SortedSet.new # []
298
- set_timer_quantum(0.1)
299
- @current_loop_time = Time.now
300
- @next_heartbeat = @current_loop_time + HeartbeatInterval
301
- end
278
+ # Called before run, this is a good place to clear out arrays
279
+ # with cruft that may be left over from a previous run.
280
+ # @private
281
+ def initialize_for_run
282
+ @running = false
283
+ @stop_scheduled = false
284
+ @selectables ||= {}; @selectables.clear
285
+ @timers = SortedSet.new # []
286
+ set_timer_quantum(0.1)
287
+ @current_loop_time = Time.now
288
+ @next_heartbeat = @current_loop_time + HeartbeatInterval
289
+ end
302
290
 
303
- def add_selectable io
304
- @selectables[io.uuid] = io
305
- end
291
+ def add_selectable io
292
+ @selectables[io.uuid] = io
293
+ end
306
294
 
307
- def get_selectable uuid
308
- @selectables[uuid]
309
- end
295
+ def get_selectable uuid
296
+ @selectables[uuid]
297
+ end
310
298
 
311
- def run
312
- raise Error.new( "already running" ) if @running
313
- @running = true
299
+ def run
300
+ raise Error.new( "already running" ) if @running
301
+ @running = true
314
302
 
315
- begin
316
- open_loopbreaker
303
+ begin
304
+ open_loopbreaker
317
305
 
318
- loop {
319
- @current_loop_time = Time.now
306
+ loop {
307
+ @current_loop_time = Time.now
320
308
 
321
- break if @stop_scheduled
322
- run_timers
323
- break if @stop_scheduled
324
- crank_selectables
325
- break if @stop_scheduled
326
- run_heartbeats
327
- }
328
- ensure
329
- close_loopbreaker
330
- @selectables.each {|k, io| io.close}
331
- @selectables.clear
309
+ break if @stop_scheduled
310
+ run_timers
311
+ break if @stop_scheduled
312
+ crank_selectables
313
+ break if @stop_scheduled
314
+ run_heartbeats
315
+ }
316
+ ensure
317
+ close_loopbreaker
318
+ @selectables.each {|k, io| io.close}
319
+ @selectables.clear
320
+
321
+ @running = false
322
+ end
332
323
 
333
- @running = false
334
324
  end
335
325
 
336
- end
326
+ def run_timers
327
+ @timers.each {|t|
328
+ if t.first <= @current_loop_time
329
+ @timers.delete t
330
+ EventMachine::event_callback "", TimerFired, t.last
331
+ else
332
+ break
333
+ end
334
+ }
335
+ #while @timers.length > 0 and @timers.first.first <= now
336
+ # t = @timers.shift
337
+ # EventMachine::event_callback "", TimerFired, t.last
338
+ #end
339
+ end
337
340
 
338
- def run_timers
339
- @timers.each {|t|
340
- if t.first <= @current_loop_time
341
- @timers.delete t
342
- EventMachine::event_callback "", TimerFired, t.last
343
- else
344
- break
341
+ def run_heartbeats
342
+ if @next_heartbeat <= @current_loop_time
343
+ @next_heartbeat = @current_loop_time + HeartbeatInterval
344
+ @selectables.each {|k,io| io.heartbeat}
345
345
  end
346
- }
347
- #while @timers.length > 0 and @timers.first.first <= now
348
- # t = @timers.shift
349
- # EventMachine::event_callback "", TimerFired, t.last
350
- #end
351
- end
352
-
353
- def run_heartbeats
354
- if @next_heartbeat <= @current_loop_time
355
- @next_heartbeat = @current_loop_time + HeartbeatInterval
356
- @selectables.each {|k,io| io.heartbeat}
357
346
  end
358
- end
359
347
 
360
- def crank_selectables
348
+ def crank_selectables
361
349
  #$stderr.write 'R'
362
350
 
363
351
  readers = @selectables.values.select {|io| io.select_for_reading?}
@@ -374,56 +362,54 @@ class Reactor
374
362
  true
375
363
  end
376
364
  }
377
- end
365
+ end
378
366
 
379
- # #stop
380
- def stop
381
- raise Error.new( "not running") unless @running
382
- @stop_scheduled = true
383
- end
367
+ # #stop
368
+ def stop
369
+ raise Error.new( "not running") unless @running
370
+ @stop_scheduled = true
371
+ end
372
+
373
+ def open_loopbreaker
374
+ # Can't use an IO.pipe because they can't be set nonselectable in Windows.
375
+ # Pick a random localhost UDP port.
376
+ #@loopbreak_writer.close if @loopbreak_writer
377
+ #rd,@loopbreak_writer = IO.pipe
378
+ @loopbreak_reader = UDPSocket.new
379
+ @loopbreak_writer = UDPSocket.new
380
+ bound = false
381
+ 100.times {
382
+ @loopbreak_port = rand(10000) + 40000
383
+ begin
384
+ @loopbreak_reader.bind "localhost", @loopbreak_port
385
+ bound = true
386
+ break
387
+ rescue
388
+ end
389
+ }
390
+ raise "Unable to bind Loopbreaker" unless bound
391
+ LoopbreakReader.new(@loopbreak_reader)
392
+ end
384
393
 
385
- def open_loopbreaker
386
- # Can't use an IO.pipe because they can't be set nonselectable in Windows.
387
- # Pick a random localhost UDP port.
388
- #@loopbreak_writer.close if @loopbreak_writer
389
- #rd,@loopbreak_writer = IO.pipe
390
- @loopbreak_reader = UDPSocket.new
391
- @loopbreak_writer = UDPSocket.new
392
- bound = false
393
- 100.times {
394
- @loopbreak_port = rand(10000) + 40000
395
- begin
396
- @loopbreak_reader.bind "localhost", @loopbreak_port
397
- bound = true
398
- break
399
- rescue
400
- end
401
- }
402
- raise "Unable to bind Loopbreaker" unless bound
403
- LoopbreakReader.new(@loopbreak_reader)
404
- end
394
+ def close_loopbreaker
395
+ @loopbreak_writer.close
396
+ @loopbreak_writer = nil
397
+ end
405
398
 
406
- def close_loopbreaker
407
- @loopbreak_writer.close
408
- @loopbreak_writer = nil
409
- end
399
+ def signal_loopbreak
400
+ #@loopbreak_writer.write '+' if @loopbreak_writer
401
+ @loopbreak_writer.send('+',0,"localhost",@loopbreak_port) if @loopbreak_writer
402
+ end
410
403
 
411
- def signal_loopbreak
412
- #@loopbreak_writer.write '+' if @loopbreak_writer
413
- @loopbreak_writer.send('+',0,"localhost",@loopbreak_port) if @loopbreak_writer
414
- end
404
+ def set_timer_quantum interval_in_seconds
405
+ @timer_quantum = interval_in_seconds
406
+ end
415
407
 
416
- def set_timer_quantum interval_in_seconds
417
- @timer_quantum = interval_in_seconds
418
408
  end
419
409
 
420
410
  end
421
411
 
422
- end
423
-
424
-
425
- #--------------------------------------------------------------
426
-
412
+ # @private
427
413
  class IO
428
414
  extend Forwardable
429
415
  def_delegator :@my_selectable, :close_scheduled?
@@ -441,9 +427,8 @@ class IO
441
427
  def_delegator :@my_selectable, :heartbeat
442
428
  end
443
429
 
444
- #--------------------------------------------------------------
445
-
446
430
  module EventMachine
431
+ # @private
447
432
  class Selectable
448
433
 
449
434
  attr_reader :io, :uuid
@@ -463,7 +448,7 @@ module EventMachine
463
448
  s = Socket.for_fd(@io.fileno)
464
449
  s.fcntl( Fcntl::F_SETFL, Fcntl::O_NONBLOCK )
465
450
  rescue Errno::EINVAL, Errno::EBADF
466
- STDERR.puts "Serious error: unable to set descriptor non-blocking"
451
+ warn "Serious error: unable to set descriptor non-blocking"
467
452
  end
468
453
  end
469
454
  # TODO, should set CLOEXEC on Unix?
@@ -501,11 +486,8 @@ module EventMachine
501
486
 
502
487
  end
503
488
 
504
- #--------------------------------------------------------------
505
-
506
-
507
489
  module EventMachine
508
-
490
+ # @private
509
491
  class StreamObject < Selectable
510
492
  def initialize io
511
493
  super io
@@ -581,10 +563,10 @@ module EventMachine
581
563
  begin
582
564
  data = data.to_s
583
565
  w = if io.respond_to?(:write_nonblock)
584
- io.write_nonblock data
585
- else
586
- io.syswrite data
587
- end
566
+ io.write_nonblock data
567
+ else
568
+ io.syswrite data
569
+ end
588
570
 
589
571
  if w < data.length
590
572
  @outbound_q.unshift data[w..-1]
@@ -647,6 +629,7 @@ end
647
629
 
648
630
 
649
631
  module EventMachine
632
+ # @private
650
633
  class EvmaTCPClient < StreamObject
651
634
 
652
635
  def self.connect bind_addr, bind_port, host, port
@@ -693,11 +676,10 @@ module EventMachine
693
676
  end
694
677
  end
695
678
 
696
- #--------------------------------------------------------------
697
-
698
679
 
699
680
 
700
681
  module EventMachine
682
+ # @private
701
683
  class EvmaKeyboard < StreamObject
702
684
 
703
685
  def self.open
@@ -723,11 +705,9 @@ module EventMachine
723
705
  end
724
706
 
725
707
 
726
- #--------------------------------------------------------------
727
-
728
-
729
708
 
730
709
  module EventMachine
710
+ # @private
731
711
  class EvmaUNIXClient < StreamObject
732
712
 
733
713
  def self.connect chain
@@ -776,6 +756,7 @@ end
776
756
  #--------------------------------------------------------------
777
757
 
778
758
  module EventMachine
759
+ # @private
779
760
  class EvmaTCPServer < Selectable
780
761
 
781
762
  # TODO, refactor and unify with EvmaUNIXServer.
@@ -831,6 +812,7 @@ end
831
812
  #--------------------------------------------------------------
832
813
 
833
814
  module EventMachine
815
+ # @private
834
816
  class EvmaUNIXServer < Selectable
835
817
 
836
818
  # TODO, refactor and unify with EvmaTCPServer.
@@ -887,6 +869,7 @@ end
887
869
  #--------------------------------------------------------------
888
870
 
889
871
  module EventMachine
872
+ # @private
890
873
  class LoopbreakReader < Selectable
891
874
 
892
875
  def select_for_reading?
@@ -894,18 +877,18 @@ module EventMachine
894
877
  end
895
878
 
896
879
  def eventable_read
897
- io.sysread(128)
898
- EventMachine::event_callback "", LoopbreakSignalled, ""
880
+ io.sysread(128)
881
+ EventMachine::event_callback "", LoopbreakSignalled, ""
899
882
  end
900
883
 
901
884
  end
902
885
  end
903
886
 
904
- #--------------------------------------------------------------
905
887
 
906
888
 
889
+ # @private
907
890
  module EventMachine
908
-
891
+ # @private
909
892
  class DatagramObject < Selectable
910
893
  def initialize io
911
894
  super io
@@ -949,9 +932,8 @@ module EventMachine
949
932
  end
950
933
 
951
934
 
952
- #--------------------------------------------------------------
953
-
954
935
  module EventMachine
936
+ # @private
955
937
  class EvmaUDPSocket < DatagramObject
956
938
 
957
939
  class << self
@@ -1017,6 +999,7 @@ module EventMachine
1017
999
  end
1018
1000
  end
1019
1001
 
1020
- #--------------------------------------------------------------
1021
-
1002
+ # load base EM api on top, now that we have the underlying pure ruby
1003
+ # implementation defined
1004
+ require 'eventmachine'
1022
1005