ruby-changes:48190
From: knu <ko1@a...>
Date: Sun, 22 Oct 2017 00:57:36 +0900 (JST)
Subject: [ruby-changes:48190] knu:r60304 (trunk): Use a mutex to make SortedSet.setup thread-safe
knu 2017-10-22 00:57:32 +0900 (Sun, 22 Oct 2017) New Revision: 60304 https://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=revision&revision=60304 Log: Use a mutex to make SortedSet.setup thread-safe This should fix [Bug #13735]. Modified files: trunk/lib/set.rb Index: lib/set.rb =================================================================== --- lib/set.rb (revision 60303) +++ lib/set.rb (revision 60304) @@ -634,6 +634,7 @@ end https://github.com/ruby/ruby/blob/trunk/lib/set.rb#L634 # class SortedSet < Set @@setup = false + @@mutex = Mutex.new class << self def [](*ary) # :nodoc: @@ -643,97 +644,98 @@ class SortedSet < Set https://github.com/ruby/ruby/blob/trunk/lib/set.rb#L644 def setup # :nodoc: @@setup and return - # a hack to shut up warning - alias_method :old_init, :initialize + @@mutex.synchronize do + # a hack to shut up warning + alias_method :old_init, :initialize + + begin + require 'rbtree' + + module_eval <<-END, __FILE__, __LINE__+1 + def initialize(*args) + @hash = RBTree.new + super + end + + def add(o) + o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" + super + end + alias << add + END + rescue LoadError + module_eval <<-END, __FILE__, __LINE__+1 + def initialize(*args) + @keys = nil + super + end + + def clear + @keys = nil + super + end + + def replace(enum) + @keys = nil + super + end + + def add(o) + o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" + @keys = nil + super + end + alias << add + + def delete(o) + @keys = nil + @hash.delete(o) + self + end + + def delete_if + block_given? or return enum_for(__method__) { size } + n = @hash.size + super + @keys = nil if @hash.size != n + self + end + + def keep_if + block_given? or return enum_for(__method__) { size } + n = @hash.size + super + @keys = nil if @hash.size != n + self + end + + def merge(enum) + @keys = nil + super + end + + def each(&block) + block or return enum_for(__method__) { size } + to_a.each(&block) + self + end + + def to_a + (@keys = @hash.keys).sort! unless @keys + @keys + end + + def freeze + to_a + super + end + END + end + # a hack to shut up warning + remove_method :old_init - begin - require 'rbtree' - - module_eval <<-END, __FILE__, __LINE__+1 - def initialize(*args) - @hash = RBTree.new - super - end - - def add(o) - o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" - super - end - alias << add - END - rescue LoadError - module_eval <<-END, __FILE__, __LINE__+1 - def initialize(*args) - @keys = nil - super - end - - def clear - @keys = nil - super - end - - def replace(enum) - @keys = nil - super - end - - def add(o) - o.respond_to?(:<=>) or raise ArgumentError, "value must respond to <=>" - @keys = nil - super - end - alias << add - - def delete(o) - @keys = nil - @hash.delete(o) - self - end - - def delete_if - block_given? or return enum_for(__method__) { size } - n = @hash.size - super - @keys = nil if @hash.size != n - self - end - - def keep_if - block_given? or return enum_for(__method__) { size } - n = @hash.size - super - @keys = nil if @hash.size != n - self - end - - def merge(enum) - @keys = nil - super - end - - def each(&block) - block or return enum_for(__method__) { size } - to_a.each(&block) - self - end - - def to_a - (@keys = @hash.keys).sort! unless @keys - @keys - end - - def freeze - to_a - super - end - END + @@setup = true end - - # a hack to shut up warning - remove_method :old_init - - @@setup = true end end -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/