summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-10-21 15:57:32 +0000
committerknu <knu@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2017-10-21 15:57:32 +0000
commit8daa6985dc0b42e23810756f99fac83e6dca49f5 (patch)
treefb4ff8395de529ba5506669d584f61c5d45625e9 /lib
parent76e38253768dd4a73c70c1e78a97788c956316a6 (diff)
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
Diffstat (limited to 'lib')
-rw-r--r--lib/set.rb182
1 files changed, 92 insertions, 90 deletions
diff --git a/lib/set.rb b/lib/set.rb
index a4ed61f..caf80aa 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