concurrent-ruby 0.1.1 → 0.2.0

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 (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