concurrent-ruby 1.0.5 → 1.1.10

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 (164) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +155 -0
  3. data/Gemfile +37 -0
  4. data/LICENSE.txt +18 -18
  5. data/README.md +260 -103
  6. data/Rakefile +329 -0
  7. data/ext/concurrent-ruby/ConcurrentRubyService.java +17 -0
  8. data/ext/concurrent-ruby/com/concurrent_ruby/ext/AtomicReferenceLibrary.java +175 -0
  9. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JRubyMapBackendLibrary.java +248 -0
  10. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicBooleanLibrary.java +93 -0
  11. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaAtomicFixnumLibrary.java +113 -0
  12. data/ext/concurrent-ruby/com/concurrent_ruby/ext/JavaSemaphoreLibrary.java +189 -0
  13. data/ext/concurrent-ruby/com/concurrent_ruby/ext/SynchronizationLibrary.java +307 -0
  14. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMap.java +31 -0
  15. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/ConcurrentHashMapV8.java +3863 -0
  16. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/LongAdder.java +203 -0
  17. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/Striped64.java +342 -0
  18. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/ConcurrentHashMapV8.java +3800 -0
  19. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/LongAdder.java +204 -0
  20. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166e/nounsafe/Striped64.java +291 -0
  21. data/ext/concurrent-ruby/com/concurrent_ruby/ext/jsr166y/ThreadLocalRandom.java +199 -0
  22. data/lib/{concurrent → concurrent-ruby/concurrent}/agent.rb +7 -7
  23. data/lib/concurrent-ruby/concurrent/array.rb +66 -0
  24. data/lib/{concurrent → concurrent-ruby/concurrent}/async.rb +28 -24
  25. data/lib/{concurrent → concurrent-ruby/concurrent}/atom.rb +10 -10
  26. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_boolean.rb +26 -22
  27. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/atomic_fixnum.rb +27 -23
  28. data/lib/concurrent-ruby/concurrent/atomic/atomic_markable_reference.rb +164 -0
  29. data/lib/concurrent-ruby/concurrent/atomic/atomic_reference.rb +205 -0
  30. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/count_down_latch.rb +7 -7
  31. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/cyclic_barrier.rb +1 -1
  32. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/event.rb +3 -3
  33. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_count_down_latch.rb +9 -6
  34. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_boolean.rb +2 -0
  35. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_count_down_latch.rb +1 -0
  36. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_semaphore.rb +18 -2
  37. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/read_write_lock.rb +2 -1
  38. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/reentrant_read_write_lock.rb +7 -7
  39. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/ruby_thread_local_var.rb +60 -40
  40. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/semaphore.rb +34 -13
  41. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/thread_local_var.rb +8 -8
  42. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/mutex_atomic.rb +3 -8
  43. data/lib/{concurrent → concurrent-ruby/concurrent}/atomic_reference/numeric_cas_wrapper.rb +1 -1
  44. data/lib/concurrent-ruby/concurrent/atomics.rb +10 -0
  45. data/lib/concurrent-ruby/concurrent/collection/lock_free_stack.rb +158 -0
  46. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/atomic_reference_map_backend.rb +3 -3
  47. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/mri_map_backend.rb +1 -1
  48. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/non_concurrent_map_backend.rb +1 -2
  49. data/lib/concurrent-ruby/concurrent/collection/map/truffleruby_map_backend.rb +14 -0
  50. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/non_concurrent_priority_queue.rb +30 -30
  51. data/lib/{concurrent → concurrent-ruby/concurrent}/collection/ruby_non_concurrent_priority_queue.rb +11 -1
  52. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/dereferenceable.rb +3 -3
  53. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/logging.rb +6 -1
  54. data/lib/{concurrent → concurrent-ruby/concurrent}/concern/observable.rb +7 -7
  55. data/lib/concurrent-ruby/concurrent/concurrent_ruby.jar +0 -0
  56. data/lib/{concurrent → concurrent-ruby/concurrent}/configuration.rb +15 -15
  57. data/lib/{concurrent → concurrent-ruby/concurrent}/constants.rb +1 -1
  58. data/lib/{concurrent → concurrent-ruby/concurrent}/dataflow.rb +2 -1
  59. data/lib/{concurrent → concurrent-ruby/concurrent}/delay.rb +9 -7
  60. data/lib/{concurrent → concurrent-ruby/concurrent}/exchanger.rb +21 -25
  61. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/abstract_executor_service.rb +35 -38
  62. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/cached_thread_pool.rb +5 -5
  63. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/executor_service.rb +17 -17
  64. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/fixed_thread_pool.rb +47 -33
  65. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_executor_service.rb +20 -17
  66. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_single_thread_executor.rb +4 -3
  67. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/java_thread_pool_executor.rb +29 -9
  68. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_executor_service.rb +10 -6
  69. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_single_thread_executor.rb +0 -1
  70. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/ruby_thread_pool_executor.rb +46 -42
  71. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/safe_task_executor.rb +5 -5
  72. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/simple_executor_service.rb +1 -1
  73. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/single_thread_executor.rb +3 -2
  74. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/thread_pool_executor.rb +7 -6
  75. data/lib/{concurrent → concurrent-ruby/concurrent}/executor/timer_set.rb +14 -17
  76. data/lib/{concurrent → concurrent-ruby/concurrent}/future.rb +4 -1
  77. data/lib/concurrent-ruby/concurrent/hash.rb +59 -0
  78. data/lib/{concurrent → concurrent-ruby/concurrent}/immutable_struct.rb +9 -1
  79. data/lib/{concurrent → concurrent-ruby/concurrent}/ivar.rb +5 -6
  80. data/lib/concurrent-ruby/concurrent/map.rb +346 -0
  81. data/lib/{concurrent → concurrent-ruby/concurrent}/maybe.rb +1 -1
  82. data/lib/{concurrent → concurrent-ruby/concurrent}/mutable_struct.rb +27 -16
  83. data/lib/{concurrent → concurrent-ruby/concurrent}/mvar.rb +2 -2
  84. data/lib/{concurrent → concurrent-ruby/concurrent}/promise.rb +54 -21
  85. data/lib/concurrent-ruby/concurrent/promises.rb +2167 -0
  86. data/lib/concurrent-ruby/concurrent/re_include.rb +58 -0
  87. data/lib/{concurrent → concurrent-ruby/concurrent}/scheduled_task.rb +29 -16
  88. data/lib/concurrent-ruby/concurrent/set.rb +74 -0
  89. data/lib/{concurrent → concurrent-ruby/concurrent}/settable_struct.rb +12 -1
  90. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_lockable_object.rb +5 -5
  91. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_struct.rb +18 -4
  92. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/condition.rb +2 -0
  93. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_object.rb +1 -0
  94. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lock.rb +2 -0
  95. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/lockable_object.rb +8 -10
  96. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/mri_object.rb +1 -0
  97. data/lib/concurrent-ruby/concurrent/synchronization/mutex_lockable_object.rb +88 -0
  98. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/object.rb +53 -23
  99. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_lockable_object.rb +6 -0
  100. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/rbx_object.rb +1 -0
  101. data/lib/concurrent-ruby/concurrent/synchronization/truffleruby_object.rb +47 -0
  102. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/volatile.rb +11 -9
  103. data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization.rb +4 -5
  104. data/lib/concurrent-ruby/concurrent/thread_safe/util/data_structures.rb +88 -0
  105. data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/striped64.rb +9 -4
  106. data/lib/{concurrent → concurrent-ruby/concurrent}/timer_task.rb +15 -35
  107. data/lib/{concurrent → concurrent-ruby/concurrent}/tuple.rb +1 -1
  108. data/lib/{concurrent → concurrent-ruby/concurrent}/tvar.rb +21 -58
  109. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/engine.rb +4 -4
  110. data/lib/concurrent-ruby/concurrent/utility/monotonic_time.rb +90 -0
  111. data/lib/concurrent-ruby/concurrent/utility/native_extension_loader.rb +79 -0
  112. data/lib/{concurrent → concurrent-ruby/concurrent}/utility/processor_counter.rb +5 -35
  113. data/lib/concurrent-ruby/concurrent/version.rb +3 -0
  114. data/lib/concurrent-ruby/concurrent-ruby.rb +5 -0
  115. data/lib/{concurrent.rb → concurrent-ruby/concurrent.rb} +24 -20
  116. metadata +149 -134
  117. data/lib/concurrent/array.rb +0 -39
  118. data/lib/concurrent/atomic/atomic_reference.rb +0 -51
  119. data/lib/concurrent/atomic_reference/concurrent_update_error.rb +0 -8
  120. data/lib/concurrent/atomic_reference/direct_update.rb +0 -81
  121. data/lib/concurrent/atomic_reference/jruby+truffle.rb +0 -2
  122. data/lib/concurrent/atomic_reference/jruby.rb +0 -16
  123. data/lib/concurrent/atomic_reference/rbx.rb +0 -22
  124. data/lib/concurrent/atomic_reference/ruby.rb +0 -32
  125. data/lib/concurrent/atomics.rb +0 -53
  126. data/lib/concurrent/edge.rb +0 -26
  127. data/lib/concurrent/hash.rb +0 -36
  128. data/lib/concurrent/lazy_register.rb +0 -81
  129. data/lib/concurrent/map.rb +0 -240
  130. data/lib/concurrent/synchronization/mri_lockable_object.rb +0 -71
  131. data/lib/concurrent/synchronization/truffle_lockable_object.rb +0 -9
  132. data/lib/concurrent/synchronization/truffle_object.rb +0 -31
  133. data/lib/concurrent/thread_safe/util/array_hash_rbx.rb +0 -30
  134. data/lib/concurrent/utility/at_exit.rb +0 -97
  135. data/lib/concurrent/utility/monotonic_time.rb +0 -58
  136. data/lib/concurrent/utility/native_extension_loader.rb +0 -73
  137. data/lib/concurrent/version.rb +0 -4
  138. /data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/abstract_thread_local_var.rb +0 -0
  139. /data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/java_thread_local_var.rb +0 -0
  140. /data/lib/{concurrent → concurrent-ruby/concurrent}/atomic/mutex_atomic_fixnum.rb +0 -0
  141. /data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_notify_observer_set.rb +0 -0
  142. /data/lib/{concurrent → concurrent-ruby/concurrent}/collection/copy_on_write_observer_set.rb +0 -0
  143. /data/lib/{concurrent → concurrent-ruby/concurrent}/collection/java_non_concurrent_priority_queue.rb +0 -0
  144. /data/lib/{concurrent → concurrent-ruby/concurrent}/collection/map/synchronized_map_backend.rb +0 -0
  145. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/deprecation.rb +0 -0
  146. /data/lib/{concurrent → concurrent-ruby/concurrent}/concern/obligation.rb +0 -0
  147. /data/lib/{concurrent → concurrent-ruby/concurrent}/errors.rb +0 -0
  148. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/immediate_executor.rb +0 -0
  149. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/indirect_immediate_executor.rb +0 -0
  150. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serial_executor_service.rb +0 -0
  151. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution.rb +0 -0
  152. /data/lib/{concurrent → concurrent-ruby/concurrent}/executor/serialized_execution_delegator.rb +0 -0
  153. /data/lib/{concurrent → concurrent-ruby/concurrent}/executors.rb +0 -0
  154. /data/lib/{concurrent → concurrent-ruby/concurrent}/options.rb +0 -0
  155. /data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/abstract_object.rb +0 -0
  156. /data/lib/{concurrent → concurrent-ruby/concurrent}/synchronization/jruby_lockable_object.rb +0 -0
  157. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/synchronized_delegator.rb +0 -0
  158. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/adder.rb +0 -0
  159. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/cheap_lockable.rb +0 -0
  160. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/power_of_two_tuple.rb +0 -0
  161. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/volatile.rb +0 -0
  162. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util/xor_shift_random.rb +0 -0
  163. /data/lib/{concurrent → concurrent-ruby/concurrent}/thread_safe/util.rb +0 -0
  164. /data/lib/{concurrent → concurrent-ruby/concurrent}/utility/native_integer.rb +0 -0
@@ -1,6 +1,6 @@
1
+ require 'concurrent/utility/engine'
1
2
  require 'concurrent/collection/java_non_concurrent_priority_queue'
2
3
  require 'concurrent/collection/ruby_non_concurrent_priority_queue'
3
- require 'concurrent/utility/engine'
4
4
 
5
5
  module Concurrent
6
6
  module Collection
@@ -15,7 +15,7 @@ module Concurrent
15
15
  end
16
16
  private_constant :NonConcurrentPriorityQueueImplementation
17
17
 
18
- # @!macro [attach] priority_queue
18
+ # @!macro priority_queue
19
19
  #
20
20
  # A queue collection in which the elements are sorted based on their
21
21
  # comparison (spaceship) operator `<=>`. Items are added to the queue
@@ -45,7 +45,7 @@ module Concurrent
45
45
  # @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html
46
46
  #
47
47
  # @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html
48
- #
48
+ #
49
49
  # @!visibility private
50
50
  class NonConcurrentPriorityQueue < NonConcurrentPriorityQueueImplementation
51
51
 
@@ -60,83 +60,83 @@ module Concurrent
60
60
  alias_method :enq, :push
61
61
 
62
62
  # @!method initialize(opts = {})
63
- # @!macro [new] priority_queue_method_initialize
63
+ # @!macro priority_queue_method_initialize
64
64
  #
65
65
  # Create a new priority queue with no items.
66
- #
66
+ #
67
67
  # @param [Hash] opts the options for creating the queue
68
68
  # @option opts [Symbol] :order (:max) dictates the order in which items are
69
69
  # stored: from highest to lowest when `:max` or `:high`; from lowest to
70
70
  # highest when `:min` or `:low`
71
71
 
72
72
  # @!method clear
73
- # @!macro [new] priority_queue_method_clear
73
+ # @!macro priority_queue_method_clear
74
74
  #
75
75
  # Removes all of the elements from this priority queue.
76
76
 
77
77
  # @!method delete(item)
78
- # @!macro [new] priority_queue_method_delete
78
+ # @!macro priority_queue_method_delete
79
79
  #
80
80
  # Deletes all items from `self` that are equal to `item`.
81
- #
81
+ #
82
82
  # @param [Object] item the item to be removed from the queue
83
83
  # @return [Object] true if the item is found else false
84
84
 
85
85
  # @!method empty?
86
- # @!macro [new] priority_queue_method_empty
87
- #
86
+ # @!macro priority_queue_method_empty
87
+ #
88
88
  # Returns `true` if `self` contains no elements.
89
- #
89
+ #
90
90
  # @return [Boolean] true if there are no items in the queue else false
91
91
 
92
92
  # @!method include?(item)
93
- # @!macro [new] priority_queue_method_include
93
+ # @!macro priority_queue_method_include
94
94
  #
95
95
  # Returns `true` if the given item is present in `self` (that is, if any
96
96
  # element == `item`), otherwise returns false.
97
- #
97
+ #
98
98
  # @param [Object] item the item to search for
99
- #
99
+ #
100
100
  # @return [Boolean] true if the item is found else false
101
101
 
102
102
  # @!method length
103
- # @!macro [new] priority_queue_method_length
104
- #
103
+ # @!macro priority_queue_method_length
104
+ #
105
105
  # The current length of the queue.
106
- #
106
+ #
107
107
  # @return [Fixnum] the number of items in the queue
108
108
 
109
109
  # @!method peek
110
- # @!macro [new] priority_queue_method_peek
111
- #
110
+ # @!macro priority_queue_method_peek
111
+ #
112
112
  # Retrieves, but does not remove, the head of this queue, or returns `nil`
113
113
  # if this queue is empty.
114
- #
114
+ #
115
115
  # @return [Object] the head of the queue or `nil` when empty
116
116
 
117
117
  # @!method pop
118
- # @!macro [new] priority_queue_method_pop
119
- #
118
+ # @!macro priority_queue_method_pop
119
+ #
120
120
  # Retrieves and removes the head of this queue, or returns `nil` if this
121
121
  # queue is empty.
122
- #
122
+ #
123
123
  # @return [Object] the head of the queue or `nil` when empty
124
124
 
125
125
  # @!method push(item)
126
- # @!macro [new] priority_queue_method_push
127
- #
126
+ # @!macro priority_queue_method_push
127
+ #
128
128
  # Inserts the specified element into this priority queue.
129
- #
129
+ #
130
130
  # @param [Object] item the item to insert onto the queue
131
131
 
132
132
  # @!method self.from_list(list, opts = {})
133
- # @!macro [new] priority_queue_method_from_list
134
- #
133
+ # @!macro priority_queue_method_from_list
134
+ #
135
135
  # Create a new priority queue from the given list.
136
- #
136
+ #
137
137
  # @param [Enumerable] list the list to build the queue from
138
138
  # @param [Hash] opts the options for creating the queue
139
- #
139
+ #
140
140
  # @return [NonConcurrentPriorityQueue] the newly created and populated queue
141
141
  end
142
142
  end
@@ -30,7 +30,7 @@ module Concurrent
30
30
  if @queue[k] == item
31
31
  swap(k, @length)
32
32
  @length -= 1
33
- sink(k)
33
+ sink(k) || swim(k)
34
34
  @queue.pop
35
35
  else
36
36
  k += 1
@@ -126,12 +126,17 @@ module Concurrent
126
126
  #
127
127
  # @!visibility private
128
128
  def sink(k)
129
+ success = false
130
+
129
131
  while (j = (2 * k)) <= @length do
130
132
  j += 1 if j < @length && ! ordered?(j, j+1)
131
133
  break if ordered?(k, j)
132
134
  swap(k, j)
135
+ success = true
133
136
  k = j
134
137
  end
138
+
139
+ success
135
140
  end
136
141
 
137
142
  # Percolate up to maintain heap invariant.
@@ -140,10 +145,15 @@ module Concurrent
140
145
  #
141
146
  # @!visibility private
142
147
  def swim(k)
148
+ success = false
149
+
143
150
  while k > 1 && ! ordered?(k/2, k) do
144
151
  swap(k, k/2)
145
152
  k = k/2
153
+ success = true
146
154
  end
155
+
156
+ success
147
157
  end
148
158
  end
149
159
  end
@@ -32,13 +32,13 @@ module Concurrent
32
32
  synchronize{ @value = value }
33
33
  end
34
34
 
35
- # @!macro [attach] dereferenceable_set_deref_options
35
+ # @!macro dereferenceable_set_deref_options
36
36
  # Set the options which define the operations #value performs before
37
37
  # returning data to the caller (dereferencing).
38
38
  #
39
39
  # @note Most classes that include this module will call `#set_deref_options`
40
- # from within the constructor, thus allowing these options to be set at
41
- # object creation.
40
+ # from within the constructor, thus allowing these options to be set at
41
+ # object creation.
42
42
  #
43
43
  # @param [Hash] opts the options defining dereference behavior.
44
44
  # @option opts [String] :dup_on_deref (false) call `#dup` before returning the data
@@ -17,7 +17,12 @@ module Concurrent
17
17
  def log(level, progname, message = nil, &block)
18
18
  #NOTE: Cannot require 'concurrent/configuration' above due to circular references.
19
19
  # Assume that the gem has been initialized if we've gotten this far.
20
- (@logger || Concurrent.global_logger).call level, progname, message, &block
20
+ logger = if defined?(@logger) && @logger
21
+ @logger
22
+ else
23
+ Concurrent.global_logger
24
+ end
25
+ logger.call level, progname, message, &block
21
26
  rescue => error
22
27
  $stderr.puts "`Concurrent.configuration.logger` failed to log #{[level, progname, message, block]}\n" +
23
28
  "#{error.message} (#{error.class})\n#{error.backtrace.join "\n"}"
@@ -49,7 +49,7 @@ module Concurrent
49
49
  # or an AtomicFixum)
50
50
  module Observable
51
51
 
52
- # @!macro [attach] observable_add_observer
52
+ # @!macro observable_add_observer
53
53
  #
54
54
  # Adds an observer to this set. If a block is passed, the observer will be
55
55
  # created by this method and no other params should be passed.
@@ -72,8 +72,8 @@ module Concurrent
72
72
  self
73
73
  end
74
74
 
75
- # @!macro [attach] observable_delete_observer
76
- #
75
+ # @!macro observable_delete_observer
76
+ #
77
77
  # Remove `observer` as an observer on this object so that it will no
78
78
  # longer receive notifications.
79
79
  #
@@ -83,17 +83,17 @@ module Concurrent
83
83
  observers.delete_observer(observer)
84
84
  end
85
85
 
86
- # @!macro [attach] observable_delete_observers
87
- #
86
+ # @!macro observable_delete_observers
87
+ #
88
88
  # Remove all observers associated with this object.
89
- #
89
+ #
90
90
  # @return [Observable] self
91
91
  def delete_observers
92
92
  observers.delete_observers
93
93
  self
94
94
  end
95
95
 
96
- # @!macro [attach] observable_count_observers
96
+ # @!macro observable_count_observers
97
97
  #
98
98
  # Return the number of observers associated with this object.
99
99
  #
@@ -3,12 +3,14 @@ require 'concurrent/delay'
3
3
  require 'concurrent/errors'
4
4
  require 'concurrent/atomic/atomic_reference'
5
5
  require 'concurrent/concern/logging'
6
+ require 'concurrent/concern/deprecation'
6
7
  require 'concurrent/executor/immediate_executor'
7
- require 'concurrent/utility/at_exit'
8
+ require 'concurrent/executor/cached_thread_pool'
8
9
  require 'concurrent/utility/processor_counter'
9
10
 
10
11
  module Concurrent
11
12
  extend Concern::Logging
13
+ extend Concern::Deprecation
12
14
 
13
15
  autoload :Options, 'concurrent/options'
14
16
  autoload :TimerSet, 'concurrent/executor/timer_set'
@@ -96,15 +98,15 @@ module Concurrent
96
98
  end
97
99
 
98
100
  # @!visibility private
99
- GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor(auto_terminate: true) }
101
+ GLOBAL_FAST_EXECUTOR = Delay.new { Concurrent.new_fast_executor }
100
102
  private_constant :GLOBAL_FAST_EXECUTOR
101
103
 
102
104
  # @!visibility private
103
- GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor(auto_terminate: true) }
105
+ GLOBAL_IO_EXECUTOR = Delay.new { Concurrent.new_io_executor }
104
106
  private_constant :GLOBAL_IO_EXECUTOR
105
107
 
106
108
  # @!visibility private
107
- GLOBAL_TIMER_SET = Delay.new { TimerSet.new(auto_terminate: true) }
109
+ GLOBAL_TIMER_SET = Delay.new { TimerSet.new }
108
110
  private_constant :GLOBAL_TIMER_SET
109
111
 
110
112
  # @!visibility private
@@ -114,7 +116,7 @@ module Concurrent
114
116
  # Disables AtExit handlers including pool auto-termination handlers.
115
117
  # When disabled it will be the application programmer's responsibility
116
118
  # to ensure that the handlers are shutdown properly prior to application
117
- # exit by calling {AtExit.run} method.
119
+ # exit by calling `AtExit.run` method.
118
120
  #
119
121
  # @note this option should be needed only because of `at_exit` ordering
120
122
  # issues which may arise when running some of the testing frameworks.
@@ -124,9 +126,10 @@ module Concurrent
124
126
  # @note This method should *never* be called
125
127
  # from within a gem. It should *only* be used from within the main
126
128
  # application and even then it should be used only when necessary.
127
- # @see AtExit
129
+ # @deprecated Has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841.
130
+ #
128
131
  def self.disable_at_exit_handlers!
129
- AtExit.enabled = false
132
+ deprecated "Method #disable_at_exit_handlers! has no effect since it is no longer needed, see https://github.com/ruby-concurrency/concurrent-ruby/pull/841."
130
133
  end
131
134
 
132
135
  # Global thread pool optimized for short, fast *operations*.
@@ -170,19 +173,16 @@ module Concurrent
170
173
  auto_terminate: opts.fetch(:auto_terminate, true),
171
174
  idletime: 60, # 1 minute
172
175
  max_queue: 0, # unlimited
173
- fallback_policy: :abort # shouldn't matter -- 0 max queue
176
+ fallback_policy: :abort, # shouldn't matter -- 0 max queue
177
+ name: "fast"
174
178
  )
175
179
  end
176
180
 
177
181
  def self.new_io_executor(opts = {})
178
- ThreadPoolExecutor.new(
179
- min_threads: [2, Concurrent.processor_count].max,
180
- max_threads: ThreadPoolExecutor::DEFAULT_MAX_POOL_SIZE,
181
- # max_threads: 1000,
182
+ CachedThreadPool.new(
182
183
  auto_terminate: opts.fetch(:auto_terminate, true),
183
- idletime: 60, # 1 minute
184
- max_queue: 0, # unlimited
185
- fallback_policy: :abort # shouldn't matter -- 0 max queue
184
+ fallback_policy: :abort, # shouldn't matter -- 0 max queue
185
+ name: "io"
186
186
  )
187
187
  end
188
188
  end
@@ -3,6 +3,6 @@ module Concurrent
3
3
  # Various classes within allows for +nil+ values to be stored,
4
4
  # so a special +NULL+ token is required to indicate the "nil-ness".
5
5
  # @!visibility private
6
- NULL = Object.new
6
+ NULL = ::Object.new
7
7
 
8
8
  end
@@ -18,7 +18,8 @@ module Concurrent
18
18
  end
19
19
  end
20
20
 
21
- # {include:file:doc/dataflow.md}
21
+ # Dataflow allows you to create a task that will be scheduled when all of its data dependencies are available.
22
+ # {include:file:docs-source/dataflow.md}
22
23
  #
23
24
  # @param [Future] inputs zero or more `Future` operations that this dataflow depends upon
24
25
  #
@@ -32,7 +32,7 @@ module Concurrent
32
32
  #
33
33
  # @!macro copy_options
34
34
  #
35
- # @!macro [attach] delay_note_regarding_blocking
35
+ # @!macro delay_note_regarding_blocking
36
36
  # @note The default behavior of `Delay` is to block indefinitely when
37
37
  # calling either `value` or `wait`, executing the delayed operation on
38
38
  # the current thread. This makes the `timeout` value completely
@@ -81,13 +81,15 @@ module Concurrent
81
81
  # this function has been optimized for performance and
82
82
  # should not be modified without running new benchmarks
83
83
  synchronize do
84
- execute = @computing = true unless @computing
84
+ execute = @evaluation_started = true unless @evaluation_started
85
85
  if execute
86
86
  begin
87
87
  set_state(true, @task.call, nil)
88
88
  rescue => ex
89
89
  set_state(false, nil, ex)
90
90
  end
91
+ elsif incomplete?
92
+ raise IllegalOperationError, 'Recursive call to #value during evaluation of the Delay'
91
93
  end
92
94
  end
93
95
  if @do_nothing_on_deref
@@ -144,7 +146,7 @@ module Concurrent
144
146
  def reconfigure(&block)
145
147
  synchronize do
146
148
  raise ArgumentError.new('no block given') unless block_given?
147
- unless @computing
149
+ unless @evaluation_started
148
150
  @task = block
149
151
  true
150
152
  else
@@ -160,9 +162,9 @@ module Concurrent
160
162
  set_deref_options(opts)
161
163
  @executor = opts[:executor]
162
164
 
163
- @task = block
164
- @state = :pending
165
- @computing = false
165
+ @task = block
166
+ @state = :pending
167
+ @evaluation_started = false
166
168
  end
167
169
 
168
170
  private
@@ -173,7 +175,7 @@ module Concurrent
173
175
  # should not be modified without running new benchmarks
174
176
  execute = task = nil
175
177
  synchronize do
176
- execute = @computing = true unless @computing
178
+ execute = @evaluation_started = true unless @evaluation_started
177
179
  task = @task
178
180
  end
179
181
 
@@ -8,7 +8,7 @@ require 'concurrent/utility/monotonic_time'
8
8
 
9
9
  module Concurrent
10
10
 
11
- # @!macro [attach] exchanger
11
+ # @!macro exchanger
12
12
  #
13
13
  # A synchronization point at which threads can pair and swap elements within
14
14
  # pairs. Each thread presents some object on entry to the exchange method,
@@ -24,9 +24,6 @@ module Concurrent
24
24
  # will remain correct.
25
25
  #
26
26
  # @see http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/Exchanger.html java.util.concurrent.Exchanger
27
- #
28
- # @!macro edge_warning
29
- #
30
27
  # @example
31
28
  #
32
29
  # exchanger = Concurrent::Exchanger.new
@@ -36,20 +33,19 @@ module Concurrent
36
33
  # Thread.new { puts "second: " << exchanger.exchange('bar', 1) } #=> "second: foo"
37
34
  # ]
38
35
  # threads.each {|t| t.join(2) }
39
- #
36
+
40
37
  # @!visibility private
41
38
  class AbstractExchanger < Synchronization::Object
42
39
 
43
40
  # @!visibility private
44
- CANCEL = Object.new
41
+ CANCEL = ::Object.new
45
42
  private_constant :CANCEL
46
43
 
47
- # @!macro [attach] exchanger_method_initialize
48
44
  def initialize
49
45
  super
50
46
  end
51
47
 
52
- # @!macro [attach] exchanger_method_do_exchange
48
+ # @!macro exchanger_method_do_exchange
53
49
  #
54
50
  # Waits for another thread to arrive at this exchange point (unless the
55
51
  # current thread is interrupted), and then transfers the given object to
@@ -61,7 +57,7 @@ module Concurrent
61
57
  # @param [Object] value the value to exchange with another thread
62
58
  # @param [Numeric, nil] timeout in seconds, `nil` blocks indefinitely
63
59
  #
64
- # @!macro [attach] exchanger_method_exchange
60
+ # @!macro exchanger_method_exchange
65
61
  #
66
62
  # In some edge cases when a `timeout` is given a return value of `nil` may be
67
63
  # ambiguous. Specifically, if `nil` is a valid value in the exchange it will
@@ -75,8 +71,7 @@ module Concurrent
75
71
  end
76
72
 
77
73
  # @!macro exchanger_method_do_exchange
78
- #
79
- # @!macro [attach] exchanger_method_exchange_bang
74
+ # @!macro exchanger_method_exchange_bang
80
75
  #
81
76
  # On timeout a {Concurrent::TimeoutError} exception will be raised.
82
77
  #
@@ -91,8 +86,7 @@ module Concurrent
91
86
  end
92
87
 
93
88
  # @!macro exchanger_method_do_exchange
94
- #
95
- # @!macro [attach] exchanger_method_try_exchange
89
+ # @!macro exchanger_method_try_exchange
96
90
  #
97
91
  # The return value will be a {Concurrent::Maybe} set to `Just` on success or
98
92
  # `Nothing` on timeout.
@@ -130,7 +124,6 @@ module Concurrent
130
124
  end
131
125
  end
132
126
 
133
- # @!macro exchanger
134
127
  # @!macro internal_implementation_note
135
128
  # @!visibility private
136
129
  class RubyExchanger < AbstractExchanger
@@ -148,8 +141,8 @@ module Concurrent
148
141
 
149
142
  def initialize(item)
150
143
  super()
151
- @Item = item
152
- @Latch = Concurrent::CountDownLatch.new
144
+ @Item = item
145
+ @Latch = Concurrent::CountDownLatch.new
153
146
  self.value = nil
154
147
  end
155
148
 
@@ -163,7 +156,6 @@ module Concurrent
163
156
  end
164
157
  private_constant :Node
165
158
 
166
- # @!macro exchanger_method_initialize
167
159
  def initialize
168
160
  super
169
161
  end
@@ -218,7 +210,7 @@ module Concurrent
218
210
  # node's initial value. It never changes. It's what the fulfiller returns on
219
211
  # success. The occupier's hole is where the fulfiller put its item. It's the
220
212
  # item that the occupier returns on success. The latch is used for synchronization.
221
- # Becuase a thread may act as either an occupier or fulfiller (or possibly
213
+ # Because a thread may act as either an occupier or fulfiller (or possibly
222
214
  # both in periods of high contention) every thread creates a node when
223
215
  # the exchange method is first called.
224
216
  #
@@ -260,8 +252,8 @@ module Concurrent
260
252
  # - Wake the sleeping occupier
261
253
  # - Return the occupier's item
262
254
 
263
- value = NULL if value.nil? # The sentinel allows nil to be a valid value
264
- me = Node.new(value) # create my node in case I need to occupy
255
+ value = NULL if value.nil? # The sentinel allows nil to be a valid value
256
+ me = Node.new(value) # create my node in case I need to occupy
265
257
  end_at = Concurrent.monotonic_time + timeout.to_f # The time to give up
266
258
 
267
259
  result = loop do
@@ -298,12 +290,10 @@ module Concurrent
298
290
 
299
291
  if Concurrent.on_jruby?
300
292
 
301
- # @!macro exchanger
302
293
  # @!macro internal_implementation_note
303
294
  # @!visibility private
304
295
  class JavaExchanger < AbstractExchanger
305
296
 
306
- # @!macro exchanger_method_initialize
307
297
  def initialize
308
298
  @exchanger = java.util.concurrent.Exchanger.new
309
299
  end
@@ -314,11 +304,17 @@ module Concurrent
314
304
  #
315
305
  # @return [Object, CANCEL] the value exchanged by the other thread; {CANCEL} on timeout
316
306
  def do_exchange(value, timeout)
307
+ result = nil
317
308
  if timeout.nil?
318
- @exchanger.exchange(value)
309
+ Synchronization::JRuby.sleep_interruptibly do
310
+ result = @exchanger.exchange(value)
311
+ end
319
312
  else
320
- @exchanger.exchange(value, 1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
313
+ Synchronization::JRuby.sleep_interruptibly do
314
+ result = @exchanger.exchange(value, 1000 * timeout, java.util.concurrent.TimeUnit::MILLISECONDS)
315
+ end
321
316
  end
317
+ result
322
318
  rescue java.util.concurrent.TimeoutException
323
319
  CANCEL
324
320
  end
@@ -339,7 +335,7 @@ module Concurrent
339
335
  class Exchanger < ExchangerImplementation
340
336
 
341
337
  # @!method initialize
342
- # @!macro exchanger_method_initialize
338
+ # Creates exchanger instance
343
339
 
344
340
  # @!method exchange(value, timeout = nil)
345
341
  # @!macro exchanger_method_do_exchange