concurrent-ruby 0.8.0 → 0.9.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +97 -2
  3. data/README.md +103 -54
  4. data/lib/concurrent.rb +34 -14
  5. data/lib/concurrent/async.rb +164 -50
  6. data/lib/concurrent/atom.rb +171 -0
  7. data/lib/concurrent/atomic/atomic_boolean.rb +57 -107
  8. data/lib/concurrent/atomic/atomic_fixnum.rb +73 -101
  9. data/lib/concurrent/atomic/atomic_reference.rb +49 -0
  10. data/lib/concurrent/atomic/condition.rb +23 -12
  11. data/lib/concurrent/atomic/count_down_latch.rb +23 -21
  12. data/lib/concurrent/atomic/cyclic_barrier.rb +47 -47
  13. data/lib/concurrent/atomic/event.rb +33 -42
  14. data/lib/concurrent/atomic/read_write_lock.rb +252 -0
  15. data/lib/concurrent/atomic/semaphore.rb +64 -89
  16. data/lib/concurrent/atomic/thread_local_var.rb +130 -58
  17. data/lib/concurrent/atomic/thread_local_var/weak_key_map.rb +236 -0
  18. data/lib/concurrent/atomic_reference/direct_update.rb +3 -0
  19. data/lib/concurrent/atomic_reference/jruby.rb +6 -3
  20. data/lib/concurrent/atomic_reference/mutex_atomic.rb +10 -32
  21. data/lib/concurrent/atomic_reference/numeric_cas_wrapper.rb +3 -0
  22. data/lib/concurrent/atomic_reference/rbx.rb +4 -1
  23. data/lib/concurrent/atomic_reference/ruby.rb +6 -3
  24. data/lib/concurrent/atomics.rb +74 -4
  25. data/lib/concurrent/collection/copy_on_notify_observer_set.rb +115 -0
  26. data/lib/concurrent/collection/copy_on_write_observer_set.rb +119 -0
  27. data/lib/concurrent/collection/priority_queue.rb +300 -245
  28. data/lib/concurrent/concern/deprecation.rb +27 -0
  29. data/lib/concurrent/concern/dereferenceable.rb +88 -0
  30. data/lib/concurrent/concern/logging.rb +25 -0
  31. data/lib/concurrent/concern/obligation.rb +228 -0
  32. data/lib/concurrent/concern/observable.rb +85 -0
  33. data/lib/concurrent/configuration.rb +226 -112
  34. data/lib/concurrent/dataflow.rb +2 -3
  35. data/lib/concurrent/delay.rb +141 -50
  36. data/lib/concurrent/edge.rb +30 -0
  37. data/lib/concurrent/errors.rb +10 -0
  38. data/lib/concurrent/exchanger.rb +25 -1
  39. data/lib/concurrent/executor/cached_thread_pool.rb +46 -33
  40. data/lib/concurrent/executor/executor.rb +46 -299
  41. data/lib/concurrent/executor/executor_service.rb +521 -0
  42. data/lib/concurrent/executor/fixed_thread_pool.rb +206 -26
  43. data/lib/concurrent/executor/immediate_executor.rb +9 -9
  44. data/lib/concurrent/executor/indirect_immediate_executor.rb +4 -3
  45. data/lib/concurrent/executor/java_cached_thread_pool.rb +18 -16
  46. data/lib/concurrent/executor/java_fixed_thread_pool.rb +11 -18
  47. data/lib/concurrent/executor/java_single_thread_executor.rb +17 -16
  48. data/lib/concurrent/executor/java_thread_pool_executor.rb +55 -102
  49. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +9 -18
  50. data/lib/concurrent/executor/ruby_fixed_thread_pool.rb +10 -21
  51. data/lib/concurrent/executor/ruby_single_thread_executor.rb +14 -16
  52. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +250 -166
  53. data/lib/concurrent/executor/safe_task_executor.rb +5 -4
  54. data/lib/concurrent/executor/serialized_execution.rb +22 -18
  55. data/lib/concurrent/executor/{per_thread_executor.rb → simple_executor_service.rb} +29 -20
  56. data/lib/concurrent/executor/single_thread_executor.rb +32 -21
  57. data/lib/concurrent/executor/thread_pool_executor.rb +72 -60
  58. data/lib/concurrent/executor/timer_set.rb +96 -84
  59. data/lib/concurrent/executors.rb +1 -1
  60. data/lib/concurrent/future.rb +70 -38
  61. data/lib/concurrent/immutable_struct.rb +89 -0
  62. data/lib/concurrent/ivar.rb +152 -60
  63. data/lib/concurrent/lazy_register.rb +40 -20
  64. data/lib/concurrent/maybe.rb +226 -0
  65. data/lib/concurrent/mutable_struct.rb +227 -0
  66. data/lib/concurrent/mvar.rb +44 -43
  67. data/lib/concurrent/promise.rb +208 -134
  68. data/lib/concurrent/scheduled_task.rb +339 -43
  69. data/lib/concurrent/settable_struct.rb +127 -0
  70. data/lib/concurrent/synchronization.rb +17 -0
  71. data/lib/concurrent/synchronization/abstract_object.rb +163 -0
  72. data/lib/concurrent/synchronization/abstract_struct.rb +158 -0
  73. data/lib/concurrent/synchronization/condition.rb +53 -0
  74. data/lib/concurrent/synchronization/java_object.rb +35 -0
  75. data/lib/concurrent/synchronization/lock.rb +32 -0
  76. data/lib/concurrent/synchronization/monitor_object.rb +24 -0
  77. data/lib/concurrent/synchronization/mutex_object.rb +43 -0
  78. data/lib/concurrent/synchronization/object.rb +78 -0
  79. data/lib/concurrent/synchronization/rbx_object.rb +75 -0
  80. data/lib/concurrent/timer_task.rb +87 -100
  81. data/lib/concurrent/tvar.rb +42 -38
  82. data/lib/concurrent/utilities.rb +3 -1
  83. data/lib/concurrent/utility/at_exit.rb +97 -0
  84. data/lib/concurrent/utility/engine.rb +40 -0
  85. data/lib/concurrent/utility/monotonic_time.rb +59 -0
  86. data/lib/concurrent/utility/native_extension_loader.rb +56 -0
  87. data/lib/concurrent/utility/processor_counter.rb +156 -0
  88. data/lib/concurrent/utility/timeout.rb +18 -14
  89. data/lib/concurrent/utility/timer.rb +11 -6
  90. data/lib/concurrent/version.rb +2 -1
  91. data/lib/concurrent_ruby.rb +1 -0
  92. metadata +47 -83
  93. data/lib/concurrent/actor.rb +0 -103
  94. data/lib/concurrent/actor/behaviour.rb +0 -70
  95. data/lib/concurrent/actor/behaviour/abstract.rb +0 -48
  96. data/lib/concurrent/actor/behaviour/awaits.rb +0 -21
  97. data/lib/concurrent/actor/behaviour/buffer.rb +0 -54
  98. data/lib/concurrent/actor/behaviour/errors_on_unknown_message.rb +0 -12
  99. data/lib/concurrent/actor/behaviour/executes_context.rb +0 -18
  100. data/lib/concurrent/actor/behaviour/linking.rb +0 -45
  101. data/lib/concurrent/actor/behaviour/pausing.rb +0 -77
  102. data/lib/concurrent/actor/behaviour/removes_child.rb +0 -16
  103. data/lib/concurrent/actor/behaviour/sets_results.rb +0 -36
  104. data/lib/concurrent/actor/behaviour/supervised.rb +0 -59
  105. data/lib/concurrent/actor/behaviour/supervising.rb +0 -34
  106. data/lib/concurrent/actor/behaviour/terminates_children.rb +0 -13
  107. data/lib/concurrent/actor/behaviour/termination.rb +0 -54
  108. data/lib/concurrent/actor/context.rb +0 -154
  109. data/lib/concurrent/actor/core.rb +0 -217
  110. data/lib/concurrent/actor/default_dead_letter_handler.rb +0 -9
  111. data/lib/concurrent/actor/envelope.rb +0 -41
  112. data/lib/concurrent/actor/errors.rb +0 -27
  113. data/lib/concurrent/actor/internal_delegations.rb +0 -49
  114. data/lib/concurrent/actor/public_delegations.rb +0 -40
  115. data/lib/concurrent/actor/reference.rb +0 -81
  116. data/lib/concurrent/actor/root.rb +0 -37
  117. data/lib/concurrent/actor/type_check.rb +0 -48
  118. data/lib/concurrent/actor/utils.rb +0 -10
  119. data/lib/concurrent/actor/utils/ad_hoc.rb +0 -21
  120. data/lib/concurrent/actor/utils/balancer.rb +0 -42
  121. data/lib/concurrent/actor/utils/broadcast.rb +0 -52
  122. data/lib/concurrent/actor/utils/pool.rb +0 -59
  123. data/lib/concurrent/actress.rb +0 -3
  124. data/lib/concurrent/agent.rb +0 -209
  125. data/lib/concurrent/atomic.rb +0 -92
  126. data/lib/concurrent/atomic/copy_on_notify_observer_set.rb +0 -118
  127. data/lib/concurrent/atomic/copy_on_write_observer_set.rb +0 -117
  128. data/lib/concurrent/atomic/synchronization.rb +0 -51
  129. data/lib/concurrent/channel/buffered_channel.rb +0 -85
  130. data/lib/concurrent/channel/channel.rb +0 -41
  131. data/lib/concurrent/channel/unbuffered_channel.rb +0 -35
  132. data/lib/concurrent/channel/waitable_list.rb +0 -40
  133. data/lib/concurrent/channels.rb +0 -5
  134. data/lib/concurrent/collection/blocking_ring_buffer.rb +0 -71
  135. data/lib/concurrent/collection/ring_buffer.rb +0 -59
  136. data/lib/concurrent/collections.rb +0 -3
  137. data/lib/concurrent/dereferenceable.rb +0 -108
  138. data/lib/concurrent/executor/ruby_thread_pool_worker.rb +0 -73
  139. data/lib/concurrent/logging.rb +0 -20
  140. data/lib/concurrent/obligation.rb +0 -171
  141. data/lib/concurrent/observable.rb +0 -73
  142. data/lib/concurrent/options_parser.rb +0 -52
  143. data/lib/concurrent/utility/processor_count.rb +0 -152
  144. data/lib/extension_helper.rb +0 -37
@@ -1,305 +1,360 @@
1
1
  module Concurrent
2
+ module Collection
2
3
 
3
- # @!macro [attach] priority_queue
4
- #
5
- # A queue collection in which the elements are sorted based on their
6
- # comparison (spaceship) operator `<=>`. Items are added to the queue
7
- # at a position relative to their priority. On removal the element
8
- # with the "highest" priority is removed. By default the sort order is
9
- # from highest to lowest, but a lowest-to-highest sort order can be
10
- # set on construction.
11
- #
12
- # The API is based on the `Queue` class from the Ruby standard library.
13
- #
14
- # The pure Ruby implementation, `MutexPriorityQueue` uses a heap algorithm
15
- # stored in an array. The algorithm is based on the work of Robert Sedgewick
16
- # and Kevin Wayne.
17
- #
18
- # The JRuby native implementation is a thin wrapper around the standard
19
- # library `java.util.PriorityQueue`.
20
- #
21
- # When running under JRuby the class `PriorityQueue` extends `JavaPriorityQueue`.
22
- # When running under all other interpreters it extends `MutexPriorityQueue`.
23
- #
24
- # @note This implementation is *not* thread safe and performs no blocking.
25
- #
26
- # @see http://en.wikipedia.org/wiki/Priority_queue
27
- # @see http://ruby-doc.org/stdlib-2.0.0/libdoc/thread/rdoc/Queue.html
28
- #
29
- # @see http://algs4.cs.princeton.edu/24pq/index.php#2.6
30
- # @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html
31
- #
32
- # @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html
33
- class MutexPriorityQueue
34
-
35
- # @!macro [attach] priority_queue_method_initialize
4
+ # @!macro [attach] priority_queue
36
5
  #
37
- # Create a new priority queue with no items.
38
- #
39
- # @param [Hash] opts the options for creating the queue
40
- # @option opts [Symbol] :order (:max) dictates the order in which items are
41
- # stored: from highest to lowest when `:max` or `:high`; from lowest to
42
- # highest when `:min` or `:low`
43
- def initialize(opts = {})
44
- order = opts.fetch(:order, :max)
45
- @comparator = [:min, :low].include?(order) ? -1 : 1
46
- clear
47
- end
48
-
49
- # @!macro [attach] priority_queue_method_clear
6
+ # A queue collection in which the elements are sorted based on their
7
+ # comparison (spaceship) operator `<=>`. Items are added to the queue
8
+ # at a position relative to their priority. On removal the element
9
+ # with the "highest" priority is removed. By default the sort order is
10
+ # from highest to lowest, but a lowest-to-highest sort order can be
11
+ # set on construction.
50
12
  #
51
- # Removes all of the elements from this priority queue.
52
- def clear
53
- @queue = [nil]
54
- @length = 0
55
- true
56
- end
57
-
58
- # @!macro [attach] priority_queue_method_delete
13
+ # The API is based on the `Queue` class from the Ruby standard library.
59
14
  #
60
- # Deletes all items from `self` that are equal to `item`.
61
- #
62
- # @param [Object] item the item to be removed from the queue
63
- # @return [Object] true if the item is found else false
64
- def delete(item)
65
- original_length = @length
66
- k = 1
67
- while k <= @length
68
- if @queue[k] == item
69
- swap(k, @length)
70
- @length -= 1
71
- sink(k)
72
- @queue.pop
73
- else
74
- k += 1
75
- end
76
- end
77
- @length != original_length
78
- end
79
-
80
- # @!macro [attach] priority_queue_method_empty
81
- #
82
- # Returns `true` if `self` contains no elements.
83
- #
84
- # @return [Boolean] true if there are no items in the queue else false
85
- def empty?
86
- size == 0
87
- end
88
-
89
- # @!macro [attach] priority_queue_method_include
15
+ # The pure Ruby implementation, `MutexPriorityQueue` uses a heap algorithm
16
+ # stored in an array. The algorithm is based on the work of Robert Sedgewick
17
+ # and Kevin Wayne.
90
18
  #
91
- # Returns `true` if the given item is present in `self` (that is, if any
92
- # element == `item`), otherwise returns false.
93
- #
94
- # @param [Object] item the item to search for
95
- #
96
- # @return [Boolean] true if the item is found else false
97
- def include?(item)
98
- @queue.include?(item)
99
- end
100
- alias_method :has_priority?, :include?
101
-
102
- # @!macro [attach] priority_queue_method_length
103
- #
104
- # The current length of the queue.
105
- #
106
- # @return [Fixnum] the number of items in the queue
107
- def length
108
- @length
109
- end
110
- alias_method :size, :length
111
-
112
- # @!macro [attach] priority_queue_method_peek
113
- #
114
- # Retrieves, but does not remove, the head of this queue, or returns `nil`
115
- # if this queue is empty.
116
- #
117
- # @return [Object] the head of the queue or `nil` when empty
118
- def peek
119
- @queue[1]
120
- end
121
-
122
- # @!macro [attach] priority_queue_method_pop
123
- #
124
- # Retrieves and removes the head of this queue, or returns `nil` if this
125
- # queue is empty.
126
- #
127
- # @return [Object] the head of the queue or `nil` when empty
128
- def pop
129
- max = @queue[1]
130
- swap(1, @length)
131
- @length -= 1
132
- sink(1)
133
- @queue.pop
134
- max
135
- end
136
- alias_method :deq, :pop
137
- alias_method :shift, :pop
138
-
139
- # @!macro [attach] priority_queue_method_push
140
- #
141
- # Inserts the specified element into this priority queue.
142
- #
143
- # @param [Object] item the item to insert onto the queue
144
- def push(item)
145
- @length += 1
146
- @queue << item
147
- swim(@length)
148
- true
149
- end
150
- alias_method :<<, :push
151
- alias_method :enq, :push
152
-
153
- # @!macro [attach] priority_queue_method_from_list
154
- #
155
- # Create a new priority queue from the given list.
156
- #
157
- # @param [Enumerable] list the list to build the queue from
158
- # @param [Hash] opts the options for creating the queue
159
- #
160
- # @return [PriorityQueue] the newly created and populated queue
161
- def self.from_list(list, opts = {})
162
- queue = new(opts)
163
- list.each{|item| queue << item }
164
- queue
165
- end
166
-
167
- protected
168
-
169
- # Exchange the values at the given indexes within the internal array.
170
- #
171
- # @param [Integer] x the first index to swap
172
- # @param [Integer] y the second index to swap
173
- #
174
- # @!visibility private
175
- def swap(x, y)
176
- temp = @queue[x]
177
- @queue[x] = @queue[y]
178
- @queue[y] = temp
179
- end
180
-
181
- # Are the items at the given indexes ordered based on the priority
182
- # order specified at construction?
19
+ # The JRuby native implementation is a thin wrapper around the standard
20
+ # library `java.util.PriorityQueue`.
183
21
  #
184
- # @param [Integer] x the first index from which to retrieve a comparable value
185
- # @param [Integer] y the second index from which to retrieve a comparable value
22
+ # When running under JRuby the class `PriorityQueue` extends `JavaPriorityQueue`.
23
+ # When running under all other interpreters it extends `MutexPriorityQueue`.
186
24
  #
187
- # @return [Boolean] true if the two elements are in the correct priority order
188
- # else false
189
- #
190
- # @!visibility private
191
- def ordered?(x, y)
192
- (@queue[x] <=> @queue[y]) == @comparator
193
- end
194
-
195
- # Percolate down to maintain heap invariant.
196
- #
197
- # @param [Integer] k the index at which to start the percolation
198
- #
199
- # @!visibility private
200
- def sink(k)
201
- while (j = (2 * k)) <= @length do
202
- j += 1 if j < @length && ! ordered?(j, j+1)
203
- break if ordered?(k, j)
204
- swap(k, j)
205
- k = j
206
- end
207
- end
208
-
209
- # Percolate up to maintain heap invariant.
210
- #
211
- # @param [Integer] k the index at which to start the percolation
25
+ # @note This implementation is *not* thread safe.
26
+ #
27
+ # @see http://en.wikipedia.org/wiki/Priority_queue
28
+ # @see http://ruby-doc.org/stdlib-2.0.0/libdoc/thread/rdoc/Queue.html
29
+ #
30
+ # @see http://algs4.cs.princeton.edu/24pq/index.php#2.6
31
+ # @see http://algs4.cs.princeton.edu/24pq/MaxPQ.java.html
32
+ #
33
+ # @see http://docs.oracle.com/javase/7/docs/api/java/util/PriorityQueue.html
212
34
  #
213
35
  # @!visibility private
214
- def swim(k)
215
- while k > 1 && ! ordered?(k/2, k) do
216
- swap(k, k/2)
217
- k = k/2
218
- end
219
- end
220
- end
36
+ # @!macro internal_implementation_note
37
+ class MutexPriorityQueue
221
38
 
222
- if RUBY_PLATFORM == 'java'
223
-
224
- # @!macro priority_queue
225
- class JavaPriorityQueue
226
-
227
- # @!macro priority_queue_method_initialize
39
+ # @!macro [attach] priority_queue_method_initialize
40
+ #
41
+ # Create a new priority queue with no items.
42
+ #
43
+ # @param [Hash] opts the options for creating the queue
44
+ # @option opts [Symbol] :order (:max) dictates the order in which items are
45
+ # stored: from highest to lowest when `:max` or `:high`; from lowest to
46
+ # highest when `:min` or `:low`
228
47
  def initialize(opts = {})
229
48
  order = opts.fetch(:order, :max)
230
- if [:min, :low].include?(order)
231
- @queue = java.util.PriorityQueue.new(11) # 11 is the default initial capacity
232
- else
233
- @queue = java.util.PriorityQueue.new(11, java.util.Collections.reverseOrder())
234
- end
49
+ @comparator = [:min, :low].include?(order) ? -1 : 1
50
+ clear
235
51
  end
236
52
 
237
- # @!macro priority_queue_method_clear
53
+ # @!macro [attach] priority_queue_method_clear
54
+ #
55
+ # Removes all of the elements from this priority queue.
238
56
  def clear
239
- @queue.clear
57
+ @queue = [nil]
58
+ @length = 0
240
59
  true
241
60
  end
242
61
 
243
- # @!macro priority_queue_method_delete
62
+ # @!macro [attach] priority_queue_method_delete
63
+ #
64
+ # Deletes all items from `self` that are equal to `item`.
65
+ #
66
+ # @param [Object] item the item to be removed from the queue
67
+ # @return [Object] true if the item is found else false
244
68
  def delete(item)
245
- found = false
246
- while @queue.remove(item) do
247
- found = true
69
+ original_length = @length
70
+ k = 1
71
+ while k <= @length
72
+ if @queue[k] == item
73
+ swap(k, @length)
74
+ @length -= 1
75
+ sink(k)
76
+ @queue.pop
77
+ else
78
+ k += 1
79
+ end
248
80
  end
249
- found
81
+ @length != original_length
250
82
  end
251
83
 
252
- # @!macro priority_queue_method_empty
84
+ # @!macro [attach] priority_queue_method_empty
85
+ #
86
+ # Returns `true` if `self` contains no elements.
87
+ #
88
+ # @return [Boolean] true if there are no items in the queue else false
253
89
  def empty?
254
- @queue.size == 0
90
+ size == 0
255
91
  end
256
92
 
257
- # @!macro priority_queue_method_include
93
+ # @!macro [attach] priority_queue_method_include
94
+ #
95
+ # Returns `true` if the given item is present in `self` (that is, if any
96
+ # element == `item`), otherwise returns false.
97
+ #
98
+ # @param [Object] item the item to search for
99
+ #
100
+ # @return [Boolean] true if the item is found else false
258
101
  def include?(item)
259
- @queue.contains(item)
102
+ @queue.include?(item)
260
103
  end
261
104
  alias_method :has_priority?, :include?
262
105
 
263
- # @!macro priority_queue_method_length
106
+ # @!macro [attach] priority_queue_method_length
107
+ #
108
+ # The current length of the queue.
109
+ #
110
+ # @return [Fixnum] the number of items in the queue
264
111
  def length
265
- @queue.size
112
+ @length
266
113
  end
267
114
  alias_method :size, :length
268
115
 
269
- # @!macro priority_queue_method_peek
116
+ # @!macro [attach] priority_queue_method_peek
117
+ #
118
+ # Retrieves, but does not remove, the head of this queue, or returns `nil`
119
+ # if this queue is empty.
120
+ #
121
+ # @return [Object] the head of the queue or `nil` when empty
270
122
  def peek
271
- @queue.peek
123
+ @queue[1]
272
124
  end
273
125
 
274
- # @!macro priority_queue_method_pop
126
+ # @!macro [attach] priority_queue_method_pop
127
+ #
128
+ # Retrieves and removes the head of this queue, or returns `nil` if this
129
+ # queue is empty.
130
+ #
131
+ # @return [Object] the head of the queue or `nil` when empty
275
132
  def pop
276
- @queue.poll
133
+ max = @queue[1]
134
+ swap(1, @length)
135
+ @length -= 1
136
+ sink(1)
137
+ @queue.pop
138
+ max
277
139
  end
278
140
  alias_method :deq, :pop
279
141
  alias_method :shift, :pop
280
142
 
281
- # @!macro priority_queue_method_push
143
+ # @!macro [attach] priority_queue_method_push
144
+ #
145
+ # Inserts the specified element into this priority queue.
146
+ #
147
+ # @param [Object] item the item to insert onto the queue
282
148
  def push(item)
283
- @queue.add(item)
149
+ @length += 1
150
+ @queue << item
151
+ swim(@length)
152
+ true
284
153
  end
285
154
  alias_method :<<, :push
286
155
  alias_method :enq, :push
287
156
 
288
- # @!macro priority_queue_method_from_list
157
+ # @!macro [attach] priority_queue_method_from_list
158
+ #
159
+ # Create a new priority queue from the given list.
160
+ #
161
+ # @param [Enumerable] list the list to build the queue from
162
+ # @param [Hash] opts the options for creating the queue
163
+ #
164
+ # @return [PriorityQueue] the newly created and populated queue
289
165
  def self.from_list(list, opts = {})
290
166
  queue = new(opts)
291
167
  list.each{|item| queue << item }
292
168
  queue
293
169
  end
170
+
171
+ protected
172
+
173
+ # Exchange the values at the given indexes within the internal array.
174
+ #
175
+ # @param [Integer] x the first index to swap
176
+ # @param [Integer] y the second index to swap
177
+ #
178
+ # @!visibility private
179
+ def swap(x, y)
180
+ temp = @queue[x]
181
+ @queue[x] = @queue[y]
182
+ @queue[y] = temp
183
+ end
184
+
185
+ # Are the items at the given indexes ordered based on the priority
186
+ # order specified at construction?
187
+ #
188
+ # @param [Integer] x the first index from which to retrieve a comparable value
189
+ # @param [Integer] y the second index from which to retrieve a comparable value
190
+ #
191
+ # @return [Boolean] true if the two elements are in the correct priority order
192
+ # else false
193
+ #
194
+ # @!visibility private
195
+ def ordered?(x, y)
196
+ (@queue[x] <=> @queue[y]) == @comparator
197
+ end
198
+
199
+ # Percolate down to maintain heap invariant.
200
+ #
201
+ # @param [Integer] k the index at which to start the percolation
202
+ #
203
+ # @!visibility private
204
+ def sink(k)
205
+ while (j = (2 * k)) <= @length do
206
+ j += 1 if j < @length && ! ordered?(j, j+1)
207
+ break if ordered?(k, j)
208
+ swap(k, j)
209
+ k = j
210
+ end
211
+ end
212
+
213
+ # Percolate up to maintain heap invariant.
214
+ #
215
+ # @param [Integer] k the index at which to start the percolation
216
+ #
217
+ # @!visibility private
218
+ def swim(k)
219
+ while k > 1 && ! ordered?(k/2, k) do
220
+ swap(k, k/2)
221
+ k = k/2
222
+ end
223
+ end
294
224
  end
295
225
 
296
- # @!macro priority_queue
297
- class PriorityQueue < JavaPriorityQueue
226
+ if Concurrent.on_jruby?
227
+
228
+ # @!macro priority_queue
229
+ #
230
+ # @!visibility private
231
+ # @!macro internal_implementation_note
232
+ class JavaPriorityQueue
233
+
234
+ # @!macro priority_queue_method_initialize
235
+ def initialize(opts = {})
236
+ order = opts.fetch(:order, :max)
237
+ if [:min, :low].include?(order)
238
+ @queue = java.util.PriorityQueue.new(11) # 11 is the default initial capacity
239
+ else
240
+ @queue = java.util.PriorityQueue.new(11, java.util.Collections.reverseOrder())
241
+ end
242
+ end
243
+
244
+ # @!macro priority_queue_method_clear
245
+ def clear
246
+ @queue.clear
247
+ true
248
+ end
249
+
250
+ # @!macro priority_queue_method_delete
251
+ def delete(item)
252
+ found = false
253
+ while @queue.remove(item) do
254
+ found = true
255
+ end
256
+ found
257
+ end
258
+
259
+ # @!macro priority_queue_method_empty
260
+ def empty?
261
+ @queue.size == 0
262
+ end
263
+
264
+ # @!macro priority_queue_method_include
265
+ def include?(item)
266
+ @queue.contains(item)
267
+ end
268
+ alias_method :has_priority?, :include?
269
+
270
+ # @!macro priority_queue_method_length
271
+ def length
272
+ @queue.size
273
+ end
274
+ alias_method :size, :length
275
+
276
+ # @!macro priority_queue_method_peek
277
+ def peek
278
+ @queue.peek
279
+ end
280
+
281
+ # @!macro priority_queue_method_pop
282
+ def pop
283
+ @queue.poll
284
+ end
285
+ alias_method :deq, :pop
286
+ alias_method :shift, :pop
287
+
288
+ # @!macro priority_queue_method_push
289
+ def push(item)
290
+ @queue.add(item)
291
+ end
292
+ alias_method :<<, :push
293
+ alias_method :enq, :push
294
+
295
+ # @!macro priority_queue_method_from_list
296
+ def self.from_list(list, opts = {})
297
+ queue = new(opts)
298
+ list.each{|item| queue << item }
299
+ queue
300
+ end
301
+ end
298
302
  end
299
- else
303
+
304
+ # @!visibility private
305
+ # @!macro internal_implementation_note
306
+ PriorityQueueImplementation = case
307
+ when Concurrent.on_jruby?
308
+ JavaPriorityQueue
309
+ else
310
+ MutexPriorityQueue
311
+ end
312
+ private_constant :PriorityQueueImplementation
300
313
 
301
314
  # @!macro priority_queue
302
- class PriorityQueue < MutexPriorityQueue
315
+ #
316
+ # @!visibility private
317
+ class PriorityQueue < PriorityQueueImplementation
318
+
319
+ alias_method :has_priority?, :include?
320
+
321
+ alias_method :size, :length
322
+
323
+ alias_method :deq, :pop
324
+ alias_method :shift, :pop
325
+
326
+ alias_method :<<, :push
327
+ alias_method :enq, :push
328
+
329
+ # @!method initialize(opts = {})
330
+ # @!macro priority_queue_method_initialize
331
+
332
+ # @!method clear
333
+ # @!macro priority_queue_method_clear
334
+
335
+ # @!method delete(item)
336
+ # @!macro priority_queue_method_delete
337
+
338
+ # @!method empty?
339
+ # @!macro priority_queue_method_empty
340
+
341
+ # @!method include?(item)
342
+ # @!macro priority_queue_method_include
343
+
344
+ # @!method length
345
+ # @!macro priority_queue_method_length
346
+
347
+ # @!method peek
348
+ # @!macro priority_queue_method_peek
349
+
350
+ # @!method pop
351
+ # @!macro priority_queue_method_pop
352
+
353
+ # @!method push(item)
354
+ # @!macro priority_queue_method_push
355
+
356
+ # @!method self.from_list(list, opts = {})
357
+ # @!macro priority_queue_method_from_list
303
358
  end
304
359
  end
305
360
  end