concurrent-ruby 1.1.4 → 1.1.8

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 (131) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +51 -0
  3. data/Gemfile +11 -8
  4. data/{LICENSE.md → LICENSE.txt} +18 -20
  5. data/README.md +40 -5
  6. data/Rakefile +52 -64
  7. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +9 -8
  8. data/lib/{concurrent-ruby.rb → concurrent-ruby/concurrent-ruby.rb} +0 -0
  9. data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +0 -0
  10. data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +0 -0
  11. data/lib/{concurrent → concurrent-ruby/concurrent}/array.rb +9 -9
  12. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +23 -20
  13. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +1 -1
  14. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
  15. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +2 -2
  16. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +2 -2
  17. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_markable_reference.rb +0 -0
  18. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_reference.rb +0 -0
  19. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +1 -1
  20. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +0 -0
  21. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +0 -0
  22. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +0 -0
  23. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +0 -0
  25. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +0 -0
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +0 -0
  28. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +0 -0
  29. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +0 -0
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +60 -40
  31. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +0 -0
  32. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +1 -1
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +0 -0
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +0 -0
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/atomics.rb +0 -0
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  39. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/lock_free_stack.rb +1 -1
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +0 -0
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +1 -1
  42. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +0 -0
  43. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  44. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +1 -1
  45. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +0 -0
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +2 -2
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +0 -0
  49. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +0 -0
  51. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +13 -9
  53. data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +0 -0
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +0 -0
  55. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +0 -0
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +0 -0
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +17 -23
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +4 -4
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +2 -2
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +16 -12
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +18 -6
  65. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +15 -2
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +0 -2
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +20 -5
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +0 -0
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +1 -0
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +2 -1
  77. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +13 -16
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +0 -0
  80. data/lib/{concurrent → concurrent-ruby/concurrent}/hash.rb +4 -4
  81. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +9 -1
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +0 -0
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/map.rb +1 -1
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +0 -0
  85. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +12 -2
  86. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +0 -0
  87. data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  88. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +0 -0
  89. data/lib/{concurrent → concurrent-ruby/concurrent}/promises.rb +348 -117
  90. data/lib/{concurrent → concurrent-ruby/concurrent}/re_include.rb +0 -0
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +0 -0
  92. data/lib/{concurrent → concurrent-ruby/concurrent}/set.rb +5 -5
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +11 -1
  94. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +0 -0
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +0 -0
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
  97. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +12 -0
  98. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
  101. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
  102. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +2 -2
  103. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
  104. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mutex_lockable_object.rb +0 -0
  105. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +46 -20
  106. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +0 -0
  107. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
  108. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/truffleruby_object.rb +1 -0
  109. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +0 -0
  110. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
  111. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  112. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  113. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
  114. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/data_structures.rb +0 -0
  115. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  116. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +1 -1
  117. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  118. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  119. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +0 -1
  120. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +0 -0
  121. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +9 -6
  122. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +0 -0
  123. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/monotonic_time.rb +0 -0
  124. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_extension_loader.rb +0 -0
  125. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
  126. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -0
  127. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  128. metadata +129 -129
  129. data/lib/concurrent/concurrent_ruby.jar +0 -0
  130. data/lib/concurrent/utility/at_exit.rb +0 -97
  131. data/lib/concurrent/version.rb +0 -4
@@ -11,11 +11,11 @@ module Concurrent
11
11
  # or writing at a time. This includes iteration methods like `#each`.
12
12
  #
13
13
  # @note `a += b` is **not** a **thread-safe** operation on
14
- # `Concurrent::Set`. It reads Set `a`, then it creates new `Concurrent::Set`
15
- # which is union of `a` and `b`, then it writes the union to `a`.
16
- # The read and write are independent operations they do not form a single atomic
17
- # operation therefore when two `+=` operations are executed concurrently updates
18
- # may be lost. Use `#merge` instead.
14
+ # `Concurrent::Set`. It reads Set `a`, then it creates new `Concurrent::Set`
15
+ # which is union of `a` and `b`, then it writes the union to `a`.
16
+ # The read and write are independent operations they do not form a single atomic
17
+ # operation therefore when two `+=` operations are executed concurrently updates
18
+ # may be lost. Use `#merge` instead.
19
19
  #
20
20
  # @see http://ruby-doc.org/stdlib-2.4.0/libdoc/set/rdoc/Set.html Ruby standard library `Set`
21
21
 
@@ -9,7 +9,7 @@ module Concurrent
9
9
  # or any time thereafter. Attempting to assign a value to a member
10
10
  # that has already been set will result in a `Concurrent::ImmutabilityError`.
11
11
  #
12
- # @see http://ruby-doc.org/core-2.2.0/Struct.html Ruby standard library `Struct`
12
+ # @see http://ruby-doc.org/core/Struct.html Ruby standard library `Struct`
13
13
  # @see http://en.wikipedia.org/wiki/Final_(Java) Java `final` keyword
14
14
  module SettableStruct
15
15
  include Synchronization::AbstractStruct
@@ -91,6 +91,16 @@ module Concurrent
91
91
  raise NameError.new("no member '#{member}' in struct")
92
92
  end
93
93
 
94
+ private
95
+
96
+ # @!visibility private
97
+ def initialize_copy(original)
98
+ synchronize do
99
+ super(original)
100
+ ns_initialize_copy
101
+ end
102
+ end
103
+
94
104
  # @!macro struct_new
95
105
  def self.new(*args, &block)
96
106
  clazz_name = nil
@@ -115,6 +115,17 @@ module Concurrent
115
115
  self.class.new(*self.to_h.merge(other, &block).values)
116
116
  end
117
117
 
118
+ # @!visibility private
119
+ def ns_initialize_copy
120
+ @values = @values.map do |val|
121
+ begin
122
+ val.clone
123
+ rescue TypeError
124
+ val
125
+ end
126
+ end
127
+ end
128
+
118
129
  # @!visibility private
119
130
  def pr_underscore(clazz)
120
131
  word = clazz.to_s.dup # dup string to workaround JRuby 9.2.0.0 bug https://github.com/jruby/jruby/issues/5229
@@ -152,6 +163,7 @@ module Concurrent
152
163
  end
153
164
  end
154
165
  clazz.class_exec(&block) unless block.nil?
166
+ clazz.singleton_class.send :alias_method, :[], :new
155
167
  clazz
156
168
  end
157
169
  end
@@ -1,5 +1,7 @@
1
1
  module Concurrent
2
2
  module Synchronization
3
+
4
+ # @!visibility private
3
5
  # TODO (pitr-ch 04-Dec-2016): should be in edge
4
6
  class Condition < LockableObject
5
7
  safe_initialization!
@@ -3,6 +3,7 @@ module Concurrent
3
3
 
4
4
  if Concurrent.on_jruby? && Concurrent.java_extensions_loaded?
5
5
 
6
+ # @!visibility private
6
7
  module JRubyAttrVolatile
7
8
  def self.included(base)
8
9
  base.extend(ClassMethods)
@@ -1,5 +1,7 @@
1
1
  module Concurrent
2
2
  module Synchronization
3
+
4
+ # @!visibility private
3
5
  # TODO (pitr-ch 04-Dec-2016): should be in edge
4
6
  class Lock < LockableObject
5
7
  # TODO use JavaReentrantLock on JRuby
@@ -26,8 +26,8 @@ module Concurrent
26
26
  # the classes using it. Use {Synchronization::Object} not this abstract class.
27
27
  #
28
28
  # @note this object does not support usage together with
29
- # [`Thread#wakeup`](http://ruby-doc.org/core-2.2.0/Thread.html#method-i-wakeup)
30
- # and [`Thread#raise`](http://ruby-doc.org/core-2.2.0/Thread.html#method-i-raise).
29
+ # [`Thread#wakeup`](http://ruby-doc.org/core/Thread.html#method-i-wakeup)
30
+ # and [`Thread#raise`](http://ruby-doc.org/core/Thread.html#method-i-raise).
31
31
  # `Thread#sleep` and `Thread#wakeup` will work as expected but mixing `Synchronization::Object#wait` and
32
32
  # `Thread#wakeup` will not work on all platforms.
33
33
  #
@@ -1,6 +1,7 @@
1
1
  module Concurrent
2
2
  module Synchronization
3
3
 
4
+ # @!visibility private
4
5
  module MriAttrVolatile
5
6
  def self.included(base)
6
7
  base.extend(ClassMethods)
@@ -27,15 +27,15 @@ module Concurrent
27
27
 
28
28
  # @!method self.attr_volatile(*names)
29
29
  # Creates methods for reading and writing (as `attr_accessor` does) to a instance variable with
30
- # volatile (Java) semantic. The instance variable should be accessed oly through generated methods.
30
+ # volatile (Java) semantic. The instance variable should be accessed only through generated methods.
31
31
  #
32
- # @param [Array<Symbol>] names of the instance variables to be volatile
33
- # @return [Array<Symbol>] names of defined method names
32
+ # @param [::Array<Symbol>] names of the instance variables to be volatile
33
+ # @return [::Array<Symbol>] names of defined method names
34
34
 
35
35
  # Has to be called by children.
36
36
  def initialize
37
37
  super
38
- initialize_volatile_with_cas
38
+ __initialize_atomic_fields__
39
39
  end
40
40
 
41
41
  # By calling this method on a class, it and all its children are marked to be constructed safely. Meaning that
@@ -49,10 +49,12 @@ module Concurrent
49
49
  # @AFinalValue = 'value' # published safely, does not have to be synchronized
50
50
  # end
51
51
  # end
52
+ # @return [true]
52
53
  def self.safe_initialization!
53
54
  # define only once, and not again in children
54
55
  return if safe_initialization?
55
56
 
57
+ # @!visibility private
56
58
  def self.new(*args, &block)
57
59
  object = super(*args, &block)
58
60
  ensure
@@ -70,6 +72,8 @@ module Concurrent
70
72
 
71
73
  # For testing purposes, quite slow. Injects assert code to new method which will raise if class instance contains
72
74
  # any instance variables with CamelCase names and isn't {.safe_initialization?}.
75
+ # @raise when offend found
76
+ # @return [true]
73
77
  def self.ensure_safe_initialization_when_final_fields_are_present
74
78
  Object.class_eval do
75
79
  def self.new(*args, &block)
@@ -81,6 +85,7 @@ module Concurrent
81
85
  end
82
86
  end
83
87
  end
88
+ true
84
89
  end
85
90
 
86
91
  # Creates methods for reading and writing to a instance variable with
@@ -89,13 +94,30 @@ module Concurrent
89
94
  # This method generates following methods: `value`, `value=(new_value) #=> new_value`,
90
95
  # `swap_value(new_value) #=> old_value`,
91
96
  # `compare_and_set_value(expected, value) #=> true || false`, `update_value(&block)`.
92
- # @param [Array<Symbol>] names of the instance variables to be volatile with CAS.
93
- # @return [Array<Symbol>] names of defined method names.
97
+ # @param [::Array<Symbol>] names of the instance variables to be volatile with CAS.
98
+ # @return [::Array<Symbol>] names of defined method names.
99
+ # @!macro attr_atomic
100
+ # @!method $1
101
+ # @return [Object] The $1.
102
+ # @!method $1=(new_$1)
103
+ # Set the $1.
104
+ # @return [Object] new_$1.
105
+ # @!method swap_$1(new_$1)
106
+ # Set the $1 to new_$1 and return the old $1.
107
+ # @return [Object] old $1
108
+ # @!method compare_and_set_$1(expected_$1, new_$1)
109
+ # Sets the $1 to new_$1 if the current $1 is expected_$1
110
+ # @return [true, false]
111
+ # @!method update_$1(&block)
112
+ # Updates the $1 using the block.
113
+ # @yield [Object] Calculate a new $1 using given (old) $1
114
+ # @yieldparam [Object] old $1
115
+ # @return [Object] new $1
94
116
  def self.attr_atomic(*names)
95
- @volatile_cas_fields ||= []
96
- @volatile_cas_fields += names
117
+ @__atomic_fields__ ||= []
118
+ @__atomic_fields__ += names
97
119
  safe_initialization!
98
- define_initialize_volatile_with_cas
120
+ define_initialize_atomic_fields
99
121
 
100
122
  names.each do |name|
101
123
  ivar = :"@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }}"
@@ -124,32 +146,36 @@ module Concurrent
124
146
  names.flat_map { |n| [n, :"#{n}=", :"swap_#{n}", :"compare_and_set_#{n}", :"update_#{n}"] }
125
147
  end
126
148
 
127
- # @param [true,false] inherited should inherited volatile with CAS fields be returned?
128
- # @return [Array<Symbol>] Returns defined volatile with CAS fields on this class.
129
- def self.volatile_cas_fields(inherited = true)
130
- @volatile_cas_fields ||= []
131
- ((superclass.volatile_cas_fields if superclass.respond_to?(:volatile_cas_fields) && inherited) || []) +
132
- @volatile_cas_fields
149
+ # @param [true, false] inherited should inherited volatile with CAS fields be returned?
150
+ # @return [::Array<Symbol>] Returns defined volatile with CAS fields on this class.
151
+ def self.atomic_attributes(inherited = true)
152
+ @__atomic_fields__ ||= []
153
+ ((superclass.atomic_attributes if superclass.respond_to?(:atomic_attributes) && inherited) || []) + @__atomic_fields__
154
+ end
155
+
156
+ # @return [true, false] is the attribute with name atomic?
157
+ def self.atomic_attribute?(name)
158
+ atomic_attributes.include? name
133
159
  end
134
160
 
135
161
  private
136
162
 
137
- def self.define_initialize_volatile_with_cas
138
- assignments = @volatile_cas_fields.map do |name|
163
+ def self.define_initialize_atomic_fields
164
+ assignments = @__atomic_fields__.map do |name|
139
165
  "@Atomic#{name.to_s.gsub(/(?:^|_)(.)/) { $1.upcase }} = Concurrent::AtomicReference.new(nil)"
140
166
  end.join("\n")
141
167
 
142
168
  class_eval <<-RUBY, __FILE__, __LINE__ + 1
143
- def initialize_volatile_with_cas
169
+ def __initialize_atomic_fields__
144
170
  super
145
171
  #{assignments}
146
172
  end
147
173
  RUBY
148
174
  end
149
175
 
150
- private_class_method :define_initialize_volatile_with_cas
176
+ private_class_method :define_initialize_atomic_fields
151
177
 
152
- def initialize_volatile_with_cas
178
+ def __initialize_atomic_fields__
153
179
  end
154
180
 
155
181
  end
@@ -1,6 +1,7 @@
1
1
  module Concurrent
2
2
  module Synchronization
3
3
 
4
+ # @!visibility private
4
5
  module RbxAttrVolatile
5
6
  def self.included(base)
6
7
  base.extend(ClassMethods)
@@ -1,6 +1,7 @@
1
1
  module Concurrent
2
2
  module Synchronization
3
3
 
4
+ # @!visibility private
4
5
  module TruffleRubyAttrVolatile
5
6
  def self.included(base)
6
7
  base.extend(ClassMethods)
@@ -97,7 +97,7 @@ module Concurrent
97
97
  # TODO: this only adds padding after the :value slot, need to find a way to add padding before the slot
98
98
  # TODO (pitr-ch 28-Jul-2018): the padding instance vars may not be created
99
99
  # hide from yardoc in a method
100
- attr_reader *(12.times.collect{ |i| "padding_#{i}".to_sym })
100
+ attr_reader :padding_0, :padding_1, :padding_2, :padding_3, :padding_4, :padding_5, :padding_6, :padding_7, :padding_8, :padding_9, :padding_10, :padding_11
101
101
  end
102
102
  padding
103
103
  end
@@ -325,7 +325,6 @@ module Concurrent
325
325
  def timeout_task(completion)
326
326
  return unless @running.true?
327
327
  if completion.try?
328
- self.value = value
329
328
  schedule_next_task
330
329
  observers.notify_observers(Time.now, nil, Concurrent::TimeoutError.new)
331
330
  end
@@ -188,7 +188,10 @@ module Concurrent
188
188
  def write(tvar, value)
189
189
  # Have we already written to this TVar?
190
190
 
191
- unless @write_log.has_key? tvar
191
+ if @write_log.has_key? tvar
192
+ # Record the value written
193
+ @write_log[tvar] = value
194
+ else
192
195
  # Try to lock the TVar
193
196
 
194
197
  unless tvar.unsafe_lock.try_lock
@@ -196,7 +199,11 @@ module Concurrent
196
199
  Concurrent::abort_transaction
197
200
  end
198
201
 
199
- # If we previously wrote to it, check the version hasn't changed
202
+ # Record the value written
203
+
204
+ @write_log[tvar] = value
205
+
206
+ # If we previously read from it, check the version hasn't changed
200
207
 
201
208
  @read_log.each do |log_entry|
202
209
  if log_entry.tvar == tvar and tvar.unsafe_version > log_entry.version
@@ -204,10 +211,6 @@ module Concurrent
204
211
  end
205
212
  end
206
213
  end
207
-
208
- # Record the value written
209
-
210
- @write_log[tvar] = value
211
214
  end
212
215
 
213
216
  def abort
@@ -1,3 +1,4 @@
1
+ require 'etc'
1
2
  require 'rbconfig'
2
3
  require 'concurrent/delay'
3
4
 
@@ -22,6 +23,8 @@ module Concurrent
22
23
  # occasionally poll this property." Subsequently the result will NOT be
23
24
  # memoized under JRuby.
24
25
  #
26
+ # Ruby's Etc.nprocessors will be used if available (MRI 2.2+).
27
+ #
25
28
  # On Windows the Win32 API will be queried for the
26
29
  # `NumberOfLogicalProcessors from Win32_Processor`. This will return the
27
30
  # total number "logical processors for the current instance of the
@@ -76,6 +79,8 @@ module Concurrent
76
79
  def compute_processor_count
77
80
  if Concurrent.on_jruby?
78
81
  java.lang.Runtime.getRuntime.availableProcessors
82
+ elsif Etc.respond_to?(:nprocessors) && (nprocessor = Etc.nprocessors rescue nil)
83
+ nprocessor
79
84
  else
80
85
  os_name = RbConfig::CONFIG["target_os"]
81
86
  if os_name =~ /mingw|mswin/
@@ -0,0 +1,3 @@
1
+ module Concurrent
2
+ VERSION = '1.1.8'
3
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.4
4
+ version: 1.1.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry D'Antonio
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2018-12-15 00:00:00.000000000 Z
13
+ date: 2021-01-20 00:00:00.000000000 Z
14
14
  dependencies: []
15
15
  description: |
16
16
  Modern concurrency tools including agents, futures, promises, thread pools, actors, supervisors, and more.
@@ -20,12 +20,12 @@ executables: []
20
20
  extensions: []
21
21
  extra_rdoc_files:
22
22
  - README.md
23
- - LICENSE.md
23
+ - LICENSE.txt
24
24
  - CHANGELOG.md
25
25
  files:
26
26
  - CHANGELOG.md
27
27
  - Gemfile
28
- - LICENSE.md
28
+ - LICENSE.txt
29
29
  - README.md
30
30
  - Rakefile
31
31
  - ext/concurrent-ruby/ConcurrentRubyService.java
@@ -43,135 +43,136 @@ files:
43
43
  - ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java
44
44
  - ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java
45
45
  - ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java
46
- - lib/concurrent-ruby.rb
47
- - lib/concurrent.rb
48
- - lib/concurrent/agent.rb
49
- - lib/concurrent/array.rb
50
- - lib/concurrent/async.rb
51
- - lib/concurrent/atom.rb
52
- - lib/concurrent/atomic/abstract_thread_local_var.rb
53
- - lib/concurrent/atomic/atomic_boolean.rb
54
- - lib/concurrent/atomic/atomic_fixnum.rb
55
- - lib/concurrent/atomic/atomic_markable_reference.rb
56
- - lib/concurrent/atomic/atomic_reference.rb
57
- - lib/concurrent/atomic/count_down_latch.rb
58
- - lib/concurrent/atomic/cyclic_barrier.rb
59
- - lib/concurrent/atomic/event.rb
60
- - lib/concurrent/atomic/java_count_down_latch.rb
61
- - lib/concurrent/atomic/java_thread_local_var.rb
62
- - lib/concurrent/atomic/mutex_atomic_boolean.rb
63
- - lib/concurrent/atomic/mutex_atomic_fixnum.rb
64
- - lib/concurrent/atomic/mutex_count_down_latch.rb
65
- - lib/concurrent/atomic/mutex_semaphore.rb
66
- - lib/concurrent/atomic/read_write_lock.rb
67
- - lib/concurrent/atomic/reentrant_read_write_lock.rb
68
- - lib/concurrent/atomic/ruby_thread_local_var.rb
69
- - lib/concurrent/atomic/semaphore.rb
70
- - lib/concurrent/atomic/thread_local_var.rb
71
- - lib/concurrent/atomic_reference/mutex_atomic.rb
72
- - lib/concurrent/atomic_reference/numeric_cas_wrapper.rb
73
- - lib/concurrent/atomics.rb
74
- - lib/concurrent/collection/copy_on_notify_observer_set.rb
75
- - lib/concurrent/collection/copy_on_write_observer_set.rb
76
- - lib/concurrent/collection/java_non_concurrent_priority_queue.rb
77
- - lib/concurrent/collection/lock_free_stack.rb
78
- - lib/concurrent/collection/map/atomic_reference_map_backend.rb
79
- - lib/concurrent/collection/map/mri_map_backend.rb
80
- - lib/concurrent/collection/map/non_concurrent_map_backend.rb
81
- - lib/concurrent/collection/map/synchronized_map_backend.rb
82
- - lib/concurrent/collection/non_concurrent_priority_queue.rb
83
- - lib/concurrent/collection/ruby_non_concurrent_priority_queue.rb
84
- - lib/concurrent/concern/deprecation.rb
85
- - lib/concurrent/concern/dereferenceable.rb
86
- - lib/concurrent/concern/logging.rb
87
- - lib/concurrent/concern/obligation.rb
88
- - lib/concurrent/concern/observable.rb
89
- - lib/concurrent/concurrent_ruby.jar
90
- - lib/concurrent/configuration.rb
91
- - lib/concurrent/constants.rb
92
- - lib/concurrent/dataflow.rb
93
- - lib/concurrent/delay.rb
94
- - lib/concurrent/errors.rb
95
- - lib/concurrent/exchanger.rb
96
- - lib/concurrent/executor/abstract_executor_service.rb
97
- - lib/concurrent/executor/cached_thread_pool.rb
98
- - lib/concurrent/executor/executor_service.rb
99
- - lib/concurrent/executor/fixed_thread_pool.rb
100
- - lib/concurrent/executor/immediate_executor.rb
101
- - lib/concurrent/executor/indirect_immediate_executor.rb
102
- - lib/concurrent/executor/java_executor_service.rb
103
- - lib/concurrent/executor/java_single_thread_executor.rb
104
- - lib/concurrent/executor/java_thread_pool_executor.rb
105
- - lib/concurrent/executor/ruby_executor_service.rb
106
- - lib/concurrent/executor/ruby_single_thread_executor.rb
107
- - lib/concurrent/executor/ruby_thread_pool_executor.rb
108
- - lib/concurrent/executor/safe_task_executor.rb
109
- - lib/concurrent/executor/serial_executor_service.rb
110
- - lib/concurrent/executor/serialized_execution.rb
111
- - lib/concurrent/executor/serialized_execution_delegator.rb
112
- - lib/concurrent/executor/simple_executor_service.rb
113
- - lib/concurrent/executor/single_thread_executor.rb
114
- - lib/concurrent/executor/thread_pool_executor.rb
115
- - lib/concurrent/executor/timer_set.rb
116
- - lib/concurrent/executors.rb
117
- - lib/concurrent/future.rb
118
- - lib/concurrent/hash.rb
119
- - lib/concurrent/immutable_struct.rb
120
- - lib/concurrent/ivar.rb
121
- - lib/concurrent/map.rb
122
- - lib/concurrent/maybe.rb
123
- - lib/concurrent/mutable_struct.rb
124
- - lib/concurrent/mvar.rb
125
- - lib/concurrent/options.rb
126
- - lib/concurrent/promise.rb
127
- - lib/concurrent/promises.rb
128
- - lib/concurrent/re_include.rb
129
- - lib/concurrent/scheduled_task.rb
130
- - lib/concurrent/set.rb
131
- - lib/concurrent/settable_struct.rb
132
- - lib/concurrent/synchronization.rb
133
- - lib/concurrent/synchronization/abstract_lockable_object.rb
134
- - lib/concurrent/synchronization/abstract_object.rb
135
- - lib/concurrent/synchronization/abstract_struct.rb
136
- - lib/concurrent/synchronization/condition.rb
137
- - lib/concurrent/synchronization/jruby_lockable_object.rb
138
- - lib/concurrent/synchronization/jruby_object.rb
139
- - lib/concurrent/synchronization/lock.rb
140
- - lib/concurrent/synchronization/lockable_object.rb
141
- - lib/concurrent/synchronization/mri_object.rb
142
- - lib/concurrent/synchronization/mutex_lockable_object.rb
143
- - lib/concurrent/synchronization/object.rb
144
- - lib/concurrent/synchronization/rbx_lockable_object.rb
145
- - lib/concurrent/synchronization/rbx_object.rb
146
- - lib/concurrent/synchronization/truffleruby_object.rb
147
- - lib/concurrent/synchronization/volatile.rb
148
- - lib/concurrent/thread_safe/synchronized_delegator.rb
149
- - lib/concurrent/thread_safe/util.rb
150
- - lib/concurrent/thread_safe/util/adder.rb
151
- - lib/concurrent/thread_safe/util/cheap_lockable.rb
152
- - lib/concurrent/thread_safe/util/data_structures.rb
153
- - lib/concurrent/thread_safe/util/power_of_two_tuple.rb
154
- - lib/concurrent/thread_safe/util/striped64.rb
155
- - lib/concurrent/thread_safe/util/volatile.rb
156
- - lib/concurrent/thread_safe/util/xor_shift_random.rb
157
- - lib/concurrent/timer_task.rb
158
- - lib/concurrent/tuple.rb
159
- - lib/concurrent/tvar.rb
160
- - lib/concurrent/utility/at_exit.rb
161
- - lib/concurrent/utility/engine.rb
162
- - lib/concurrent/utility/monotonic_time.rb
163
- - lib/concurrent/utility/native_extension_loader.rb
164
- - lib/concurrent/utility/native_integer.rb
165
- - lib/concurrent/utility/processor_counter.rb
166
- - lib/concurrent/version.rb
46
+ - lib/concurrent-ruby/concurrent-ruby.rb
47
+ - lib/concurrent-ruby/concurrent.rb
48
+ - lib/concurrent-ruby/concurrent/agent.rb
49
+ - lib/concurrent-ruby/concurrent/array.rb
50
+ - lib/concurrent-ruby/concurrent/async.rb
51
+ - lib/concurrent-ruby/concurrent/atom.rb
52
+ - lib/concurrent-ruby/concurrent/atomic/abstract_thread_local_var.rb
53
+ - lib/concurrent-ruby/concurrent/atomic/atomic_boolean.rb
54
+ - lib/concurrent-ruby/concurrent/atomic/atomic_fixnum.rb
55
+ - lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb
56
+ - lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb
57
+ - lib/concurrent-ruby/concurrent/atomic/count_down_latch.rb
58
+ - lib/concurrent-ruby/concurrent/atomic/cyclic_barrier.rb
59
+ - lib/concurrent-ruby/concurrent/atomic/event.rb
60
+ - lib/concurrent-ruby/concurrent/atomic/java_count_down_latch.rb
61
+ - lib/concurrent-ruby/concurrent/atomic/java_thread_local_var.rb
62
+ - lib/concurrent-ruby/concurrent/atomic/mutex_atomic_boolean.rb
63
+ - lib/concurrent-ruby/concurrent/atomic/mutex_atomic_fixnum.rb
64
+ - lib/concurrent-ruby/concurrent/atomic/mutex_count_down_latch.rb
65
+ - lib/concurrent-ruby/concurrent/atomic/mutex_semaphore.rb
66
+ - lib/concurrent-ruby/concurrent/atomic/read_write_lock.rb
67
+ - lib/concurrent-ruby/concurrent/atomic/reentrant_read_write_lock.rb
68
+ - lib/concurrent-ruby/concurrent/atomic/ruby_thread_local_var.rb
69
+ - lib/concurrent-ruby/concurrent/atomic/semaphore.rb
70
+ - lib/concurrent-ruby/concurrent/atomic/thread_local_var.rb
71
+ - lib/concurrent-ruby/concurrent/atomic_reference/mutex_atomic.rb
72
+ - lib/concurrent-ruby/concurrent/atomic_reference/numeric_cas_wrapper.rb
73
+ - lib/concurrent-ruby/concurrent/atomics.rb
74
+ - lib/concurrent-ruby/concurrent/collection/copy_on_notify_observer_set.rb
75
+ - lib/concurrent-ruby/concurrent/collection/copy_on_write_observer_set.rb
76
+ - lib/concurrent-ruby/concurrent/collection/java_non_concurrent_priority_queue.rb
77
+ - lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb
78
+ - lib/concurrent-ruby/concurrent/collection/map/atomic_reference_map_backend.rb
79
+ - lib/concurrent-ruby/concurrent/collection/map/mri_map_backend.rb
80
+ - lib/concurrent-ruby/concurrent/collection/map/non_concurrent_map_backend.rb
81
+ - lib/concurrent-ruby/concurrent/collection/map/synchronized_map_backend.rb
82
+ - lib/concurrent-ruby/concurrent/collection/non_concurrent_priority_queue.rb
83
+ - lib/concurrent-ruby/concurrent/collection/ruby_non_concurrent_priority_queue.rb
84
+ - lib/concurrent-ruby/concurrent/concern/deprecation.rb
85
+ - lib/concurrent-ruby/concurrent/concern/dereferenceable.rb
86
+ - lib/concurrent-ruby/concurrent/concern/logging.rb
87
+ - lib/concurrent-ruby/concurrent/concern/obligation.rb
88
+ - lib/concurrent-ruby/concurrent/concern/observable.rb
89
+ - lib/concurrent-ruby/concurrent/concurrent_ruby.jar
90
+ - lib/concurrent-ruby/concurrent/configuration.rb
91
+ - lib/concurrent-ruby/concurrent/constants.rb
92
+ - lib/concurrent-ruby/concurrent/dataflow.rb
93
+ - lib/concurrent-ruby/concurrent/delay.rb
94
+ - lib/concurrent-ruby/concurrent/errors.rb
95
+ - lib/concurrent-ruby/concurrent/exchanger.rb
96
+ - lib/concurrent-ruby/concurrent/executor/abstract_executor_service.rb
97
+ - lib/concurrent-ruby/concurrent/executor/cached_thread_pool.rb
98
+ - lib/concurrent-ruby/concurrent/executor/executor_service.rb
99
+ - lib/concurrent-ruby/concurrent/executor/fixed_thread_pool.rb
100
+ - lib/concurrent-ruby/concurrent/executor/immediate_executor.rb
101
+ - lib/concurrent-ruby/concurrent/executor/indirect_immediate_executor.rb
102
+ - lib/concurrent-ruby/concurrent/executor/java_executor_service.rb
103
+ - lib/concurrent-ruby/concurrent/executor/java_single_thread_executor.rb
104
+ - lib/concurrent-ruby/concurrent/executor/java_thread_pool_executor.rb
105
+ - lib/concurrent-ruby/concurrent/executor/ruby_executor_service.rb
106
+ - lib/concurrent-ruby/concurrent/executor/ruby_single_thread_executor.rb
107
+ - lib/concurrent-ruby/concurrent/executor/ruby_thread_pool_executor.rb
108
+ - lib/concurrent-ruby/concurrent/executor/safe_task_executor.rb
109
+ - lib/concurrent-ruby/concurrent/executor/serial_executor_service.rb
110
+ - lib/concurrent-ruby/concurrent/executor/serialized_execution.rb
111
+ - lib/concurrent-ruby/concurrent/executor/serialized_execution_delegator.rb
112
+ - lib/concurrent-ruby/concurrent/executor/simple_executor_service.rb
113
+ - lib/concurrent-ruby/concurrent/executor/single_thread_executor.rb
114
+ - lib/concurrent-ruby/concurrent/executor/thread_pool_executor.rb
115
+ - lib/concurrent-ruby/concurrent/executor/timer_set.rb
116
+ - lib/concurrent-ruby/concurrent/executors.rb
117
+ - lib/concurrent-ruby/concurrent/future.rb
118
+ - lib/concurrent-ruby/concurrent/hash.rb
119
+ - lib/concurrent-ruby/concurrent/immutable_struct.rb
120
+ - lib/concurrent-ruby/concurrent/ivar.rb
121
+ - lib/concurrent-ruby/concurrent/map.rb
122
+ - lib/concurrent-ruby/concurrent/maybe.rb
123
+ - lib/concurrent-ruby/concurrent/mutable_struct.rb
124
+ - lib/concurrent-ruby/concurrent/mvar.rb
125
+ - lib/concurrent-ruby/concurrent/options.rb
126
+ - lib/concurrent-ruby/concurrent/promise.rb
127
+ - lib/concurrent-ruby/concurrent/promises.rb
128
+ - lib/concurrent-ruby/concurrent/re_include.rb
129
+ - lib/concurrent-ruby/concurrent/scheduled_task.rb
130
+ - lib/concurrent-ruby/concurrent/set.rb
131
+ - lib/concurrent-ruby/concurrent/settable_struct.rb
132
+ - lib/concurrent-ruby/concurrent/synchronization.rb
133
+ - lib/concurrent-ruby/concurrent/synchronization/abstract_lockable_object.rb
134
+ - lib/concurrent-ruby/concurrent/synchronization/abstract_object.rb
135
+ - lib/concurrent-ruby/concurrent/synchronization/abstract_struct.rb
136
+ - lib/concurrent-ruby/concurrent/synchronization/condition.rb
137
+ - lib/concurrent-ruby/concurrent/synchronization/jruby_lockable_object.rb
138
+ - lib/concurrent-ruby/concurrent/synchronization/jruby_object.rb
139
+ - lib/concurrent-ruby/concurrent/synchronization/lock.rb
140
+ - lib/concurrent-ruby/concurrent/synchronization/lockable_object.rb
141
+ - lib/concurrent-ruby/concurrent/synchronization/mri_object.rb
142
+ - lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb
143
+ - lib/concurrent-ruby/concurrent/synchronization/object.rb
144
+ - lib/concurrent-ruby/concurrent/synchronization/rbx_lockable_object.rb
145
+ - lib/concurrent-ruby/concurrent/synchronization/rbx_object.rb
146
+ - lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb
147
+ - lib/concurrent-ruby/concurrent/synchronization/volatile.rb
148
+ - lib/concurrent-ruby/concurrent/thread_safe/synchronized_delegator.rb
149
+ - lib/concurrent-ruby/concurrent/thread_safe/util.rb
150
+ - lib/concurrent-ruby/concurrent/thread_safe/util/adder.rb
151
+ - lib/concurrent-ruby/concurrent/thread_safe/util/cheap_lockable.rb
152
+ - lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb
153
+ - lib/concurrent-ruby/concurrent/thread_safe/util/power_of_two_tuple.rb
154
+ - lib/concurrent-ruby/concurrent/thread_safe/util/striped64.rb
155
+ - lib/concurrent-ruby/concurrent/thread_safe/util/volatile.rb
156
+ - lib/concurrent-ruby/concurrent/thread_safe/util/xor_shift_random.rb
157
+ - lib/concurrent-ruby/concurrent/timer_task.rb
158
+ - lib/concurrent-ruby/concurrent/tuple.rb
159
+ - lib/concurrent-ruby/concurrent/tvar.rb
160
+ - lib/concurrent-ruby/concurrent/utility/engine.rb
161
+ - lib/concurrent-ruby/concurrent/utility/monotonic_time.rb
162
+ - lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb
163
+ - lib/concurrent-ruby/concurrent/utility/native_integer.rb
164
+ - lib/concurrent-ruby/concurrent/utility/processor_counter.rb
165
+ - lib/concurrent-ruby/concurrent/version.rb
167
166
  homepage: http://www.concurrent-ruby.com
168
167
  licenses:
169
168
  - MIT
170
- metadata: {}
169
+ metadata:
170
+ source_code_uri: https://github.com/ruby-concurrency/concurrent-ruby
171
+ changelog_uri: https://github.com/ruby-concurrency/concurrent-ruby/blob/master/CHANGELOG.md
171
172
  post_install_message:
172
173
  rdoc_options: []
173
174
  require_paths:
174
- - lib
175
+ - lib/concurrent-ruby
175
176
  required_ruby_version: !ruby/object:Gem::Requirement
176
177
  requirements:
177
178
  - - ">="
@@ -183,8 +184,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
184
  - !ruby/object:Gem::Version
184
185
  version: '0'
185
186
  requirements: []
186
- rubyforge_project:
187
- rubygems_version: 2.7.3
187
+ rubygems_version: 3.2.3
188
188
  signing_key:
189
189
  specification_version: 4
190
190
  summary: Modern concurrency tools for Ruby. Inspired by Erlang, Clojure, Scala, Haskell,