concurrent-ruby 0.2.0 → 0.2.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 (57) hide show
  1. data/LICENSE +21 -21
  2. data/README.md +275 -275
  3. data/lib/concurrent.rb +28 -28
  4. data/lib/concurrent/agent.rb +114 -114
  5. data/lib/concurrent/cached_thread_pool.rb +131 -129
  6. data/lib/concurrent/defer.rb +65 -65
  7. data/lib/concurrent/event.rb +60 -60
  8. data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
  9. data/lib/concurrent/executor.rb +96 -95
  10. data/lib/concurrent/fixed_thread_pool.rb +99 -95
  11. data/lib/concurrent/functions.rb +120 -120
  12. data/lib/concurrent/future.rb +42 -42
  13. data/lib/concurrent/global_thread_pool.rb +16 -16
  14. data/lib/concurrent/goroutine.rb +29 -29
  15. data/lib/concurrent/null_thread_pool.rb +22 -22
  16. data/lib/concurrent/obligation.rb +67 -67
  17. data/lib/concurrent/promise.rb +174 -174
  18. data/lib/concurrent/reactor.rb +166 -166
  19. data/lib/concurrent/reactor/drb_async_demux.rb +83 -83
  20. data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -131
  21. data/lib/concurrent/supervisor.rb +105 -100
  22. data/lib/concurrent/thread_pool.rb +76 -76
  23. data/lib/concurrent/utilities.rb +32 -32
  24. data/lib/concurrent/version.rb +3 -3
  25. data/lib/concurrent_ruby.rb +1 -1
  26. data/md/agent.md +123 -123
  27. data/md/defer.md +174 -174
  28. data/md/event.md +32 -32
  29. data/md/executor.md +187 -187
  30. data/md/future.md +83 -83
  31. data/md/goroutine.md +52 -52
  32. data/md/obligation.md +32 -32
  33. data/md/promise.md +227 -227
  34. data/md/thread_pool.md +224 -224
  35. data/spec/concurrent/agent_spec.rb +386 -386
  36. data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
  37. data/spec/concurrent/defer_spec.rb +195 -195
  38. data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -256
  39. data/spec/concurrent/event_spec.rb +134 -134
  40. data/spec/concurrent/executor_spec.rb +200 -200
  41. data/spec/concurrent/fixed_thread_pool_spec.rb +83 -83
  42. data/spec/concurrent/functions_spec.rb +217 -217
  43. data/spec/concurrent/future_spec.rb +108 -108
  44. data/spec/concurrent/global_thread_pool_spec.rb +38 -38
  45. data/spec/concurrent/goroutine_spec.rb +67 -67
  46. data/spec/concurrent/null_thread_pool_spec.rb +57 -54
  47. data/spec/concurrent/obligation_shared.rb +132 -132
  48. data/spec/concurrent/promise_spec.rb +312 -312
  49. data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -196
  50. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -410
  51. data/spec/concurrent/reactor_spec.rb +364 -364
  52. data/spec/concurrent/supervisor_spec.rb +269 -258
  53. data/spec/concurrent/thread_pool_shared.rb +204 -204
  54. data/spec/concurrent/utilities_spec.rb +74 -74
  55. data/spec/spec_helper.rb +32 -32
  56. metadata +20 -16
  57. checksums.yaml +0 -7
@@ -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,195 @@
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
+
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