quack_concurrency 0.4.1 → 0.5.0

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.
@@ -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