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.
- checksums.yaml +7 -0
- data/LICENSE +21 -21
- data/README.md +276 -275
- data/lib/concurrent.rb +28 -28
- data/lib/concurrent/agent.rb +114 -114
- data/lib/concurrent/cached_thread_pool.rb +131 -131
- data/lib/concurrent/defer.rb +65 -65
- data/lib/concurrent/event.rb +60 -60
- data/lib/concurrent/event_machine_defer_proxy.rb +23 -23
- data/lib/concurrent/executor.rb +96 -96
- data/lib/concurrent/fixed_thread_pool.rb +99 -99
- data/lib/concurrent/functions.rb +120 -120
- data/lib/concurrent/future.rb +42 -42
- data/lib/concurrent/global_thread_pool.rb +24 -16
- data/lib/concurrent/goroutine.rb +29 -29
- data/lib/concurrent/null_thread_pool.rb +22 -22
- data/lib/concurrent/obligation.rb +67 -67
- data/lib/concurrent/promise.rb +174 -174
- data/lib/concurrent/reactor.rb +166 -166
- data/lib/concurrent/reactor/drb_async_demux.rb +83 -83
- data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -131
- data/lib/concurrent/supervisor.rb +105 -105
- data/lib/concurrent/thread_pool.rb +76 -76
- data/lib/concurrent/utilities.rb +32 -32
- data/lib/concurrent/version.rb +3 -3
- data/lib/concurrent_ruby.rb +1 -1
- data/md/agent.md +123 -123
- data/md/defer.md +174 -174
- data/md/event.md +32 -32
- data/md/executor.md +187 -187
- data/md/future.md +83 -83
- data/md/goroutine.md +52 -52
- data/md/obligation.md +32 -32
- data/md/promise.md +227 -227
- data/md/thread_pool.md +224 -224
- data/spec/concurrent/agent_spec.rb +390 -386
- data/spec/concurrent/cached_thread_pool_spec.rb +125 -125
- data/spec/concurrent/defer_spec.rb +199 -195
- data/spec/concurrent/event_machine_defer_proxy_spec.rb +256 -256
- data/spec/concurrent/event_spec.rb +134 -134
- data/spec/concurrent/executor_spec.rb +200 -200
- data/spec/concurrent/fixed_thread_pool_spec.rb +83 -83
- data/spec/concurrent/functions_spec.rb +217 -217
- data/spec/concurrent/future_spec.rb +112 -108
- data/spec/concurrent/global_thread_pool_spec.rb +11 -38
- data/spec/concurrent/goroutine_spec.rb +67 -67
- data/spec/concurrent/null_thread_pool_spec.rb +57 -57
- data/spec/concurrent/obligation_shared.rb +132 -132
- data/spec/concurrent/promise_spec.rb +316 -312
- data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -196
- data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -410
- data/spec/concurrent/reactor_spec.rb +364 -364
- data/spec/concurrent/supervisor_spec.rb +269 -269
- data/spec/concurrent/thread_pool_shared.rb +204 -204
- data/spec/concurrent/uses_global_thread_pool_shared.rb +64 -0
- data/spec/concurrent/utilities_spec.rb +74 -74
- data/spec/spec_helper.rb +32 -32
- metadata +17 -19
@@ -1,204 +1,204 @@
|
|
1
|
-
require 'spec_helper'
|
2
|
-
|
3
|
-
share_examples_for 'Thread Pool' do
|
4
|
-
|
5
|
-
context '#running?' do
|
6
|
-
|
7
|
-
it 'returns true when the thread pool is running' do
|
8
|
-
subject.should be_running
|
9
|
-
end
|
10
|
-
|
11
|
-
it 'returns false when the thread pool is shutting down' do
|
12
|
-
subject.post{ sleep(1) }
|
13
|
-
subject.shutdown
|
14
|
-
subject.should_not be_running
|
15
|
-
end
|
16
|
-
|
17
|
-
it 'returns false when the thread pool is shutdown' do
|
18
|
-
subject.shutdown
|
19
|
-
subject.should_not be_running
|
20
|
-
end
|
21
|
-
|
22
|
-
it 'returns false when the thread pool is killed' do
|
23
|
-
subject.shutdown
|
24
|
-
subject.should_not be_running
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
context '#shutdown?' do
|
29
|
-
|
30
|
-
it 'returns true if #shutdown is complete' do
|
31
|
-
subject.shutdown
|
32
|
-
sleep(0.1)
|
33
|
-
subject.should be_shutdown
|
34
|
-
end
|
35
|
-
|
36
|
-
it 'returns false when running' do
|
37
|
-
subject.should_not be_shutdown
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
context '#killed?' do
|
42
|
-
|
43
|
-
it 'returns true if tasks were killed at shutdown' do
|
44
|
-
subject.post{ sleep(1) }
|
45
|
-
subject.kill
|
46
|
-
subject.should be_killed
|
47
|
-
end
|
48
|
-
|
49
|
-
it 'returns false when running' do
|
50
|
-
subject.should_not be_killed
|
51
|
-
end
|
52
|
-
end
|
53
|
-
|
54
|
-
context '#shutdown' do
|
55
|
-
|
56
|
-
it 'stops accepting new tasks' do
|
57
|
-
subject.post{ sleep(1) }
|
58
|
-
subject.shutdown
|
59
|
-
@expected = false
|
60
|
-
subject.post{ @expected = true }.should be_false
|
61
|
-
sleep(1)
|
62
|
-
@expected.should be_false
|
63
|
-
end
|
64
|
-
|
65
|
-
it 'allows in-progress tasks to complete' do
|
66
|
-
@expected = false
|
67
|
-
subject.post{ sleep(0.5); @expected = true }
|
68
|
-
subject.shutdown
|
69
|
-
sleep(1)
|
70
|
-
@expected.should be_true
|
71
|
-
end
|
72
|
-
|
73
|
-
it 'allows pending tasks to complete' do
|
74
|
-
@expected = false
|
75
|
-
subject.post{ sleep(0.2) }
|
76
|
-
subject.post{ sleep(0.2); @expected = true }
|
77
|
-
subject.shutdown
|
78
|
-
sleep(1)
|
79
|
-
@expected.should be_true
|
80
|
-
end
|
81
|
-
|
82
|
-
it 'allows threads to exit normally' do
|
83
|
-
subject.shutdown
|
84
|
-
sleep(1)
|
85
|
-
subject.status.should be_empty
|
86
|
-
end
|
87
|
-
end
|
88
|
-
|
89
|
-
context '#kill' do
|
90
|
-
|
91
|
-
it 'stops accepting new tasks' do
|
92
|
-
subject.post{ sleep(1) }
|
93
|
-
subject.kill
|
94
|
-
@expected = false
|
95
|
-
subject.post{ @expected = true }.should be_false
|
96
|
-
sleep(1)
|
97
|
-
@expected.should be_false
|
98
|
-
end
|
99
|
-
|
100
|
-
it 'attempts to kill all in-progress tasks' do
|
101
|
-
@expected = false
|
102
|
-
subject.post{ sleep(1); @expected = true }
|
103
|
-
subject.kill
|
104
|
-
sleep(1)
|
105
|
-
@expected.should be_false
|
106
|
-
end
|
107
|
-
|
108
|
-
it 'rejects all pending tasks' do
|
109
|
-
@expected = false
|
110
|
-
subject.post{ sleep(0.5) }
|
111
|
-
subject.post{ sleep(0.5); @expected = true }
|
112
|
-
subject.kill
|
113
|
-
sleep(1)
|
114
|
-
@expected.should be_false
|
115
|
-
end
|
116
|
-
end
|
117
|
-
|
118
|
-
context '#wait_for_termination' do
|
119
|
-
|
120
|
-
it 'immediately returns true after shutdown has complete' do
|
121
|
-
subject.shutdown
|
122
|
-
subject.wait_for_termination.should be_true
|
123
|
-
end
|
124
|
-
|
125
|
-
it 'blocks indefinitely when timeout it nil' do
|
126
|
-
subject.post{ sleep(1) }
|
127
|
-
subject.shutdown
|
128
|
-
subject.wait_for_termination(nil).should be_true
|
129
|
-
end
|
130
|
-
|
131
|
-
it 'returns true when shutdown sucessfully completes before timeout' do
|
132
|
-
subject.post{ sleep(0.5) }
|
133
|
-
subject.shutdown
|
134
|
-
subject.wait_for_termination(1).should be_true
|
135
|
-
end
|
136
|
-
|
137
|
-
it 'returns false when shutdown fails to complete before timeout' do
|
138
|
-
subject.post{ sleep(1) }
|
139
|
-
subject.shutdown
|
140
|
-
subject.wait_for_termination(0.5).should be_false
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
context '#post' do
|
145
|
-
|
146
|
-
it 'raises an exception if no block is given' do
|
147
|
-
lambda {
|
148
|
-
subject.post
|
149
|
-
}.should raise_error(ArgumentError)
|
150
|
-
end
|
151
|
-
|
152
|
-
it 'returns true when the block is added to the queue' do
|
153
|
-
subject.post{ nil }.should be_true
|
154
|
-
end
|
155
|
-
|
156
|
-
it 'calls the block with the given arguments' do
|
157
|
-
@expected = nil
|
158
|
-
subject.post(1, 2, 3)do |a, b, c|
|
159
|
-
@expected = a + b + c
|
160
|
-
end
|
161
|
-
sleep(0.1)
|
162
|
-
@expected.should eq 6
|
163
|
-
end
|
164
|
-
|
165
|
-
it 'rejects the block while shutting down' do
|
166
|
-
subject.post{ sleep(1) }
|
167
|
-
subject.shutdown
|
168
|
-
@expected = nil
|
169
|
-
subject.post(1, 2, 3)do |a, b, c|
|
170
|
-
@expected = a + b + c
|
171
|
-
end
|
172
|
-
@expected.should be_nil
|
173
|
-
end
|
174
|
-
|
175
|
-
it 'returns false while shutting down' do
|
176
|
-
subject.post{ sleep(1) }
|
177
|
-
subject.shutdown
|
178
|
-
subject.post{ nil }.should be_false
|
179
|
-
end
|
180
|
-
|
181
|
-
it 'rejects the block once shutdown' do
|
182
|
-
subject.shutdown
|
183
|
-
@expected = nil
|
184
|
-
subject.post(1, 2, 3)do |a, b, c|
|
185
|
-
@expected = a + b + c
|
186
|
-
end
|
187
|
-
@expected.should be_nil
|
188
|
-
end
|
189
|
-
|
190
|
-
it 'returns false once shutdown' do
|
191
|
-
subject.post{ nil }
|
192
|
-
subject.shutdown
|
193
|
-
sleep(0.1)
|
194
|
-
subject.post{ nil }.should be_false
|
195
|
-
end
|
196
|
-
|
197
|
-
it 'aliases #<<' do
|
198
|
-
@expected = false
|
199
|
-
subject << proc { @expected = true }
|
200
|
-
sleep(0.1)
|
201
|
-
@expected.should be_true
|
202
|
-
end
|
203
|
-
end
|
204
|
-
end
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
share_examples_for 'Thread Pool' do
|
4
|
+
|
5
|
+
context '#running?' do
|
6
|
+
|
7
|
+
it 'returns true when the thread pool is running' do
|
8
|
+
subject.should be_running
|
9
|
+
end
|
10
|
+
|
11
|
+
it 'returns false when the thread pool is shutting down' do
|
12
|
+
subject.post{ sleep(1) }
|
13
|
+
subject.shutdown
|
14
|
+
subject.should_not be_running
|
15
|
+
end
|
16
|
+
|
17
|
+
it 'returns false when the thread pool is shutdown' do
|
18
|
+
subject.shutdown
|
19
|
+
subject.should_not be_running
|
20
|
+
end
|
21
|
+
|
22
|
+
it 'returns false when the thread pool is killed' do
|
23
|
+
subject.shutdown
|
24
|
+
subject.should_not be_running
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
context '#shutdown?' do
|
29
|
+
|
30
|
+
it 'returns true if #shutdown is complete' do
|
31
|
+
subject.shutdown
|
32
|
+
sleep(0.1)
|
33
|
+
subject.should be_shutdown
|
34
|
+
end
|
35
|
+
|
36
|
+
it 'returns false when running' do
|
37
|
+
subject.should_not be_shutdown
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context '#killed?' do
|
42
|
+
|
43
|
+
it 'returns true if tasks were killed at shutdown' do
|
44
|
+
subject.post{ sleep(1) }
|
45
|
+
subject.kill
|
46
|
+
subject.should be_killed
|
47
|
+
end
|
48
|
+
|
49
|
+
it 'returns false when running' do
|
50
|
+
subject.should_not be_killed
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context '#shutdown' do
|
55
|
+
|
56
|
+
it 'stops accepting new tasks' do
|
57
|
+
subject.post{ sleep(1) }
|
58
|
+
subject.shutdown
|
59
|
+
@expected = false
|
60
|
+
subject.post{ @expected = true }.should be_false
|
61
|
+
sleep(1)
|
62
|
+
@expected.should be_false
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'allows in-progress tasks to complete' do
|
66
|
+
@expected = false
|
67
|
+
subject.post{ sleep(0.5); @expected = true }
|
68
|
+
subject.shutdown
|
69
|
+
sleep(1)
|
70
|
+
@expected.should be_true
|
71
|
+
end
|
72
|
+
|
73
|
+
it 'allows pending tasks to complete' do
|
74
|
+
@expected = false
|
75
|
+
subject.post{ sleep(0.2) }
|
76
|
+
subject.post{ sleep(0.2); @expected = true }
|
77
|
+
subject.shutdown
|
78
|
+
sleep(1)
|
79
|
+
@expected.should be_true
|
80
|
+
end
|
81
|
+
|
82
|
+
it 'allows threads to exit normally' do
|
83
|
+
subject.shutdown
|
84
|
+
sleep(1)
|
85
|
+
subject.status.should be_empty
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context '#kill' do
|
90
|
+
|
91
|
+
it 'stops accepting new tasks' do
|
92
|
+
subject.post{ sleep(1) }
|
93
|
+
subject.kill
|
94
|
+
@expected = false
|
95
|
+
subject.post{ @expected = true }.should be_false
|
96
|
+
sleep(1)
|
97
|
+
@expected.should be_false
|
98
|
+
end
|
99
|
+
|
100
|
+
it 'attempts to kill all in-progress tasks' do
|
101
|
+
@expected = false
|
102
|
+
subject.post{ sleep(1); @expected = true }
|
103
|
+
subject.kill
|
104
|
+
sleep(1)
|
105
|
+
@expected.should be_false
|
106
|
+
end
|
107
|
+
|
108
|
+
it 'rejects all pending tasks' do
|
109
|
+
@expected = false
|
110
|
+
subject.post{ sleep(0.5) }
|
111
|
+
subject.post{ sleep(0.5); @expected = true }
|
112
|
+
subject.kill
|
113
|
+
sleep(1)
|
114
|
+
@expected.should be_false
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
context '#wait_for_termination' do
|
119
|
+
|
120
|
+
it 'immediately returns true after shutdown has complete' do
|
121
|
+
subject.shutdown
|
122
|
+
subject.wait_for_termination.should be_true
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'blocks indefinitely when timeout it nil' do
|
126
|
+
subject.post{ sleep(1) }
|
127
|
+
subject.shutdown
|
128
|
+
subject.wait_for_termination(nil).should be_true
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'returns true when shutdown sucessfully completes before timeout' do
|
132
|
+
subject.post{ sleep(0.5) }
|
133
|
+
subject.shutdown
|
134
|
+
subject.wait_for_termination(1).should be_true
|
135
|
+
end
|
136
|
+
|
137
|
+
it 'returns false when shutdown fails to complete before timeout' do
|
138
|
+
subject.post{ sleep(1) }
|
139
|
+
subject.shutdown
|
140
|
+
subject.wait_for_termination(0.5).should be_false
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
context '#post' do
|
145
|
+
|
146
|
+
it 'raises an exception if no block is given' do
|
147
|
+
lambda {
|
148
|
+
subject.post
|
149
|
+
}.should raise_error(ArgumentError)
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'returns true when the block is added to the queue' do
|
153
|
+
subject.post{ nil }.should be_true
|
154
|
+
end
|
155
|
+
|
156
|
+
it 'calls the block with the given arguments' do
|
157
|
+
@expected = nil
|
158
|
+
subject.post(1, 2, 3)do |a, b, c|
|
159
|
+
@expected = a + b + c
|
160
|
+
end
|
161
|
+
sleep(0.1)
|
162
|
+
@expected.should eq 6
|
163
|
+
end
|
164
|
+
|
165
|
+
it 'rejects the block while shutting down' do
|
166
|
+
subject.post{ sleep(1) }
|
167
|
+
subject.shutdown
|
168
|
+
@expected = nil
|
169
|
+
subject.post(1, 2, 3)do |a, b, c|
|
170
|
+
@expected = a + b + c
|
171
|
+
end
|
172
|
+
@expected.should be_nil
|
173
|
+
end
|
174
|
+
|
175
|
+
it 'returns false while shutting down' do
|
176
|
+
subject.post{ sleep(1) }
|
177
|
+
subject.shutdown
|
178
|
+
subject.post{ nil }.should be_false
|
179
|
+
end
|
180
|
+
|
181
|
+
it 'rejects the block once shutdown' do
|
182
|
+
subject.shutdown
|
183
|
+
@expected = nil
|
184
|
+
subject.post(1, 2, 3)do |a, b, c|
|
185
|
+
@expected = a + b + c
|
186
|
+
end
|
187
|
+
@expected.should be_nil
|
188
|
+
end
|
189
|
+
|
190
|
+
it 'returns false once shutdown' do
|
191
|
+
subject.post{ nil }
|
192
|
+
subject.shutdown
|
193
|
+
sleep(0.1)
|
194
|
+
subject.post{ nil }.should be_false
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'aliases #<<' do
|
198
|
+
@expected = false
|
199
|
+
subject << proc { @expected = true }
|
200
|
+
sleep(0.1)
|
201
|
+
@expected.should be_true
|
202
|
+
end
|
203
|
+
end
|
204
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
share_examples_for Concurrent::UsesGlobalThreadPool do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
$GLOBAL_THREAD_POOL = Concurrent::FixedThreadPool.new(1)
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'defaults to the global thread pool' do
|
10
|
+
clazz = Class.new(thread_pool_user)
|
11
|
+
clazz.thread_pool.should eq $GLOBAL_THREAD_POOL
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'sets and gets the thread pool for the class' do
|
15
|
+
pool = Concurrent::NullThreadPool.new
|
16
|
+
thread_pool_user.thread_pool = pool
|
17
|
+
thread_pool_user.thread_pool.should eq pool
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'gives each class its own thread pool' do
|
21
|
+
subject1 = Class.new(thread_pool_user){ include Concurrent::UsesGlobalThreadPool }
|
22
|
+
subject2 = Class.new(thread_pool_user){ include Concurrent::UsesGlobalThreadPool }
|
23
|
+
subject3 = Class.new(thread_pool_user){ include Concurrent::UsesGlobalThreadPool }
|
24
|
+
|
25
|
+
subject1.thread_pool = Concurrent::FixedThreadPool.new(1)
|
26
|
+
subject2.thread_pool = Concurrent::CachedThreadPool.new
|
27
|
+
subject3.thread_pool = Concurrent::NullThreadPool.new
|
28
|
+
|
29
|
+
subject1.thread_pool.should_not eq subject2.thread_pool
|
30
|
+
subject2.thread_pool.should_not eq subject3.thread_pool
|
31
|
+
subject3.thread_pool.should_not eq subject1.thread_pool
|
32
|
+
end
|
33
|
+
|
34
|
+
it 'uses the new global thread pool after the global thread pool is changed' do
|
35
|
+
null_thread_pool = Concurrent::NullThreadPool.new
|
36
|
+
thread_pool_user.thread_pool = $GLOBAL_THREAD_POOL
|
37
|
+
|
38
|
+
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
39
|
+
thread_pool_user.thread_pool.should_not eq null_thread_pool
|
40
|
+
|
41
|
+
$GLOBAL_THREAD_POOL = null_thread_pool
|
42
|
+
|
43
|
+
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
44
|
+
thread_pool_user.thread_pool.should eq null_thread_pool
|
45
|
+
end
|
46
|
+
|
47
|
+
it 'responds to multiple changes in the global thread pool' do
|
48
|
+
thread_pool_user.thread_pool = $GLOBAL_THREAD_POOL
|
49
|
+
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
50
|
+
|
51
|
+
thread_pool_user.thread_pool = Concurrent::NullThreadPool.new
|
52
|
+
thread_pool_user.thread_pool.should_not eq $GLOBAL_THREAD_POOL
|
53
|
+
|
54
|
+
$GLOBAL_THREAD_POOL = Concurrent::FixedThreadPool.new(1)
|
55
|
+
thread_pool_user.thread_pool = $GLOBAL_THREAD_POOL
|
56
|
+
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
57
|
+
|
58
|
+
$GLOBAL_THREAD_POOL = Concurrent::CachedThreadPool.new
|
59
|
+
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
60
|
+
|
61
|
+
$GLOBAL_THREAD_POOL = Concurrent::NullThreadPool.new
|
62
|
+
thread_pool_user.thread_pool.should eq $GLOBAL_THREAD_POOL
|
63
|
+
end
|
64
|
+
end
|