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,97 @@
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 'executor'
21
+
22
+ module Garcon
23
+
24
+ class RubySingleThreadExecutor
25
+ include RubyExecutor
26
+ include SerialExecutor
27
+
28
+ # Create a new thread pool.
29
+ #
30
+ # @option opts [Symbol] :fallback_policy (:discard)
31
+ # The policy for handling new tasks that are received when the queue size
32
+ # has reached `max_queue` or after the executor has shut down.
33
+ #
34
+ def initialize(opts = {})
35
+ @queue = Queue.new
36
+ @thread = nil
37
+ @fallback_policy = opts.fetch(:fallback_policy, :discard)
38
+ if !FALLBACK_POLICY.include?(fallback)
39
+ raise ArgumentError, "#{fallback} is not a valid fallback policy"
40
+ end
41
+ init_executor
42
+ enable_at_exit_handler!(opts)
43
+ end
44
+
45
+ protected # A T T E N Z I O N E A R E A P R O T E T T A
46
+
47
+ # @!visibility private
48
+ def execute(*args, &task)
49
+ supervise
50
+ @queue << [args, task]
51
+ end
52
+
53
+ # @!visibility private
54
+ def shutdown_execution
55
+ @queue << :stop
56
+ stopped_event.set unless alive?
57
+ end
58
+
59
+ # @!visibility private
60
+ def kill_execution
61
+ @queue.clear
62
+ @thread.kill if alive?
63
+ end
64
+
65
+ # @!visibility private
66
+ def alive?
67
+ @thread && @thread.alive?
68
+ end
69
+
70
+ # @!visibility private
71
+ def supervise
72
+ @thread = new_worker_thread unless alive?
73
+ end
74
+
75
+ # @!visibility private
76
+ def new_worker_thread
77
+ Thread.new do
78
+ Thread.current.abort_on_exception = false
79
+ work
80
+ end
81
+ end
82
+
83
+ # @!visibility private
84
+ def work
85
+ loop do
86
+ task = @queue.pop
87
+ break if task == :stop
88
+ begin
89
+ task.last.call(*task.first)
90
+ rescue => e
91
+ Chef::Log.debug "Caught exception => #{e}"
92
+ end
93
+ end
94
+ stopped_event.set
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,71 @@
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 'executor'
21
+
22
+ module Garcon
23
+
24
+ # A thread pool that dynamically grows and shrinks to fit the current
25
+ # workload. New threads are created as needed, existing threads are reused,
26
+ # and threads that remain idle for too long are killed and removed from the
27
+ # pool. These pools are particularly suited to applications that perform a
28
+ # high volume of short-lived tasks.
29
+ #
30
+ # On creation a `CachedThreadPool` has zero running threads. New threads are
31
+ # created on the pool as new operations are `#post`. The size of the pool
32
+ # will grow until `#max_length` threads are in the pool or until the number
33
+ # of threads exceeds the number of running and pending operations. When a new
34
+ # operation is post to the pool the first available idle thread will be
35
+ # tasked with the new operation.
36
+ #
37
+ # Should a thread crash for any reason the thread will immediately be removed
38
+ # from the pool. Similarly, threads which remain idle for an extended period
39
+ # of time will be killed and reclaimed. Thus these thread pools are very
40
+ # efficient at reclaiming unused resources.
41
+ #
42
+ class CachedThreadPool < ThreadPoolExecutor
43
+ # Create a new thread pool.
44
+ #
45
+ # @param [Hash] opts
46
+ # The options defining pool behavior.
47
+ #
48
+ # @raise [ArgumentError] if `fallback` is not a known policy
49
+ #
50
+ # @option opts [Symbol] :fallback (`:abort`)
51
+ # The fallback policy
52
+ #
53
+ # @api public
54
+ def initialize(opts = {})
55
+ fallback = opts.fetch(:fallback, :abort)
56
+
57
+ unless FALLBACK_POLICY.include?(fallback)
58
+ raise ArgumentError, "#{fallback} is not a valid fallback policy"
59
+ end
60
+
61
+ opts = opts.merge(
62
+ min_threads: 0,
63
+ max_threads: DEFAULT_MAX_POOL_SIZE,
64
+ fallback: fallback,
65
+ max_queue: DEFAULT_MAX_QUEUE_SIZE,
66
+ idletime: DEFAULT_THREAD_IDLETIMEOUT)
67
+
68
+ super(opts)
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,294 @@
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_relative 'worker'
22
+ require_relative '../event'
23
+ require_relative '../executor'
24
+ require_relative '../monotonic_time'
25
+
26
+ module Garcon
27
+
28
+ class ThreadPoolExecutor
29
+ include RubyExecutor
30
+
31
+ # Default maximum number of threads that will be created in the pool.
32
+ DEFAULT_MAX_POOL_SIZE = 2**15 # 32768
33
+
34
+ # Default minimum number of threads that will be retained in the pool.
35
+ DEFAULT_MIN_POOL_SIZE = 0
36
+
37
+ # Default maximum number of tasks that may be added to the task queue.
38
+ DEFAULT_MAX_QUEUE_SIZE = 0
39
+
40
+ # Default maximum number of seconds a thread in the pool may remain idle
41
+ # before being reclaimed.
42
+ DEFAULT_THREAD_IDLETIMEOUT = 60
43
+
44
+ # The maximum number of threads that may be created in the pool.
45
+ attr_reader :max_length
46
+
47
+ # The minimum number of threads that may be retained in the pool.
48
+ attr_reader :min_length
49
+
50
+ # The largest number of threads that have been created in the pool since
51
+ # construction.
52
+ attr_reader :largest_length
53
+
54
+ # The number of tasks that have been scheduled for execution on the pool
55
+ # since construction.
56
+ attr_reader :scheduled_task_count
57
+
58
+ # The number of tasks that have been completed by the pool since
59
+ # construction.
60
+ attr_reader :completed_task_count
61
+
62
+ # The number of seconds that a thread may be idle before being reclaimed.
63
+ attr_reader :idletime
64
+
65
+ # The maximum number of tasks that may be waiting in the work queue at any
66
+ # one time. When the queue size reaches `max_queue` subsequent tasks will be
67
+ # rejected in accordance with the configured `fallback`.
68
+ attr_reader :max_queue
69
+
70
+ # Create a new thread pool.
71
+ #
72
+ # @param [Hash] opts
73
+ # The options which configure the thread pool.
74
+ #
75
+ # @option opts [Integer] :max_threads (DEFAULT_MAX_POOL_SIZE)
76
+ # The maximum number of threads to be created.
77
+ #
78
+ # @option opts [Integer] :min_threads (DEFAULT_MIN_POOL_SIZE)
79
+ # The minimum number of threads to be retained.
80
+ #
81
+ # @option opts [Integer] :idletime (DEFAULT_THREAD_IDLETIMEOUT)
82
+ # Maximum number of seconds a thread may be idle before being reclaimed.
83
+ #
84
+ # @option opts [Integer] :max_queue (DEFAULT_MAX_QUEUE_SIZE)
85
+ # The maximum number of tasks allowed in the work queue at any one time;
86
+ # a value of zero means the queue may grow without bound.
87
+ #
88
+ # @option opts [Symbol] :fallback (:abort)
89
+ # The policy for handling new tasks that are received when the queue size
90
+ # has reached `max_queue` or the executor has shut down.
91
+ #
92
+ # @raise [ArgumentError] if `:max_threads` is less than one
93
+ #
94
+ # @raise [ArgumentError] if `:min_threads` is less than zero
95
+ #
96
+ # @raise [ArgumentError] if `:fallback` is not one of the values specified
97
+ # in `FALLBACK_POLICY`
98
+ #
99
+ def initialize(opts = {})
100
+ @min_length = opts.fetch(:min_threads, DEFAULT_MIN_POOL_SIZE).to_i
101
+ @max_length = opts.fetch(:max_threads, DEFAULT_MAX_POOL_SIZE).to_i
102
+ @idletime = opts.fetch(:idletime, DEFAULT_THREAD_IDLETIMEOUT).to_i
103
+ @max_queue = opts.fetch(:max_queue, DEFAULT_MAX_QUEUE_SIZE).to_i
104
+ @fallback = opts.fetch(:fallback, :abort)
105
+
106
+ if @max_length <= 0
107
+ raise ArgumentError, 'max_threads must be greater than zero'
108
+ elsif @min_length < 0
109
+ raise ArgumentError, 'min_threads cannot be less than zero'
110
+ elsif min_length > max_length
111
+ raise ArgumentError, 'min_threads cannot be more than max_threads'
112
+ elsif !FALLBACK_POLICY.include?(@fallback)
113
+ raise ArgumentError, "#{fallback} is not a valid fallback policy"
114
+ end
115
+
116
+ init_executor
117
+ enable_at_exit_handler!(opts)
118
+
119
+ @pool = []
120
+ @queue = Queue.new
121
+ @scheduled_task_count = 0
122
+ @completed_task_count = 0
123
+ @largest_length = 0
124
+
125
+ @gc_interval = opts.fetch(:gc_interval, 1).to_i
126
+ @last_gc_time = Garcon.monotonic_time - [1.0, (@gc_interval * 2.0)].max
127
+ end
128
+
129
+ # @!macro executor_module_method_can_overflow_question
130
+ def can_overflow?
131
+ @max_queue != 0
132
+ end
133
+
134
+ # The number of threads currently in the pool.
135
+ #
136
+ # @return [Integer] the length
137
+ def length
138
+ mutex.synchronize { running? ? @pool.length : 0 }
139
+ end
140
+
141
+ alias_method :current_length, :length
142
+
143
+ # The number of tasks in the queue awaiting execution.
144
+ #
145
+ # @return [Integer] the queue_length
146
+ def queue_length
147
+ mutex.synchronize { running? ? @queue.length : 666 }
148
+ end
149
+
150
+ # Returns an array with the status of each thread in the pool
151
+ #
152
+ def status
153
+ mutex.synchronize { @pool.collect { |worker| worker.status } }
154
+ end
155
+
156
+ # Number of tasks that may be enqueued before reaching `max_queue` and
157
+ # rejecting new tasks. A value of -1 indicates that the queue may grow
158
+ # without bound.
159
+ #
160
+ # @return [Integer] the remaining_capacity
161
+ def remaining_capacity
162
+ mutex.synchronize { @max_queue == 0 ? -1 : @max_queue - @queue.length }
163
+ end
164
+
165
+ # Run on task completion.
166
+ #
167
+ # @!visibility private
168
+ def on_end_task
169
+ mutex.synchronize do
170
+ @completed_task_count += 1 #if success
171
+ break unless running?
172
+ end
173
+ end
174
+
175
+ # Run when a thread worker exits.
176
+ #
177
+ # @!visibility private
178
+ def on_worker_exit(worker)
179
+ mutex.synchronize do
180
+ @pool.delete(worker)
181
+ if @pool.empty? && !running?
182
+ stop_event.set
183
+ stopped_event.set
184
+ end
185
+ end
186
+ end
187
+
188
+ protected # A T T E N Z I O N E A R E A P R O T E T T A
189
+
190
+ # @!visibility private
191
+ def execute(*args, &task)
192
+ if ensure_capacity?
193
+ @scheduled_task_count += 1
194
+ @queue << [args, task]
195
+ else
196
+ if @max_queue != 0 && @queue.length >= @max_queue
197
+ handle_fallback(*args, &task)
198
+ end
199
+ end
200
+ prune_pool
201
+ end
202
+
203
+ # @!visibility private
204
+ def shutdown_execution
205
+ if @pool.empty?
206
+ stopped_event.set
207
+ else
208
+ @pool.length.times { @queue << :stop }
209
+ end
210
+ end
211
+
212
+ # @!visibility private
213
+ def kill_execution
214
+ @queue.clear
215
+ drain_pool
216
+ end
217
+
218
+ # Check the thread pool configuration and determine if the pool
219
+ # has enought capacity to handle the request. Will grow the size
220
+ # of the pool if necessary.
221
+ #
222
+ # @return [Boolean] true if the pool has enough capacity else false
223
+ #
224
+ # @!visibility private
225
+ def ensure_capacity?
226
+ additional = 0
227
+ capacity = true
228
+
229
+ if @pool.size < @min_length
230
+ additional = @min_length - @pool.size
231
+ elsif @queue.empty? && @queue.num_waiting >= 1
232
+ additional = 0
233
+ elsif @pool.size == 0 && @min_length == 0
234
+ additional = 1
235
+ elsif @pool.size < @max_length || @max_length == 0
236
+ additional = 1
237
+ elsif @max_queue == 0 || @queue.size < @max_queue
238
+ additional = 0
239
+ else
240
+ capacity = false
241
+ end
242
+
243
+ additional.times do
244
+ @pool << create_worker_thread
245
+ end
246
+
247
+ if additional > 0
248
+ @largest_length = [@largest_length, @pool.length].max
249
+ end
250
+
251
+ capacity
252
+ end
253
+
254
+ # Scan all threads in the pool and reclaim any that are dead or
255
+ # have been idle too long. Will check the last time the pool was
256
+ # pruned and only run if the configured garbage collection
257
+ # interval has passed.
258
+ #
259
+ # @!visibility private
260
+ def prune_pool
261
+ if Garcon.monotonic_time - @gc_interval >= @last_gc_time
262
+ @pool.delete_if { |worker| worker.dead? }
263
+ # send :stop for each thread over idletime
264
+ @pool.select { |worker| @idletime != 0 &&
265
+ Garcon.monotonic_time - @idletime > worker.last_activity
266
+ }.each { @queue << :stop }
267
+ @last_gc_time = Garcon.monotonic_time
268
+ end
269
+ end
270
+
271
+ # Reclaim all threads in the pool.
272
+ #
273
+ # @!visibility private
274
+ def drain_pool
275
+ @pool.each { |worker| worker.kill }
276
+ @pool.clear
277
+ end
278
+
279
+ # Create a single worker thread to be added to the pool.
280
+ #
281
+ # @return [Thread] the new thread.
282
+ #
283
+ # @!visibility private
284
+ def create_worker_thread
285
+ wrkr = ThreadPoolWorker.new(@queue, self)
286
+ Thread.new(wrkr, self) do |worker, parent|
287
+ Thread.current.abort_on_exception = false
288
+ worker.run
289
+ parent.on_worker_exit(worker)
290
+ end
291
+ return wrkr
292
+ end
293
+ end
294
+ end