concurrent-ruby 0.6.0.pre.1 → 0.6.0.pre.2

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 (142) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +16 -0
  3. data/lib/concurrent.rb +9 -29
  4. data/lib/concurrent/{actor.rb → actor/actor.rb} +3 -3
  5. data/lib/concurrent/actor/actor_context.rb +77 -0
  6. data/lib/concurrent/actor/actor_ref.rb +67 -0
  7. data/lib/concurrent/{postable.rb → actor/postable.rb} +1 -1
  8. data/lib/concurrent/actor/simple_actor_ref.rb +94 -0
  9. data/lib/concurrent/actors.rb +5 -0
  10. data/lib/concurrent/agent.rb +81 -47
  11. data/lib/concurrent/async.rb +35 -35
  12. data/lib/concurrent/atomic/atomic_boolean.rb +157 -0
  13. data/lib/concurrent/atomic/atomic_fixnum.rb +170 -0
  14. data/lib/concurrent/{condition.rb → atomic/condition.rb} +0 -0
  15. data/lib/concurrent/{copy_on_notify_observer_set.rb → atomic/copy_on_notify_observer_set.rb} +48 -13
  16. data/lib/concurrent/{copy_on_write_observer_set.rb → atomic/copy_on_write_observer_set.rb} +41 -20
  17. data/lib/concurrent/atomic/count_down_latch.rb +116 -0
  18. data/lib/concurrent/atomic/cyclic_barrier.rb +106 -0
  19. data/lib/concurrent/atomic/event.rb +103 -0
  20. data/lib/concurrent/{thread_local_var.rb → atomic/thread_local_var.rb} +0 -0
  21. data/lib/concurrent/atomics.rb +9 -0
  22. data/lib/concurrent/channel/buffered_channel.rb +6 -4
  23. data/lib/concurrent/channel/channel.rb +30 -2
  24. data/lib/concurrent/channel/unbuffered_channel.rb +2 -2
  25. data/lib/concurrent/channel/waitable_list.rb +3 -1
  26. data/lib/concurrent/channels.rb +5 -0
  27. data/lib/concurrent/{channel → collection}/blocking_ring_buffer.rb +16 -5
  28. data/lib/concurrent/collection/priority_queue.rb +305 -0
  29. data/lib/concurrent/{channel → collection}/ring_buffer.rb +6 -1
  30. data/lib/concurrent/collections.rb +3 -0
  31. data/lib/concurrent/configuration.rb +68 -19
  32. data/lib/concurrent/dataflow.rb +9 -9
  33. data/lib/concurrent/delay.rb +21 -13
  34. data/lib/concurrent/dereferenceable.rb +40 -33
  35. data/lib/concurrent/exchanger.rb +3 -0
  36. data/lib/concurrent/{cached_thread_pool.rb → executor/cached_thread_pool.rb} +8 -9
  37. data/lib/concurrent/executor/executor.rb +222 -0
  38. data/lib/concurrent/{fixed_thread_pool.rb → executor/fixed_thread_pool.rb} +6 -7
  39. data/lib/concurrent/{immediate_executor.rb → executor/immediate_executor.rb} +5 -5
  40. data/lib/concurrent/executor/java_cached_thread_pool.rb +31 -0
  41. data/lib/concurrent/{java_fixed_thread_pool.rb → executor/java_fixed_thread_pool.rb} +7 -11
  42. data/lib/concurrent/executor/java_single_thread_executor.rb +21 -0
  43. data/lib/concurrent/{java_thread_pool_executor.rb → executor/java_thread_pool_executor.rb} +66 -77
  44. data/lib/concurrent/executor/one_by_one.rb +65 -0
  45. data/lib/concurrent/{per_thread_executor.rb → executor/per_thread_executor.rb} +4 -4
  46. data/lib/concurrent/executor/ruby_cached_thread_pool.rb +29 -0
  47. data/lib/concurrent/{ruby_fixed_thread_pool.rb → executor/ruby_fixed_thread_pool.rb} +5 -4
  48. data/lib/concurrent/executor/ruby_single_thread_executor.rb +72 -0
  49. data/lib/concurrent/executor/ruby_thread_pool_executor.rb +282 -0
  50. data/lib/concurrent/{ruby_thread_pool_worker.rb → executor/ruby_thread_pool_worker.rb} +6 -6
  51. data/lib/concurrent/{safe_task_executor.rb → executor/safe_task_executor.rb} +20 -13
  52. data/lib/concurrent/executor/single_thread_executor.rb +35 -0
  53. data/lib/concurrent/executor/thread_pool_executor.rb +68 -0
  54. data/lib/concurrent/executor/timer_set.rb +138 -0
  55. data/lib/concurrent/executors.rb +9 -0
  56. data/lib/concurrent/future.rb +39 -40
  57. data/lib/concurrent/ivar.rb +22 -15
  58. data/lib/concurrent/mvar.rb +2 -1
  59. data/lib/concurrent/obligation.rb +9 -3
  60. data/lib/concurrent/observable.rb +33 -0
  61. data/lib/concurrent/options_parser.rb +46 -0
  62. data/lib/concurrent/promise.rb +23 -24
  63. data/lib/concurrent/scheduled_task.rb +21 -45
  64. data/lib/concurrent/timer_task.rb +204 -126
  65. data/lib/concurrent/tvar.rb +1 -1
  66. data/lib/concurrent/utilities.rb +3 -36
  67. data/lib/concurrent/{processor_count.rb → utility/processor_count.rb} +1 -1
  68. data/lib/concurrent/utility/timeout.rb +36 -0
  69. data/lib/concurrent/utility/timer.rb +21 -0
  70. data/lib/concurrent/version.rb +1 -1
  71. data/lib/concurrent_ruby_ext.bundle +0 -0
  72. data/spec/concurrent/{actor_context_spec.rb → actor/actor_context_spec.rb} +0 -8
  73. data/spec/concurrent/{actor_ref_shared.rb → actor/actor_ref_shared.rb} +9 -59
  74. data/spec/concurrent/{actor_spec.rb → actor/actor_spec.rb} +43 -41
  75. data/spec/concurrent/{postable_shared.rb → actor/postable_shared.rb} +0 -0
  76. data/spec/concurrent/actor/simple_actor_ref_spec.rb +135 -0
  77. data/spec/concurrent/agent_spec.rb +160 -71
  78. data/spec/concurrent/atomic/atomic_boolean_spec.rb +172 -0
  79. data/spec/concurrent/atomic/atomic_fixnum_spec.rb +186 -0
  80. data/spec/concurrent/{condition_spec.rb → atomic/condition_spec.rb} +2 -2
  81. data/spec/concurrent/{copy_on_notify_observer_set_spec.rb → atomic/copy_on_notify_observer_set_spec.rb} +0 -0
  82. data/spec/concurrent/{copy_on_write_observer_set_spec.rb → atomic/copy_on_write_observer_set_spec.rb} +0 -0
  83. data/spec/concurrent/atomic/count_down_latch_spec.rb +151 -0
  84. data/spec/concurrent/atomic/cyclic_barrier_spec.rb +248 -0
  85. data/spec/concurrent/{event_spec.rb → atomic/event_spec.rb} +18 -3
  86. data/spec/concurrent/{observer_set_shared.rb → atomic/observer_set_shared.rb} +15 -6
  87. data/spec/concurrent/{thread_local_var_spec.rb → atomic/thread_local_var_spec.rb} +0 -0
  88. data/spec/concurrent/channel/buffered_channel_spec.rb +1 -1
  89. data/spec/concurrent/channel/channel_spec.rb +6 -4
  90. data/spec/concurrent/channel/probe_spec.rb +37 -9
  91. data/spec/concurrent/channel/unbuffered_channel_spec.rb +2 -2
  92. data/spec/concurrent/{channel → collection}/blocking_ring_buffer_spec.rb +0 -0
  93. data/spec/concurrent/collection/priority_queue_spec.rb +317 -0
  94. data/spec/concurrent/{channel → collection}/ring_buffer_spec.rb +0 -0
  95. data/spec/concurrent/configuration_spec.rb +4 -70
  96. data/spec/concurrent/dereferenceable_shared.rb +5 -4
  97. data/spec/concurrent/exchanger_spec.rb +10 -5
  98. data/spec/concurrent/{cached_thread_pool_shared.rb → executor/cached_thread_pool_shared.rb} +15 -37
  99. data/spec/concurrent/{fixed_thread_pool_shared.rb → executor/fixed_thread_pool_shared.rb} +0 -0
  100. data/spec/concurrent/{global_thread_pool_shared.rb → executor/global_thread_pool_shared.rb} +10 -8
  101. data/spec/concurrent/{immediate_executor_spec.rb → executor/immediate_executor_spec.rb} +0 -0
  102. data/spec/concurrent/{java_cached_thread_pool_spec.rb → executor/java_cached_thread_pool_spec.rb} +1 -21
  103. data/spec/concurrent/{java_fixed_thread_pool_spec.rb → executor/java_fixed_thread_pool_spec.rb} +0 -0
  104. data/spec/concurrent/executor/java_single_thread_executor_spec.rb +21 -0
  105. data/spec/concurrent/{java_thread_pool_executor_spec.rb → executor/java_thread_pool_executor_spec.rb} +0 -0
  106. data/spec/concurrent/{per_thread_executor_spec.rb → executor/per_thread_executor_spec.rb} +0 -4
  107. data/spec/concurrent/{ruby_cached_thread_pool_spec.rb → executor/ruby_cached_thread_pool_spec.rb} +1 -1
  108. data/spec/concurrent/{ruby_fixed_thread_pool_spec.rb → executor/ruby_fixed_thread_pool_spec.rb} +0 -0
  109. data/spec/concurrent/executor/ruby_single_thread_executor_spec.rb +18 -0
  110. data/spec/concurrent/{ruby_thread_pool_executor_spec.rb → executor/ruby_thread_pool_executor_spec.rb} +12 -24
  111. data/spec/concurrent/executor/safe_task_executor_spec.rb +103 -0
  112. data/spec/concurrent/{thread_pool_class_cast_spec.rb → executor/thread_pool_class_cast_spec.rb} +12 -0
  113. data/spec/concurrent/{thread_pool_executor_shared.rb → executor/thread_pool_executor_shared.rb} +0 -0
  114. data/spec/concurrent/{thread_pool_shared.rb → executor/thread_pool_shared.rb} +84 -119
  115. data/spec/concurrent/executor/timer_set_spec.rb +183 -0
  116. data/spec/concurrent/future_spec.rb +12 -0
  117. data/spec/concurrent/ivar_spec.rb +11 -1
  118. data/spec/concurrent/observable_shared.rb +173 -0
  119. data/spec/concurrent/observable_spec.rb +51 -0
  120. data/spec/concurrent/options_parser_spec.rb +71 -0
  121. data/spec/concurrent/runnable_shared.rb +6 -0
  122. data/spec/concurrent/scheduled_task_spec.rb +60 -40
  123. data/spec/concurrent/timer_task_spec.rb +130 -144
  124. data/spec/concurrent/{processor_count_spec.rb → utility/processor_count_spec.rb} +0 -0
  125. data/spec/concurrent/{utilities_spec.rb → utility/timeout_spec.rb} +0 -0
  126. data/spec/concurrent/utility/timer_spec.rb +52 -0
  127. metadata +147 -108
  128. data/lib/concurrent/actor_context.rb +0 -31
  129. data/lib/concurrent/actor_ref.rb +0 -39
  130. data/lib/concurrent/atomic.rb +0 -121
  131. data/lib/concurrent/channel/probe.rb +0 -19
  132. data/lib/concurrent/count_down_latch.rb +0 -60
  133. data/lib/concurrent/event.rb +0 -80
  134. data/lib/concurrent/java_cached_thread_pool.rb +0 -45
  135. data/lib/concurrent/ruby_cached_thread_pool.rb +0 -37
  136. data/lib/concurrent/ruby_thread_pool_executor.rb +0 -268
  137. data/lib/concurrent/simple_actor_ref.rb +0 -124
  138. data/lib/concurrent/thread_pool_executor.rb +0 -30
  139. data/spec/concurrent/atomic_spec.rb +0 -201
  140. data/spec/concurrent/count_down_latch_spec.rb +0 -125
  141. data/spec/concurrent/safe_task_executor_spec.rb +0 -58
  142. data/spec/concurrent/simple_actor_ref_spec.rb +0 -219
@@ -0,0 +1,9 @@
1
+ require 'concurrent/atomic/atomic_boolean'
2
+ require 'concurrent/atomic/atomic_fixnum'
3
+ require 'concurrent/atomic/condition'
4
+ require 'concurrent/atomic/copy_on_notify_observer_set'
5
+ require 'concurrent/atomic/copy_on_write_observer_set'
6
+ require 'concurrent/atomic/cyclic_barrier'
7
+ require 'concurrent/atomic/count_down_latch'
8
+ require 'concurrent/atomic/event'
9
+ require 'concurrent/atomic/thread_local_var'
@@ -1,3 +1,5 @@
1
+ require 'concurrent/atomic/condition'
2
+
1
3
  require_relative 'waitable_list'
2
4
 
3
5
  module Concurrent
@@ -26,7 +28,7 @@ module Concurrent
26
28
  end
27
29
 
28
30
  def pop
29
- probe = Probe.new
31
+ probe = Channel::Probe.new
30
32
  select(probe)
31
33
  probe.value
32
34
  end
@@ -38,7 +40,7 @@ module Concurrent
38
40
  @probe_set.put(probe)
39
41
  true
40
42
  else
41
- shift_buffer if probe.set_unless_assigned peek_buffer
43
+ shift_buffer if probe.set_unless_assigned(peek_buffer, self)
42
44
  end
43
45
 
44
46
  end
@@ -74,10 +76,10 @@ module Concurrent
74
76
  push_into_buffer(value)
75
77
  true
76
78
  else
77
- @probe_set.take.set_unless_assigned(value)
79
+ @probe_set.take.set_unless_assigned(value, self)
78
80
  end
79
81
  end
80
82
  end
81
83
 
82
84
  end
83
- end
85
+ end
@@ -1,9 +1,37 @@
1
1
  module Concurrent
2
- class Channel
2
+ module Channel
3
+
4
+ class Probe < IVar
5
+
6
+ def initialize(value = NO_VALUE, opts = {})
7
+ super(value, opts)
8
+ end
9
+
10
+ def set_unless_assigned(value, channel)
11
+ mutex.synchronize do
12
+ return false if [:fulfilled, :rejected].include? @state
13
+
14
+ set_state(true, [value, channel], nil)
15
+ event.set
16
+ true
17
+ end
18
+ end
19
+
20
+ alias_method :composite_value, :value
21
+
22
+ def value
23
+ composite_value.nil? ? nil : composite_value[0]
24
+ end
25
+
26
+ def channel
27
+ composite_value.nil? ? nil : composite_value[1]
28
+ end
29
+ end
30
+
3
31
  def self.select(*channels)
4
32
  probe = Probe.new
5
33
  channels.each { |channel| channel.select(probe) }
6
- result = probe.value
34
+ result = probe.composite_value
7
35
  channels.each { |channel| channel.remove_probe(probe) }
8
36
  result
9
37
  end
@@ -12,12 +12,12 @@ module Concurrent
12
12
  end
13
13
 
14
14
  def push(value)
15
- until @probe_set.take.set_unless_assigned(value)
15
+ until @probe_set.take.set_unless_assigned(value, self)
16
16
  end
17
17
  end
18
18
 
19
19
  def pop
20
- probe = Probe.new
20
+ probe = Channel::Probe.new
21
21
  select(probe)
22
22
  probe.value
23
23
  end
@@ -1,3 +1,5 @@
1
+ require 'concurrent/atomic/condition'
2
+
1
3
  module Concurrent
2
4
  class WaitableList
3
5
 
@@ -35,4 +37,4 @@ module Concurrent
35
37
  end
36
38
 
37
39
  end
38
- end
40
+ end
@@ -0,0 +1,5 @@
1
+ require 'concurrent/collections'
2
+
3
+ require 'concurrent/channel/channel'
4
+ require 'concurrent/channel/unbuffered_channel'
5
+ require 'concurrent/channel/buffered_channel'
@@ -1,3 +1,5 @@
1
+ require 'concurrent/atomic/condition'
2
+
1
3
  module Concurrent
2
4
  class BlockingRingBuffer
3
5
 
@@ -9,30 +11,38 @@ module Concurrent
9
11
  @condition = Condition.new
10
12
  end
11
13
 
14
+ # @return [Integer] the capacity of the buffer
12
15
  def capacity
13
16
  @mutex.synchronize { @buffer.capacity }
14
17
  end
15
18
 
19
+ # @return [Integer] the number of elements currently in the buffer
16
20
  def count
17
21
  @mutex.synchronize { @buffer.count }
18
22
  end
19
23
 
20
- def full?
21
- @mutex.synchronize { @buffer.full? }
22
- end
23
-
24
+ # @return [Boolean] true if buffer is empty, false otherwise
24
25
  def empty?
25
26
  @mutex.synchronize { @buffer.empty? }
26
27
  end
27
28
 
29
+ # @return [Boolean] true if buffer is full, false otherwise
30
+ def full?
31
+ @mutex.synchronize { @buffer.full? }
32
+ end
33
+
34
+ # @param [Object] value. This methods blocks until an empty slot is available
35
+ # @return [Boolean] true if value has been inserted, false otherwise
28
36
  def put(value)
29
37
  @mutex.synchronize do
30
38
  wait_while_full
31
39
  @buffer.offer(value)
32
40
  @condition.signal
41
+ true
33
42
  end
34
43
  end
35
44
 
45
+ # @return [Object] the first available value and removes it from the buffer. If buffer is empty it blocks until an element is available
36
46
  def take
37
47
  @mutex.synchronize do
38
48
  wait_while_empty
@@ -42,6 +52,7 @@ module Concurrent
42
52
  end
43
53
  end
44
54
 
55
+ # @return [Object] the first available value and without removing it from the buffer. If buffer is empty returns nil
45
56
  def peek
46
57
  @mutex.synchronize { @buffer.peek }
47
58
  end
@@ -57,4 +68,4 @@ module Concurrent
57
68
  end
58
69
 
59
70
  end
60
- end
71
+ end
@@ -0,0 +1,305 @@
1
+ module Concurrent
2
+
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
36
+ #
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
50
+ #
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
59
+ #
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
90
+ #
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?
183
+ #
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
186
+ #
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
212
+ #
213
+ # @!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
221
+
222
+ if RUBY_PLATFORM == 'java'
223
+
224
+ # @!macro priority_queue
225
+ class JavaPriorityQueue
226
+
227
+ # @!macro priority_queue_method_initialize
228
+ def initialize(opts = {})
229
+ 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
235
+ end
236
+
237
+ # @!macro priority_queue_method_clear
238
+ def clear
239
+ @queue.clear
240
+ true
241
+ end
242
+
243
+ # @!macro priority_queue_method_delete
244
+ def delete(item)
245
+ found = false
246
+ while @queue.remove(item) do
247
+ found = true
248
+ end
249
+ found
250
+ end
251
+
252
+ # @!macro priority_queue_method_empty
253
+ def empty?
254
+ @queue.size == 0
255
+ end
256
+
257
+ # @!macro priority_queue_method_include
258
+ def include?(item)
259
+ @queue.contains(item)
260
+ end
261
+ alias_method :has_priority?, :include?
262
+
263
+ # @!macro priority_queue_method_length
264
+ def length
265
+ @queue.size
266
+ end
267
+ alias_method :size, :length
268
+
269
+ # @!macro priority_queue_method_peek
270
+ def peek
271
+ @queue.peek
272
+ end
273
+
274
+ # @!macro priority_queue_method_pop
275
+ def pop
276
+ @queue.poll
277
+ end
278
+ alias_method :deq, :pop
279
+ alias_method :shift, :pop
280
+
281
+ # @!macro priority_queue_method_push
282
+ def push(item)
283
+ @queue.add(item)
284
+ end
285
+ alias_method :<<, :push
286
+ alias_method :enq, :push
287
+
288
+ # @!macro priority_queue_method_from_list
289
+ def self.from_list(list, opts = {})
290
+ queue = new(opts)
291
+ list.each{|item| queue << item }
292
+ queue
293
+ end
294
+ end
295
+
296
+ # @!macro priority_queue
297
+ class PriorityQueue < JavaPriorityQueue
298
+ end
299
+ else
300
+
301
+ # @!macro priority_queue
302
+ class PriorityQueue < MutexPriorityQueue
303
+ end
304
+ end
305
+ end