async-pool 0.3.3 → 0.3.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 91d47d29e5bb2e6a93668145c06b432ee26393019cb253d284ffb48cf2c8285b
4
- data.tar.gz: 3b3d98e86aec3e783fa5ed98eb803d0f8efe382c0f4b32d518779c09ca736c2d
3
+ metadata.gz: 53496ca8f02b057c94d8cef37e92f7d14bb3d7062267ea53f363d5ca3c2ee7d4
4
+ data.tar.gz: b59bb3a498bb16b1306eea4b6bcb765efa60a479701f546a3c2b6785ff5203e1
5
5
  SHA512:
6
- metadata.gz: 34260d06050fe9829ddd40c2a29444548707661262e34df4bd956f3f1a37dd34ab7f6a59cb78ae1acc7388951ec3777b52beff1fa8e2bf6426ad46214e724d21
7
- data.tar.gz: f82218caa4733fec59c17ef9aff190e1617aee3049a16629ecfbc15b0c7e6618f1176f9f2bb26e2e67db0388b5f5dc7f164add84efd09f9e49c0776bb36a690d
6
+ metadata.gz: f53063512c044675725eed75b72346644a36c99704bf2f1559692420f7176b88063cb79200d4a24f19f8cd081be224e307a811d91dc8a94923cccb87cf850cc4
7
+ data.tar.gz: 366355082c92722989dd76607f611fd81f520844b8733e15872db4164a146bc2e257e40f316bc87c173a49b65d465e07cccdf459fea242b9c8445841c13f7580
@@ -32,9 +32,13 @@ module Async
32
32
  end
33
33
 
34
34
  def initialize(constructor, limit: nil)
35
+ # All available resources:
35
36
  @resources = {}
36
37
 
38
+ # Resources which may be available to be acquired:
39
+ # This list may contain false positives, or resources which were okay but have since entered a state which is unusuable.
37
40
  @available = []
41
+
38
42
  @notification = Async::Notification.new
39
43
 
40
44
  @limit = limit
@@ -45,7 +49,7 @@ module Async
45
49
  @gardener = nil
46
50
  end
47
51
 
48
- # @attr [Hash<Resource, Integer>] all allocated resources, and their associated usage.
52
+ # @attribute [Hash(Resource, Integer)] all allocated resources, and their associated usage.
49
53
  attr :resources
50
54
 
51
55
  def size
@@ -66,6 +70,11 @@ module Async
66
70
  return false
67
71
  end
68
72
 
73
+ # Whether there are available resources, i.e. whether {#acquire} can reuse an existing resource.
74
+ def available?
75
+ @available.any?
76
+ end
77
+
69
78
  # Wait until a pool resource has been freed.
70
79
  def wait
71
80
  @notification.wait
@@ -119,7 +128,9 @@ module Async
119
128
  unused = []
120
129
 
121
130
  @resources.each do |resource, usage|
122
- unused << resource if usage.zero?
131
+ if usage.zero?
132
+ unused << resource
133
+ end
123
134
  end
124
135
 
125
136
  unused.each do |resource|
@@ -132,6 +143,14 @@ module Async
132
143
  break if @resources.size <= retain
133
144
  end
134
145
 
146
+ # Update availability list:
147
+ @available.clear
148
+ @resources.each do |resource, usage|
149
+ if usage < resource.concurrency and resource.reusable?
150
+ @available << resource
151
+ end
152
+ end
153
+
135
154
  return unused.size
136
155
  end
137
156
 
@@ -170,11 +189,42 @@ module Async
170
189
  end.join(";")
171
190
  end
172
191
 
192
+ def usage
193
+ @resources.count{|resource, usage| usage > 0}
194
+ end
195
+
196
+ def free
197
+ @resources.count{|resource, usage| usage == 0}
198
+ end
199
+
200
+ # @returns [Boolean] Whether the number of available resources is excessive and we should retire some.
201
+ def overflowing?
202
+ if @resources.any?
203
+ (self.free.to_f / @resources.size) > 0.5
204
+ end
205
+ end
206
+
173
207
  def reuse(resource)
174
208
  Async.logger.debug(self) {"Reuse #{resource}"}
209
+ usage = @resources[resource]
210
+
211
+ if usage.zero?
212
+ raise "Trying to reuse unacquired resource: #{resource}!"
213
+ end
214
+
215
+ # We retire resources when adding to the @available list would overflow our pool:
216
+ if usage == 1
217
+ if overflowing?
218
+ return retire(resource)
219
+ end
220
+ end
221
+
222
+ # If the resource was fully utilized, it now becomes available:
223
+ if usage == resource.concurrency
224
+ @available.push(resource)
225
+ end
175
226
 
176
- @resources[resource] -= 1
177
- @available.push(resource)
227
+ @resources[resource] = usage - 1
178
228
 
179
229
  @notification.signal
180
230
  end
@@ -194,6 +244,7 @@ module Async
194
244
  return resource
195
245
  end
196
246
 
247
+ # @returns [Object] A new resource in a "used" state.
197
248
  def create_resource
198
249
  self.start_gardener
199
250
 
@@ -201,18 +252,27 @@ module Async
201
252
  if resource = @constructor.call
202
253
  @resources[resource] = 1
203
254
 
204
- @available.push(resource) if resource.concurrency > 1
255
+ # Make the resource available if it can be used multiple times:
256
+ if resource.concurrency > 1
257
+ @available.push(resource)
258
+ end
205
259
  end
206
260
 
207
261
  return resource
208
262
  end
209
263
 
264
+ # @returns [Object] An existing resource in a "used" state.
210
265
  def available_resource
211
266
  @guard.acquire do
212
267
  while resource = @available.last
213
268
  if usage = @resources[resource] and usage < resource.concurrency
214
269
  if resource.viable?
215
- @resources[resource] += 1
270
+ usage = (@resources[resource] += 1)
271
+
272
+ if usage == resource.concurrency
273
+ # The resource is used up to it's limit:
274
+ @available.pop
275
+ end
216
276
 
217
277
  return resource
218
278
  else
@@ -220,6 +280,7 @@ module Async
220
280
  @available.pop
221
281
  end
222
282
  else
283
+ # The resource has been removed already, so skip it and remove it from the availability list.
223
284
  @available.pop
224
285
  end
225
286
  end
@@ -20,6 +20,6 @@
20
20
 
21
21
  module Async
22
22
  module Pool
23
- VERSION = "0.3.3"
23
+ VERSION = "0.3.4"
24
24
  end
25
25
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async-pool
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-11-15 00:00:00.000000000 Z
11
+ date: 2021-02-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: async