Skip to content

Commit f37ef9f

Browse files
flavorjonespitr-ch
authored andcommitted
fix: make Concurrent::Set thread-safe on CRuby
Closes #900
1 parent a515290 commit f37ef9f

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

lib/concurrent-ruby/concurrent/set.rb

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,13 @@ module Concurrent
2323
# @!macro internal_implementation_note
2424
SetImplementation = case
2525
when Concurrent.on_cruby?
26-
# Because MRI never runs code in parallel, the existing
27-
# non-thread-safe structures should usually work fine.
28-
::Set
26+
require 'monitor'
27+
require 'concurrent/thread_safe/util/data_structures'
28+
29+
class CRubySet < ::Set
30+
end
31+
ThreadSafe::Util.make_synchronized_on_cruby Concurrent::CRubySet
32+
CRubySet
2933

3034
when Concurrent.on_jruby?
3135
require 'jruby/synchronized'

lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,25 @@ def self.synchronized(object, &block)
1212
module Concurrent
1313
module ThreadSafe
1414
module Util
15+
def self.make_synchronized_on_cruby(klass)
16+
klass.class_eval do
17+
def initialize(*args, &block)
18+
@_monitor = Monitor.new
19+
super
20+
end
21+
end
22+
23+
klass.superclass.instance_methods(false).each do |method|
24+
klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
25+
def #{method}(*args)
26+
monitor = @_monitor
27+
monitor or raise("BUG: Internal monitor was not properly initialized. Please report this to the concurrent-ruby developers.")
28+
monitor.synchronize { super }
29+
end
30+
RUBY
31+
end
32+
end
33+
1534
def self.make_synchronized_on_rbx(klass)
1635
klass.class_eval do
1736
private

0 commit comments

Comments
 (0)