concurrent-ruby 0.1.1.pre.5 → 0.1.1

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