garcun 0.0.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 (139) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +17 -0
  3. data/.gitignore +197 -0
  4. data/.rspec +2 -0
  5. data/Gemfile +22 -0
  6. data/LICENSE +201 -0
  7. data/README.md +521 -0
  8. data/Rakefile +47 -0
  9. data/garcun.gemspec +83 -0
  10. data/lib/garcon.rb +290 -0
  11. data/lib/garcon/chef/chef_helpers.rb +343 -0
  12. data/lib/garcon/chef/coerce/coercer.rb +134 -0
  13. data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
  14. data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
  15. data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
  16. data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
  17. data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
  18. data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
  19. data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
  20. data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
  21. data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
  22. data/lib/garcon/chef/handler/devreporter.rb +127 -0
  23. data/lib/garcon/chef/log.rb +64 -0
  24. data/lib/garcon/chef/node.rb +100 -0
  25. data/lib/garcon/chef/provider/civilize.rb +209 -0
  26. data/lib/garcon/chef/provider/development.rb +159 -0
  27. data/lib/garcon/chef/provider/download.rb +420 -0
  28. data/lib/garcon/chef/provider/house_keeping.rb +265 -0
  29. data/lib/garcon/chef/provider/node_cache.rb +31 -0
  30. data/lib/garcon/chef/provider/partial.rb +183 -0
  31. data/lib/garcon/chef/provider/recovery.rb +80 -0
  32. data/lib/garcon/chef/provider/zip_file.rb +271 -0
  33. data/lib/garcon/chef/resource/attribute.rb +52 -0
  34. data/lib/garcon/chef/resource/base_dsl.rb +174 -0
  35. data/lib/garcon/chef/resource/blender.rb +140 -0
  36. data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
  37. data/lib/garcon/chef/resource/resource_name.rb +109 -0
  38. data/lib/garcon/chef/secret_bag.rb +204 -0
  39. data/lib/garcon/chef/validations.rb +76 -0
  40. data/lib/garcon/chef_inclusions.rb +151 -0
  41. data/lib/garcon/configuration.rb +138 -0
  42. data/lib/garcon/core_ext.rb +39 -0
  43. data/lib/garcon/core_ext/array.rb +27 -0
  44. data/lib/garcon/core_ext/binding.rb +64 -0
  45. data/lib/garcon/core_ext/boolean.rb +66 -0
  46. data/lib/garcon/core_ext/duration.rb +271 -0
  47. data/lib/garcon/core_ext/enumerable.rb +34 -0
  48. data/lib/garcon/core_ext/file.rb +127 -0
  49. data/lib/garcon/core_ext/filetest.rb +62 -0
  50. data/lib/garcon/core_ext/hash.rb +279 -0
  51. data/lib/garcon/core_ext/kernel.rb +159 -0
  52. data/lib/garcon/core_ext/lazy.rb +222 -0
  53. data/lib/garcon/core_ext/method_access.rb +243 -0
  54. data/lib/garcon/core_ext/module.rb +92 -0
  55. data/lib/garcon/core_ext/nil.rb +53 -0
  56. data/lib/garcon/core_ext/numeric.rb +44 -0
  57. data/lib/garcon/core_ext/object.rb +342 -0
  58. data/lib/garcon/core_ext/pathname.rb +152 -0
  59. data/lib/garcon/core_ext/process.rb +41 -0
  60. data/lib/garcon/core_ext/random.rb +497 -0
  61. data/lib/garcon/core_ext/string.rb +312 -0
  62. data/lib/garcon/core_ext/struct.rb +49 -0
  63. data/lib/garcon/core_ext/symbol.rb +170 -0
  64. data/lib/garcon/core_ext/time.rb +234 -0
  65. data/lib/garcon/exceptions.rb +101 -0
  66. data/lib/garcon/inflections.rb +237 -0
  67. data/lib/garcon/inflections/defaults.rb +79 -0
  68. data/lib/garcon/inflections/inflections.rb +182 -0
  69. data/lib/garcon/inflections/rules_collection.rb +37 -0
  70. data/lib/garcon/secret.rb +271 -0
  71. data/lib/garcon/stash/format.rb +114 -0
  72. data/lib/garcon/stash/journal.rb +226 -0
  73. data/lib/garcon/stash/queue.rb +83 -0
  74. data/lib/garcon/stash/serializer.rb +86 -0
  75. data/lib/garcon/stash/store.rb +435 -0
  76. data/lib/garcon/task.rb +31 -0
  77. data/lib/garcon/task/atomic.rb +151 -0
  78. data/lib/garcon/task/atomic_boolean.rb +127 -0
  79. data/lib/garcon/task/condition.rb +99 -0
  80. data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
  81. data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
  82. data/lib/garcon/task/count_down_latch.rb +92 -0
  83. data/lib/garcon/task/delay.rb +196 -0
  84. data/lib/garcon/task/dereferenceable.rb +144 -0
  85. data/lib/garcon/task/event.rb +119 -0
  86. data/lib/garcon/task/executor.rb +275 -0
  87. data/lib/garcon/task/executor_options.rb +59 -0
  88. data/lib/garcon/task/future.rb +107 -0
  89. data/lib/garcon/task/immediate_executor.rb +84 -0
  90. data/lib/garcon/task/ivar.rb +171 -0
  91. data/lib/garcon/task/lazy_reference.rb +74 -0
  92. data/lib/garcon/task/monotonic_time.rb +69 -0
  93. data/lib/garcon/task/obligation.rb +256 -0
  94. data/lib/garcon/task/observable.rb +101 -0
  95. data/lib/garcon/task/priority_queue.rb +234 -0
  96. data/lib/garcon/task/processor_count.rb +128 -0
  97. data/lib/garcon/task/read_write_lock.rb +304 -0
  98. data/lib/garcon/task/safe_task_executor.rb +58 -0
  99. data/lib/garcon/task/single_thread_executor.rb +97 -0
  100. data/lib/garcon/task/thread_pool/cached.rb +71 -0
  101. data/lib/garcon/task/thread_pool/executor.rb +294 -0
  102. data/lib/garcon/task/thread_pool/fixed.rb +61 -0
  103. data/lib/garcon/task/thread_pool/worker.rb +90 -0
  104. data/lib/garcon/task/timer.rb +44 -0
  105. data/lib/garcon/task/timer_set.rb +194 -0
  106. data/lib/garcon/task/timer_task.rb +377 -0
  107. data/lib/garcon/task/waitable_list.rb +58 -0
  108. data/lib/garcon/utility/ansi.rb +199 -0
  109. data/lib/garcon/utility/at_random.rb +77 -0
  110. data/lib/garcon/utility/crypto.rb +292 -0
  111. data/lib/garcon/utility/equalizer.rb +146 -0
  112. data/lib/garcon/utility/faker/extensions/array.rb +22 -0
  113. data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
  114. data/lib/garcon/utility/faker/faker.rb +164 -0
  115. data/lib/garcon/utility/faker/faker/company.rb +17 -0
  116. data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
  117. data/lib/garcon/utility/faker/faker/version.rb +3 -0
  118. data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
  119. data/lib/garcon/utility/faker/locales/en.yml +21 -0
  120. data/lib/garcon/utility/file_helper.rb +170 -0
  121. data/lib/garcon/utility/hookers.rb +178 -0
  122. data/lib/garcon/utility/interpolation.rb +90 -0
  123. data/lib/garcon/utility/memstash.rb +364 -0
  124. data/lib/garcon/utility/misc.rb +54 -0
  125. data/lib/garcon/utility/msg_from_god.rb +62 -0
  126. data/lib/garcon/utility/retry.rb +238 -0
  127. data/lib/garcon/utility/timeout.rb +58 -0
  128. data/lib/garcon/utility/uber/builder.rb +91 -0
  129. data/lib/garcon/utility/uber/callable.rb +7 -0
  130. data/lib/garcon/utility/uber/delegates.rb +13 -0
  131. data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
  132. data/lib/garcon/utility/uber/options.rb +101 -0
  133. data/lib/garcon/utility/uber/uber_version.rb +3 -0
  134. data/lib/garcon/utility/uber/version.rb +33 -0
  135. data/lib/garcon/utility/url_helper.rb +100 -0
  136. data/lib/garcon/utils.rb +29 -0
  137. data/lib/garcon/version.rb +62 -0
  138. data/lib/garcun.rb +24 -0
  139. metadata +680 -0
@@ -0,0 +1,256 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require 'thread'
21
+ require 'timeout'
22
+ require_relative 'dereferenceable'
23
+ require_relative 'event'
24
+
25
+ module Garcon
26
+
27
+ module Obligation
28
+ include Dereferenceable
29
+
30
+ # Has the obligation been fulfilled?
31
+ #
32
+ # @return [Boolean]
33
+ #
34
+ def fulfilled?
35
+ state == :fulfilled
36
+ end
37
+ alias_method :realized?, :fulfilled?
38
+
39
+ # Has the obligation been rejected?
40
+ #
41
+ # @return [Boolean]
42
+ #
43
+ def rejected?
44
+ state == :rejected
45
+ end
46
+
47
+ # Is obligation completion still pending?
48
+ #
49
+ # @return [Boolean]
50
+ #
51
+ def pending?
52
+ state == :pending
53
+ end
54
+
55
+ # Is the obligation still unscheduled?
56
+ #
57
+ # @return [Boolean]
58
+ #
59
+ def unscheduled?
60
+ state == :unscheduled
61
+ end
62
+
63
+ # Has the obligation completed processing?
64
+ #
65
+ # @return [Boolean]
66
+ #
67
+ def complete?
68
+ [:fulfilled, :rejected].include? state
69
+ end
70
+
71
+ # Is the obligation still awaiting completion of processing?
72
+ #
73
+ # @return [Boolean]
74
+ #
75
+ def incomplete?
76
+ [:unscheduled, :pending].include? state
77
+ end
78
+
79
+ # The current value of the obligation. Will be `nil` while the state is
80
+ # pending or the operation has been rejected.
81
+ #
82
+ # @param [Numeric]
83
+ # Timeout the maximum time in seconds to wait.
84
+ #
85
+ # @return [Object]
86
+ # see Dereferenceable#deref
87
+ #
88
+ def value(timeout = nil)
89
+ wait timeout
90
+ deref
91
+ end
92
+
93
+ # Wait until obligation is complete or the timeout has been reached.
94
+ #
95
+ # @param [Numeric]
96
+ # Timeout the maximum time in seconds to wait.
97
+ #
98
+ # @return [Obligation] self
99
+ #
100
+ def wait(timeout = nil)
101
+ event.wait(timeout) if timeout != 0 && incomplete?
102
+ self
103
+ end
104
+
105
+ # Wait until obligation is complete or the timeout is reached. Will re-raise
106
+ # any exceptions raised during processing (but will not raise an exception
107
+ # on timeout).
108
+ #
109
+ # @param [Numeric] timeout
110
+ # The maximum time in second to wait.
111
+ #
112
+ # @raise [Exception]
113
+ # Raises the reason when rejected`
114
+ #
115
+ # @return [Obligation] self
116
+ #
117
+ def wait!(timeout = nil)
118
+ wait(timeout).tap { raise self if rejected? }
119
+ end
120
+ alias_method :no_error!, :wait!
121
+
122
+ # The current value of the obligation. Will be `nil` while the state is
123
+ # pending or the operation has been rejected. Will re-raise any exceptions
124
+ # raised during processing (but will not raise an exception on timeout).
125
+ #
126
+ # @param [Numeric]
127
+ # Timeout the maximum time in seconds to wait.
128
+ #
129
+ # @raise [Exception]
130
+ # Raises the reason when rejected.
131
+ #
132
+ # @return [Object]
133
+ # see Dereferenceable#deref
134
+ #
135
+ def value!(timeout = nil)
136
+ wait(timeout)
137
+ if rejected?
138
+ raise self
139
+ else
140
+ deref
141
+ end
142
+ end
143
+
144
+ # The current state of the obligation.
145
+ #
146
+ # @return [Symbol]
147
+ # The current state.
148
+ #
149
+ def state
150
+ mutex.lock
151
+ @state
152
+ ensure
153
+ mutex.unlock
154
+ end
155
+
156
+ # If an exception was raised during processing this will return the
157
+ # exception object. Will return `nil` when the state is pending or if
158
+ # the obligation has been successfully fulfilled.
159
+ #
160
+ # @return [Exception]
161
+ # The exception raised during processing or `nil`
162
+ #
163
+ def reason
164
+ mutex.lock
165
+ @reason
166
+ ensure
167
+ mutex.unlock
168
+ end
169
+
170
+ # @example allows Obligation to be risen
171
+ # rejected_ivar = Ivar.new.fail
172
+ # raise rejected_ivar
173
+ def exception(*args)
174
+ raise 'obligation is not rejected' unless rejected?
175
+ reason.exception(*args)
176
+ end
177
+
178
+ protected # A T T E N Z I O N E A R E A P R O T E T T A
179
+
180
+ # @!visibility private
181
+ def get_arguments_from(opts = {})
182
+ [*opts.fetch(:args, [])]
183
+ end
184
+
185
+ # @!visibility private
186
+ def init_obligation
187
+ init_mutex
188
+ @event = Event.new
189
+ end
190
+
191
+ # @!visibility private
192
+ def event
193
+ @event
194
+ end
195
+
196
+ # @!visibility private
197
+ def set_state(success, value, reason)
198
+ if success
199
+ @value = value
200
+ @state = :fulfilled
201
+ else
202
+ @reason = reason
203
+ @state = :rejected
204
+ end
205
+ end
206
+
207
+ # @!visibility private
208
+ def state=(value)
209
+ mutex.lock
210
+ @state = value
211
+ ensure
212
+ mutex.unlock
213
+ end
214
+
215
+ # Atomic compare and set operation. State is set to `next_state` only if
216
+ # `current state == expected_current`.
217
+ #
218
+ # @param [Symbol] next_state
219
+ # @param [Symbol] expected_current
220
+ #
221
+ # @return [Boolean]
222
+ # TRrue is state is changed, false otherwise
223
+ #
224
+ # @!visibility private
225
+ def compare_and_set_state(next_state, expected_current) # :nodoc:
226
+ mutex.lock
227
+ if @state == expected_current
228
+ @state = next_state
229
+ true
230
+ else
231
+ false
232
+ end
233
+ ensure
234
+ mutex.unlock
235
+ end
236
+
237
+ # executes the block within mutex if current state is included in
238
+ # expected_states
239
+ #
240
+ # @return block value if executed, false otherwise
241
+ #
242
+ # @!visibility private
243
+ def if_state(*expected_states)
244
+ mutex.lock
245
+ raise ArgumentError, 'no block given' unless block_given?
246
+
247
+ if expected_states.include? @state
248
+ yield
249
+ else
250
+ false
251
+ end
252
+ ensure
253
+ mutex.unlock
254
+ end
255
+ end
256
+ end
@@ -0,0 +1,101 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ require_relative 'copy_on_notify_observer_set'
21
+ require_relative 'copy_on_write_observer_set'
22
+
23
+ module Garcon
24
+
25
+ # The [observer pattern] is one of the most useful design patterns.
26
+ #
27
+ # The workflow is very simple:
28
+ # - an `observer` can register itself to a `subject` via a callback
29
+ # - many `observers` can be registered to the same `subject`
30
+ # - the `subject` notifies all registered observers when its status changes
31
+ # - an `observer` can deregister itself when is no more interested to receive
32
+ # event notifications
33
+ #
34
+ # In a single threaded environment the whole pattern is very easy: the
35
+ # `subject` can use a simple data structure to manage all its subscribed
36
+ # `observer`s and every `observer` can react directly to every event without
37
+ # caring about synchronization.
38
+ #
39
+ # In a multi threaded environment things are more complex. The `subject` must
40
+ # synchronize the access to its data structure and to do so currently we're
41
+ # using two specialized ObserverSet: CopyOnWriteObserverSet and
42
+ # CopyOnNotifyObserverSet.
43
+ #
44
+ # When implementing and `observer` there's a very important rule to remember:
45
+ # **there are no guarantees about the thread that will execute the callback**
46
+ #
47
+ # Let's take this example
48
+ # ```
49
+ # class Observer
50
+ # def initialize
51
+ # @count = 0
52
+ # end
53
+ #
54
+ # def update
55
+ # @count += 1
56
+ # end
57
+ # end
58
+ #
59
+ # obs = Observer.new
60
+ # [obj1, obj2, obj3, obj4].each { |o| o.add_observer(obs) }
61
+ # # execute [obj1, obj2, obj3, obj4]
62
+ # ```
63
+ #
64
+ # `obs` is wrong because the variable `@count` can be accessed by different
65
+ # threads at the same time, so it should be synchronized (using either a Mutex
66
+ # or an AtomicFixum)
67
+ module Observable
68
+
69
+ # @return [Object] the added observer
70
+ def add_observer(*args, &block)
71
+ observers.add_observer(*args, &block)
72
+ end
73
+
74
+ # as #add_observer but it can be used for chaining
75
+ # @return [Observable] self
76
+ def with_observer(*args, &block)
77
+ add_observer(*args, &block)
78
+ self
79
+ end
80
+
81
+ # @return [Object] the deleted observer
82
+ def delete_observer(*args)
83
+ observers.delete_observer(*args)
84
+ end
85
+
86
+ # @return [Observable] self
87
+ def delete_observers
88
+ observers.delete_observers
89
+ self
90
+ end
91
+
92
+ # @return [Integer] the observers count
93
+ def count_observers
94
+ observers.count_observers
95
+ end
96
+
97
+ protected # A T T E N Z I O N E A R E A P R O T E T T A
98
+
99
+ attr_accessor :observers
100
+ end
101
+ end
@@ -0,0 +1,234 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ module Garcon
21
+
22
+ # A queue collection in which the elements are sorted based on their
23
+ # comparison (spaceship) operator `<=>`. Items are added to the queue at a
24
+ # position relative to their priority. On removal the element with the
25
+ # "highest" priority is removed. By default the sort order is from highest to
26
+ # lowest, but a lowest-to-highest sort order can be set on construction.
27
+ #
28
+ # The API is based on the `Queue` class from the Ruby standard library.
29
+ #
30
+ class MutexPriorityQueue
31
+
32
+ # Create a new priority queue with no items.
33
+ #
34
+ # @param [Hash] opts
35
+ # The options for creating the queue.
36
+ #
37
+ # @option opts [Symbol] :order (:max)
38
+ # dictates the order in which items are stored: from highest to lowest
39
+ # when `:max` or `:high`; from lowest to highest when `:min` or `:low`
40
+ #
41
+ def initialize(opts = {})
42
+ order = opts.fetch(:order, :max)
43
+ @comparator = [:min, :low].include?(order) ? -1 : 1
44
+ clear
45
+ end
46
+
47
+ # Removes all of the elements from this priority queue.
48
+ #
49
+ def clear
50
+ @queue = [nil]
51
+ @length = 0
52
+ true
53
+ end
54
+
55
+ # Deletes all items from `self` that are equal to `item`.
56
+ #
57
+ # @param [Object] item
58
+ # The item to be removed from the queue.
59
+ #
60
+ # @return [Object]
61
+ # True if the item is found else false.
62
+ #
63
+ def delete(item)
64
+ original_length = @length
65
+ k = 1
66
+ while k <= @length
67
+ if @queue[k] == item
68
+ swap(k, @length)
69
+ @length -= 1
70
+ sink(k)
71
+ @queue.pop
72
+ else
73
+ k += 1
74
+ end
75
+ end
76
+ @length != original_length
77
+ end
78
+
79
+ # Returns `true` if `self` contains no elements.
80
+ #
81
+ # @return [Boolean]
82
+ # True if there are no items in the queue else false.
83
+ #
84
+ def empty?
85
+ size == 0
86
+ end
87
+
88
+ # Returns `true` if the given item is present in `self` (that is, if any
89
+ # element == `item`), otherwise returns false.
90
+ #
91
+ # @param [Object] item
92
+ # The item to search for
93
+ #
94
+ # @return [Boolean]
95
+ # True if the item is found else false.
96
+ #
97
+ def include?(item)
98
+ @queue.include?(item)
99
+ end
100
+ alias_method :has_priority?, :include?
101
+
102
+ # The current length of the queue.
103
+ #
104
+ # @return [Fixnum]
105
+ # The number of items in the queue.
106
+ #
107
+ def length
108
+ @length
109
+ end
110
+ alias_method :size, :length
111
+
112
+ # Retrieves, but does not remove, the head of this queue, or returns `nil`
113
+ # if this queue is empty.
114
+ #
115
+ # @return [Object]
116
+ # The head of the queue or `nil` when empty.
117
+ #
118
+ def peek
119
+ @queue[1]
120
+ end
121
+
122
+ # Retrieves and removes the head of this queue, or returns `nil` if this
123
+ # queue is empty.
124
+ #
125
+ # @return [Object]
126
+ # The head of the queue or `nil` when empty.
127
+ #
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
+ # Inserts the specified element into this priority queue.
140
+ #
141
+ # @param [Object]
142
+ # Item the item to insert onto the queue.
143
+ #
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
+ # Create a new priority queue from the given list.
154
+ #
155
+ # @param [Enumerable] list
156
+ # The list to build the queue from.
157
+ #
158
+ # @param [Hash] opts
159
+ # The options for creating the queue.
160
+ #
161
+ # @return [PriorityQueue]
162
+ # The newly created and populated queue.
163
+ #
164
+ def self.from_list(list, opts = {})
165
+ queue = new(opts)
166
+ list.each { |item| queue << item }
167
+ queue
168
+ end
169
+
170
+ protected # A T T E N Z I O N E A R E A P R O T E T T A
171
+
172
+ # Exchange the values at the given indexes within the internal array.
173
+ #
174
+ # @param [Integer] x
175
+ # The first index to swap.
176
+ #
177
+ # @param [Integer] y
178
+ # The second index to swap.
179
+ #
180
+ # @!visibility private
181
+ def swap(x, y)
182
+ temp = @queue[x]
183
+ @queue[x] = @queue[y]
184
+ @queue[y] = temp
185
+ end
186
+
187
+ # Are the items at the given indexes ordered based on the priority
188
+ # order specified at construction?
189
+ #
190
+ # @param [Integer] x
191
+ # The first index from which to retrieve a comparable value.
192
+ #
193
+ # @param [Integer] y
194
+ # The second index from which to retrieve a comparable value.
195
+ #
196
+ # @return [Boolean]
197
+ # True if the two elements are in the correct priority order else false.
198
+ #
199
+ # @!visibility private
200
+ def ordered?(x, y)
201
+ (@queue[x] <=> @queue[y]) == @comparator
202
+ end
203
+
204
+ # Percolate down to maintain heap invariant.
205
+ #
206
+ # @param [Integer] k
207
+ # The index at which to start the percolation.
208
+ #
209
+ # @!visibility private
210
+ def sink(k)
211
+ while (j = (2 * k)) <= @length do
212
+ j += 1 if j < @length && ! ordered?(j, j+1)
213
+ break if ordered?(k, j)
214
+ swap(k, j)
215
+ k = j
216
+ end
217
+ end
218
+
219
+ # Percolate up to maintain heap invariant.
220
+ #
221
+ # @param [Integer] k
222
+ # The index at which to start the percolation.
223
+ #
224
+ # @!visibility private
225
+ def swim(k)
226
+ while k > 1 && ! ordered?(k/2, k) do
227
+ swap(k, k/2)
228
+ k = k/2
229
+ end
230
+ end
231
+ end
232
+
233
+ class PriorityQueue < MutexPriorityQueue; end
234
+ end