concurrent-ruby 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +48 -1
  3. data/lib/concurrent.rb +8 -1
  4. data/lib/concurrent/agent.rb +19 -40
  5. data/lib/concurrent/cached_thread_pool.rb +10 -11
  6. data/lib/concurrent/defer.rb +8 -12
  7. data/lib/concurrent/executor.rb +95 -0
  8. data/lib/concurrent/fixed_thread_pool.rb +12 -6
  9. data/lib/concurrent/functions.rb +120 -0
  10. data/lib/concurrent/future.rb +8 -20
  11. data/lib/concurrent/global_thread_pool.rb +13 -0
  12. data/lib/concurrent/goroutine.rb +5 -1
  13. data/lib/concurrent/null_thread_pool.rb +22 -0
  14. data/lib/concurrent/obligation.rb +10 -64
  15. data/lib/concurrent/promise.rb +38 -60
  16. data/lib/concurrent/reactor.rb +166 -0
  17. data/lib/concurrent/reactor/drb_async_demux.rb +83 -0
  18. data/lib/concurrent/reactor/tcp_sync_demux.rb +131 -0
  19. data/lib/concurrent/supervisor.rb +100 -0
  20. data/lib/concurrent/thread_pool.rb +16 -5
  21. data/lib/concurrent/utilities.rb +8 -0
  22. data/lib/concurrent/version.rb +1 -1
  23. data/md/defer.md +4 -4
  24. data/md/executor.md +187 -0
  25. data/md/promise.md +2 -0
  26. data/md/thread_pool.md +27 -0
  27. data/spec/concurrent/agent_spec.rb +8 -27
  28. data/spec/concurrent/cached_thread_pool_spec.rb +14 -1
  29. data/spec/concurrent/defer_spec.rb +17 -21
  30. data/spec/concurrent/event_machine_defer_proxy_spec.rb +159 -149
  31. data/spec/concurrent/executor_spec.rb +200 -0
  32. data/spec/concurrent/fixed_thread_pool_spec.rb +2 -3
  33. data/spec/concurrent/functions_spec.rb +217 -0
  34. data/spec/concurrent/future_spec.rb +4 -11
  35. data/spec/concurrent/global_thread_pool_spec.rb +38 -0
  36. data/spec/concurrent/goroutine_spec.rb +15 -0
  37. data/spec/concurrent/null_thread_pool_spec.rb +54 -0
  38. data/spec/concurrent/obligation_shared.rb +127 -116
  39. data/spec/concurrent/promise_spec.rb +16 -14
  40. data/spec/concurrent/reactor/drb_async_demux_spec.rb +196 -0
  41. data/spec/concurrent/reactor/tcp_sync_demux_spec.rb +410 -0
  42. data/spec/concurrent/reactor_spec.rb +364 -0
  43. data/spec/concurrent/supervisor_spec.rb +258 -0
  44. data/spec/concurrent/thread_pool_shared.rb +156 -161
  45. data/spec/concurrent/utilities_spec.rb +30 -1
  46. data/spec/spec_helper.rb +13 -0
  47. metadata +38 -9
@@ -1,209 +1,204 @@
1
1
  require 'spec_helper'
2
2
 
3
- module Concurrent
3
+ share_examples_for 'Thread Pool' do
4
4
 
5
- share_examples_for 'Thread Pool' do
5
+ context '#running?' do
6
6
 
7
- context '#running?' do
8
-
9
- it 'returns true when the thread pool is running' do
10
- subject.should be_running
11
- end
7
+ it 'returns true when the thread pool is running' do
8
+ subject.should be_running
9
+ end
12
10
 
13
- it 'returns false when the thread pool is shutting down' do
14
- subject.post{ sleep(1) }
15
- subject.shutdown
16
- subject.should_not be_running
17
- end
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
18
16
 
19
- it 'returns false when the thread pool is shutdown' do
20
- subject.shutdown
21
- subject.should_not be_running
22
- end
17
+ it 'returns false when the thread pool is shutdown' do
18
+ subject.shutdown
19
+ subject.should_not be_running
20
+ end
23
21
 
24
- it 'returns false when the thread pool is killed' do
25
- subject.shutdown
26
- subject.should_not be_running
27
- end
22
+ it 'returns false when the thread pool is killed' do
23
+ subject.shutdown
24
+ subject.should_not be_running
28
25
  end
26
+ end
29
27
 
30
- context '#shutdown?' do
28
+ context '#shutdown?' do
31
29
 
32
- it 'returns true if #shutdown has been called' do
33
- subject.shutdown
34
- subject.should be_shutdown
35
- end
30
+ it 'returns true if #shutdown is complete' do
31
+ subject.shutdown
32
+ sleep(0.1)
33
+ subject.should be_shutdown
34
+ end
36
35
 
37
- it 'returns false when running' do
38
- subject.should_not be_shutdown
39
- end
36
+ it 'returns false when running' do
37
+ subject.should_not be_shutdown
40
38
  end
39
+ end
41
40
 
42
- context '#killed?' do
41
+ context '#killed?' do
43
42
 
44
- it 'returns true if tasks were killed at shutdown' do
45
- subject.post{ sleep(1) }
46
- subject.kill
47
- subject.should be_killed
48
- end
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
49
48
 
50
- it 'returns false when running' do
51
- subject.should_not be_killed
52
- end
49
+ it 'returns false when running' do
50
+ subject.should_not be_killed
53
51
  end
52
+ end
54
53
 
55
- context '#shutdown' do
54
+ context '#shutdown' do
56
55
 
57
- it 'stops accepting new tasks' do
58
- subject.post{ sleep(1) }
59
- subject.shutdown
60
- @expected = false
61
- subject.post{ @expected = true }.should be_false
62
- sleep(1)
63
- @expected.should be_false
64
- end
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
65
64
 
66
- it 'allows in-progress tasks to complete' do
67
- @expected = false
68
- subject.post{ sleep(0.5); @expected = true }
69
- subject.shutdown
70
- sleep(1)
71
- @expected.should be_true
72
- end
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
73
72
 
74
- it 'allows pending tasks to complete' do
75
- @expected = false
76
- subject.post{ sleep(0.2) }
77
- subject.post{ sleep(0.2); @expected = true }
78
- subject.shutdown
79
- sleep(1)
80
- @expected.should be_true
81
- end
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
82
81
 
83
- it 'allows threads to exit normally' do
84
- pool = FixedThreadPool.new(5)
85
- pool.shutdown
86
- sleep(1)
87
- pool.status.should be_empty
88
- end
82
+ it 'allows threads to exit normally' do
83
+ subject.shutdown
84
+ sleep(1)
85
+ subject.status.should be_empty
89
86
  end
87
+ end
90
88
 
91
- context '#kill' do
89
+ context '#kill' do
92
90
 
93
- it 'stops accepting new tasks' do
94
- subject.post{ sleep(1) }
95
- subject.kill
96
- @expected = false
97
- subject.post{ @expected = true }.should be_false
98
- sleep(1)
99
- @expected.should be_false
100
- end
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
101
99
 
102
- it 'attempts to kill all in-progress tasks' do
103
- @expected = false
104
- subject.post{ sleep(1); @expected = true }
105
- subject.kill
106
- sleep(1)
107
- @expected.should be_false
108
- end
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
109
107
 
110
- it 'rejects all pending tasks' do
111
- @expected = false
112
- subject.post{ sleep(0.5) }
113
- subject.post{ sleep(0.5); @expected = true }
114
- subject.kill
115
- sleep(1)
116
- @expected.should be_false
117
- end
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
118
115
  end
116
+ end
119
117
 
120
- context '#wait_for_termination' do
118
+ context '#wait_for_termination' do
121
119
 
122
- it 'immediately returns true after shutdown has complete' do
123
- subject.shutdown
124
- subject.wait_for_termination.should be_true
125
- end
120
+ it 'immediately returns true after shutdown has complete' do
121
+ subject.shutdown
122
+ subject.wait_for_termination.should be_true
123
+ end
126
124
 
127
- it 'blocks indefinitely when timeout it nil' do
128
- subject.post{ sleep(1) }
129
- subject.shutdown
130
- subject.wait_for_termination(nil).should be_true
131
- end
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
132
130
 
133
- it 'returns true when shutdown sucessfully completes before timeout' do
134
- subject.post{ sleep(0.5) }
135
- subject.shutdown
136
- subject.wait_for_termination(1).should be_true
137
- end
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
138
136
 
139
- it 'returns false when shutdown fails to complete before timeout' do
140
- subject.post{ sleep(1) }
141
- subject.shutdown
142
- subject.wait_for_termination(0.5).should be_true
143
- end
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
144
141
  end
142
+ end
145
143
 
146
- context '#post' do
144
+ context '#post' do
147
145
 
148
- it 'raises an exception if no block is given' do
149
- lambda {
150
- subject.post
151
- }.should raise_error(ArgumentError)
152
- end
146
+ it 'raises an exception if no block is given' do
147
+ lambda {
148
+ subject.post
149
+ }.should raise_error(ArgumentError)
150
+ end
153
151
 
154
- it 'returns true when the block is added to the queue' do
155
- subject.post{ nil }.should be_true
156
- end
152
+ it 'returns true when the block is added to the queue' do
153
+ subject.post{ nil }.should be_true
154
+ end
157
155
 
158
- it 'calls the block with the given arguments' do
159
- @expected = nil
160
- subject.post(1, 2, 3)do |a, b, c|
161
- @expected = a + b + c
162
- end
163
- sleep(0.1)
164
- @expected.should eq 6
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
165
160
  end
161
+ sleep(0.1)
162
+ @expected.should eq 6
163
+ end
166
164
 
167
- it 'rejects the block while shutting down' do
168
- pool = FixedThreadPool.new(5)
169
- pool.post{ sleep(1) }
170
- pool.shutdown
171
- @expected = nil
172
- pool.post(1, 2, 3)do |a, b, c|
173
- @expected = a + b + c
174
- end
175
- @expected.should be_nil
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
176
171
  end
172
+ @expected.should be_nil
173
+ end
177
174
 
178
- it 'returns false while shutting down' do
179
- subject.post{ sleep(1) }
180
- subject.shutdown
181
- subject.post{ nil }.should be_false
182
- end
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
183
180
 
184
- it 'rejects the block once shutdown' do
185
- pool = FixedThreadPool.new(5)
186
- pool.shutdown
187
- @expected = nil
188
- pool.post(1, 2, 3)do |a, b, c|
189
- @expected = a + b + c
190
- end
191
- @expected.should be_nil
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
192
186
  end
187
+ @expected.should be_nil
188
+ end
193
189
 
194
- it 'returns false once shutdown' do
195
- subject.post{ nil }
196
- subject.shutdown
197
- sleep(0.1)
198
- subject.post{ nil }.should be_false
199
- end
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
200
196
 
201
- it 'aliases #<<' do
202
- @expected = false
203
- subject << proc { @expected = true }
204
- sleep(0.1)
205
- @expected.should be_true
206
- end
197
+ it 'aliases #<<' do
198
+ @expected = false
199
+ subject << proc { @expected = true }
200
+ sleep(0.1)
201
+ @expected.should be_true
207
202
  end
208
203
  end
209
204
  end
@@ -1,4 +1,5 @@
1
1
  require 'spec_helper'
2
+ require 'thread'
2
3
 
3
4
  describe 'utilities' do
4
5
 
@@ -26,7 +27,7 @@ describe 'utilities' do
26
27
  it 'raises an exception if no block is given' do
27
28
  lambda {
28
29
  atomic()
29
- }.should raise_error
30
+ }.should raise_error(ArgumentError)
30
31
  end
31
32
 
32
33
  it 'creates a new Fiber' do
@@ -42,4 +43,32 @@ describe 'utilities' do
42
43
  atomic{ 'foo' }
43
44
  end
44
45
  end
46
+
47
+ context Mutex do
48
+
49
+ context '#sync_with_timeout' do
50
+
51
+ it 'returns the result of the block if a lock is obtained before timeout' do
52
+ mutex = Mutex.new
53
+ result = mutex.sync_with_timeout(30){ 42 }
54
+ result.should eq 42
55
+ end
56
+
57
+ it 'raises Timeout::Error if the timeout is exceeded' do
58
+ mutex = Mutex.new
59
+ thread = Thread.new{ mutex.synchronize{ sleep(30) } }
60
+ sleep(0.1)
61
+ lambda {
62
+ mutex.sync_and_wait(1)
63
+ }.should raise_error(NoMethodError)
64
+ Thread.kill(thread)
65
+ end
66
+
67
+ it 'raises an exception if no block given' do
68
+ lambda {
69
+ Mutex.new.sync_with_timeout()
70
+ }.should raise_error(ArgumentError)
71
+ end
72
+ end
73
+ end
45
74
  end
@@ -1,11 +1,24 @@
1
+ require 'simplecov'
2
+ SimpleCov.start do
3
+ project_name 'concurrent-ruby'
4
+ add_filter '/md/'
5
+ add_filter '/pkg/'
6
+ add_filter '/spec/'
7
+ add_filter '/tasks/'
8
+ end
9
+
1
10
  require 'eventmachine'
2
11
 
3
12
  require 'concurrent'
13
+ require 'concurrent/functions'
14
+
15
+ require 'functional'
4
16
 
5
17
  # import all the support files
6
18
  Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require File.expand_path(f) }
7
19
 
8
20
  RSpec.configure do |config|
21
+ config.order = 'random'
9
22
 
10
23
  config.before(:suite) do
11
24
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jerry D'Antonio
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-07-29 00:00:00.000000000 Z
11
+ date: 2013-08-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: functional-ruby
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ~>
18
18
  - !ruby/object:Gem::Version
19
- version: 0.7.0
19
+ version: 0.7.4
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ~>
25
25
  - !ruby/object:Gem::Version
26
- version: 0.7.0
26
+ version: 0.7.4
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -39,7 +39,8 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  description: |2
42
- A gem for adding Erlang, Clojure, and Go inspired concurrent programming tools to Ruby.
42
+ Modern concurrency tools including agents, futures, promises, thread pools, reactors, and more.
43
+ Inspired by Erlang, Clojure, Go, JavaScript, actors, and classic concurrency patterns.
43
44
  email: jerry.dantonio@gmail.com
44
45
  executables: []
45
46
  extensions: []
@@ -54,12 +55,19 @@ files:
54
55
  - lib/concurrent/defer.rb
55
56
  - lib/concurrent/event.rb
56
57
  - lib/concurrent/event_machine_defer_proxy.rb
58
+ - lib/concurrent/executor.rb
57
59
  - lib/concurrent/fixed_thread_pool.rb
60
+ - lib/concurrent/functions.rb
58
61
  - lib/concurrent/future.rb
59
62
  - lib/concurrent/global_thread_pool.rb
60
63
  - lib/concurrent/goroutine.rb
64
+ - lib/concurrent/null_thread_pool.rb
61
65
  - lib/concurrent/obligation.rb
62
66
  - lib/concurrent/promise.rb
67
+ - lib/concurrent/reactor/drb_async_demux.rb
68
+ - lib/concurrent/reactor/tcp_sync_demux.rb
69
+ - lib/concurrent/reactor.rb
70
+ - lib/concurrent/supervisor.rb
63
71
  - lib/concurrent/thread_pool.rb
64
72
  - lib/concurrent/utilities.rb
65
73
  - lib/concurrent/version.rb
@@ -68,6 +76,7 @@ files:
68
76
  - md/agent.md
69
77
  - md/defer.md
70
78
  - md/event.md
79
+ - md/executor.md
71
80
  - md/future.md
72
81
  - md/goroutine.md
73
82
  - md/obligation.md
@@ -78,19 +87,30 @@ files:
78
87
  - spec/concurrent/defer_spec.rb
79
88
  - spec/concurrent/event_machine_defer_proxy_spec.rb
80
89
  - spec/concurrent/event_spec.rb
90
+ - spec/concurrent/executor_spec.rb
81
91
  - spec/concurrent/fixed_thread_pool_spec.rb
92
+ - spec/concurrent/functions_spec.rb
82
93
  - spec/concurrent/future_spec.rb
94
+ - spec/concurrent/global_thread_pool_spec.rb
83
95
  - spec/concurrent/goroutine_spec.rb
96
+ - spec/concurrent/null_thread_pool_spec.rb
84
97
  - spec/concurrent/obligation_shared.rb
85
98
  - spec/concurrent/promise_spec.rb
99
+ - spec/concurrent/reactor/drb_async_demux_spec.rb
100
+ - spec/concurrent/reactor/tcp_sync_demux_spec.rb
101
+ - spec/concurrent/reactor_spec.rb
102
+ - spec/concurrent/supervisor_spec.rb
86
103
  - spec/concurrent/thread_pool_shared.rb
87
104
  - spec/concurrent/utilities_spec.rb
88
105
  - spec/spec_helper.rb
89
- homepage: https://github.com/jdantonio/concurrent-ruby/
106
+ homepage: http://www.concurrent-ruby.com
90
107
  licenses:
91
108
  - MIT
92
109
  metadata: {}
93
- post_install_message:
110
+ post_install_message: |2
111
+ future = Concurrent::Future.new{ 'Hello, world!' }
112
+ puts future.value
113
+ #=> Hello, world!
94
114
  rdoc_options: []
95
115
  require_paths:
96
116
  - lib
@@ -106,21 +126,30 @@ required_rubygems_version: !ruby/object:Gem::Requirement
106
126
  version: '0'
107
127
  requirements: []
108
128
  rubyforge_project:
109
- rubygems_version: 2.0.3
129
+ rubygems_version: 2.0.6
110
130
  signing_key:
111
131
  specification_version: 4
112
- summary: Erlang, Clojure, and Go inspired concurrent programming tools for Ruby.
132
+ summary: Modern concurrency tools including agents, futures, promises, thread pools,
133
+ reactors, and more.
113
134
  test_files:
114
135
  - spec/concurrent/agent_spec.rb
115
136
  - spec/concurrent/cached_thread_pool_spec.rb
116
137
  - spec/concurrent/defer_spec.rb
117
138
  - spec/concurrent/event_machine_defer_proxy_spec.rb
118
139
  - spec/concurrent/event_spec.rb
140
+ - spec/concurrent/executor_spec.rb
119
141
  - spec/concurrent/fixed_thread_pool_spec.rb
142
+ - spec/concurrent/functions_spec.rb
120
143
  - spec/concurrent/future_spec.rb
144
+ - spec/concurrent/global_thread_pool_spec.rb
121
145
  - spec/concurrent/goroutine_spec.rb
146
+ - spec/concurrent/null_thread_pool_spec.rb
122
147
  - spec/concurrent/obligation_shared.rb
123
148
  - spec/concurrent/promise_spec.rb
149
+ - spec/concurrent/reactor/drb_async_demux_spec.rb
150
+ - spec/concurrent/reactor/tcp_sync_demux_spec.rb
151
+ - spec/concurrent/reactor_spec.rb
152
+ - spec/concurrent/supervisor_spec.rb
124
153
  - spec/concurrent/thread_pool_shared.rb
125
154
  - spec/concurrent/utilities_spec.rb
126
155
  - spec/spec_helper.rb