eventmachine 0.12.8-java → 0.12.10-java

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 (66) hide show
  1. data/.gitignore +2 -1
  2. data/Rakefile +155 -45
  3. data/eventmachine.gemspec +4 -5
  4. data/ext/binder.cpp +13 -14
  5. data/ext/binder.h +5 -7
  6. data/ext/cmain.cpp +184 -42
  7. data/ext/cplusplus.cpp +20 -20
  8. data/ext/ed.cpp +242 -81
  9. data/ext/ed.h +39 -22
  10. data/ext/em.cpp +127 -108
  11. data/ext/em.h +27 -18
  12. data/ext/emwin.cpp +3 -3
  13. data/ext/eventmachine.h +49 -38
  14. data/ext/eventmachine_cpp.h +4 -4
  15. data/ext/extconf.rb +28 -13
  16. data/ext/fastfilereader/extconf.rb +11 -5
  17. data/ext/project.h +12 -1
  18. data/ext/rubymain.cpp +222 -103
  19. data/ext/ssl.cpp +3 -3
  20. data/ext/ssl.h +2 -2
  21. data/java/src/com/rubyeventmachine/EmReactor.java +396 -249
  22. data/java/src/com/rubyeventmachine/EventableChannel.java +16 -4
  23. data/java/src/com/rubyeventmachine/EventableDatagramChannel.java +23 -5
  24. data/java/src/com/rubyeventmachine/EventableSocketChannel.java +181 -61
  25. data/java/src/com/rubyeventmachine/{Application.java → application/Application.java} +25 -31
  26. data/java/src/com/rubyeventmachine/{Connection.java → application/Connection.java} +2 -2
  27. data/java/src/com/rubyeventmachine/{ConnectionFactory.java → application/ConnectionFactory.java} +1 -1
  28. data/java/src/com/rubyeventmachine/{DefaultConnectionFactory.java → application/DefaultConnectionFactory.java} +2 -2
  29. data/java/src/com/rubyeventmachine/{PeriodicTimer.java → application/PeriodicTimer.java} +1 -1
  30. data/java/src/com/rubyeventmachine/{Timer.java → application/Timer.java} +1 -1
  31. data/java/src/com/rubyeventmachine/tests/ApplicationTest.java +1 -0
  32. data/java/src/com/rubyeventmachine/tests/ConnectTest.java +4 -2
  33. data/java/src/com/rubyeventmachine/tests/TestDatagrams.java +1 -1
  34. data/java/src/com/rubyeventmachine/tests/TestServers.java +1 -0
  35. data/java/src/com/rubyeventmachine/tests/TestTimers.java +1 -0
  36. data/lib/em/connection.rb +71 -12
  37. data/lib/em/deferrable.rb +5 -0
  38. data/lib/em/protocols.rb +1 -0
  39. data/lib/em/protocols/httpclient2.rb +8 -0
  40. data/lib/em/protocols/line_and_text.rb +0 -1
  41. data/lib/em/protocols/linetext2.rb +1 -0
  42. data/lib/em/protocols/object_protocol.rb +8 -2
  43. data/lib/em/protocols/smtpclient.rb +42 -16
  44. data/lib/em/protocols/socks4.rb +66 -0
  45. data/lib/em/queue.rb +1 -1
  46. data/lib/em/timers.rb +2 -1
  47. data/lib/em/version.rb +1 -1
  48. data/lib/eventmachine.rb +125 -169
  49. data/lib/jeventmachine.rb +124 -9
  50. data/tasks/{cpp.rake → cpp.rake_example} +0 -0
  51. data/tests/test_attach.rb +29 -4
  52. data/tests/test_basic.rb +1 -2
  53. data/tests/test_connection_count.rb +10 -20
  54. data/tests/test_epoll.rb +0 -2
  55. data/tests/test_get_sock_opt.rb +30 -0
  56. data/tests/test_httpclient2.rb +3 -3
  57. data/tests/test_inactivity_timeout.rb +21 -1
  58. data/tests/test_ltp.rb +0 -6
  59. data/tests/test_next_tick.rb +0 -2
  60. data/tests/test_pause.rb +70 -0
  61. data/tests/test_pending_connect_timeout.rb +48 -0
  62. data/tests/test_ssl_args.rb +16 -5
  63. data/tests/test_timers.rb +22 -1
  64. metadata +59 -52
  65. data/tasks/project.rake +0 -79
  66. data/tasks/tests.rake +0 -193
@@ -41,7 +41,7 @@ module EventMachine
41
41
  # next reactor tick.
42
42
  def push(*items)
43
43
  EM.schedule do
44
- @items.concat items
44
+ @items.push(*items)
45
45
  @popq.shift.call @items.shift until @items.empty? || @popq.empty?
46
46
  end
47
47
  end
@@ -31,6 +31,7 @@ module EventMachine
31
31
  def initialize interval, callback=nil, &block
32
32
  @interval = interval
33
33
  @code = callback || block
34
+ @cancelled = false
34
35
  schedule
35
36
  end
36
37
 
@@ -43,7 +44,7 @@ module EventMachine
43
44
  attr_accessor :interval
44
45
 
45
46
  def schedule # :nodoc:
46
- EventMachine::add_timer @interval, proc {self.fire}
47
+ EventMachine::add_timer @interval, method(:fire)
47
48
  end
48
49
  def fire # :nodoc:
49
50
  unless @cancelled
@@ -1,3 +1,3 @@
1
1
  module EventMachine
2
- VERSION = "0.12.8"
2
+ VERSION = "0.12.10"
3
3
  end
@@ -90,6 +90,7 @@ require 'em/file_watch'
90
90
  require 'em/process_watch'
91
91
 
92
92
  require 'shellwords'
93
+ require 'thread'
93
94
 
94
95
  # == Introduction
95
96
  # EventMachine provides a fast, lightweight framework for implementing
@@ -180,6 +181,18 @@ require 'shellwords'
180
181
  # Interesting thought.
181
182
  #
182
183
  module EventMachine
184
+ class <<self
185
+ # Exposed to allow joining on the thread, when run in a multithreaded
186
+ # environment. Performing other actions on the thread has undefined
187
+ # semantics.
188
+ attr_reader :reactor_thread
189
+ end
190
+ @next_tick_mutex = Mutex.new
191
+ @reactor_running = false
192
+ @next_tick_queue = nil
193
+ @threadpool = nil
194
+
195
+
183
196
  # EventMachine::run initializes and runs an event loop.
184
197
  # This method only returns if user-callback code calls stop_event_loop.
185
198
  # Use the supplied block to define your clients and servers.
@@ -231,6 +244,7 @@ module EventMachine
231
244
  @acceptors = {}
232
245
  @timers = {}
233
246
  @wrapped_exception = nil
247
+ @next_tick_queue ||= []
234
248
  begin
235
249
  @reactor_running = true
236
250
  initialize_event_machine
@@ -241,26 +255,31 @@ module EventMachine
241
255
  @reactor_thread = Thread.current
242
256
  run_machine
243
257
  ensure
258
+ until @tails.empty?
259
+ @tails.pop.call
260
+ end
261
+
244
262
  begin
245
263
  release_machine
246
264
  ensure
247
265
  if @threadpool
248
266
  @threadpool.each { |t| t.exit }
249
- @threadpool.each { |t| t.kill! if t.alive? }
267
+ @threadpool.each do |t|
268
+ next unless t.alive?
269
+ # ruby 1.9 has no kill!
270
+ t.respond_to?(:kill!) ? t.kill! : t.kill
271
+ end
250
272
  @threadqueue = nil
251
273
  @resultqueue = nil
274
+ @threadpool = nil
252
275
  end
253
- @threadpool = nil
276
+
254
277
  @next_tick_queue = nil
255
278
  end
256
279
  @reactor_running = false
257
280
  @reactor_thread = nil
258
281
  end
259
282
 
260
- until @tails.empty?
261
- @tails.pop.call
262
- end
263
-
264
283
  raise @wrapped_exception if @wrapped_exception
265
284
  end
266
285
  end
@@ -381,19 +400,18 @@ module EventMachine
381
400
  def self.add_periodic_timer *args, &block
382
401
  interval = args.shift
383
402
  code = args.shift || block
384
- if code
385
- block_1 = proc {
386
- code.call
387
- EventMachine::add_periodic_timer interval, code
388
- }
389
- add_timer interval, block_1
390
- end
403
+
404
+ EventMachine::PeriodicTimer.new(interval, code)
391
405
  end
392
406
 
393
407
  # Cancel a timer using its signature. You can also use EventMachine::Timer#cancel
394
408
  #
395
- def self.cancel_timer signature
396
- @timers[signature] = false if @timers.has_key?(signature)
409
+ def self.cancel_timer timer_or_sig
410
+ if timer_or_sig.respond_to? :cancel
411
+ timer_or_sig.cancel
412
+ else
413
+ @timers[timer_or_sig] = false if @timers.has_key?(timer_or_sig)
414
+ end
397
415
  end
398
416
 
399
417
 
@@ -548,18 +566,7 @@ module EventMachine
548
566
  port = nil
549
567
  end if port
550
568
 
551
- klass = if (handler and handler.is_a?(Class))
552
- raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
553
- handler
554
- else
555
- Class.new( Connection ) {handler and include handler}
556
- end
557
-
558
- arity = klass.instance_method(:initialize).arity
559
- expected = arity >= 0 ? arity : -(arity + 1)
560
- if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
561
- raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
562
- end
569
+ klass = klass_from_handler(Connection, handler, *args)
563
570
 
564
571
  s = if port
565
572
  start_tcp_server server, port
@@ -614,11 +621,13 @@ module EventMachine
614
621
  # def post_init
615
622
  # send_data "GET / HTTP/1.1\r\nHost: _\r\n\r\n"
616
623
  # @data = ""
624
+ # @parsed = false
617
625
  # end
618
626
  #
619
627
  # def receive_data data
620
628
  # @data << data
621
- # if @data =~ /[\n][\r]*[\n]/m
629
+ # if !@parsed and @data =~ /[\n][\r]*[\n]/m
630
+ # @parsed = true
622
631
  # puts "RECEIVED HTTP HEADER:"
623
632
  # $`.each {|line| puts ">>> #{line}" }
624
633
  #
@@ -679,6 +688,12 @@ module EventMachine
679
688
  # to have them behave differently with respect to post_init
680
689
  # if at all possible.
681
690
  #
691
+ def self.connect server, port=nil, handler=nil, *args, &blk
692
+ bind_connect nil, nil, server, port, handler, *args, &blk
693
+ end
694
+
695
+ # EventMachine::bind_connect is like EventMachine::connect, but allows for a local address/port
696
+ # to bind the connection to.
682
697
  def self.bind_connect bind_addr, bind_port, server, port=nil, handler=nil, *args
683
698
  begin
684
699
  port = Integer(port)
@@ -690,22 +705,11 @@ module EventMachine
690
705
  port = nil
691
706
  end if port
692
707
 
693
- klass = if (handler and handler.is_a?(Class))
694
- raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
695
- handler
696
- else
697
- Class.new( Connection ) {handler and include handler}
698
- end
699
-
700
- arity = klass.instance_method(:initialize).arity
701
- expected = arity >= 0 ? arity : -(arity + 1)
702
- if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
703
- raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
704
- end
708
+ klass = klass_from_handler(Connection, handler, *args)
705
709
 
706
710
  s = if port
707
711
  if bind_addr
708
- bind_connect_server bind_addr, bind_port, server, port
712
+ bind_connect_server bind_addr, bind_port.to_i, server, port
709
713
  else
710
714
  connect_server server, port
711
715
  end
@@ -719,30 +723,25 @@ module EventMachine
719
723
  c
720
724
  end
721
725
 
722
- def self.connect server, port=nil, handler=nil, *args, &blk
723
- bind_connect nil, nil, server, port, handler, *args, &blk
724
- end
725
-
726
- # EventMachine::attach registers a given file descriptor or IO object with the eventloop
726
+ # EventMachine::watch registers a given file descriptor or IO object with the eventloop. The
727
+ # file descriptor will not be modified (it will remain blocking or non-blocking).
728
+ #
729
+ # The eventloop can be used to process readable and writable events on the file descriptor, using
730
+ # EventMachine::Connection#notify_readable= and EventMachine::Connection#notify_writable=
727
731
  #
728
- # If the handler provided has the functions notify_readable or notify_writable defined,
729
- # EventMachine will not read or write from the socket, and instead fire the corresponding
730
- # callback on the handler.
732
+ # EventMachine::Connection#notify_readable? and EventMachine::Connection#notify_writable? can be used
733
+ # to check what events are enabled on the connection.
731
734
  #
732
735
  # To detach the file descriptor, use EventMachine::Connection#detach
733
736
  #
734
737
  # === Usage Example
735
738
  #
736
739
  # module SimpleHttpClient
737
- # def initialize sock
738
- # @sock = sock
739
- # end
740
- #
741
740
  # def notify_readable
742
- # header = @sock.readline
741
+ # header = @io.readline
743
742
  #
744
743
  # if header == "\r\n"
745
- # # detach returns the file descriptor number (fd == @sock.fileno)
744
+ # # detach returns the file descriptor number (fd == @io.fileno)
746
745
  # fd = detach
747
746
  # end
748
747
  # rescue EOFError
@@ -752,7 +751,7 @@ module EventMachine
752
751
  # def unbind
753
752
  # EM.next_tick do
754
753
  # # socket is detached from the eventloop, but still open
755
- # data = @sock.read
754
+ # data = @io.read
756
755
  # end
757
756
  # end
758
757
  # end
@@ -760,31 +759,45 @@ module EventMachine
760
759
  # EM.run{
761
760
  # $sock = TCPSocket.new('site.com', 80)
762
761
  # $sock.write("GET / HTTP/1.0\r\n\r\n")
763
- # EM.attach $sock, SimpleHttpClient, $sock
762
+ # conn = EM.watch $sock, SimpleHttpClient
763
+ # conn.notify_readable = true
764
764
  # }
765
765
  #
766
766
  #--
767
767
  # Thanks to Riham Aldakkak (eSpace Technologies) for the initial patch
768
- def EventMachine::attach io, handler=nil, *args
769
- klass = if (handler and handler.is_a?(Class))
770
- raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
771
- handler
772
- else
773
- Class.new( Connection ) {handler and include handler}
768
+ def EventMachine::watch io, handler=nil, *args, &blk
769
+ attach_io io, true, handler, *args, &blk
770
+ end
771
+
772
+ # Attaches an IO object or file descriptor to the eventloop as a regular connection.
773
+ # The file descriptor will be set as non-blocking, and EventMachine will process
774
+ # receive_data and send_data events on it as it would for any other connection.
775
+ #
776
+ # To watch a fd instead, use EventMachine::watch, which will not alter the state of the socket
777
+ # and fire notify_readable and notify_writable events instead.
778
+ def EventMachine::attach io, handler=nil, *args, &blk
779
+ attach_io io, false, handler, *args, &blk
780
+ end
781
+
782
+ def EventMachine::attach_io io, watch_mode, handler=nil, *args # :nodoc:
783
+ klass = klass_from_handler(Connection, handler, *args)
784
+
785
+ if !watch_mode and klass.public_instance_methods.any?{|m| [:notify_readable, :notify_writable].include? m.to_sym }
786
+ raise ArgumentError, "notify_readable/writable with EM.attach is not supported. Use EM.watch(io){ |c| c.notify_readable = true }"
774
787
  end
775
788
 
776
- arity = klass.instance_method(:initialize).arity
777
- expected = arity >= 0 ? arity : -(arity + 1)
778
- if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
779
- raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
789
+ if io.respond_to?(:fileno)
790
+ fd = defined?(JRuby) ? JRuby.runtime.getDescriptorByFileno(io.fileno).getChannel : io.fileno
791
+ else
792
+ fd = io
780
793
  end
781
794
 
782
- readmode = klass.public_instance_methods.any?{|m| m.to_sym == :notify_readable }
783
- writemode = klass.public_instance_methods.any?{|m| m.to_sym == :notify_writable }
795
+ s = attach_fd fd, watch_mode
796
+ c = klass.new s, *args
784
797
 
785
- s = attach_fd io.respond_to?(:fileno) ? io.fileno : io, readmode, writemode
798
+ c.instance_variable_set(:@io, io)
799
+ c.instance_variable_set(:@fd, fd)
786
800
 
787
- c = klass.new s, *args
788
801
  @conns[s] = c
789
802
  block_given? and yield c
790
803
  c
@@ -793,8 +806,6 @@ module EventMachine
793
806
 
794
807
  # Connect to a given host/port and re-use the provided EventMachine::Connection instance
795
808
  #--
796
- # EXPERIMENTAL. DO NOT RELY ON THIS METHOD TO BE HERE IN THIS FORM, OR AT ALL.
797
- # (03Nov06)
798
809
  # Observe, the test for already-connected FAILS if we call a reconnect inside post_init,
799
810
  # because we haven't set up the connection in @conns by that point.
800
811
  # RESIST THE TEMPTATION to "fix" this problem by redefining the behavior of post_init.
@@ -900,19 +911,7 @@ module EventMachine
900
911
  # out that this originally did not take a class but only a module.
901
912
  #
902
913
  def self.open_datagram_socket address, port, handler=nil, *args
903
- klass = if (handler and handler.is_a?(Class))
904
- raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
905
- handler
906
- else
907
- Class.new( Connection ) {handler and include handler}
908
- end
909
-
910
- arity = klass.instance_method(:initialize).arity
911
- expected = arity >= 0 ? arity : -(arity + 1)
912
- if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
913
- raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
914
- end
915
-
914
+ klass = klass_from_handler(Connection, handler, *args)
916
915
  s = open_udp_socket address, port.to_i
917
916
  c = klass.new s, *args
918
917
  @conns[s] = c
@@ -990,26 +989,11 @@ module EventMachine
990
989
  cback.call result if cback
991
990
  end
992
991
 
993
- @next_tick_queue ||= []
994
- if (l = @next_tick_queue.length) > 0
995
- l.times {|i| @next_tick_queue[i].call}
996
- @next_tick_queue.slice!( 0...l )
992
+ jobs = @next_tick_mutex.synchronize do
993
+ jobs, @next_tick_queue = @next_tick_queue, []
994
+ jobs
997
995
  end
998
-
999
- =begin
1000
- (@next_tick_queue ||= []).length.times {
1001
- cback=@next_tick_queue.pop and cback.call
1002
- }
1003
- =end
1004
- =begin
1005
- if (@next_tick_queue ||= []) and @next_tick_queue.length > 0
1006
- ary = @next_tick_queue.dup
1007
- @next_tick_queue.clear
1008
- until ary.empty?
1009
- cback=ary.pop and cback.call
1010
- end
1011
- end
1012
- =end
996
+ jobs.each { |j| j.call }
1013
997
  end
1014
998
 
1015
999
 
@@ -1069,7 +1053,7 @@ module EventMachine
1069
1053
  end
1070
1054
 
1071
1055
  def self.spawn_threadpool # :nodoc:
1072
- until @threadpool.size == @threadpool_size
1056
+ until @threadpool.size == @threadpool_size.to_i
1073
1057
  thread = Thread.new do
1074
1058
  while true
1075
1059
  op, cback = *@threadqueue.pop
@@ -1106,18 +1090,11 @@ module EventMachine
1106
1090
  # extremely expensive even if they're just sleeping.
1107
1091
  #
1108
1092
  def self.next_tick pr=nil, &block
1109
- raise "no argument or block given" unless ((pr && pr.respond_to?(:call)) or block)
1110
- (@next_tick_queue ||= []) << ( pr || block )
1111
- signal_loopbreak if reactor_running?
1112
- =begin
1113
- (@next_tick_procs ||= []) << (pr || block)
1114
- if @next_tick_procs.length == 1
1115
- add_timer(0) {
1116
- @next_tick_procs.each {|t| t.call}
1117
- @next_tick_procs.clear
1118
- }
1093
+ raise ArgumentError, "no proc or block given" unless ((pr && pr.respond_to?(:call)) or block)
1094
+ @next_tick_mutex.synchronize do
1095
+ (@next_tick_queue ||= []) << ( pr || block )
1119
1096
  end
1120
- =end
1097
+ signal_loopbreak if reactor_running?
1121
1098
  end
1122
1099
 
1123
1100
  # A wrapper over the setuid system call. Particularly useful when opening a network
@@ -1182,13 +1159,7 @@ module EventMachine
1182
1159
  # Perhaps misnamed since the underlying function uses socketpair and is full-duplex.
1183
1160
  #
1184
1161
  def self.popen cmd, handler=nil, *args
1185
- klass = if (handler and handler.is_a?(Class))
1186
- raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
1187
- handler
1188
- else
1189
- Class.new( Connection ) {handler and include handler}
1190
- end
1191
-
1162
+ klass = klass_from_handler(Connection, handler, *args)
1192
1163
  w = Shellwords::shellwords( cmd )
1193
1164
  w.unshift( w.first ) if w.first
1194
1165
  s = invoke_popen( w )
@@ -1218,18 +1189,7 @@ module EventMachine
1218
1189
  #
1219
1190
  #
1220
1191
  def self.open_keyboard handler=nil, *args
1221
- klass = if (handler and handler.is_a?(Class))
1222
- raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
1223
- handler
1224
- else
1225
- Class.new( Connection ) {handler and include handler}
1226
- end
1227
-
1228
- arity = klass.instance_method(:initialize).arity
1229
- expected = arity >= 0 ? arity : -(arity + 1)
1230
- if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
1231
- raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
1232
- end
1192
+ klass = klass_from_handler(Connection, handler, *args)
1233
1193
 
1234
1194
  s = read_keyboard
1235
1195
  c = klass.new s, *args
@@ -1286,6 +1246,8 @@ module EventMachine
1286
1246
  # end
1287
1247
  # end
1288
1248
  #
1249
+ # EM.kqueue = true if EM.kqueue? # file watching requires kqueue on OSX
1250
+ #
1289
1251
  # EM.run {
1290
1252
  # EM.watch_file("/tmp/foo", Handler)
1291
1253
  # }
@@ -1299,18 +1261,7 @@ module EventMachine
1299
1261
  # Calling #path will always return the filename you originally used.
1300
1262
  #
1301
1263
  def self.watch_file(filename, handler=nil, *args)
1302
- klass = if (handler and handler.is_a?(Class))
1303
- raise ArgumentError, 'must provide module or subclass of EventMachine::FileWatch' unless FileWatch > handler
1304
- handler
1305
- else
1306
- Class.new( FileWatch ) {handler and include handler}
1307
- end
1308
-
1309
- arity = klass.instance_method(:initialize).arity
1310
- expected = arity >= 0 ? arity : -(arity + 1)
1311
- if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
1312
- raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
1313
- end
1264
+ klass = klass_from_handler(FileWatch, handler, *args)
1314
1265
 
1315
1266
  s = EM::watch_filename(filename)
1316
1267
  c = klass.new s, *args
@@ -1341,18 +1292,7 @@ module EventMachine
1341
1292
  def self.watch_process(pid, handler=nil, *args)
1342
1293
  pid = pid.to_i
1343
1294
 
1344
- klass = if (handler and handler.is_a?(Class))
1345
- raise ArgumentError, 'must provide module or subclass of EventMachine::ProcessWatch' unless ProcessWatch > handler
1346
- handler
1347
- else
1348
- Class.new( ProcessWatch ) {handler and include handler}
1349
- end
1350
-
1351
- arity = klass.instance_method(:initialize).arity
1352
- expected = arity >= 0 ? arity : -(arity + 1)
1353
- if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
1354
- raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
1355
- end
1295
+ klass = klass_from_handler(ProcessWatch, handler, *args)
1356
1296
 
1357
1297
  s = EM::watch_pid(pid)
1358
1298
  c = klass.new s, *args
@@ -1429,8 +1369,8 @@ module EventMachine
1429
1369
  # EM.run {
1430
1370
  # EM.start_server("127.0.0.1", 8080, ProxyServer)
1431
1371
  # }
1432
- def self.enable_proxy(from, to)
1433
- EM::start_proxy(from.signature, to.signature)
1372
+ def self.enable_proxy(from, to, bufsize=0)
1373
+ EM::start_proxy(from.signature, to.signature, bufsize)
1434
1374
  end
1435
1375
 
1436
1376
  # disable_proxy takes just one argument, a Connection that has proxying enabled via enable_proxy.
@@ -1495,7 +1435,8 @@ module EventMachine
1495
1435
  c = @conns[conn_binding] or raise ConnectionNotBound, "received ConnectionCompleted for unknown signature: #{conn_binding}"
1496
1436
  c.connection_completed
1497
1437
  ##
1498
- # The remaining code is a fallback for the pure ruby reactor. Usually these events are handled in the C event_callback() in rubymain.cpp
1438
+ # The remaining code is a fallback for the pure ruby and java reactors.
1439
+ # In the C++ reactor, these events are handled in the C event_callback() in rubymain.cpp
1499
1440
  elsif opcode == TimerFired
1500
1441
  t = @timers.delete( data )
1501
1442
  return if t == false # timer cancelled
@@ -1616,12 +1557,7 @@ module EventMachine
1616
1557
  # This is a provisional implementation of a stream-oriented file access object.
1617
1558
  # We also experiment with wrapping up some better exception reporting.
1618
1559
  def self._open_file_for_writing filename, handler=nil # :nodoc:
1619
- klass = if (handler and handler.is_a?(Class))
1620
- raise ArgumentError, 'must provide module or subclass of EventMachine::Connection' unless Connection > handler
1621
- handler
1622
- else
1623
- Class.new( Connection ) {handler and include handler}
1624
- end
1560
+ klass = klass_from_handler(Connection, handler)
1625
1561
 
1626
1562
  s = _write_file filename
1627
1563
  c = klass.new s
@@ -1629,6 +1565,26 @@ module EventMachine
1629
1565
  block_given? and yield c
1630
1566
  c
1631
1567
  end
1568
+
1569
+ private
1570
+ def self.klass_from_handler(klass = Connection, handler = nil, *args)
1571
+ klass = if handler and handler.is_a?(Class)
1572
+ raise ArgumentError, "must provide module or subclass of #{klass.name}" unless klass >= handler
1573
+ handler
1574
+ elsif handler
1575
+ Class.new(klass){ include handler }
1576
+ else
1577
+ klass
1578
+ end
1579
+
1580
+ arity = klass.instance_method(:initialize).arity
1581
+ expected = arity >= 0 ? arity : -(arity + 1)
1582
+ if (arity >= 0 and args.size != expected) or (arity < 0 and args.size < expected)
1583
+ raise ArgumentError, "wrong number of arguments for #{klass}#initialize (#{args.size} for #{expected})"
1584
+ end
1585
+
1586
+ klass
1587
+ end
1632
1588
  end # module EventMachine
1633
1589
 
1634
1590
  # Save everyone some typing.