async 1.8.0 → 1.9.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8342091acbc6da153552ca269239949b27898eb7bff55ca9425687e86f314751
4
- data.tar.gz: fa8fd142667ba572fd66554d25bf9490625811f91005c9c4b0ac76f9329dba69
3
+ metadata.gz: 4525bee2a2f58fece634c89881975c3f326ecaaecf4b5495a53f93b6e99360f7
4
+ data.tar.gz: e23e0f0caa1b383f695aec88aa567bc8daa9028907427ea371579fcd5adf94f6
5
5
  SHA512:
6
- metadata.gz: f8e9d025de96cee15d9967e344a81dd01e3c3f6e64895f1deba1f2fd77edbbff2d9d7d63294cdaca6492add2112e5b0742e326c70845c52b8041b10eba96fd17
7
- data.tar.gz: 4f07e3153419bd128c53c86f63fca88dcde579d906689e9bbaff488b6f782f11d3950a1f6754894f20880aa8aa09fcde50b7608c0c47b97ef0fe9314b5d5343b
6
+ metadata.gz: fd2b49c02f4ea805cfe5a3dad3b515adac78cc0edd2190c46f41b3c48460fc5e5d7daa0d3da5803a385552af69c1e557dc43a89f6a13a71e048a1a08c61c3a64
7
+ data.tar.gz: bb875d2e36bebb80c4850cfa1c4afc938189b2ff559652085cd932659d1363ecc82529bfcedf95197a0b73984821ab49247ef093388131a125efc3e7e9706a98
@@ -18,6 +18,7 @@ matrix:
18
18
  - rvm: 2.3
19
19
  - rvm: 2.4
20
20
  - rvm: 2.5
21
+ - rvm: 2.6
21
22
  - rvm: jruby-head
22
23
  env: JRUBY_OPTS="--debug -X+O"
23
24
  - rvm: ruby-head
@@ -0,0 +1,96 @@
1
+ # Copyright, 2017, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ module Async
22
+ # A semaphore is used to control access to a common resource in a concurrent system. A useful way to think of a semaphore as used in the real-world systems is as a record of how many units of a particular resource are available, coupled with operations to adjust that record safely (i.e. to avoid race conditions) as units are required or become free, and, if necessary, wait until a unit of the resource becomes available.
23
+ class Semaphore
24
+ def initialize(limit = 1)
25
+ @count = 0
26
+ @limit = limit
27
+ @waiting = []
28
+ end
29
+
30
+ # The current number of tasks that have acquired the semaphore.
31
+ attr :count
32
+
33
+ # The maximum number of tasks that can acquire the semaphore.
34
+ attr :limit
35
+
36
+ # Whether trying to acquire this semaphore would block.
37
+ def blocking?
38
+ @count >= @limit
39
+ end
40
+
41
+ # Acquire the semaphore, block if we are at the limit.
42
+ # If no block is provided, you must call release manually.
43
+ # @yield when the semaphore can be acquired
44
+ # @return the result of the block if invoked
45
+ def acquire
46
+ self.wait while blocking?
47
+
48
+ @count += 1
49
+
50
+ return unless block_given?
51
+
52
+ begin
53
+ return yield
54
+ ensure
55
+ self.release
56
+ end
57
+ end
58
+
59
+ # Release the semaphore. Must match up with a corresponding call to `acquire`.
60
+ def release
61
+ @count -= 1
62
+
63
+ self.signal
64
+ end
65
+
66
+ # Is anyone waiting?
67
+ def empty?
68
+ @waiting.empty?
69
+ end
70
+
71
+ # Wait on this semaphore.
72
+ def wait
73
+ @waiting << Fiber.current
74
+ Task.yield
75
+ end
76
+
77
+ # Resume any waiting tasks.
78
+ def signal(task: Task.current)
79
+ task.reactor << self if @waiting.any?
80
+ end
81
+
82
+ # Whether this semaphore has work to do when being resumed.
83
+ def alive?
84
+ @waiting.any?
85
+ end
86
+
87
+ # Resume tasks waiting on the semaphore, up to the maximum to the available limit.
88
+ def resume
89
+ available = @waiting.pop(@limit - @count)
90
+
91
+ available.each do |fiber|
92
+ fiber.resume if fiber.alive?
93
+ end
94
+ end
95
+ end
96
+ end
@@ -19,5 +19,5 @@
19
19
  # THE SOFTWARE.
20
20
 
21
21
  module Async
22
- VERSION = "1.8.0"
22
+ VERSION = "1.9.0"
23
23
  end
@@ -0,0 +1,45 @@
1
+ # Copyright, 2018, by Samuel G. D. Williams. <http://www.codeotaku.com>
2
+ #
3
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ # of this software and associated documentation files (the "Software"), to deal
5
+ # in the Software without restriction, including without limitation the rights
6
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ # copies of the Software, and to permit persons to whom the Software is
8
+ # furnished to do so, subject to the following conditions:
9
+ #
10
+ # The above copyright notice and this permission notice shall be included in
11
+ # all copies or substantial portions of the Software.
12
+ #
13
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
19
+ # THE SOFTWARE.
20
+
21
+ require 'async/semaphore'
22
+
23
+ RSpec.describe Async::Semaphore do
24
+ include_context Async::RSpec::Reactor
25
+
26
+ it 'should process work in batches' do
27
+ semaphore = Async::Semaphore.new(4)
28
+ current, maximum = 0, 0
29
+
30
+ 100.times.map do
31
+ reactor.async do |task|
32
+ semaphore.acquire do
33
+ current += 1
34
+ maximum = [current, maximum].max
35
+ task.sleep(0.01)
36
+ current -= 1
37
+ end
38
+ end
39
+ end.collect(&:result)
40
+
41
+ expect(maximum).to be == 4
42
+ end
43
+
44
+ it_behaves_like Async::Condition
45
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: async
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.8.0
4
+ version: 1.9.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Samuel Williams
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-29 00:00:00.000000000 Z
11
+ date: 2018-06-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: nio4r
@@ -128,6 +128,7 @@ files:
128
128
  - lib/async/notification.rb
129
129
  - lib/async/queue.rb
130
130
  - lib/async/reactor.rb
131
+ - lib/async/semaphore.rb
131
132
  - lib/async/task.rb
132
133
  - lib/async/version.rb
133
134
  - lib/async/wrapper.rb
@@ -145,6 +146,7 @@ files:
145
146
  - spec/async/queue_spec.rb
146
147
  - spec/async/reactor/nested_spec.rb
147
148
  - spec/async/reactor_spec.rb
149
+ - spec/async/semaphore_spec.rb
148
150
  - spec/async/task_spec.rb
149
151
  - spec/async/wrapper_spec.rb
150
152
  - spec/spec_helper.rb
@@ -183,6 +185,7 @@ test_files:
183
185
  - spec/async/queue_spec.rb
184
186
  - spec/async/reactor/nested_spec.rb
185
187
  - spec/async/reactor_spec.rb
188
+ - spec/async/semaphore_spec.rb
186
189
  - spec/async/task_spec.rb
187
190
  - spec/async/wrapper_spec.rb
188
191
  - spec/spec_helper.rb