concurrent-ruby 0.2.1 → 0.2.2

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 (58) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -21
  3. data/README.md +276 -275
  4. data/lib/concurrent.rb +28 -28
  5. data/lib/concurrent/agent.rb +114 -114
  6. data/lib/concurrent/cached_thread_pool.rb +131 -131
  7. data/lib/concurrent/defer.rb +65 -65
  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 +96 -96
  11. data/lib/concurrent/fixed_thread_pool.rb +99 -99
  12. data/lib/concurrent/functions.rb +120 -120
  13. data/lib/concurrent/future.rb +42 -42
  14. data/lib/concurrent/global_thread_pool.rb +24 -16
  15. data/lib/concurrent/goroutine.rb +29 -29
  16. data/lib/concurrent/null_thread_pool.rb +22 -22
  17. data/lib/concurrent/obligation.rb +67 -67
  18. data/lib/concurrent/promise.rb +174 -174
  19. data/lib/concurrent/reactor.rb +166 -166
  20. data/lib/concurrent/reactor/drb_async_demux.rb +83 -83
  21. data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -131
  22. data/lib/concurrent/supervisor.rb +105 -105
  23. data/lib/concurrent/thread_pool.rb +76 -76
  24. data/lib/concurrent/utilities.rb +32 -32
  25. data/lib/concurrent/version.rb +3 -3
  26. data/lib/concurrent_ruby.rb +1 -1
  27. data/md/agent.md +123 -123
  28. data/md/defer.md +174 -174
  29. data/md/event.md +32 -32
  30. data/md/executor.md +187 -187
  31. data/md/future.md +83 -83
  32. data/md/goroutine.md +52 -52
  33. data/md/obligation.md +32 -32
  34. data/md/promise.md +227 -227
  35. data/md/thread_pool.md +224 -224
  36. data/spec/concurrent/agent_spec.rb +390 -386
  37. data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
  38. data/spec/concurrent/defer_spec.rb +199 -195
  39. data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -256
  40. data/spec/concurrent/event_spec.rb +134 -134
  41. data/spec/concurrent/executor_spec.rb +200 -200
  42. data/spec/concurrent/fixed_thread_pool_spec.rb +83 -83
  43. data/spec/concurrent/functions_spec.rb +217 -217
  44. data/spec/concurrent/future_spec.rb +112 -108
  45. data/spec/concurrent/global_thread_pool_spec.rb +11 -38
  46. data/spec/concurrent/goroutine_spec.rb +67 -67
  47. data/spec/concurrent/null_thread_pool_spec.rb +57 -57
  48. data/spec/concurrent/obligation_shared.rb +132 -132
  49. data/spec/concurrent/promise_spec.rb +316 -312
  50. data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -196
  51. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -410
  52. data/spec/concurrent/reactor_spec.rb +364 -364
  53. data/spec/concurrent/supervisor_spec.rb +269 -269
  54. data/spec/concurrent/thread_pool_shared.rb +204 -204
  55. data/spec/concurrent/uses_global_thread_pool_shared.rb +64 -0
  56. data/spec/concurrent/utilities_spec.rb +74 -74
  57. data/spec/spec_helper.rb +32 -32
  58. metadata +17 -19
@@ -1,125 +1,125 @@
1
- require 'spec_helper'
2
- require_relative 'thread_pool_shared'
3
-
4
- module Concurrent
5
-
6
- describe CachedThreadPool do
7
-
8
- subject { CachedThreadPool.new }
9
-
10
- it_should_behave_like 'Thread Pool'
11
-
12
- context '#initialize' do
13
-
14
- it 'aliases Concurrent#new_cached_thread_pool' do
15
- pool = Concurrent.new_cached_thread_pool
16
- pool.should be_a(CachedThreadPool)
17
- pool.size.should eq 0
18
- end
19
- end
20
-
21
- context '#kill' do
22
-
23
- it 'kills all threads' do
24
- Thread.should_receive(:kill).at_least(5).times
25
- pool = CachedThreadPool.new
26
- 5.times{ sleep(0.1); pool << proc{ sleep(1) } }
27
- sleep(1)
28
- pool.kill
29
- sleep(0.1)
30
- end
31
- end
32
-
33
- context '#size' do
34
-
35
- it 'returns zero for a new thread pool' do
36
- subject.size.should eq 0
37
- end
38
-
39
- it 'returns the size of the subject when running' do
40
- 5.times{ sleep(0.1); subject << proc{ sleep(1) } }
41
- subject.size.should eq 5
42
- end
43
-
44
- it 'returns zero once shut down' do
45
- subject.shutdown
46
- subject.size.should eq 0
47
- end
48
- end
49
-
50
- context 'worker creation and caching' do
51
-
52
- it 'creates new workers when there are none available' do
53
- subject.size.should eq 0
54
- 5.times{ sleep(0.1); subject << proc{ sleep(1000) } }
55
- sleep(1)
56
- subject.size.should eq 5
57
- end
58
-
59
- it 'uses existing idle threads' do
60
- 5.times{ sleep(0.05); subject << proc{ sleep(0.5) } }
61
- sleep(1)
62
- 3.times{ sleep(0.1); subject << proc{ sleep(0.5) } }
63
- subject.size.should eq 5
64
- end
65
- end
66
-
67
- context 'garbage collection' do
68
-
69
- subject{ CachedThreadPool.new(gc_interval: 1, thread_idleime: 1) }
70
-
71
- it 'starts when the first thread is added to the pool' do
72
- subject.should_receive(:collect_garbage)
73
- subject << proc{ nil }
74
- sleep(0.1)
75
- end
76
-
77
- it 'removes from pool any thread that has been idle too long' do
78
- subject << proc{ nil }
79
- subject.size.should eq 1
80
- sleep(1.5)
81
- subject.size.should eq 0
82
- end
83
-
84
- it 'removed from pool any dead thread' do
85
- subject << proc{ raise StandardError }
86
- subject.size.should eq 1
87
- sleep(1.5)
88
- subject.size.should eq 0
89
- end
90
-
91
- it 'resets the working count appropriately' do
92
- subject << proc{ sleep(1000) }
93
- sleep(0.1)
94
- subject << proc{ raise StandardError }
95
- sleep(0.1)
96
- subject << proc{ nil }
97
-
98
- sleep(0.1)
99
- subject.working.should eq 2
100
-
101
- sleep(1.5)
102
- subject.working.should eq 1
103
- end
104
-
105
- it 'stops collection when the pool size becomes zero' do
106
- 3.times{ sleep(0.1); subject << proc{ sleep(0.5) } }
107
- subject.instance_variable_get(:@collector).status.should eq 'sleep'
108
- sleep(1.5)
109
- subject.instance_variable_get(:@collector).status.should be_false
110
- end
111
- 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
- end
125
- end
1
+ require 'spec_helper'
2
+ require_relative 'thread_pool_shared'
3
+
4
+ module Concurrent
5
+
6
+ describe CachedThreadPool do
7
+
8
+ subject { CachedThreadPool.new }
9
+
10
+ it_should_behave_like 'Thread Pool'
11
+
12
+ context '#initialize' do
13
+
14
+ it 'aliases Concurrent#new_cached_thread_pool' do
15
+ pool = Concurrent.new_cached_thread_pool
16
+ pool.should be_a(CachedThreadPool)
17
+ pool.size.should eq 0
18
+ end
19
+ end
20
+
21
+ context '#kill' do
22
+
23
+ it 'kills all threads' do
24
+ Thread.should_receive(:kill).at_least(5).times
25
+ pool = CachedThreadPool.new
26
+ 5.times{ sleep(0.1); pool << proc{ sleep(1) } }
27
+ sleep(1)
28
+ pool.kill
29
+ sleep(0.1)
30
+ end
31
+ end
32
+
33
+ context '#size' do
34
+
35
+ it 'returns zero for a new thread pool' do
36
+ subject.size.should eq 0
37
+ end
38
+
39
+ it 'returns the size of the subject when running' do
40
+ 5.times{ sleep(0.1); subject << proc{ sleep(1) } }
41
+ subject.size.should eq 5
42
+ end
43
+
44
+ it 'returns zero once shut down' do
45
+ subject.shutdown
46
+ subject.size.should eq 0
47
+ end
48
+ end
49
+
50
+ context 'worker creation and caching' do
51
+
52
+ it 'creates new workers when there are none available' do
53
+ subject.size.should eq 0
54
+ 5.times{ sleep(0.1); subject << proc{ sleep(1000) } }
55
+ sleep(1)
56
+ subject.size.should eq 5
57
+ end
58
+
59
+ it 'uses existing idle threads' do
60
+ 5.times{ sleep(0.05); subject << proc{ sleep(0.5) } }
61
+ sleep(1)
62
+ 3.times{ sleep(0.1); subject << proc{ sleep(0.5) } }
63
+ subject.size.should eq 5
64
+ end
65
+ end
66
+
67
+ context 'garbage collection' do
68
+
69
+ subject{ CachedThreadPool.new(gc_interval: 1, thread_idleime: 1) }
70
+
71
+ it 'starts when the first thread is added to the pool' do
72
+ subject.should_receive(:collect_garbage)
73
+ subject << proc{ nil }
74
+ sleep(0.1)
75
+ end
76
+
77
+ it 'removes from pool any thread that has been idle too long' do
78
+ subject << proc{ nil }
79
+ subject.size.should eq 1
80
+ sleep(1.5)
81
+ subject.size.should eq 0
82
+ end
83
+
84
+ it 'removed from pool any dead thread' do
85
+ subject << proc{ raise StandardError }
86
+ subject.size.should eq 1
87
+ sleep(1.5)
88
+ subject.size.should eq 0
89
+ end
90
+
91
+ it 'resets the working count appropriately' do
92
+ subject << proc{ sleep(1000) }
93
+ sleep(0.1)
94
+ subject << proc{ raise StandardError }
95
+ sleep(0.1)
96
+ subject << proc{ nil }
97
+
98
+ sleep(0.1)
99
+ subject.working.should eq 2
100
+
101
+ sleep(1.5)
102
+ subject.working.should eq 1
103
+ end
104
+
105
+ it 'stops collection when the pool size becomes zero' do
106
+ 3.times{ sleep(0.1); subject << proc{ sleep(0.5) } }
107
+ subject.instance_variable_get(:@collector).status.should eq 'sleep'
108
+ sleep(1.5)
109
+ subject.instance_variable_get(:@collector).status.should be_false
110
+ end
111
+ 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
+ end
125
+ end
@@ -1,195 +1,199 @@
1
- require 'spec_helper'
2
-
3
- module Concurrent
4
-
5
- describe Defer do
6
-
7
- before(:each) do
8
- Defer.thread_pool = FixedThreadPool.new(1)
9
- end
10
-
11
- context '#initialize' do
12
-
13
- it 'raises an exception if no block or operation given' do
14
- lambda {
15
- Defer.new
16
- }.should raise_error(ArgumentError)
17
- end
18
-
19
- it 'raises an exception if both a block and an operation given' do
20
- lambda {
21
- operation = proc{ nil }
22
- Defer.new(op: operation){ nil }
23
- }.should raise_error(ArgumentError)
24
- end
25
-
26
- it 'starts the thread if an operation is given' do
27
- Defer.thread_pool.should_receive(:post).once.with(any_args())
28
- operation = proc{ nil }
29
- Defer.new(op: operation)
30
- end
31
-
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 }
35
- end
36
- end
37
-
38
- context '#then' do
39
-
40
- it 'raises an exception if no block given' do
41
- lambda {
42
- Defer.new{ nil }.then
43
- }.should raise_error(ArgumentError)
44
- end
45
-
46
- it 'raises an exception if called twice' do
47
- lambda {
48
- Defer.new{ nil }.then{|result| nil }.then{|result| nil }
49
- }.should raise_error(IllegalMethodCallError)
50
- end
51
-
52
- it 'raises an exception if an operation was provided at construction' do
53
- lambda {
54
- operation = proc{ nil }
55
- Defer.new(op: operation).then{|result| nil }
56
- }.should raise_error(IllegalMethodCallError)
57
- end
58
-
59
- it 'raises an exception if a callback was provided at construction' do
60
- lambda {
61
- callback = proc{|result|nil }
62
- Defer.new(callback: callback){ nil }.then{|result| nil }
63
- }.should raise_error(IllegalMethodCallError)
64
- end
65
-
66
- it 'returns self' do
67
- deferred = Defer.new{ nil }
68
- deferred.then{|result| nil }.should eq deferred
69
- end
70
- end
71
-
72
- context '#rescue' do
73
-
74
- it 'raises an exception if no block given' do
75
- lambda {
76
- Defer.new{ nil }.rescue
77
- }.should raise_error(ArgumentError)
78
- end
79
-
80
- it 'raises an exception if called twice' do
81
- lambda {
82
- Defer.new{ nil }.rescue{ nil }.rescue{ nil }
83
- }.should raise_error(IllegalMethodCallError)
84
- end
85
-
86
- it 'raises an exception if an operation was provided at construction' do
87
- lambda {
88
- operation = proc{ nil }
89
- Defer.new(op: operation).rescue{|ex| nil }
90
- }.should raise_error(IllegalMethodCallError)
91
- end
92
-
93
- it 'raises an exception if an errorback was provided at construction' do
94
- lambda {
95
- errorback = proc{|ex| nil }
96
- Defer.new(errorback: errorback){ nil }.rescue{|ex| nil }
97
- }.should raise_error(IllegalMethodCallError)
98
- end
99
-
100
- it 'returns self' do
101
- deferred = Defer.new{ nil }
102
- deferred.rescue{|ex| nil }.should eq deferred
103
- end
104
-
105
- it 'aliases #catch' do
106
- lambda {
107
- Defer.new{ nil }.catch{|ex| nil }
108
- }.should_not raise_error
109
- end
110
-
111
- it 'aliases #on_error' do
112
- lambda {
113
- Defer.new{ nil }.on_error{|ex| nil }
114
- }.should_not raise_error
115
- end
116
- end
117
-
118
- context '#go' do
119
-
120
- it 'starts the thread if not started' do
121
- deferred = Defer.new{ nil }
122
- Defer.thread_pool.should_receive(:post).once.with(any_args())
123
- deferred.go
124
- end
125
-
126
- it 'does nothing if called more than once' do
127
- deferred = Defer.new{ nil }
128
- deferred.go
129
- Defer.thread_pool.should_not_receive(:post)
130
- deferred.go
131
- end
132
-
133
- it 'does nothing if thread started at construction' do
134
- operation = proc{ nil }
135
- callback = proc{|result| nil }
136
- errorback = proc{|ex| nil }
137
- deferred = Defer.new(op: operation, callback: callback, errorback: errorback)
138
- Defer.thread_pool.should_not_receive(:post)
139
- deferred.go
140
- end
141
- end
142
-
143
- context 'fulfillment' do
144
-
145
- it 'runs the operation' do
146
- @expected = false
147
- Defer.new{ @expected = true }.go
148
- sleep(0.1)
149
- @expected.should be_true
150
- end
151
-
152
- it 'calls the callback when the operation is successful' do
153
- @expected = false
154
- Defer.new{ true }.then{|result| @expected = true }.go
155
- sleep(0.1)
156
- @expected.should be_true
157
- end
158
-
159
- it 'passes the result of the block to the callback' do
160
- @expected = false
161
- Defer.new{ 'w00t' }.then{|result| @expected = result }.go
162
- sleep(0.1)
163
- @expected.should eq 'w00t'
164
- end
165
-
166
- it 'does not call the errorback when the operation is successful' do
167
- @expected = true
168
- Defer.new{ nil }.rescue{|ex| @expected = false }.go
169
- sleep(0.1)
170
- @expected.should be_true
171
- end
172
-
173
- it 'calls the errorback if the operation throws an exception' do
174
- @expected = false
175
- Defer.new{ raise StandardError }.rescue{|ex| @expected = true }.go
176
- sleep(0.1)
177
- @expected.should be_true
178
- end
179
-
180
- it 'passes the exception object to the errorback' do
181
- @expected = nil
182
- Defer.new{ raise StandardError }.rescue{|ex| @expected = ex }.go
183
- sleep(0.1)
184
- @expected.should be_a(StandardError)
185
- end
186
-
187
- it 'does not call the callback when the operation fails' do
188
- @expected = true
189
- Defer.new{ raise StandardError }.then{|result| @expected = false }.go
190
- sleep(0.1)
191
- @expected.should be_true
192
- end
193
- end
194
- end
195
- end
1
+ require 'spec_helper'
2
+ require_relative 'uses_global_thread_pool_shared'
3
+
4
+ module Concurrent
5
+
6
+ describe Defer do
7
+
8
+ let!(:thread_pool_user){ Defer }
9
+ it_should_behave_like Concurrent::UsesGlobalThreadPool
10
+
11
+ before(:each) do
12
+ Defer.thread_pool = FixedThreadPool.new(1)
13
+ end
14
+
15
+ context '#initialize' do
16
+
17
+ it 'raises an exception if no block or operation given' do
18
+ lambda {
19
+ Defer.new
20
+ }.should raise_error(ArgumentError)
21
+ end
22
+
23
+ it 'raises an exception if both a block and an operation given' do
24
+ lambda {
25
+ operation = proc{ nil }
26
+ Defer.new(op: operation){ nil }
27
+ }.should raise_error(ArgumentError)
28
+ end
29
+
30
+ it 'starts the thread if an operation is given' do
31
+ Defer.thread_pool.should_receive(:post).once.with(any_args())
32
+ operation = proc{ nil }
33
+ Defer.new(op: operation)
34
+ end
35
+
36
+ it 'does not start the thread if neither a callback or errorback is given' do
37
+ Defer.thread_pool.should_not_receive(:post)
38
+ Defer.new{ nil }
39
+ end
40
+ end
41
+
42
+ context '#then' do
43
+
44
+ it 'raises an exception if no block given' do
45
+ lambda {
46
+ Defer.new{ nil }.then
47
+ }.should raise_error(ArgumentError)
48
+ end
49
+
50
+ it 'raises an exception if called twice' do
51
+ lambda {
52
+ Defer.new{ nil }.then{|result| nil }.then{|result| nil }
53
+ }.should raise_error(IllegalMethodCallError)
54
+ end
55
+
56
+ it 'raises an exception if an operation was provided at construction' do
57
+ lambda {
58
+ operation = proc{ nil }
59
+ Defer.new(op: operation).then{|result| nil }
60
+ }.should raise_error(IllegalMethodCallError)
61
+ end
62
+
63
+ it 'raises an exception if a callback was provided at construction' do
64
+ lambda {
65
+ callback = proc{|result|nil }
66
+ Defer.new(callback: callback){ nil }.then{|result| nil }
67
+ }.should raise_error(IllegalMethodCallError)
68
+ end
69
+
70
+ it 'returns self' do
71
+ deferred = Defer.new{ nil }
72
+ deferred.then{|result| nil }.should eq deferred
73
+ end
74
+ end
75
+
76
+ context '#rescue' do
77
+
78
+ it 'raises an exception if no block given' do
79
+ lambda {
80
+ Defer.new{ nil }.rescue
81
+ }.should raise_error(ArgumentError)
82
+ end
83
+
84
+ it 'raises an exception if called twice' do
85
+ lambda {
86
+ Defer.new{ nil }.rescue{ nil }.rescue{ nil }
87
+ }.should raise_error(IllegalMethodCallError)
88
+ end
89
+
90
+ it 'raises an exception if an operation was provided at construction' do
91
+ lambda {
92
+ operation = proc{ nil }
93
+ Defer.new(op: operation).rescue{|ex| nil }
94
+ }.should raise_error(IllegalMethodCallError)
95
+ end
96
+
97
+ it 'raises an exception if an errorback was provided at construction' do
98
+ lambda {
99
+ errorback = proc{|ex| nil }
100
+ Defer.new(errorback: errorback){ nil }.rescue{|ex| nil }
101
+ }.should raise_error(IllegalMethodCallError)
102
+ end
103
+
104
+ it 'returns self' do
105
+ deferred = Defer.new{ nil }
106
+ deferred.rescue{|ex| nil }.should eq deferred
107
+ end
108
+
109
+ it 'aliases #catch' do
110
+ lambda {
111
+ Defer.new{ nil }.catch{|ex| nil }
112
+ }.should_not raise_error
113
+ end
114
+
115
+ it 'aliases #on_error' do
116
+ lambda {
117
+ Defer.new{ nil }.on_error{|ex| nil }
118
+ }.should_not raise_error
119
+ end
120
+ end
121
+
122
+ context '#go' do
123
+
124
+ it 'starts the thread if not started' do
125
+ deferred = Defer.new{ nil }
126
+ Defer.thread_pool.should_receive(:post).once.with(any_args())
127
+ deferred.go
128
+ end
129
+
130
+ it 'does nothing if called more than once' do
131
+ deferred = Defer.new{ nil }
132
+ deferred.go
133
+ Defer.thread_pool.should_not_receive(:post)
134
+ deferred.go
135
+ end
136
+
137
+ it 'does nothing if thread started at construction' do
138
+ operation = proc{ nil }
139
+ callback = proc{|result| nil }
140
+ errorback = proc{|ex| nil }
141
+ deferred = Defer.new(op: operation, callback: callback, errorback: errorback)
142
+ Defer.thread_pool.should_not_receive(:post)
143
+ deferred.go
144
+ end
145
+ end
146
+
147
+ context 'fulfillment' do
148
+
149
+ it 'runs the operation' do
150
+ @expected = false
151
+ Defer.new{ @expected = true }.go
152
+ sleep(0.1)
153
+ @expected.should be_true
154
+ end
155
+
156
+ it 'calls the callback when the operation is successful' do
157
+ @expected = false
158
+ Defer.new{ true }.then{|result| @expected = true }.go
159
+ sleep(0.1)
160
+ @expected.should be_true
161
+ end
162
+
163
+ it 'passes the result of the block to the callback' do
164
+ @expected = false
165
+ Defer.new{ 'w00t' }.then{|result| @expected = result }.go
166
+ sleep(0.1)
167
+ @expected.should eq 'w00t'
168
+ end
169
+
170
+ it 'does not call the errorback when the operation is successful' do
171
+ @expected = true
172
+ Defer.new{ nil }.rescue{|ex| @expected = false }.go
173
+ sleep(0.1)
174
+ @expected.should be_true
175
+ end
176
+
177
+ it 'calls the errorback if the operation throws an exception' do
178
+ @expected = false
179
+ Defer.new{ raise StandardError }.rescue{|ex| @expected = true }.go
180
+ sleep(0.1)
181
+ @expected.should be_true
182
+ end
183
+
184
+ it 'passes the exception object to the errorback' do
185
+ @expected = nil
186
+ Defer.new{ raise StandardError }.rescue{|ex| @expected = ex }.go
187
+ sleep(0.1)
188
+ @expected.should be_a(StandardError)
189
+ end
190
+
191
+ it 'does not call the callback when the operation fails' do
192
+ @expected = true
193
+ Defer.new{ raise StandardError }.then{|result| @expected = false }.go
194
+ sleep(0.1)
195
+ @expected.should be_true
196
+ end
197
+ end
198
+ end
199
+ end