concurrent-ruby 0.3.0.pre.1 → 0.3.0.pre.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 (50) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +10 -33
  3. data/lib/concurrent.rb +5 -11
  4. data/lib/concurrent/{channel.rb → actor.rb} +14 -18
  5. data/lib/concurrent/agent.rb +5 -4
  6. data/lib/concurrent/cached_thread_pool.rb +116 -25
  7. data/lib/concurrent/cached_thread_pool/worker.rb +91 -0
  8. data/lib/concurrent/event.rb +13 -14
  9. data/lib/concurrent/event_machine_defer_proxy.rb +0 -1
  10. data/lib/concurrent/executor.rb +0 -1
  11. data/lib/concurrent/fixed_thread_pool.rb +111 -14
  12. data/lib/concurrent/fixed_thread_pool/worker.rb +54 -0
  13. data/lib/concurrent/future.rb +0 -2
  14. data/lib/concurrent/global_thread_pool.rb +21 -3
  15. data/lib/concurrent/goroutine.rb +1 -5
  16. data/lib/concurrent/obligation.rb +0 -19
  17. data/lib/concurrent/promise.rb +2 -5
  18. data/lib/concurrent/runnable.rb +2 -8
  19. data/lib/concurrent/supervisor.rb +9 -4
  20. data/lib/concurrent/utilities.rb +24 -0
  21. data/lib/concurrent/version.rb +1 -1
  22. data/md/agent.md +3 -3
  23. data/md/future.md +4 -4
  24. data/md/promise.md +15 -25
  25. data/md/thread_pool.md +9 -8
  26. data/spec/concurrent/actor_spec.rb +377 -0
  27. data/spec/concurrent/agent_spec.rb +2 -1
  28. data/spec/concurrent/cached_thread_pool_spec.rb +19 -29
  29. data/spec/concurrent/event_machine_defer_proxy_spec.rb +1 -1
  30. data/spec/concurrent/event_spec.rb +1 -1
  31. data/spec/concurrent/executor_spec.rb +0 -8
  32. data/spec/concurrent/fixed_thread_pool_spec.rb +27 -16
  33. data/spec/concurrent/future_spec.rb +0 -13
  34. data/spec/concurrent/global_thread_pool_spec.rb +73 -0
  35. data/spec/concurrent/goroutine_spec.rb +0 -15
  36. data/spec/concurrent/obligation_shared.rb +1 -38
  37. data/spec/concurrent/promise_spec.rb +28 -47
  38. data/spec/concurrent/supervisor_spec.rb +1 -2
  39. data/spec/concurrent/thread_pool_shared.rb +28 -7
  40. data/spec/concurrent/utilities_spec.rb +50 -0
  41. data/spec/spec_helper.rb +0 -1
  42. data/spec/support/functions.rb +17 -0
  43. metadata +12 -27
  44. data/lib/concurrent/functions.rb +0 -105
  45. data/lib/concurrent/null_thread_pool.rb +0 -25
  46. data/lib/concurrent/thread_pool.rb +0 -149
  47. data/md/reactor.md +0 -32
  48. data/spec/concurrent/channel_spec.rb +0 -446
  49. data/spec/concurrent/functions_spec.rb +0 -197
  50. data/spec/concurrent/null_thread_pool_spec.rb +0 -78
@@ -8,7 +8,6 @@ module Concurrent
8
8
 
9
9
  let(:worker_class) do
10
10
  Class.new {
11
- behavior(:runnable)
12
11
  attr_reader :start_count, :stop_count
13
12
  def run() @start_count ||= 0; @start_count += 1; return true; end
14
13
  def stop() @stop_count ||= 0; @stop_count += 1; return true; end
@@ -296,7 +295,7 @@ module Concurrent
296
295
  @thread = Thread.new{ sleep(0.5); supervisor.stop }
297
296
  sleep(0.1)
298
297
  lambda {
299
- Timeout::timeout(1){ supervisor.run }
298
+ Concurrent::timeout(1){ supervisor.run }
300
299
  }.should_not raise_error
301
300
  Thread.kill(@thread) unless @thread.nil?
302
301
  end
@@ -43,7 +43,8 @@ share_examples_for :thread_pool do
43
43
 
44
44
  it 'allows in-progress tasks to complete' do
45
45
  @expected = false
46
- subject.post{ sleep(0.5); @expected = true }
46
+ subject.post{ @expected = true }
47
+ sleep(0.1)
47
48
  subject.shutdown
48
49
  sleep(1)
49
50
  @expected.should be_true
@@ -53,15 +54,20 @@ share_examples_for :thread_pool do
53
54
  @expected = false
54
55
  subject.post{ sleep(0.2) }
55
56
  subject.post{ sleep(0.2); @expected = true }
57
+ sleep(0.1)
56
58
  subject.shutdown
57
59
  sleep(1)
58
60
  @expected.should be_true
59
61
  end
60
62
 
61
63
  it 'allows threads to exit normally' do
64
+ before_thread_count = Thread.list.size
65
+ 10.times{ subject << proc{ nil } }
66
+ sleep(0.1)
67
+ Thread.list.size.should > before_thread_count
62
68
  subject.shutdown
63
69
  sleep(1)
64
- subject.status.should be_empty
70
+ Thread.list.size.should == before_thread_count
65
71
  end
66
72
  end
67
73
 
@@ -69,6 +75,7 @@ share_examples_for :thread_pool do
69
75
 
70
76
  it 'stops accepting new tasks' do
71
77
  subject.post{ sleep(1) }
78
+ sleep(0.1)
72
79
  subject.kill
73
80
  @expected = false
74
81
  subject.post{ @expected = true }.should be_false
@@ -79,6 +86,7 @@ share_examples_for :thread_pool do
79
86
  it 'attempts to kill all in-progress tasks' do
80
87
  @expected = false
81
88
  subject.post{ sleep(1); @expected = true }
89
+ sleep(0.1)
82
90
  subject.kill
83
91
  sleep(1)
84
92
  @expected.should be_false
@@ -88,43 +96,56 @@ share_examples_for :thread_pool do
88
96
  @expected = false
89
97
  subject.post{ sleep(0.5) }
90
98
  subject.post{ sleep(0.5); @expected = true }
99
+ sleep(0.1)
91
100
  subject.kill
92
101
  sleep(1)
93
102
  @expected.should be_false
94
103
  end
95
104
 
96
105
  it 'kills all threads' do
106
+ before_thread_count = Thread.list.size
97
107
  100.times { subject << proc{ sleep(1) } }
98
108
  sleep(0.1)
99
- Thread.should_receive(:kill).at_least(subject.size).times
109
+ Thread.list.size.should > before_thread_count
100
110
  subject.kill
101
111
  sleep(0.1)
112
+ Thread.list.size.should == before_thread_count
102
113
  end
103
114
  end
104
115
 
105
116
  context '#wait_for_termination' do
106
117
 
107
- it 'immediately returns true after shutdown has complete' do
118
+ it 'immediately returns true when no threads running' do
119
+ subject.shutdown
120
+ subject.wait_for_termination.should be_true
121
+ end
122
+
123
+ it 'returns true after shutdown has complete' do
124
+ 10.times { subject << proc{ sleep(0.1) } }
125
+ sleep(0.1)
108
126
  subject.shutdown
109
127
  subject.wait_for_termination.should be_true
110
128
  end
111
129
 
112
- it 'blocks indefinitely when timeout it nil' do
130
+ it 'blocks indefinitely when timeout is nil' do
113
131
  subject.post{ sleep(1) }
132
+ sleep(0.1)
114
133
  subject.shutdown
115
134
  subject.wait_for_termination(nil).should be_true
116
135
  end
117
136
 
118
137
  it 'returns true when shutdown sucessfully completes before timeout' do
119
138
  subject.post{ sleep(0.5) }
139
+ sleep(0.1)
120
140
  subject.shutdown
121
141
  subject.wait_for_termination(1).should be_true
122
142
  end
123
143
 
124
144
  it 'returns false when shutdown fails to complete before timeout' do
125
- subject.post{ sleep(1) }
145
+ subject.post{ sleep }
146
+ sleep(0.1)
126
147
  subject.shutdown
127
- subject.wait_for_termination(0.5).should be_false
148
+ subject.wait_for_termination(1).should be_false
128
149
  end
129
150
  end
130
151
 
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ module Concurrent
4
+
5
+ describe '#timeout' do
6
+
7
+ it 'raises an exception if no block is given' do
8
+ expect {
9
+ Concurrent::timeout(1)
10
+ }.to raise_error
11
+ end
12
+
13
+ it 'returns the value of the block on success' do
14
+ result = Concurrent::timeout(1) { 42 }
15
+ result.should eq 42
16
+ end
17
+
18
+ it 'raises an exception if the timeout value is reached' do
19
+ expect {
20
+ Concurrent::timeout(1){ sleep }
21
+ }.to raise_error(Concurrent::TimeoutError)
22
+ end
23
+
24
+ it 'bubbles thread exceptions' do
25
+ expect {
26
+ Concurrent::timeout(1){ raise NotImplementedError }
27
+ }.to raise_error
28
+ end
29
+
30
+ it 'kills the thread on success' do
31
+ result = Concurrent::timeout(1) { 42 }
32
+ Thread.should_receive(:kill).with(any_args())
33
+ Concurrent::timeout(1){ 42 }
34
+ end
35
+
36
+ it 'kills the thread on timeout' do
37
+ Thread.should_receive(:kill).with(any_args())
38
+ expect {
39
+ Concurrent::timeout(1){ sleep }
40
+ }.to raise_error
41
+ end
42
+
43
+ it 'kills the thread on exception' do
44
+ Thread.should_receive(:kill).with(any_args())
45
+ expect {
46
+ Concurrent::timeout(1){ raise NotImplementedError }
47
+ }.to raise_error
48
+ end
49
+ end
50
+ end
@@ -17,7 +17,6 @@ end
17
17
  require 'eventmachine'
18
18
 
19
19
  require 'concurrent'
20
- require 'concurrent/functions'
21
20
 
22
21
  # import all the support files
23
22
  Dir[File.join(File.dirname(__FILE__), 'support/**/*.rb')].each { |f| require File.expand_path(f) }
@@ -0,0 +1,17 @@
1
+ require 'rbconfig'
2
+
3
+ def delta(v1, v2)
4
+ if block_given?
5
+ v1 = yield(v1)
6
+ v2 = yield(v2)
7
+ end
8
+ return (v1 - v2).abs
9
+ end
10
+
11
+ def mri?
12
+ RbConfig::CONFIG['ruby_install_name']=~ /^ruby$/i
13
+ end
14
+
15
+ def jruby?
16
+ RbConfig::CONFIG['ruby_install_name']=~ /^jruby$/i
17
+ end
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: concurrent-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0.pre.1
4
+ version: 0.3.0.pre.2
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-10-09 00:00:00.000000000 Z
11
+ date: 2013-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: functional-ruby
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - ~>
18
- - !ruby/object:Gem::Version
19
- version: 0.7.4
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - ~>
25
- - !ruby/object:Gem::Version
26
- version: 0.7.4
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bundler
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -50,23 +36,23 @@ extra_rdoc_files:
50
36
  files:
51
37
  - README.md
52
38
  - LICENSE
39
+ - lib/concurrent/actor.rb
53
40
  - lib/concurrent/agent.rb
41
+ - lib/concurrent/cached_thread_pool/worker.rb
54
42
  - lib/concurrent/cached_thread_pool.rb
55
- - lib/concurrent/channel.rb
56
43
  - lib/concurrent/event.rb
57
44
  - lib/concurrent/event_machine_defer_proxy.rb
58
45
  - lib/concurrent/executor.rb
46
+ - lib/concurrent/fixed_thread_pool/worker.rb
59
47
  - lib/concurrent/fixed_thread_pool.rb
60
- - lib/concurrent/functions.rb
61
48
  - lib/concurrent/future.rb
62
49
  - lib/concurrent/global_thread_pool.rb
63
50
  - lib/concurrent/goroutine.rb
64
- - lib/concurrent/null_thread_pool.rb
65
51
  - lib/concurrent/obligation.rb
66
52
  - lib/concurrent/promise.rb
67
53
  - lib/concurrent/runnable.rb
68
54
  - lib/concurrent/supervisor.rb
69
- - lib/concurrent/thread_pool.rb
55
+ - lib/concurrent/utilities.rb
70
56
  - lib/concurrent/version.rb
71
57
  - lib/concurrent.rb
72
58
  - lib/concurrent_ruby.rb
@@ -77,21 +63,18 @@ files:
77
63
  - md/goroutine.md
78
64
  - md/obligation.md
79
65
  - md/promise.md
80
- - md/reactor.md
81
66
  - md/supervisor.md
82
67
  - md/thread_pool.md
68
+ - spec/concurrent/actor_spec.rb
83
69
  - spec/concurrent/agent_spec.rb
84
70
  - spec/concurrent/cached_thread_pool_spec.rb
85
- - spec/concurrent/channel_spec.rb
86
71
  - spec/concurrent/event_machine_defer_proxy_spec.rb
87
72
  - spec/concurrent/event_spec.rb
88
73
  - spec/concurrent/executor_spec.rb
89
74
  - spec/concurrent/fixed_thread_pool_spec.rb
90
- - spec/concurrent/functions_spec.rb
91
75
  - spec/concurrent/future_spec.rb
92
76
  - spec/concurrent/global_thread_pool_spec.rb
93
77
  - spec/concurrent/goroutine_spec.rb
94
- - spec/concurrent/null_thread_pool_spec.rb
95
78
  - spec/concurrent/obligation_shared.rb
96
79
  - spec/concurrent/promise_spec.rb
97
80
  - spec/concurrent/runnable_shared.rb
@@ -99,7 +82,9 @@ files:
99
82
  - spec/concurrent/supervisor_spec.rb
100
83
  - spec/concurrent/thread_pool_shared.rb
101
84
  - spec/concurrent/uses_global_thread_pool_shared.rb
85
+ - spec/concurrent/utilities_spec.rb
102
86
  - spec/spec_helper.rb
87
+ - spec/support/functions.rb
103
88
  homepage: http://www.concurrent-ruby.com
104
89
  licenses:
105
90
  - MIT
@@ -129,18 +114,16 @@ specification_version: 4
129
114
  summary: Modern concurrency tools including agents, futures, promises, thread pools,
130
115
  actors, and more.
131
116
  test_files:
117
+ - spec/concurrent/actor_spec.rb
132
118
  - spec/concurrent/agent_spec.rb
133
119
  - spec/concurrent/cached_thread_pool_spec.rb
134
- - spec/concurrent/channel_spec.rb
135
120
  - spec/concurrent/event_machine_defer_proxy_spec.rb
136
121
  - spec/concurrent/event_spec.rb
137
122
  - spec/concurrent/executor_spec.rb
138
123
  - spec/concurrent/fixed_thread_pool_spec.rb
139
- - spec/concurrent/functions_spec.rb
140
124
  - spec/concurrent/future_spec.rb
141
125
  - spec/concurrent/global_thread_pool_spec.rb
142
126
  - spec/concurrent/goroutine_spec.rb
143
- - spec/concurrent/null_thread_pool_spec.rb
144
127
  - spec/concurrent/obligation_shared.rb
145
128
  - spec/concurrent/promise_spec.rb
146
129
  - spec/concurrent/runnable_shared.rb
@@ -148,4 +131,6 @@ test_files:
148
131
  - spec/concurrent/supervisor_spec.rb
149
132
  - spec/concurrent/thread_pool_shared.rb
150
133
  - spec/concurrent/uses_global_thread_pool_shared.rb
134
+ - spec/concurrent/utilities_spec.rb
151
135
  - spec/spec_helper.rb
136
+ - spec/support/functions.rb
@@ -1,105 +0,0 @@
1
- require 'concurrent/agent'
2
- require 'concurrent/future'
3
- require 'concurrent/promise'
4
-
5
- module Kernel
6
-
7
- ## agent
8
-
9
- def agent(*args, &block)
10
- return Concurrent::Agent.new(*args, &block)
11
- end
12
- module_function :agent
13
-
14
- def post(object, *args, &block)
15
- if object.respond_to?(:post)
16
- return object.post(*args, &block)
17
- else
18
- raise ArgumentError.new('object does not support #post')
19
- end
20
- end
21
- module_function :post
22
-
23
- ## future
24
-
25
- def future(*args, &block)
26
- return Concurrent::Future.new(*args, &block)
27
- end
28
- module_function :future
29
-
30
- ## obligation
31
-
32
- def deref(object, *args, &block)
33
- if object.respond_to?(:deref)
34
- return object.deref(*args, &block)
35
- elsif object.respond_to?(:value)
36
- return object.value(*args, &block)
37
- else
38
- raise ArgumentError.new('object does not support #deref')
39
- end
40
- end
41
- module_function :deref
42
-
43
- def pending?(object)
44
- if object.respond_to?(:pending?)
45
- return object.pending?
46
- else
47
- raise ArgumentError.new('object does not support #pending?')
48
- end
49
- end
50
- module_function :pending?
51
-
52
- def fulfilled?(object)
53
- if object.respond_to?(:fulfilled?)
54
- return object.fulfilled?
55
- elsif object.respond_to?(:realized?)
56
- return object.realized?
57
- else
58
- raise ArgumentError.new('object does not support #fulfilled?')
59
- end
60
- end
61
- module_function :fulfilled?
62
-
63
- def realized?(object)
64
- if object.respond_to?(:realized?)
65
- return object.realized?
66
- elsif object.respond_to?(:fulfilled?)
67
- return object.fulfilled?
68
- else
69
- raise ArgumentError.new('object does not support #realized?')
70
- end
71
- end
72
- module_function :realized?
73
-
74
- def rejected?(object)
75
- if object.respond_to?(:rejected?)
76
- return object.rejected?
77
- else
78
- raise ArgumentError.new('object does not support #rejected?')
79
- end
80
- end
81
- module_function :rejected?
82
-
83
- ## promise
84
-
85
- # Creates a new promise object. "A promise represents the eventual
86
- # value returned from the single completion of an operation."
87
- # Promises can be chained in a tree structure where each promise
88
- # has zero or more children. Promises are resolved asynchronously
89
- # in the order they are added to the tree. Parents are guaranteed
90
- # to be resolved before their children. The result of each promise
91
- # is passes to each of its children when the child resolves. When
92
- # a promise is rejected all its children will be summarily rejected.
93
- # A promise added to a rejected promise will immediately be rejected.
94
- # A promise that is neither resolved or rejected is pending.
95
- #
96
- # @param args [Array] zero or more arguments for the block
97
- # @param block [Proc] the block to call when attempting fulfillment
98
- #
99
- # @see Promise
100
- # @see http://wiki.commonjs.org/wiki/Promises/A
101
- def promise(*args, &block)
102
- return Concurrent::Promise.new(*args, &block)
103
- end
104
- module_function :promise
105
- end
@@ -1,25 +0,0 @@
1
- require 'concurrent/global_thread_pool'
2
-
3
- module Concurrent
4
-
5
- class NullThreadPool
6
- behavior(:global_thread_pool)
7
-
8
- def self.post(*args)
9
- Thread.new(*args) do
10
- Thread.current.abort_on_exception = false
11
- yield(*args)
12
- end
13
- return true
14
- end
15
-
16
- def post(*args, &block)
17
- return NullThreadPool.post(*args, &block)
18
- end
19
-
20
- def <<(block)
21
- NullThreadPool.post(&block)
22
- return self
23
- end
24
- end
25
- end