From: Charles Oliver Nutter Date: 2008-01-04T06:49:49+09:00 Subject: JRuby stdlib updated to 1.8.6, patch to stdlib attached This is a multi-part message in MIME format. --Boundary_(ID_cueuXeomQSA/A4nxyA6l9g) Content-type: text/plain; format=flowed; charset=ISO-8859-1 Content-transfer-encoding: 7BIT JRuby has updated to the 1.8.6_111 stdlib. This was done by diffing our copy of 1.8.5 libraries against actual 1.8.5 and applying the same changes to 1.8.6, then copying them over. I've attached the patch here for your perusal; any changes that seem appropriate to add to core stdlib, please go ahead. We also included a patch for the bug described here: http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-core/12107 ...since it's much more likely that JRuby users will run under Tomcat. - Charlie --Boundary_(ID_cueuXeomQSA/A4nxyA6l9g) Content-type: text/plain; name=lib_changes.diff; x-mac-creator=0; x-mac-type=0 Content-transfer-encoding: 7BIT Content-disposition: inline; filename=lib_changes.diff Index: lib/pathname.rb =================================================================== --- lib/pathname.rb (revision 14877) +++ lib/pathname.rb (working copy) @@ -496,7 +496,10 @@ while r = chop_basename(path) path, basename = r end - path == '' + # enebo: mild hack for windows drive letters. Any kook trying + # to create a relative path that starts like 'c:/' will be in trouble + # so it is not the best solution... + path == '' && @path !~ /\A[a-zA-Z]:/ end # Index: lib/fileutils.rb =================================================================== --- lib/fileutils.rb (revision 14877) +++ lib/fileutils.rb (working copy) @@ -525,7 +525,7 @@ OPT_TABLE['move'] = [:force, :noop, :verbose, :secure] def rename_cannot_overwrite_file? #:nodoc: - /djgpp|cygwin|mswin|mingw|bccwin|wince|emx/ =~ RUBY_PLATFORM + /djgpp|cygwin|mswin|mingw|bccwin|wince|emx|java/ =~ RUBY_PLATFORM end private_module_function :rename_cannot_overwrite_file? Index: lib/irb/init.rb =================================================================== --- lib/irb/init.rb (revision 14877) +++ lib/irb/init.rb (working copy) @@ -119,6 +119,10 @@ def IRB.init_error @CONF[:LC_MESSAGES].load("irb/error.rb") + rescue LoadError + # ignore; when running from within an archive (JRuby's "complete" jar) this won't load + rescue + # happens with applet TODO: probably should make this more robust end FEATURE_IOPT_CHANGE_VERSION = "1.9.0" Index: lib/thread.rb =================================================================== --- lib/thread.rb (revision 14877) +++ lib/thread.rb (working copy) @@ -32,448 +32,4 @@ end end -# -# Mutex implements a simple semaphore that can be used to coordinate access to -# shared data from multiple concurrent threads. -# -# Example: -# -# require 'thread' -# semaphore = Mutex.new -# -# a = Thread.new { -# semaphore.synchronize { -# # access shared resource -# } -# } -# -# b = Thread.new { -# semaphore.synchronize { -# # access shared resource -# } -# } -# -class Mutex - # - # Creates a new Mutex - # - def initialize - @waiting = [] - @locked = false; - @waiting.taint # enable tainted comunication - self.taint - end - - # - # Returns +true+ if this lock is currently held by some thread. - # - def locked? - @locked - end - - # - # Attempts to obtain the lock and returns immediately. Returns +true+ if the - # lock was granted. - # - def try_lock - result = false - Thread.critical = true - unless @locked - @locked = true - result = true - end - Thread.critical = false - result - end - - # - # Attempts to grab the lock and waits if it isn't available. - # - def lock - while (Thread.critical = true; @locked) - @waiting.push Thread.current - Thread.stop - end - @locked = true - Thread.critical = false - self - end - - # - # Releases the lock. Returns +nil+ if ref wasn't locked. - # - def unlock - return unless @locked - Thread.critical = true - @locked = false - begin - t = @waiting.shift - t.wakeup if t - rescue ThreadError - retry - end - Thread.critical = false - begin - t.run if t - rescue ThreadError - end - self - end - - # - # Obtains a lock, runs the block, and releases the lock when the block - # completes. See the example under Mutex. - # - def synchronize - lock - begin - yield - ensure - unlock - end - end - - # - # If the mutex is locked, unlocks the mutex, wakes one waiting thread, and - # yields in a critical section. - # - def exclusive_unlock - return unless @locked - Thread.exclusive do - @locked = false - begin - t = @waiting.shift - t.wakeup if t - rescue ThreadError - retry - end - yield - end - self - end -end - -# -# ConditionVariable objects augment class Mutex. Using condition variables, -# it is possible to suspend while in the middle of a critical section until a -# resource becomes available. -# -# Example: -# -# require 'thread' -# -# mutex = Mutex.new -# resource = ConditionVariable.new -# -# a = Thread.new { -# mutex.synchronize { -# # Thread 'a' now needs the resource -# resource.wait(mutex) -# # 'a' can now have the resource -# } -# } -# -# b = Thread.new { -# mutex.synchronize { -# # Thread 'b' has finished using the resource -# resource.signal -# } -# } -# -class ConditionVariable - # - # Creates a new ConditionVariable - # - def initialize - @waiters = [] - end - - # - # Releases the lock held in +mutex+ and waits; reacquires the lock on wakeup. - # - def wait(mutex) - begin - mutex.exclusive_unlock do - @waiters.push(Thread.current) - Thread.stop - end - ensure - mutex.lock - end - end - - # - # Wakes up the first thread in line waiting for this lock. - # - def signal - begin - t = @waiters.shift - t.run if t - rescue ThreadError - retry - end - end - - # - # Wakes up all threads waiting for this lock. - # - def broadcast - waiters0 = nil - Thread.exclusive do - waiters0 = @waiters.dup - @waiters.clear - end - for t in waiters0 - begin - t.run - rescue ThreadError - end - end - end -end - -# -# This class provides a way to synchronize communication between threads. -# -# Example: -# -# require 'thread' -# -# queue = Queue.new -# -# producer = Thread.new do -# 5.times do |i| -# sleep rand(i) # simulate expense -# queue << i -# puts "#{i} produced" -# end -# end -# -# consumer = Thread.new do -# 5.times do |i| -# value = queue.pop -# sleep rand(i/2) # simulate expense -# puts "consumed #{value}" -# end -# end -# -# consumer.join -# -class Queue - # - # Creates a new queue. - # - def initialize - @que = [] - @waiting = [] - @que.taint # enable tainted comunication - @waiting.taint - self.taint - end - - # - # Pushes +obj+ to the queue. - # - def push(obj) - Thread.critical = true - @que.push obj - begin - t = @waiting.shift - t.wakeup if t - rescue ThreadError - retry - ensure - Thread.critical = false - end - begin - t.run if t - rescue ThreadError - end - end - - # - # Alias of push - # - alias << push - - # - # Alias of push - # - alias enq push - - # - # Retrieves data from the queue. If the queue is empty, the calling thread is - # suspended until data is pushed onto the queue. If +non_block+ is true, the - # thread isn't suspended, and an exception is raised. - # - def pop(non_block=false) - while (Thread.critical = true; @que.empty?) - raise ThreadError, "queue empty" if non_block - @waiting.push Thread.current - Thread.stop - end - @que.shift - ensure - Thread.critical = false - end - - # - # Alias of pop - # - alias shift pop - - # - # Alias of pop - # - alias deq pop - - # - # Returns +true+ is the queue is empty. - # - def empty? - @que.empty? - end - - # - # Removes all objects from the queue. - # - def clear - @que.clear - end - - # - # Returns the length of the queue. - # - def length - @que.length - end - - # - # Alias of length. - # - alias size length - - # - # Returns the number of threads waiting on the queue. - # - def num_waiting - @waiting.size - end -end - -# -# This class represents queues of specified size capacity. The push operation -# may be blocked if the capacity is full. -# -# See Queue for an example of how a SizedQueue works. -# -class SizedQueue 0 - @max = max - @queue_wait = [] - @queue_wait.taint # enable tainted comunication - super() - end - - # - # Returns the maximum size of the queue. - # - def max - @max - end - - # - # Sets the maximum size of the queue. - # - def max=(max) - Thread.critical = true - if max <= @max - @max = max - Thread.critical = false - else - diff = max - @max - @max = max - Thread.critical = false - diff.times do - begin - t = @queue_wait.shift - t.run if t - rescue ThreadError - retry - end - end - end - max - end - - # - # Pushes +obj+ to the queue. If there is no space left in the queue, waits - # until space becomes available. - # - def push(obj) - Thread.critical = true - while @que.length >= @max - @queue_wait.push Thread.current - Thread.stop - Thread.critical = true - end - super - end - - # - # Alias of push - # - alias << push - - # - # Alias of push - # - alias enq push - - # - # Retrieves data from the queue and runs a waiting thread, if any. - # - def pop(*args) - retval = super - Thread.critical = true - if @que.length < @max - begin - t = @queue_wait.shift - t.wakeup if t - rescue ThreadError - retry - ensure - Thread.critical = false - end - begin - t.run if t - rescue ThreadError - end - end - retval - end - - # - # Alias of pop - # - alias shift pop - - # - # Alias of pop - # - alias deq pop - - # - # Returns the number of threads waiting on the queue. - # - def num_waiting - @waiting.size + @queue_wait.size - end -end - -# Documentation comments: -# - How do you make RDoc inherit documentation from superclass? +require 'thread.so' Index: lib/net/protocol.rb =================================================================== --- lib/net/protocol.rb (revision 14877) +++ lib/net/protocol.rb (working copy) @@ -130,7 +130,7 @@ def rbuf_fill timeout(@read_timeout) { - @rbuf << @io.sysread(1024) + @rbuf << @io.sysread(8196) } end Index: lib/debug.rb =================================================================== --- lib/debug.rb (revision 14877) +++ lib/debug.rb (working copy) @@ -255,9 +255,10 @@ def debug_command(file, line, id, binding) MUTEX.lock - unless defined?($debugger_restart) and $debugger_restart - callcc{|c| $debugger_restart = c} - end +# This is removed, since JRuby doesn't support continuations +# unless defined?($debugger_restart) and $debugger_restart +# callcc{|c| $debugger_restart = c} +# end set_last_thread(Thread.current) frame_pos = 0 binding_file = file @@ -528,7 +529,8 @@ stdout.printf "%s\n", debug_eval($', binding).inspect when /^\s*r(?:estart)?$/ - $debugger_restart.call + stdout.print "JRuby doesn't support the command restart, since it depends on continuations" +# $debugger_restart.call when /^\s*h(?:elp)?$/ debug_print_help() Index: lib/generator.rb =================================================================== --- lib/generator.rb (revision 14877) +++ lib/generator.rb (working copy) @@ -56,115 +56,9 @@ # puts g.next # end # -class Generator - include Enumerable - # Creates a new generator either from an Enumerable object or from a - # block. - # - # In the former, block is ignored even if given. - # - # In the latter, the given block is called with the generator - # itself, and expected to call the +yield+ method for each element. - def initialize(enum = nil, &block) - if enum - @block = proc { |g| - enum.each { |x| g.yield x } - } - else - @block = block - end +require 'generator_internal' - @index = 0 - @queue = [] - @cont_next = @cont_yield = @cont_endp = nil - - if @cont_next = callcc { |c| c } - @block.call(self) - - @cont_endp.call(nil) if @cont_endp - end - - self - end - - # Yields an element to the generator. - def yield(value) - if @cont_yield = callcc { |c| c } - @queue << value - @cont_next.call(nil) - end - - self - end - - # Returns true if the generator has reached the end. - def end?() - if @cont_endp = callcc { |c| c } - @cont_yield.nil? && @queue.empty? - else - @queue.empty? - end - end - - # Returns true if the generator has not reached the end yet. - def next?() - !end? - end - - # Returns the current index (position) counting from zero. - def index() - @index - end - - # Returns the current index (position) counting from zero. - def pos() - @index - end - - # Returns the element at the current position and moves forward. - def next() - if end? - raise EOFError, "no more elements available" - end - - if @cont_next = callcc { |c| c } - @cont_yield.call(nil) if @cont_yield - end - - @index += 1 - - @queue.shift - end - - # Returns the element at the current position. - def current() - if @queue.empty? - raise EOFError, "no more elements available" - end - - @queue.first - end - - # Rewinds the generator. - def rewind() - initialize(nil, &@block) if @index.nonzero? - - self - end - - # Rewinds the generator and enumerates the elements. - def each - rewind - - until end? - yield self.next - end - - self - end -end - # # SyncEnumerator creates an Enumerable object from multiple Enumerable # objects and enumerates them synchronously. --Boundary_(ID_cueuXeomQSA/A4nxyA6l9g)--