concurrent-ruby 1.1.10 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (90) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +20 -1
  3. data/Gemfile +0 -1
  4. data/README.md +21 -20
  5. data/Rakefile +53 -63
  6. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
  7. data/lib/concurrent-ruby/concurrent/agent.rb +2 -1
  8. data/lib/concurrent-ruby/concurrent/array.rb +0 -10
  9. data/lib/concurrent-ruby/concurrent/atom.rb +1 -1
  10. data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +5 -4
  11. data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +5 -4
  12. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +3 -0
  13. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +81 -151
  14. data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +1 -1
  15. data/lib/concurrent-ruby/concurrent/atomic/event.rb +1 -1
  16. data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
  17. data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +1 -0
  18. data/lib/concurrent-ruby/concurrent/atomic/locals.rb +189 -0
  19. data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +28 -0
  20. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +11 -5
  21. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +11 -5
  22. data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +1 -1
  23. data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +1 -1
  24. data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +2 -1
  25. data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +5 -3
  26. data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +6 -9
  27. data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +96 -89
  28. data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
  29. data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +15 -4
  30. data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +1 -1
  31. data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +1 -1
  32. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +2 -0
  33. data/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb +2 -2
  34. data/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb +16 -8
  35. data/lib/concurrent-ruby/concurrent/concern/logging.rb +86 -2
  36. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  37. data/lib/concurrent-ruby/concurrent/configuration.rb +4 -87
  38. data/lib/concurrent-ruby/concurrent/delay.rb +2 -2
  39. data/lib/concurrent-ruby/concurrent/errors.rb +5 -0
  40. data/lib/concurrent-ruby/concurrent/exchanger.rb +1 -0
  41. data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +1 -1
  42. data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +2 -2
  43. data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +1 -1
  44. data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +1 -1
  45. data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +4 -1
  46. data/lib/concurrent-ruby/concurrent/hash.rb +0 -9
  47. data/lib/concurrent-ruby/concurrent/immutable_struct.rb +1 -1
  48. data/lib/concurrent-ruby/concurrent/ivar.rb +2 -1
  49. data/lib/concurrent-ruby/concurrent/map.rb +43 -39
  50. data/lib/concurrent-ruby/concurrent/maybe.rb +1 -1
  51. data/lib/concurrent-ruby/concurrent/mutable_struct.rb +1 -1
  52. data/lib/concurrent-ruby/concurrent/mvar.rb +1 -1
  53. data/lib/concurrent-ruby/concurrent/promise.rb +1 -1
  54. data/lib/concurrent-ruby/concurrent/promises.rb +7 -6
  55. data/lib/concurrent-ruby/concurrent/re_include.rb +2 -0
  56. data/lib/concurrent-ruby/concurrent/scheduled_task.rb +1 -1
  57. data/lib/concurrent-ruby/concurrent/set.rb +0 -10
  58. data/lib/concurrent-ruby/concurrent/settable_struct.rb +2 -2
  59. data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +5 -1
  60. data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +1 -3
  61. data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +2 -0
  62. data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
  63. data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +3 -1
  64. data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +2 -0
  65. data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +5 -2
  66. data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +6 -5
  67. data/lib/concurrent-ruby/concurrent/synchronization/object.rb +12 -44
  68. data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
  69. data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +77 -12
  70. data/lib/concurrent-ruby/concurrent/synchronization.rb +1 -18
  71. data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +36 -39
  72. data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +2 -39
  73. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +1 -37
  74. data/lib/concurrent-ruby/concurrent/tuple.rb +1 -5
  75. data/lib/concurrent-ruby/concurrent/tvar.rb +2 -1
  76. data/lib/concurrent-ruby/concurrent/utility/engine.rb +5 -16
  77. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +3 -74
  78. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +8 -10
  79. data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +1 -0
  80. data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +34 -54
  81. data/lib/concurrent-ruby/concurrent/version.rb +1 -1
  82. metadata +13 -15
  83. data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +0 -66
  84. data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +0 -37
  85. data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +0 -181
  86. data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +0 -45
  87. data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +0 -44
  88. data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +0 -71
  89. data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +0 -49
  90. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +0 -47
@@ -1,28 +1,20 @@
1
+ require 'concurrent/utility/native_extension_loader' # load native parts first
2
+
3
+ require 'concurrent/synchronization/safe_initialization'
4
+ require 'concurrent/synchronization/volatile'
5
+ require 'concurrent/atomic/atomic_reference'
6
+
1
7
  module Concurrent
2
8
  module Synchronization
3
9
 
4
- # @!visibility private
5
- # @!macro internal_implementation_note
6
- ObjectImplementation = case
7
- when Concurrent.on_cruby?
8
- MriObject
9
- when Concurrent.on_jruby?
10
- JRubyObject
11
- when Concurrent.on_rbx?
12
- RbxObject
13
- when Concurrent.on_truffleruby?
14
- TruffleRubyObject
15
- else
16
- warn 'Possibly unsupported Ruby implementation'
17
- MriObject
18
- end
19
- private_constant :ObjectImplementation
20
-
21
10
  # Abstract object providing final, volatile, ans CAS extensions to build other concurrent abstractions.
22
11
  # - final instance variables see {Object.safe_initialization!}
23
12
  # - volatile instance variables see {Object.attr_volatile}
24
13
  # - volatile instance variables see {Object.attr_atomic}
25
- class Object < ObjectImplementation
14
+ # @!visibility private
15
+ class Object < AbstractObject
16
+ include Volatile
17
+
26
18
  # TODO make it a module if possible
27
19
 
28
20
  # @!method self.attr_volatile(*names)
@@ -38,36 +30,12 @@ module Concurrent
38
30
  __initialize_atomic_fields__
39
31
  end
40
32
 
41
- # By calling this method on a class, it and all its children are marked to be constructed safely. Meaning that
42
- # all writes (ivar initializations) are made visible to all readers of newly constructed object. It ensures
43
- # same behaviour as Java's final fields.
44
- # @example
45
- # class AClass < Concurrent::Synchronization::Object
46
- # safe_initialization!
47
- #
48
- # def initialize
49
- # @AFinalValue = 'value' # published safely, does not have to be synchronized
50
- # end
51
- # end
52
- # @return [true]
53
33
  def self.safe_initialization!
54
- # define only once, and not again in children
55
- return if safe_initialization?
56
-
57
- # @!visibility private
58
- def self.new(*args, &block)
59
- object = super(*args, &block)
60
- ensure
61
- object.full_memory_barrier if object
62
- end
63
-
64
- @safe_initialization = true
34
+ extend SafeInitialization unless safe_initialization?
65
35
  end
66
36
 
67
- # @return [true, false] if this class is safely initialized.
68
37
  def self.safe_initialization?
69
- @safe_initialization = false unless defined? @safe_initialization
70
- @safe_initialization || (superclass.respond_to?(:safe_initialization?) && superclass.safe_initialization?)
38
+ self.singleton_class < SafeInitialization
71
39
  end
72
40
 
73
41
  # For testing purposes, quite slow. Injects assert code to new method which will raise if class instance contains
@@ -0,0 +1,36 @@
1
+ require 'concurrent/synchronization/full_memory_barrier'
2
+
3
+ module Concurrent
4
+ module Synchronization
5
+
6
+ # @!visibility private
7
+ # @!macro internal_implementation_note
8
+ #
9
+ # By extending this module, a class and all its children are marked to be constructed safely. Meaning that
10
+ # all writes (ivar initializations) are made visible to all readers of newly constructed object. It ensures
11
+ # same behaviour as Java's final fields.
12
+ #
13
+ # Due to using Kernel#extend, the module is not included again if already present in the ancestors,
14
+ # which avoids extra overhead.
15
+ #
16
+ # @example
17
+ # class AClass < Concurrent::Synchronization::Object
18
+ # extend Concurrent::Synchronization::SafeInitialization
19
+ #
20
+ # def initialize
21
+ # @AFinalValue = 'value' # published safely, #foo will never return nil
22
+ # end
23
+ #
24
+ # def foo
25
+ # @AFinalValue
26
+ # end
27
+ # end
28
+ module SafeInitialization
29
+ def new(*args, &block)
30
+ super(*args, &block)
31
+ ensure
32
+ Concurrent::Synchronization.full_memory_barrier
33
+ end
34
+ end
35
+ end
36
+ end
@@ -1,3 +1,7 @@
1
+ require 'concurrent/utility/native_extension_loader' # load native parts first
2
+ require 'concurrent/utility/engine'
3
+ require 'concurrent/synchronization/full_memory_barrier'
4
+
1
5
  module Concurrent
2
6
  module Synchronization
3
7
 
@@ -19,18 +23,79 @@ module Concurrent
19
23
  # => 1
20
24
  # foo.bar = 2
21
25
  # => 2
26
+ #
27
+ # @!visibility private
28
+ module Volatile
29
+ def self.included(base)
30
+ base.extend(ClassMethods)
31
+ end
32
+
33
+ def full_memory_barrier
34
+ Synchronization.full_memory_barrier
35
+ end
36
+
37
+ module ClassMethods
38
+ if Concurrent.on_cruby?
39
+ def attr_volatile(*names)
40
+ names.each do |name|
41
+ ivar = :"@volatile_#{name}"
42
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
43
+ def #{name}
44
+ #{ivar}
45
+ end
46
+
47
+ def #{name}=(value)
48
+ #{ivar} = value
49
+ end
50
+ RUBY
51
+ end
52
+ names.map { |n| [n, :"#{n}="] }.flatten
53
+ end
54
+
55
+ elsif Concurrent.on_jruby?
56
+ def attr_volatile(*names)
57
+ names.each do |name|
58
+ ivar = :"@volatile_#{name}"
59
+
60
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
61
+ def #{name}
62
+ ::Concurrent::Synchronization::JRubyAttrVolatile.instance_variable_get_volatile(self, :#{ivar})
63
+ end
64
+
65
+ def #{name}=(value)
66
+ ::Concurrent::Synchronization::JRubyAttrVolatile.instance_variable_set_volatile(self, :#{ivar}, value)
67
+ end
68
+ RUBY
69
+
70
+ end
71
+ names.map { |n| [n, :"#{n}="] }.flatten
72
+ end
73
+
74
+ else
75
+ warn 'Possibly unsupported Ruby implementation' unless Concurrent.on_truffleruby?
76
+
77
+ def attr_volatile(*names)
78
+ names.each do |name|
79
+ ivar = :"@volatile_#{name}"
80
+
81
+ class_eval <<-RUBY, __FILE__, __LINE__ + 1
82
+ def #{name}
83
+ ::Concurrent::Synchronization.full_memory_barrier
84
+ #{ivar}
85
+ end
86
+
87
+ def #{name}=(value)
88
+ #{ivar} = value
89
+ ::Concurrent::Synchronization.full_memory_barrier
90
+ end
91
+ RUBY
92
+ end
93
+
94
+ names.map { |n| [n, :"#{n}="] }.flatten
95
+ end
96
+ end
97
+ end
22
98
 
23
- Volatile = case
24
- when Concurrent.on_cruby?
25
- MriAttrVolatile
26
- when Concurrent.on_jruby?
27
- JRubyAttrVolatile
28
- when Concurrent.on_rbx?
29
- RbxAttrVolatile
30
- when Concurrent.on_truffleruby?
31
- TruffleRubyAttrVolatile
32
- else
33
- MriAttrVolatile
34
- end
99
+ end
35
100
  end
36
101
  end
@@ -1,29 +1,12 @@
1
- require 'concurrent/utility/engine'
2
-
3
- require 'concurrent/synchronization/abstract_object'
4
1
  require 'concurrent/utility/native_extension_loader' # load native parts first
5
- Concurrent.load_native_extensions
6
2
 
7
- require 'concurrent/synchronization/mri_object'
8
- require 'concurrent/synchronization/jruby_object'
9
- require 'concurrent/synchronization/rbx_object'
10
- require 'concurrent/synchronization/truffleruby_object'
11
3
  require 'concurrent/synchronization/object'
12
- require 'concurrent/synchronization/volatile'
13
-
14
- require 'concurrent/synchronization/abstract_lockable_object'
15
- require 'concurrent/synchronization/mutex_lockable_object'
16
- require 'concurrent/synchronization/jruby_lockable_object'
17
- require 'concurrent/synchronization/rbx_lockable_object'
18
-
19
4
  require 'concurrent/synchronization/lockable_object'
20
-
21
5
  require 'concurrent/synchronization/condition'
22
6
  require 'concurrent/synchronization/lock'
23
7
 
24
8
  module Concurrent
25
- # {include:file:docs-source/synchronization.md}
26
- # {include:file:docs-source/synchronization-notes.md}
9
+ # @!visibility private
27
10
  module Synchronization
28
11
  end
29
12
  end
@@ -2,49 +2,46 @@ require 'delegate'
2
2
  require 'monitor'
3
3
 
4
4
  module Concurrent
5
- unless defined?(SynchronizedDelegator)
6
-
7
- # This class provides a trivial way to synchronize all calls to a given object
8
- # by wrapping it with a `Delegator` that performs `Monitor#enter/exit` calls
9
- # around the delegated `#send`. Example:
10
- #
11
- # array = [] # not thread-safe on many impls
12
- # array = SynchronizedDelegator.new([]) # thread-safe
13
- #
14
- # A simple `Monitor` provides a very coarse-grained way to synchronize a given
15
- # object, in that it will cause synchronization for methods that have no need
16
- # for it, but this is a trivial way to get thread-safety where none may exist
17
- # currently on some implementations.
18
- #
19
- # This class is currently being considered for inclusion into stdlib, via
20
- # https://bugs.ruby-lang.org/issues/8556
21
- #
22
- # @!visibility private
23
- class SynchronizedDelegator < SimpleDelegator
24
- def setup
25
- @old_abort = Thread.abort_on_exception
26
- Thread.abort_on_exception = true
27
- end
5
+ # This class provides a trivial way to synchronize all calls to a given object
6
+ # by wrapping it with a `Delegator` that performs `Monitor#enter/exit` calls
7
+ # around the delegated `#send`. Example:
8
+ #
9
+ # array = [] # not thread-safe on many impls
10
+ # array = SynchronizedDelegator.new([]) # thread-safe
11
+ #
12
+ # A simple `Monitor` provides a very coarse-grained way to synchronize a given
13
+ # object, in that it will cause synchronization for methods that have no need
14
+ # for it, but this is a trivial way to get thread-safety where none may exist
15
+ # currently on some implementations.
16
+ #
17
+ # This class is currently being considered for inclusion into stdlib, via
18
+ # https://bugs.ruby-lang.org/issues/8556
19
+ #
20
+ # @!visibility private
21
+ class SynchronizedDelegator < SimpleDelegator
22
+ def setup
23
+ @old_abort = Thread.abort_on_exception
24
+ Thread.abort_on_exception = true
25
+ end
28
26
 
29
- def teardown
30
- Thread.abort_on_exception = @old_abort
31
- end
27
+ def teardown
28
+ Thread.abort_on_exception = @old_abort
29
+ end
32
30
 
33
- def initialize(obj)
34
- __setobj__(obj)
35
- @monitor = Monitor.new
36
- end
31
+ def initialize(obj)
32
+ __setobj__(obj)
33
+ @monitor = Monitor.new
34
+ end
37
35
 
38
- def method_missing(method, *args, &block)
39
- monitor = @monitor
40
- begin
41
- monitor.enter
42
- super
43
- ensure
44
- monitor.exit
45
- end
36
+ def method_missing(method, *args, &block)
37
+ monitor = @monitor
38
+ begin
39
+ monitor.enter
40
+ super
41
+ ensure
42
+ monitor.exit
46
43
  end
47
-
48
44
  end
45
+
49
46
  end
50
47
  end
@@ -1,5 +1,6 @@
1
1
  require 'concurrent/thread_safe/util'
2
2
  require 'concurrent/thread_safe/util/volatile'
3
+ require 'concurrent/utility/engine'
3
4
 
4
5
  module Concurrent
5
6
 
@@ -32,45 +33,7 @@ module Concurrent
32
33
  # @!visibility private
33
34
  module CheapLockable
34
35
  private
35
- engine = defined?(RUBY_ENGINE) && RUBY_ENGINE
36
- if engine == 'rbx'
37
- # Making use of the Rubinius' ability to lock via object headers to avoid the overhead of the extra Mutex objects.
38
- def cheap_synchronize
39
- Rubinius.lock(self)
40
- begin
41
- yield
42
- ensure
43
- Rubinius.unlock(self)
44
- end
45
- end
46
-
47
- def cheap_wait
48
- wchan = Rubinius::Channel.new
49
-
50
- begin
51
- waiters = @waiters ||= []
52
- waiters.push wchan
53
- Rubinius.unlock(self)
54
- signaled = wchan.receive_timeout nil
55
- ensure
56
- Rubinius.lock(self)
57
-
58
- unless signaled or waiters.delete(wchan)
59
- # we timed out, but got signaled afterwards (e.g. while waiting to
60
- # acquire @lock), so pass that signal on to the next waiter
61
- waiters.shift << true unless waiters.empty?
62
- end
63
- end
64
-
65
- self
66
- end
67
-
68
- def cheap_broadcast
69
- waiters = @waiters ||= []
70
- waiters.shift << true until waiters.empty?
71
- self
72
- end
73
- elsif engine == 'jruby'
36
+ if Concurrent.on_jruby?
74
37
  # Use Java's native synchronized (this) { wait(); notifyAll(); } to avoid the overhead of the extra Mutex objects
75
38
  require 'jruby'
76
39
 
@@ -1,4 +1,5 @@
1
1
  require 'concurrent/thread_safe/util'
2
+ require 'concurrent/utility/engine'
2
3
 
3
4
  # Shim for TruffleRuby.synchronized
4
5
  if Concurrent.on_truffleruby? && !TruffleRuby.respond_to?(:synchronized)
@@ -37,43 +38,6 @@ module Concurrent
37
38
  end
38
39
  end
39
40
 
40
- def self.make_synchronized_on_rbx(klass)
41
- klass.class_eval do
42
- private
43
-
44
- def _mon_initialize
45
- @_monitor ||= Monitor.new # avoid double initialisation
46
- end
47
-
48
- def self.new(*args)
49
- obj = super(*args)
50
- obj.send(:_mon_initialize)
51
- obj
52
- end
53
- end
54
-
55
- klass.superclass.instance_methods(false).each do |method|
56
- case method
57
- when :new_range, :new_reserved
58
- klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
59
- def #{method}(*args)
60
- obj = super
61
- obj.send(:_mon_initialize)
62
- obj
63
- end
64
- RUBY
65
- else
66
- klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
67
- def #{method}(*args)
68
- monitor = @_monitor
69
- monitor or raise("BUG: Internal monitor was not properly initialized. Please report this to the concurrent-ruby developers.")
70
- monitor.synchronize { super }
71
- end
72
- RUBY
73
- end
74
- end
75
- end
76
-
77
41
  def self.make_synchronized_on_truffleruby(klass)
78
42
  klass.superclass.instance_methods(false).each do |method|
79
43
  klass.class_eval <<-RUBY, __FILE__, __LINE__ + 1
@@ -23,16 +23,12 @@ module Concurrent
23
23
  # The (fixed) size of the tuple.
24
24
  attr_reader :size
25
25
 
26
- # @!visibility private
27
- Tuple = defined?(Rubinius::Tuple) ? Rubinius::Tuple : ::Array
28
- private_constant :Tuple
29
-
30
26
  # Create a new tuple of the given size.
31
27
  #
32
28
  # @param [Integer] size the number of elements in the tuple
33
29
  def initialize(size)
34
30
  @size = size
35
- @tuple = tuple = Tuple.new(size)
31
+ @tuple = tuple = ::Array.new(size)
36
32
  i = 0
37
33
  while i < size
38
34
  tuple[i] = Concurrent::AtomicReference.new
@@ -1,5 +1,5 @@
1
1
  require 'set'
2
- require 'concurrent/synchronization'
2
+ require 'concurrent/synchronization/object'
3
3
 
4
4
  module Concurrent
5
5
 
@@ -149,6 +149,7 @@ module Concurrent
149
149
 
150
150
  private
151
151
 
152
+ # @!visibility private
152
153
  class Transaction
153
154
 
154
155
  ABORTED = ::Object.new
@@ -1,26 +1,19 @@
1
1
  module Concurrent
2
+ # @!visibility private
2
3
  module Utility
3
4
 
4
5
  # @!visibility private
5
6
  module EngineDetector
6
- def on_jruby?
7
- ruby_engine == 'jruby'
8
- end
9
-
10
- def on_jruby_9000?
11
- on_jruby? && ruby_version(JRUBY_VERSION, :>=, 9, 0, 0)
12
- end
13
-
14
7
  def on_cruby?
15
- ruby_engine == 'ruby'
8
+ RUBY_ENGINE == 'ruby'
16
9
  end
17
10
 
18
- def on_rbx?
19
- ruby_engine == 'rbx'
11
+ def on_jruby?
12
+ RUBY_ENGINE == 'jruby'
20
13
  end
21
14
 
22
15
  def on_truffleruby?
23
- ruby_engine == 'truffleruby'
16
+ RUBY_ENGINE == 'truffleruby'
24
17
  end
25
18
 
26
19
  def on_windows?
@@ -35,10 +28,6 @@ module Concurrent
35
28
  !(RbConfig::CONFIG['host_os'] =~ /linux/).nil?
36
29
  end
37
30
 
38
- def ruby_engine
39
- defined?(RUBY_ENGINE) ? RUBY_ENGINE : 'ruby'
40
- end
41
-
42
31
  def ruby_version(version = RUBY_VERSION, comparison, major, minor, patch)
43
32
  result = (version.split('.').map(&:to_i) <=> [major, minor, patch])
44
33
  comparisons = { :== => [0],
@@ -1,10 +1,8 @@
1
- require 'concurrent/synchronization'
2
-
3
1
  module Concurrent
4
2
 
5
3
  # @!macro monotonic_get_time
6
4
  #
7
- # Returns the current time a tracked by the application monotonic clock.
5
+ # Returns the current time as tracked by the application monotonic clock.
8
6
  #
9
7
  # @param [Symbol] unit the time unit to be returned, can be either
10
8
  # :float_second, :float_millisecond, :float_microsecond, :second,
@@ -14,77 +12,8 @@ module Concurrent
14
12
  # starting point
15
13
  #
16
14
  # @!macro monotonic_clock_warning
17
- if defined?(Process::CLOCK_MONOTONIC)
18
-
19
- def monotonic_time(unit = :float_second)
20
- Process.clock_gettime(Process::CLOCK_MONOTONIC, unit)
21
- end
22
-
23
- elsif Concurrent.on_jruby?
24
-
25
- # @!visibility private
26
- TIME_UNITS = Hash.new { |_hash, key| raise ArgumentError, "unexpected unit: #{key}" }.compare_by_identity
27
- TIME_UNITS.merge!(
28
- second: 1_000_000_000,
29
- millisecond: 1_000_000,
30
- microsecond: 1_000,
31
- nanosecond: 1,
32
- float_second: 1_000_000_000.0,
33
- float_millisecond: 1_000_000.0,
34
- float_microsecond: 1_000.0,
35
- )
36
- TIME_UNITS.freeze
37
- private_constant :TIME_UNITS
38
-
39
- def monotonic_time(unit = :float_second)
40
- java.lang.System.nanoTime() / TIME_UNITS[unit]
41
- end
42
-
43
- else
44
-
45
- class_definition = Class.new(Synchronization::LockableObject) do
46
- def initialize
47
- @last_time = Time.now.to_f
48
- @time_units = Hash.new { |_hash, key| raise ArgumentError, "unexpected unit: #{key}" }.compare_by_identity
49
- @time_units.merge!(
50
- second: [nil, true],
51
- millisecond: [1_000, true],
52
- microsecond: [1_000_000, true],
53
- nanosecond: [1_000_000_000, true],
54
- float_second: [nil, false],
55
- float_millisecond: [1_000.0, false],
56
- float_microsecond: [1_000_000.0, false],
57
- )
58
- super()
59
- end
60
-
61
- # @!visibility private
62
- def get_time(unit)
63
- synchronize do
64
- now = Time.now.to_f
65
- if @last_time < now
66
- @last_time = now
67
- else # clock has moved back in time
68
- @last_time += 0.000_001
69
- end
70
- scale, to_int = @time_units[unit]
71
- now *= scale if scale
72
- now = now.to_i if to_int
73
- now
74
- end
75
- end
76
- end
77
-
78
- # Clock that cannot be set and represents monotonic time since
79
- # some unspecified starting point.
80
- #
81
- # @!visibility private
82
- GLOBAL_MONOTONIC_CLOCK = class_definition.new
83
- private_constant :GLOBAL_MONOTONIC_CLOCK
84
-
85
- def monotonic_time(unit = :float_second)
86
- GLOBAL_MONOTONIC_CLOCK.get_time(unit)
87
- end
15
+ def monotonic_time(unit = :float_second)
16
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, unit)
88
17
  end
89
18
  module_function :monotonic_time
90
19
  end
@@ -1,9 +1,10 @@
1
1
  require 'concurrent/utility/engine'
2
+ # Synchronization::AbstractObject must be defined before loading the extension
3
+ require 'concurrent/synchronization/abstract_object'
2
4
 
3
5
  module Concurrent
4
-
6
+ # @!visibility private
5
7
  module Utility
6
-
7
8
  # @!visibility private
8
9
  module NativeExtensionLoader
9
10
 
@@ -15,15 +16,7 @@ module Concurrent
15
16
  defined?(@c_extensions_loaded) && @c_extensions_loaded
16
17
  end
17
18
 
18
- def java_extensions_loaded?
19
- defined?(@java_extensions_loaded) && @java_extensions_loaded
20
- end
21
-
22
19
  def load_native_extensions
23
- unless defined? Synchronization::AbstractObject
24
- raise 'native_extension_loader loaded before Synchronization::AbstractObject'
25
- end
26
-
27
20
  if Concurrent.on_cruby? && !c_extensions_loaded?
28
21
  ['concurrent/concurrent_ruby_ext',
29
22
  "concurrent/#{RUBY_VERSION[0..2]}/concurrent_ruby_ext"
@@ -54,6 +47,10 @@ module Concurrent
54
47
  @c_extensions_loaded = true
55
48
  end
56
49
 
50
+ def java_extensions_loaded?
51
+ defined?(@java_extensions_loaded) && @java_extensions_loaded
52
+ end
53
+
57
54
  def set_java_extensions_loaded
58
55
  @java_extensions_loaded = true
59
56
  end
@@ -77,3 +74,4 @@ module Concurrent
77
74
  extend Utility::NativeExtensionLoader
78
75
  end
79
76
 
77
+ Concurrent.load_native_extensions
@@ -1,4 +1,5 @@
1
1
  module Concurrent
2
+ # @!visibility private
2
3
  module Utility
3
4
  # @private
4
5
  module NativeInteger