concurrent-ruby 1.1.10 → 1.3.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (110) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +76 -3
  3. data/Gemfile +6 -7
  4. data/README.md +28 -23
  5. data/Rakefile +90 -76
  6. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +3 -38
  7. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +10 -25
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +1 -1
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +1 -1
  10. data/lib/concurrent-ruby/concurrent/agent.rb +4 -3
  11. data/lib/concurrent-ruby/concurrent/array.rb +3 -13
  12. data/lib/concurrent-ruby/concurrent/async.rb +1 -1
  13. data/lib/concurrent-ruby/concurrent/atom.rb +2 -2
  14. data/lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb +5 -4
  15. data/lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb +5 -4
  16. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +3 -0
  17. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +90 -153
  18. data/lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb +1 -1
  19. data/lib/concurrent-ruby/concurrent/atomic/event.rb +1 -1
  20. data/lib/concurrent-ruby/concurrent/atomic/fiber_local_var.rb +109 -0
  21. data/lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb +1 -0
  22. data/lib/concurrent-ruby/concurrent/atomic/locals.rb +189 -0
  23. data/lib/concurrent-ruby/concurrent/atomic/lock_local_var.rb +29 -0
  24. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb +11 -5
  25. data/lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb +11 -5
  26. data/lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb +1 -1
  27. data/lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb +1 -1
  28. data/lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb +17 -3
  29. data/lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb +13 -4
  30. data/lib/concurrent-ruby/concurrent/atomic/semaphore.rb +6 -9
  31. data/lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb +96 -89
  32. data/lib/concurrent-ruby/concurrent/atomic_reference/atomic_direct_update.rb +37 -0
  33. data/lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb +16 -6
  34. data/lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb +9 -1
  35. data/lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb +1 -1
  36. data/lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb +1 -1
  37. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +2 -0
  38. data/lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb +2 -2
  39. data/lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb +16 -8
  40. data/lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb +23 -20
  41. data/lib/concurrent-ruby/concurrent/collection/ruby_timeout_queue.rb +55 -0
  42. data/lib/concurrent-ruby/concurrent/collection/timeout_queue.rb +18 -0
  43. data/lib/concurrent-ruby/concurrent/concern/logging.rb +95 -6
  44. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  45. data/lib/concurrent-ruby/concurrent/configuration.rb +4 -87
  46. data/lib/concurrent-ruby/concurrent/delay.rb +3 -3
  47. data/lib/concurrent-ruby/concurrent/errors.rb +5 -0
  48. data/lib/concurrent-ruby/concurrent/exchanger.rb +1 -0
  49. data/lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb +1 -1
  50. data/lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb +6 -4
  51. data/lib/concurrent-ruby/concurrent/executor/java_executor_service.rb +7 -9
  52. data/lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb +7 -0
  53. data/lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb +2 -0
  54. data/lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb +61 -31
  55. data/lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb +1 -1
  56. data/lib/concurrent-ruby/concurrent/executor/serialized_execution.rb +1 -1
  57. data/lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb +4 -1
  58. data/lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb +1 -1
  59. data/lib/concurrent-ruby/concurrent/executor/timer_set.rb +10 -3
  60. data/lib/concurrent-ruby/concurrent/executors.rb +0 -1
  61. data/lib/concurrent-ruby/concurrent/hash.rb +5 -12
  62. data/lib/concurrent-ruby/concurrent/immutable_struct.rb +1 -1
  63. data/lib/concurrent-ruby/concurrent/ivar.rb +2 -1
  64. data/lib/concurrent-ruby/concurrent/map.rb +43 -39
  65. data/lib/concurrent-ruby/concurrent/maybe.rb +1 -1
  66. data/lib/concurrent-ruby/concurrent/mutable_struct.rb +1 -1
  67. data/lib/concurrent-ruby/concurrent/mvar.rb +5 -5
  68. data/lib/concurrent-ruby/concurrent/promise.rb +3 -3
  69. data/lib/concurrent-ruby/concurrent/promises.rb +40 -29
  70. data/lib/concurrent-ruby/concurrent/re_include.rb +2 -0
  71. data/lib/concurrent-ruby/concurrent/scheduled_task.rb +2 -2
  72. data/lib/concurrent-ruby/concurrent/set.rb +0 -10
  73. data/lib/concurrent-ruby/concurrent/settable_struct.rb +2 -2
  74. data/lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb +5 -1
  75. data/lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb +1 -3
  76. data/lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb +1 -1
  77. data/lib/concurrent-ruby/concurrent/synchronization/condition.rb +2 -0
  78. data/lib/concurrent-ruby/concurrent/synchronization/full_memory_barrier.rb +29 -0
  79. data/lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb +3 -1
  80. data/lib/concurrent-ruby/concurrent/synchronization/lock.rb +2 -0
  81. data/lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb +5 -2
  82. data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +6 -5
  83. data/lib/concurrent-ruby/concurrent/synchronization/object.rb +13 -45
  84. data/lib/concurrent-ruby/concurrent/synchronization/safe_initialization.rb +36 -0
  85. data/lib/concurrent-ruby/concurrent/synchronization/volatile.rb +77 -12
  86. data/lib/concurrent-ruby/concurrent/synchronization.rb +1 -18
  87. data/lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb +36 -39
  88. data/lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb +1 -1
  89. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +1 -37
  90. data/lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb +1 -1
  91. data/lib/concurrent-ruby/concurrent/timer_task.rb +65 -10
  92. data/lib/concurrent-ruby/concurrent/tuple.rb +1 -5
  93. data/lib/concurrent-ruby/concurrent/tvar.rb +2 -1
  94. data/lib/concurrent-ruby/concurrent/utility/engine.rb +5 -16
  95. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +3 -74
  96. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +8 -10
  97. data/lib/concurrent-ruby/concurrent/utility/native_integer.rb +1 -0
  98. data/lib/concurrent-ruby/concurrent/utility/processor_counter.rb +148 -58
  99. data/lib/concurrent-ruby/concurrent/version.rb +1 -1
  100. metadata +14 -19
  101. data/lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb +0 -66
  102. data/lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb +0 -37
  103. data/lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb +0 -181
  104. data/lib/concurrent-ruby/concurrent/collection/map/atomic_reference_map_backend.rb +0 -927
  105. data/lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb +0 -45
  106. data/lib/concurrent-ruby/concurrent/synchronization/mri_object.rb +0 -44
  107. data/lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb +0 -71
  108. data/lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb +0 -49
  109. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +0 -47
  110. data/lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb +0 -118
@@ -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
@@ -9,7 +9,7 @@ module Concurrent
9
9
  # @!visibility private
10
10
  module Util
11
11
 
12
- # A Ruby port of the Doug Lea's jsr166e.LondAdder class version 1.8
12
+ # A Ruby port of the Doug Lea's jsr166e.LongAdder class version 1.8
13
13
  # available in public domain.
14
14
  #
15
15
  # Original source code available here:
@@ -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
@@ -15,7 +15,7 @@ module Concurrent
15
15
  # Usage:
16
16
  # x = XorShiftRandom.get # uses Kernel.rand to generate an initial seed
17
17
  # while true
18
- # if (x = XorShiftRandom.xorshift).odd? # thread-localy generate a next random number
18
+ # if (x = XorShiftRandom.xorshift).odd? # thread-locally generate a next random number
19
19
  # do_something_at_random
20
20
  # end
21
21
  # end
@@ -2,6 +2,7 @@ require 'concurrent/collection/copy_on_notify_observer_set'
2
2
  require 'concurrent/concern/dereferenceable'
3
3
  require 'concurrent/concern/observable'
4
4
  require 'concurrent/atomic/atomic_boolean'
5
+ require 'concurrent/atomic/atomic_fixnum'
5
6
  require 'concurrent/executor/executor_service'
6
7
  require 'concurrent/executor/ruby_executor_service'
7
8
  require 'concurrent/executor/safe_task_executor'
@@ -32,6 +33,17 @@ module Concurrent
32
33
  # be tested separately then passed to the `TimerTask` for scheduling and
33
34
  # running.
34
35
  #
36
+ # A `TimerTask` supports two different types of interval calculations.
37
+ # A fixed delay will always wait the same amount of time between the
38
+ # completion of one task and the start of the next. A fixed rate will
39
+ # attempt to maintain a constant rate of execution regardless of the
40
+ # duration of the task. For example, if a fixed rate task is scheduled
41
+ # to run every 60 seconds but the task itself takes 10 seconds to
42
+ # complete, the next task will be scheduled to run 50 seconds after
43
+ # the start of the previous task. If the task takes 70 seconds to
44
+ # complete, the next task will be start immediately after the previous
45
+ # task completes. Tasks will not be executed concurrently.
46
+ #
35
47
  # In some cases it may be necessary for a `TimerTask` to affect its own
36
48
  # execution cycle. To facilitate this, a reference to the TimerTask instance
37
49
  # is passed as an argument to the provided block every time the task is
@@ -74,6 +86,12 @@ module Concurrent
74
86
  #
75
87
  # #=> 'Boom!'
76
88
  #
89
+ # @example Configuring `:interval_type` with either :fixed_delay or :fixed_rate, default is :fixed_delay
90
+ # task = Concurrent::TimerTask.new(execution_interval: 5, interval_type: :fixed_rate) do
91
+ # puts 'Boom!'
92
+ # end
93
+ # task.interval_type #=> :fixed_rate
94
+ #
77
95
  # @example Last `#value` and `Dereferenceable` mixin
78
96
  # task = Concurrent::TimerTask.new(
79
97
  # dup_on_deref: true,
@@ -87,7 +105,7 @@ module Concurrent
87
105
  #
88
106
  # @example Controlling execution from within the block
89
107
  # timer_task = Concurrent::TimerTask.new(execution_interval: 1) do |task|
90
- # task.execution_interval.times{ print 'Boom! ' }
108
+ # task.execution_interval.to_i.times{ print 'Boom! ' }
91
109
  # print "\n"
92
110
  # task.execution_interval += 1
93
111
  # if task.execution_interval > 5
@@ -96,7 +114,7 @@ module Concurrent
96
114
  # end
97
115
  # end
98
116
  #
99
- # timer_task.execute # blocking call - this task will stop itself
117
+ # timer_task.execute
100
118
  # #=> Boom!
101
119
  # #=> Boom! Boom!
102
120
  # #=> Boom! Boom! Boom!
@@ -152,18 +170,30 @@ module Concurrent
152
170
  # Default `:execution_interval` in seconds.
153
171
  EXECUTION_INTERVAL = 60
154
172
 
155
- # Default `:timeout_interval` in seconds.
156
- TIMEOUT_INTERVAL = 30
173
+ # Maintain the interval between the end of one execution and the start of the next execution.
174
+ FIXED_DELAY = :fixed_delay
175
+
176
+ # Maintain the interval between the start of one execution and the start of the next.
177
+ # If execution time exceeds the interval, the next execution will start immediately
178
+ # after the previous execution finishes. Executions will not run concurrently.
179
+ FIXED_RATE = :fixed_rate
180
+
181
+ # Default `:interval_type`
182
+ DEFAULT_INTERVAL_TYPE = FIXED_DELAY
157
183
 
158
184
  # Create a new TimerTask with the given task and configuration.
159
185
  #
160
186
  # @!macro timer_task_initialize
161
187
  # @param [Hash] opts the options defining task execution.
162
- # @option opts [Integer] :execution_interval number of seconds between
188
+ # @option opts [Float] :execution_interval number of seconds between
163
189
  # task executions (default: EXECUTION_INTERVAL)
164
190
  # @option opts [Boolean] :run_now Whether to run the task immediately
165
191
  # upon instantiation or to wait until the first # execution_interval
166
192
  # has passed (default: false)
193
+ # @options opts [Symbol] :interval_type method to calculate the interval
194
+ # between executions, can be either :fixed_rate or :fixed_delay.
195
+ # (default: :fixed_delay)
196
+ # @option opts [Executor] executor, default is `global_io_executor`
167
197
  #
168
198
  # @!macro deref_options
169
199
  #
@@ -207,6 +237,7 @@ module Concurrent
207
237
  synchronize do
208
238
  if @running.false?
209
239
  @running.make_true
240
+ @age.increment
210
241
  schedule_next_task(@run_now ? 0 : @execution_interval)
211
242
  end
212
243
  end
@@ -242,6 +273,10 @@ module Concurrent
242
273
  end
243
274
  end
244
275
 
276
+ # @!attribute [r] interval_type
277
+ # @return [Symbol] method to calculate the interval between executions
278
+ attr_reader :interval_type
279
+
245
280
  # @!attribute [rw] timeout_interval
246
281
  # @return [Fixnum] Number of seconds the task can run before it is
247
282
  # considered to have failed.
@@ -264,12 +299,19 @@ module Concurrent
264
299
  set_deref_options(opts)
265
300
 
266
301
  self.execution_interval = opts[:execution] || opts[:execution_interval] || EXECUTION_INTERVAL
302
+ if opts[:interval_type] && ![FIXED_DELAY, FIXED_RATE].include?(opts[:interval_type])
303
+ raise ArgumentError.new('interval_type must be either :fixed_delay or :fixed_rate')
304
+ end
267
305
  if opts[:timeout] || opts[:timeout_interval]
268
306
  warn 'TimeTask timeouts are now ignored as these were not able to be implemented correctly'
269
307
  end
308
+
270
309
  @run_now = opts[:now] || opts[:run_now]
271
- @executor = Concurrent::SafeTaskExecutor.new(task)
310
+ @interval_type = opts[:interval_type] || DEFAULT_INTERVAL_TYPE
311
+ @task = Concurrent::SafeTaskExecutor.new(task)
312
+ @executor = opts[:executor] || Concurrent.global_io_executor
272
313
  @running = Concurrent::AtomicBoolean.new(false)
314
+ @age = Concurrent::AtomicFixnum.new(0)
273
315
  @value = nil
274
316
 
275
317
  self.observers = Collection::CopyOnNotifyObserverSet.new
@@ -289,17 +331,20 @@ module Concurrent
289
331
 
290
332
  # @!visibility private
291
333
  def schedule_next_task(interval = execution_interval)
292
- ScheduledTask.execute(interval, args: [Concurrent::Event.new], &method(:execute_task))
334
+ ScheduledTask.execute(interval, executor: @executor, args: [Concurrent::Event.new, @age.value], &method(:execute_task))
293
335
  nil
294
336
  end
295
337
 
296
338
  # @!visibility private
297
- def execute_task(completion)
339
+ def execute_task(completion, age_when_scheduled)
298
340
  return nil unless @running.true?
299
- _success, value, reason = @executor.execute(self)
341
+ return nil unless @age.value == age_when_scheduled
342
+
343
+ start_time = Concurrent.monotonic_time
344
+ _success, value, reason = @task.execute(self)
300
345
  if completion.try?
301
346
  self.value = value
302
- schedule_next_task
347
+ schedule_next_task(calculate_next_interval(start_time))
303
348
  time = Time.now
304
349
  observers.notify_observers do
305
350
  [time, self.value, reason]
@@ -307,5 +352,15 @@ module Concurrent
307
352
  end
308
353
  nil
309
354
  end
355
+
356
+ # @!visibility private
357
+ def calculate_next_interval(start_time)
358
+ if @interval_type == FIXED_RATE
359
+ run_time = Concurrent.monotonic_time - start_time
360
+ [execution_interval - run_time, 0].max
361
+ else # FIXED_DELAY
362
+ execution_interval
363
+ end
364
+ end
310
365
  end
311
366
  end
@@ -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