quack_concurrency 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,277 +1,244 @@
1
- require 'quack_concurrency'
1
+ #require 'quack_concurrency'
2
2
 
3
- RSpec.describe QuackConcurrency::Semaphore do
3
+ #RSpec.describe QuackConcurrency::Semaphore do
4
4
 
5
- describe "::new" do
5
+ #describe "#release" do
6
6
 
7
- context "when called without a 'duck_types' argument" do
8
- it "should create a new QuackConcurrency::Semaphore" do
9
- semaphore = QuackConcurrency::Semaphore.new
10
- expect(semaphore).to be_a(QuackConcurrency::Semaphore)
11
- end
12
- end
13
-
14
- context "when called with 'condition_variable' and 'mutex' duck types" do
15
- it "should create a new QuackConcurrency::Semaphore" do
16
- duck_types = {condition_variable: Class.new, mutex: Class.new}
17
- semaphore = QuackConcurrency::Semaphore.new(duck_types: duck_types)
18
- expect(semaphore).to be_a(QuackConcurrency::Semaphore)
19
- end
20
- end
21
-
22
- context "when called with only 'condition_variable' duck type" do
23
- it "should raise ArgumentError" do
24
- duck_types = {condition_variable: Class.new}
25
- expect{ QuackConcurrency::Semaphore.new(duck_types: duck_types) }.to raise_error(ArgumentError)
26
- end
27
- end
28
-
29
- context "when called with only 'mutex' duck type" do
30
- it "should raise ArgumentError" do
31
- duck_types = {mutex: Class.new}
32
- expect{ QuackConcurrency::Semaphore.new(duck_types: duck_types) }.to raise_error(ArgumentError)
33
- end
34
- end
35
-
36
- end
37
-
38
- describe "#release" do
39
-
40
- context "when called for the first time with many permits available" do
41
- it "should not raise error" do
42
- semaphore = QuackConcurrency::Semaphore.new(2)
7
+ #context "when called for the first time with many permits available" do
8
+ #it "should not raise error" do
9
+ #semaphore = QuackConcurrency::Semaphore.new(2)
43
10
 
44
- expect{ semaphore.release }.not_to raise_error
45
- end
46
- end
47
-
48
- context "when called a second time with one permit available" do
49
- it "should not raise error" do
50
- semaphore = QuackConcurrency::Semaphore.new(2)
51
- semaphore.release
52
- expect{ semaphore.release }.not_to raise_error
53
- end
54
- end
55
-
56
- end
57
-
58
- describe "#release, #reacquire" do
59
-
60
- context "when #release called with no permits available" do
61
- it "should wait until #reacquire is called" do
62
- semaphore = QuackConcurrency::Semaphore.new(2)
63
- semaphore.release
64
- semaphore.release
65
- thread = Thread.new do
66
- sleep 1
67
- semaphore.reacquire
68
- end
69
- start_time = Time.now
70
- semaphore.release
71
- end_time = Time.now
72
- duration = end_time - start_time
73
- thread.join
74
- expect(duration).to be > 0.5
75
- end
76
- end
77
-
78
- context "when #reacquire called when all permits are available" do
79
- it "should raise QuackConcurrency::Semaphore::Error" do
80
- semaphore = QuackConcurrency::Semaphore.new(2)
81
- expect{ semaphore.reacquire }.to raise_error(QuackConcurrency::Semaphore::Error)
82
- end
83
- end
84
-
85
- end
86
-
87
- describe "#release, #reacquire, #permit_available?, #permits_available" do
88
-
89
- context "#permit_available? and #permits_available" do
90
- it "should work as expected" do
91
- semaphore = QuackConcurrency::Semaphore.new(2)
92
- expect(semaphore.permit_available?).to eql true
93
- expect(semaphore.permits_available).to eql 2
94
- semaphore.release
95
- expect(semaphore.permit_available?).to eql true
96
- expect(semaphore.permits_available).to eql 1
97
- semaphore.release
98
- expect(semaphore.permit_available?).to eql false
99
- expect(semaphore.permits_available).to eql 0
100
- semaphore.reacquire
101
- expect(semaphore.permit_available?).to eql true
102
- expect(semaphore.permits_available).to eql 1
103
- semaphore.reacquire
104
- expect(semaphore.permit_available?).to eql true
105
- expect(semaphore.permits_available).to eql 2
106
- end
107
- end
108
-
109
- end
110
-
111
- describe "#set_permit_count, #permits_available" do
112
-
113
- context "when #set_permit_count is called with more permits then currently exist" do
114
- it "should add permits" do
115
- semaphore = QuackConcurrency::Semaphore.new(2)
116
- expect(semaphore.permits_available).to eql 2
117
- semaphore.set_permit_count(3)
118
- expect(semaphore.permits_available).to eql 3
119
- end
120
- end
121
-
122
- context "when #set_permit_count is called with less permits then currently exist" do
123
- it "should remove permits" do
124
- semaphore = QuackConcurrency::Semaphore.new(2)
125
- expect(semaphore.permits_available).to eql 2
126
- semaphore.set_permit_count(1)
127
- expect(semaphore.permits_available).to eql 1
128
- end
129
- end
130
-
131
- end
132
-
133
- describe "#set_permit_count, #permits_available, #release" do
134
-
135
- context "when #set_permit_count is called with less permits then currently available" do
136
- it "should raise QuackConcurrency::Semaphore::Error" do
137
- semaphore = QuackConcurrency::Semaphore.new(2)
138
- expect(semaphore.permits_available).to eql 2
139
- semaphore.release
140
- semaphore.release
141
- expect{ semaphore.set_permit_count(1) }.to raise_error(QuackConcurrency::Semaphore::Error)
142
- end
143
- end
144
-
145
- end
146
-
147
- describe "#set_permit_count, #release" do
148
-
149
- context "when #set_permit_count is called with more permits when one thread is waiting on #release" do
150
- it "should resume the thread" do
151
- semaphore = QuackConcurrency::Semaphore.new(2)
152
- semaphore.release
153
- semaphore.release
154
- thread = Thread.new do
155
- sleep 1
156
- semaphore.set_permit_count(3)
157
- end
158
- start_time = Time.now
159
- semaphore.release
160
- end_time = Time.now
161
- duration = end_time - start_time
162
- thread.join
163
- expect(duration).to be > 0.5
164
- end
165
- end
166
-
167
- end
168
-
169
- describe "#set_permit_count!, #permits_available" do
170
-
171
- context "when #set_permit_count! is called with more permits then currently exist" do
172
- it "should add permits" do
173
- semaphore = QuackConcurrency::Semaphore.new(2)
174
- expect(semaphore.permits_available).to eql 2
175
- semaphore.set_permit_count!(3)
176
- expect(semaphore.permits_available).to eql 3
177
- end
178
- end
179
-
180
- context "when #set_permit_count! is called with less permits then currently exist" do
181
- it "should remove permits" do
182
- semaphore = QuackConcurrency::Semaphore.new(2)
183
- expect(semaphore.permits_available).to eql 2
184
- semaphore.set_permit_count!(1)
185
- expect(semaphore.permits_available).to eql 1
186
- end
187
- end
188
-
189
- end
190
-
191
- describe "#set_permit_count!, #permits_available, #release, #reacquire" do
192
-
193
- context "when #set_permit_count! is called with less permits then currently available" do
194
- it "should force new permit count" do
195
- semaphore = QuackConcurrency::Semaphore.new(2)
196
- expect(semaphore.permits_available).to eql 2
197
- semaphore.release
198
- semaphore.release
199
- semaphore.set_permit_count!(1)
200
- expect(semaphore.permit_available?).to eql false
201
- semaphore.reacquire
202
- expect(semaphore.permit_available?).to eql false
203
- semaphore.reacquire
204
- expect(semaphore.permit_available?).to eql true
205
- end
206
- end
207
-
208
- end
209
-
210
- describe "#set_permit_count!, #release" do
211
-
212
- context "when #set_permit_count! is called with more permits when one thread is waiting on #release" do
213
- it "should resume the thread" do
214
- semaphore = QuackConcurrency::Semaphore.new(2)
215
- semaphore.release
216
- semaphore.release
217
- thread = Thread.new do
218
- sleep 1
219
- semaphore.set_permit_count(3)
220
- end
221
- start_time = Time.now
222
- semaphore.release
223
- end_time = Time.now
224
- duration = end_time - start_time
225
- thread.join
226
- expect(duration).to be > 0.5
227
- end
228
- end
229
-
230
- end
231
-
232
- describe "#set_permit_count!, #release, #permit_available?" do
233
-
234
- context "when semaphore has no permits available, them #set_permit_count! is called to remove 2 permits, then called again to add 1 permit" do
235
- it "should not have any permits available" do
236
- semaphore = QuackConcurrency::Semaphore.new(3)
237
- semaphore.release
238
- semaphore.release
239
- expect(semaphore.permit_available?).to eql true
240
- semaphore.set_permit_count!(1)
241
- expect(semaphore.permit_available?).to eql false
242
- semaphore.set_permit_count!(2)
243
- expect(semaphore.permit_available?).to eql false
244
- end
245
- end
246
-
247
- end
248
-
249
- describe "#set_permit_count!, #release, #reacquire" do
250
-
251
- context "when semaphore has no permits available, them #set_permit_count! is called to remove 2 permits, then a thread starts waiting for #release, then #set_permit_count! is called again to add 1 permit" do
252
- it "thread should wait for #reacquire to be called" do
253
- semaphore = QuackConcurrency::Semaphore.new(3)
254
- semaphore.release
255
- semaphore.release
256
- semaphore.release
257
- semaphore.set_permit_count!(1)
258
- thread = Thread.new do
259
- sleep 1
260
- semaphore.set_permit_count!(2)
261
- sleep 1
262
- semaphore.reacquire
263
- sleep 1
264
- semaphore.reacquire
265
- end
266
- start_time = Time.now
267
- semaphore.release
268
- end_time = Time.now
269
- duration = end_time - start_time
270
- thread.join
271
- expect(duration).to be_between(2.5, 3.5)
272
- end
273
- end
274
-
275
- end
11
+ #expect{ semaphore.release }.not_to raise_error
12
+ #end
13
+ #end
14
+
15
+ #context "when called a second time with one permit available" do
16
+ #it "should not raise error" do
17
+ #semaphore = QuackConcurrency::Semaphore.new(2)
18
+ #semaphore.release
19
+ #expect{ semaphore.release }.not_to raise_error
20
+ #end
21
+ #end
22
+
23
+ #end
24
+
25
+ #describe "#release, #reacquire" do
26
+
27
+ #context "when #release called with no permits available" do
28
+ #it "should wait until #reacquire is called" do
29
+ #semaphore = QuackConcurrency::Semaphore.new(2)
30
+ #semaphore.release
31
+ #semaphore.release
32
+ #thread = Thread.new do
33
+ #sleep 1
34
+ #semaphore.reacquire
35
+ #end
36
+ #start_time = Time.now
37
+ #semaphore.release
38
+ #end_time = Time.now
39
+ #duration = end_time - start_time
40
+ #thread.join
41
+ #expect(duration).to be > 0.5
42
+ #end
43
+ #end
44
+
45
+ #context "when #reacquire called when all permits are available" do
46
+ #it "should raise QuackConcurrency::Semaphore::Error" do
47
+ #semaphore = QuackConcurrency::Semaphore.new(2)
48
+ #expect{ semaphore.reacquire }.to raise_error(QuackConcurrency::Semaphore::Error)
49
+ #end
50
+ #end
51
+
52
+ #end
53
+
54
+ #describe "#release, #reacquire, #permit_available?, #permits_available" do
55
+
56
+ #context "#permit_available? and #permits_available" do
57
+ #it "should work as expected" do
58
+ #semaphore = QuackConcurrency::Semaphore.new(2)
59
+ #expect(semaphore.permit_available?).to eql true
60
+ #expect(semaphore.permits_available).to eql 2
61
+ #semaphore.release
62
+ #expect(semaphore.permit_available?).to eql true
63
+ #expect(semaphore.permits_available).to eql 1
64
+ #semaphore.release
65
+ #expect(semaphore.permit_available?).to eql false
66
+ #expect(semaphore.permits_available).to eql 0
67
+ #semaphore.reacquire
68
+ #expect(semaphore.permit_available?).to eql true
69
+ #expect(semaphore.permits_available).to eql 1
70
+ #semaphore.reacquire
71
+ #expect(semaphore.permit_available?).to eql true
72
+ #expect(semaphore.permits_available).to eql 2
73
+ #end
74
+ #end
75
+
76
+ #end
77
+
78
+ #describe "#set_permit_count, #permits_available" do
79
+
80
+ #context "when #set_permit_count is called with more permits then currently exist" do
81
+ #it "should add permits" do
82
+ #semaphore = QuackConcurrency::Semaphore.new(2)
83
+ #expect(semaphore.permits_available).to eql 2
84
+ #semaphore.set_permit_count(3)
85
+ #expect(semaphore.permits_available).to eql 3
86
+ #end
87
+ #end
88
+
89
+ #context "when #set_permit_count is called with less permits then currently exist" do
90
+ #it "should remove permits" do
91
+ #semaphore = QuackConcurrency::Semaphore.new(2)
92
+ #expect(semaphore.permits_available).to eql 2
93
+ #semaphore.set_permit_count(1)
94
+ #expect(semaphore.permits_available).to eql 1
95
+ #end
96
+ #end
97
+
98
+ #end
99
+
100
+ #describe "#set_permit_count, #permits_available, #release" do
101
+
102
+ #context "when #set_permit_count is called with less permits then currently available" do
103
+ #it "should raise QuackConcurrency::Semaphore::Error" do
104
+ #semaphore = QuackConcurrency::Semaphore.new(2)
105
+ #expect(semaphore.permits_available).to eql 2
106
+ #semaphore.release
107
+ #semaphore.release
108
+ #expect{ semaphore.set_permit_count(1) }.to raise_error(QuackConcurrency::Semaphore::Error)
109
+ #end
110
+ #end
111
+
112
+ #end
113
+
114
+ #describe "#set_permit_count, #release" do
115
+
116
+ #context "when #set_permit_count is called with more permits when one thread is waiting on #release" do
117
+ #it "should resume the thread" do
118
+ #semaphore = QuackConcurrency::Semaphore.new(2)
119
+ #semaphore.release
120
+ #semaphore.release
121
+ #thread = Thread.new do
122
+ #sleep 1
123
+ #semaphore.set_permit_count(3)
124
+ #end
125
+ #start_time = Time.now
126
+ #semaphore.release
127
+ #end_time = Time.now
128
+ #duration = end_time - start_time
129
+ #thread.join
130
+ #expect(duration).to be > 0.5
131
+ #end
132
+ #end
133
+
134
+ #end
135
+
136
+ #describe "#set_permit_count!, #permits_available" do
137
+
138
+ #context "when #set_permit_count! is called with more permits then currently exist" do
139
+ #it "should add permits" do
140
+ #semaphore = QuackConcurrency::Semaphore.new(2)
141
+ #expect(semaphore.permits_available).to eql 2
142
+ #semaphore.set_permit_count!(3)
143
+ #expect(semaphore.permits_available).to eql 3
144
+ #end
145
+ #end
146
+
147
+ #context "when #set_permit_count! is called with less permits then currently exist" do
148
+ #it "should remove permits" do
149
+ #semaphore = QuackConcurrency::Semaphore.new(2)
150
+ #expect(semaphore.permits_available).to eql 2
151
+ #semaphore.set_permit_count!(1)
152
+ #expect(semaphore.permits_available).to eql 1
153
+ #end
154
+ #end
155
+
156
+ #end
157
+
158
+ #describe "#set_permit_count!, #permits_available, #release, #reacquire" do
159
+
160
+ #context "when #set_permit_count! is called with less permits then currently available" do
161
+ #it "should force new permit count" do
162
+ #semaphore = QuackConcurrency::Semaphore.new(2)
163
+ #expect(semaphore.permits_available).to eql 2
164
+ #semaphore.release
165
+ #semaphore.release
166
+ #semaphore.set_permit_count!(1)
167
+ #expect(semaphore.permit_available?).to eql false
168
+ #semaphore.reacquire
169
+ #expect(semaphore.permit_available?).to eql false
170
+ #semaphore.reacquire
171
+ #expect(semaphore.permit_available?).to eql true
172
+ #end
173
+ #end
174
+
175
+ #end
176
+
177
+ #describe "#set_permit_count!, #release" do
178
+
179
+ #context "when #set_permit_count! is called with more permits when one thread is waiting on #release" do
180
+ #it "should resume the thread" do
181
+ #semaphore = QuackConcurrency::Semaphore.new(2)
182
+ #semaphore.release
183
+ #semaphore.release
184
+ #thread = Thread.new do
185
+ #sleep 1
186
+ #semaphore.set_permit_count(3)
187
+ #end
188
+ #start_time = Time.now
189
+ #semaphore.release
190
+ #end_time = Time.now
191
+ #duration = end_time - start_time
192
+ #thread.join
193
+ #expect(duration).to be > 0.5
194
+ #end
195
+ #end
196
+
197
+ #end
198
+
199
+ #describe "#set_permit_count!, #release, #permit_available?" do
200
+
201
+ #context "when semaphore has no permits available, them #set_permit_count! is called to remove 2 permits, then called again to add 1 permit" do
202
+ #it "should not have any permits available" do
203
+ #semaphore = QuackConcurrency::Semaphore.new(3)
204
+ #semaphore.release
205
+ #semaphore.release
206
+ #expect(semaphore.permit_available?).to eql true
207
+ #semaphore.set_permit_count!(1)
208
+ #expect(semaphore.permit_available?).to eql false
209
+ #semaphore.set_permit_count!(2)
210
+ #expect(semaphore.permit_available?).to eql false
211
+ #end
212
+ #end
213
+
214
+ #end
215
+
216
+ #describe "#set_permit_count!, #release, #reacquire" do
217
+
218
+ #context "when semaphore has no permits available, them #set_permit_count! is called to remove 2 permits, then a thread starts waiting for #release, then #set_permit_count! is called again to add 1 permit" do
219
+ #it "thread should wait for #reacquire to be called" do
220
+ #semaphore = QuackConcurrency::Semaphore.new(3)
221
+ #semaphore.release
222
+ #semaphore.release
223
+ #semaphore.release
224
+ #semaphore.set_permit_count!(1)
225
+ #thread = Thread.new do
226
+ #sleep 1
227
+ #semaphore.set_permit_count!(2)
228
+ #sleep 1
229
+ #semaphore.reacquire
230
+ #sleep 1
231
+ #semaphore.reacquire
232
+ #end
233
+ #start_time = Time.now
234
+ #semaphore.release
235
+ #end_time = Time.now
236
+ #duration = end_time - start_time
237
+ #thread.join
238
+ #expect(duration).to be_between(2.5, 3.5)
239
+ #end
240
+ #end
241
+
242
+ #end
276
243
 
277
- end
244
+ #end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quack_concurrency
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.1
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rob Fors
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-04-19 00:00:00.000000000 Z
11
+ date: 2018-05-31 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: Offers concurrency tools that could also be found in the 'Concurrent
14
14
  Ruby'. However, all these tools will also accept core class duck types to build
@@ -22,19 +22,22 @@ files:
22
22
  - README.md
23
23
  - Rakefile
24
24
  - lib/quack_concurrency.rb
25
- - lib/quack_concurrency/concurrency_tool.rb
25
+ - lib/quack_concurrency/condition_variable.rb
26
26
  - lib/quack_concurrency/error.rb
27
27
  - lib/quack_concurrency/future.rb
28
28
  - lib/quack_concurrency/future/canceled.rb
29
29
  - lib/quack_concurrency/future/complete.rb
30
- - lib/quack_concurrency/name.rb
30
+ - lib/quack_concurrency/mutex.rb
31
31
  - lib/quack_concurrency/queue.rb
32
32
  - lib/quack_concurrency/queue/error.rb
33
33
  - lib/quack_concurrency/reentrant_mutex.rb
34
34
  - lib/quack_concurrency/reentrant_mutex/error.rb
35
35
  - lib/quack_concurrency/semaphore.rb
36
36
  - lib/quack_concurrency/semaphore/error.rb
37
+ - lib/quack_concurrency/uninterruptible_condition_variable.rb
38
+ - lib/quack_concurrency/uninterruptible_sleeper.rb
37
39
  - lib/quack_concurrency/waiter.rb
40
+ - lib/quack_concurrency/yielder.rb
38
41
  - spec/future_spec.rb
39
42
  - spec/queue_spec.rb
40
43
  - spec/reentrant_mutex_spec.rb
@@ -1,28 +0,0 @@
1
- module QuackConcurrency
2
-
3
- # @api private
4
- class ConcurrencyTool
5
-
6
- def setup_duck_types(supplied_classes)
7
- resultant_classes = {}
8
- required_classes = [:condition_variable, :mutex]
9
- required_classes = required_classes.map { |name| Name.new(name.to_s) }
10
- if supplied_classes
11
- raise ArgumentError, "'supplied_classes' must be Hash" unless supplied_classes.is_a?(Hash)
12
- supplied_classes = supplied_classes.map { |k, v| [Name.new(k.to_s), v] }.to_h
13
- required_classes.each do |class_name|
14
- unless supplied_classes[class_name]
15
- raise ArgumentError, "missing duck type: #{class_name.camel_case(:upper)}"
16
- end
17
- resultant_classes[class_name.snake_case.to_sym] = supplied_classes[class_name]
18
- end
19
- else
20
- required_classes.each do |class_name|
21
- resultant_classes[class_name.snake_case.to_sym] = Object.const_get(class_name.camel_case(:upper))
22
- end
23
- end
24
- resultant_classes
25
- end
26
-
27
- end
28
- end
@@ -1,33 +0,0 @@
1
- module QuackConcurrency
2
-
3
- # @api private
4
- class Name < String
5
-
6
- def initialize(*args)
7
- super
8
- # set all names to a default case
9
- # if we create two of the same name with different cases they will now be equal
10
- replace(snake_case)
11
- end
12
-
13
- def camel_case(first_letter = :upper)
14
- case first_letter
15
- when :upper
16
- self.split('_').collect(&:capitalize).join
17
- when :lower
18
- self.camelcase(:upper)[0].downcase + self.camelcase(:upper)[1..-1]
19
- else
20
- raise ArgumentError, 'invalid option, use either :upper or :lower'
21
- end
22
- end
23
-
24
- def snake_case
25
- self.gsub(/::/, '/').
26
- gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
27
- gsub(/([a-z\d])([A-Z])/,'\1_\2').
28
- tr("- ", "_").
29
- downcase
30
- end
31
-
32
- end
33
- end