concurrent-ruby 0.1.0 → 0.1.1.pre.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. data/LICENSE +21 -21
  2. data/README.md +279 -224
  3. data/lib/concurrent.rb +27 -20
  4. data/lib/concurrent/agent.rb +106 -130
  5. data/lib/concurrent/cached_thread_pool.rb +130 -122
  6. data/lib/concurrent/defer.rb +67 -69
  7. data/lib/concurrent/drb_async_demux.rb +72 -0
  8. data/lib/concurrent/event.rb +60 -60
  9. data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
  10. data/lib/concurrent/executor.rb +87 -0
  11. data/lib/concurrent/fixed_thread_pool.rb +89 -89
  12. data/lib/concurrent/functions.rb +120 -0
  13. data/lib/concurrent/future.rb +52 -42
  14. data/lib/concurrent/global_thread_pool.rb +3 -3
  15. data/lib/concurrent/goroutine.rb +29 -25
  16. data/lib/concurrent/obligation.rb +67 -121
  17. data/lib/concurrent/promise.rb +172 -194
  18. data/lib/concurrent/reactor.rb +162 -0
  19. data/lib/concurrent/smart_mutex.rb +66 -0
  20. data/lib/concurrent/tcp_sync_demux.rb +96 -0
  21. data/lib/concurrent/thread_pool.rb +65 -61
  22. data/lib/concurrent/utilities.rb +34 -0
  23. data/lib/concurrent/version.rb +3 -3
  24. data/lib/concurrent_ruby.rb +1 -1
  25. data/md/agent.md +123 -123
  26. data/md/defer.md +174 -174
  27. data/md/event.md +32 -32
  28. data/md/executor.md +176 -0
  29. data/md/future.md +83 -83
  30. data/md/goroutine.md +52 -52
  31. data/md/obligation.md +32 -32
  32. data/md/promise.md +225 -225
  33. data/md/thread_pool.md +197 -197
  34. data/spec/concurrent/agent_spec.rb +376 -405
  35. data/spec/concurrent/cached_thread_pool_spec.rb +112 -112
  36. data/spec/concurrent/defer_spec.rb +209 -199
  37. data/spec/concurrent/event_machine_defer_proxy_spec.rb +250 -246
  38. data/spec/concurrent/event_spec.rb +134 -134
  39. data/spec/concurrent/executor_spec.rb +146 -0
  40. data/spec/concurrent/fixed_thread_pool_spec.rb +84 -84
  41. data/spec/concurrent/functions_spec.rb +57 -0
  42. data/spec/concurrent/future_spec.rb +125 -115
  43. data/spec/concurrent/goroutine_spec.rb +67 -52
  44. data/spec/concurrent/obligation_shared.rb +121 -121
  45. data/spec/concurrent/promise_spec.rb +299 -310
  46. data/spec/concurrent/smart_mutex_spec.rb +234 -0
  47. data/spec/concurrent/thread_pool_shared.rb +209 -209
  48. data/spec/concurrent/utilities_spec.rb +74 -0
  49. data/spec/spec_helper.rb +21 -19
  50. metadata +38 -14
  51. checksums.yaml +0 -7
@@ -1,246 +1,250 @@
1
- require 'spec_helper'
2
-
3
- require 'concurrent/agent'
4
- require 'concurrent/future'
5
- require 'concurrent/promise'
6
-
7
- module Concurrent
8
-
9
- describe EventMachineDeferProxy do
10
-
11
- subject { EventMachineDeferProxy.new }
12
-
13
- context '#post' do
14
-
15
- it 'proxies a call without arguments' do
16
- @expected = false
17
- EventMachine.run do
18
- subject.post{ @expected = true }
19
- sleep(0.1)
20
- EventMachine.stop
21
- end
22
- @expected.should eq true
23
- end
24
-
25
- it 'proxies a call with arguments' do
26
- @expected = []
27
- EventMachine.run do
28
- subject.post(1,2,3){|*args| @expected = args }
29
- sleep(0.1)
30
- EventMachine.stop
31
- end
32
- @expected.should eq [1,2,3]
33
- end
34
-
35
- it 'aliases #<<' do
36
- @expected = false
37
- EventMachine.run do
38
- subject << proc{ @expected = true }
39
- sleep(0.1)
40
- EventMachine.stop
41
- end
42
- @expected.should eq true
43
- end
44
- end
45
-
46
- context 'operation' do
47
-
48
- context 'goroutine' do
49
-
50
- it 'passes all arguments to the block' do
51
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
52
-
53
- EventMachine.run do
54
-
55
- @expected = nil
56
- go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
57
- sleep(0.1)
58
- @expected.should eq [3, 2, 1]
59
-
60
- EventMachine.stop
61
- end
62
- end
63
- end
64
-
65
- context Agent do
66
-
67
- subject { Agent.new(0) }
68
-
69
- it 'supports fulfillment' do
70
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
71
-
72
- EventMachine.run do
73
-
74
- @expected = []
75
- subject.post{ @expected << 1 }
76
- subject.post{ @expected << 2 }
77
- subject.post{ @expected << 3 }
78
- sleep(0.1)
79
- @expected.should eq [1,2,3]
80
-
81
- EventMachine.stop
82
- end
83
- end
84
-
85
- it 'supports validation' do
86
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
87
-
88
- EventMachine.run do
89
-
90
- @expected = nil
91
- subject.validate{ @expected = 10; true }
92
- subject.post{ nil }
93
- sleep(0.1)
94
- @expected.should eq 10
95
-
96
- EventMachine.stop
97
- end
98
- end
99
-
100
- it 'supports rejection' do
101
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
102
-
103
- EventMachine.run do
104
-
105
- @expected = nil
106
- subject.
107
- on_error(StandardError){|ex| @expected = 1 }.
108
- on_error(StandardError){|ex| @expected = 2 }.
109
- on_error(StandardError){|ex| @expected = 3 }
110
- subject.post{ raise StandardError }
111
- sleep(0.1)
112
- @expected.should eq 1
113
-
114
- EventMachine.stop
115
- end
116
- end
117
- end
118
-
119
- context Future do
120
-
121
- it 'supports fulfillment' do
122
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
123
-
124
- EventMachine.run do
125
-
126
- @a = @b = @c = nil
127
- f = Future.new(1, 2, 3) do |a, b, c|
128
- @a, @b, @c = a, b, c
129
- end
130
- sleep(0.1)
131
- [@a, @b, @c].should eq [1, 2, 3]
132
-
133
- sleep(0.1)
134
- EventMachine.stop
135
- end
136
- end
137
- end
138
-
139
- context Promise do
140
-
141
- context 'fulfillment' do
142
-
143
- it 'passes all arguments to the first promise in the chain' do
144
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
145
-
146
- EventMachine.run do
147
-
148
- @a = @b = @c = nil
149
- p = Promise.new(1, 2, 3) do |a, b, c|
150
- @a, @b, @c = a, b, c
151
- end
152
- sleep(0.1)
153
- [@a, @b, @c].should eq [1, 2, 3]
154
-
155
- sleep(0.1)
156
- EventMachine.stop
157
- end
158
- end
159
-
160
- it 'passes the result of each block to all its children' do
161
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
162
-
163
- EventMachine.run do
164
- @expected = nil
165
- Promise.new(10){|a| a * 2 }.then{|result| @expected = result}
166
- sleep(0.1)
167
- @expected.should eq 20
168
-
169
- sleep(0.1)
170
- EventMachine.stop
171
- end
172
- end
173
-
174
- it 'sets the promise value to the result if its block' do
175
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
176
-
177
- EventMachine.run do
178
-
179
- p = Promise.new(10){|a| a * 2 }.then{|result| result * 2}
180
- sleep(0.1)
181
- p.value.should eq 40
182
-
183
- sleep(0.1)
184
- EventMachine.stop
185
- end
186
- end
187
- end
188
-
189
- context 'rejection' do
190
-
191
- it 'sets the promise reason and error on exception' do
192
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
193
-
194
- EventMachine.run do
195
-
196
- p = Promise.new{ raise StandardError.new('Boom!') }
197
- sleep(0.1)
198
- p.reason.should be_a(Exception)
199
- p.reason.should.to_s =~ /Boom!/
200
- p.should be_rejected
201
-
202
- sleep(0.1)
203
- EventMachine.stop
204
- end
205
- end
206
-
207
- it 'calls the first exception block with a matching class' do
208
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
209
-
210
- EventMachine.run do
211
-
212
- @expected = nil
213
- Promise.new{ raise StandardError }.
214
- on_error(StandardError){|ex| @expected = 1 }.
215
- on_error(StandardError){|ex| @expected = 2 }.
216
- on_error(StandardError){|ex| @expected = 3 }
217
- sleep(0.1)
218
- @expected.should eq 1
219
-
220
- sleep(0.1)
221
- EventMachine.stop
222
- end
223
- end
224
-
225
- it 'passes the exception object to the matched block' do
226
- $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
227
-
228
- EventMachine.run do
229
-
230
- @expected = nil
231
- Promise.new{ raise StandardError }.
232
- on_error(ArgumentError){|ex| @expected = ex }.
233
- on_error(LoadError){|ex| @expected = ex }.
234
- on_error(Exception){|ex| @expected = ex }
235
- sleep(0.1)
236
- @expected.should be_a(StandardError)
237
-
238
- sleep(0.1)
239
- EventMachine.stop
240
- end
241
- end
242
- end
243
- end
244
- end
245
- end
246
- end
1
+ require 'spec_helper'
2
+
3
+ require 'concurrent/agent'
4
+ require 'concurrent/future'
5
+ require 'concurrent/promise'
6
+
7
+ module Concurrent
8
+
9
+ describe EventMachineDeferProxy do
10
+
11
+ subject { EventMachineDeferProxy.new }
12
+
13
+ after(:all) do
14
+ $GLOBAL_THREAD_POOL = FixedThreadPool.new(1)
15
+ end
16
+
17
+ context '#post' do
18
+
19
+ it 'proxies a call without arguments' do
20
+ @expected = false
21
+ EventMachine.run do
22
+ subject.post{ @expected = true }
23
+ sleep(0.1)
24
+ EventMachine.stop
25
+ end
26
+ @expected.should eq true
27
+ end
28
+
29
+ it 'proxies a call with arguments' do
30
+ @expected = []
31
+ EventMachine.run do
32
+ subject.post(1,2,3){|*args| @expected = args }
33
+ sleep(0.1)
34
+ EventMachine.stop
35
+ end
36
+ @expected.should eq [1,2,3]
37
+ end
38
+
39
+ it 'aliases #<<' do
40
+ @expected = false
41
+ EventMachine.run do
42
+ subject << proc{ @expected = true }
43
+ sleep(0.1)
44
+ EventMachine.stop
45
+ end
46
+ @expected.should eq true
47
+ end
48
+ end
49
+
50
+ context 'operation' do
51
+
52
+ context 'goroutine' do
53
+
54
+ it 'passes all arguments to the block' do
55
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
56
+
57
+ EventMachine.run do
58
+
59
+ @expected = nil
60
+ go(1, 2, 3){|a, b, c| @expected = [c, b, a] }
61
+ sleep(0.1)
62
+ @expected.should eq [3, 2, 1]
63
+
64
+ EventMachine.stop
65
+ end
66
+ end
67
+ end
68
+
69
+ context Agent do
70
+
71
+ subject { Agent.new(0) }
72
+
73
+ it 'supports fulfillment' do
74
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
75
+
76
+ EventMachine.run do
77
+
78
+ @expected = []
79
+ subject.post{ @expected << 1 }
80
+ subject.post{ @expected << 2 }
81
+ subject.post{ @expected << 3 }
82
+ sleep(0.1)
83
+ @expected.should eq [1,2,3]
84
+
85
+ EventMachine.stop
86
+ end
87
+ end
88
+
89
+ it 'supports validation' do
90
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
91
+
92
+ EventMachine.run do
93
+
94
+ @expected = nil
95
+ subject.validate{ @expected = 10; true }
96
+ subject.post{ nil }
97
+ sleep(0.1)
98
+ @expected.should eq 10
99
+
100
+ EventMachine.stop
101
+ end
102
+ end
103
+
104
+ it 'supports rejection' do
105
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
106
+
107
+ EventMachine.run do
108
+
109
+ @expected = nil
110
+ subject.
111
+ on_error(StandardError){|ex| @expected = 1 }.
112
+ on_error(StandardError){|ex| @expected = 2 }.
113
+ on_error(StandardError){|ex| @expected = 3 }
114
+ subject.post{ raise StandardError }
115
+ sleep(0.1)
116
+ @expected.should eq 1
117
+
118
+ EventMachine.stop
119
+ end
120
+ end
121
+ end
122
+
123
+ context Future do
124
+
125
+ it 'supports fulfillment' do
126
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
127
+
128
+ EventMachine.run do
129
+
130
+ @a = @b = @c = nil
131
+ f = Future.new(1, 2, 3) do |a, b, c|
132
+ @a, @b, @c = a, b, c
133
+ end
134
+ sleep(0.1)
135
+ [@a, @b, @c].should eq [1, 2, 3]
136
+
137
+ sleep(0.1)
138
+ EventMachine.stop
139
+ end
140
+ end
141
+ end
142
+
143
+ context Promise do
144
+
145
+ context 'fulfillment' do
146
+
147
+ it 'passes all arguments to the first promise in the chain' do
148
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
149
+
150
+ EventMachine.run do
151
+
152
+ @a = @b = @c = nil
153
+ p = Promise.new(1, 2, 3) do |a, b, c|
154
+ @a, @b, @c = a, b, c
155
+ end
156
+ sleep(0.1)
157
+ [@a, @b, @c].should eq [1, 2, 3]
158
+
159
+ sleep(0.1)
160
+ EventMachine.stop
161
+ end
162
+ end
163
+
164
+ it 'passes the result of each block to all its children' do
165
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
166
+
167
+ EventMachine.run do
168
+ @expected = nil
169
+ Promise.new(10){|a| a * 2 }.then{|result| @expected = result}
170
+ sleep(0.1)
171
+ @expected.should eq 20
172
+
173
+ sleep(0.1)
174
+ EventMachine.stop
175
+ end
176
+ end
177
+
178
+ it 'sets the promise value to the result if its block' do
179
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
180
+
181
+ EventMachine.run do
182
+
183
+ p = Promise.new(10){|a| a * 2 }.then{|result| result * 2}
184
+ sleep(0.1)
185
+ p.value.should eq 40
186
+
187
+ sleep(0.1)
188
+ EventMachine.stop
189
+ end
190
+ end
191
+ end
192
+
193
+ context 'rejection' do
194
+
195
+ it 'sets the promise reason and error on exception' do
196
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
197
+
198
+ EventMachine.run do
199
+
200
+ p = Promise.new{ raise StandardError.new('Boom!') }
201
+ sleep(0.1)
202
+ p.reason.should be_a(Exception)
203
+ p.reason.should.to_s =~ /Boom!/
204
+ p.should be_rejected
205
+
206
+ sleep(0.1)
207
+ EventMachine.stop
208
+ end
209
+ end
210
+
211
+ it 'calls the first exception block with a matching class' do
212
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
213
+
214
+ EventMachine.run do
215
+
216
+ @expected = nil
217
+ Promise.new{ raise StandardError }.
218
+ on_error(StandardError){|ex| @expected = 1 }.
219
+ on_error(StandardError){|ex| @expected = 2 }.
220
+ on_error(StandardError){|ex| @expected = 3 }
221
+ sleep(0.1)
222
+ @expected.should eq 1
223
+
224
+ sleep(0.1)
225
+ EventMachine.stop
226
+ end
227
+ end
228
+
229
+ it 'passes the exception object to the matched block' do
230
+ $GLOBAL_THREAD_POOL = EventMachineDeferProxy.new
231
+
232
+ EventMachine.run do
233
+
234
+ @expected = nil
235
+ Promise.new{ raise StandardError }.
236
+ on_error(ArgumentError){|ex| @expected = ex }.
237
+ on_error(LoadError){|ex| @expected = ex }.
238
+ on_error(Exception){|ex| @expected = ex }
239
+ sleep(0.1)
240
+ @expected.should be_a(StandardError)
241
+
242
+ sleep(0.1)
243
+ EventMachine.stop
244
+ end
245
+ end
246
+ end
247
+ end
248
+ end
249
+ end
250
+ end