eventmachine 0.12.8 → 0.12.10

Sign up to get free protection for your applications and to get access to all the features.
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 +14 -12
  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.