From 8daa6985dc0b42e23810756f99fac83e6dca49f5 Mon Sep 17 00:00:00 2001 From: knu Date: Sat, 21 Oct 2017 15:57:32 +0000 Subject: Use a mutex to make SortedSet.setup thread-safe This should fix [Bug #13735]. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60304 b2dd03c8-39d4-4d8f-98ff-823fe69b080e --- lib/set.rb | 182 +++++++++++++++++++++++++++++++------------------------------ 1 file changed, 92 insertions(+), 90 deletions(-) (limited to 'lib') diff --git a/lib/set.rb b/lib/set.rb index a4ed61f8f5..caf80aa930 100644 --- a/lib/set.rb +++ b/lib/set.rb @@ -634,6 +634,7 @@ end # class SortedSet < Set @@setup = false + @@mutex = Mutex.new class << self def [](*ary) # :nodoc: @@ -643,97 +644,98 @@ class SortedSet < Set def setup # :nodoc: @@setup and return - # 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 + @@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 - @@setup = true + @@setup = true + end end end -- cgit v1.2.3